diff options
Diffstat (limited to 'drivers/gpu/drm/msm/adreno/adreno_gpu.c')
| -rw-r--r-- | drivers/gpu/drm/msm/adreno/adreno_gpu.c | 90 |
1 files changed, 57 insertions, 33 deletions
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index a0b9d8a95b1..28ca8cd8b09 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -17,6 +17,7 @@ #include "adreno_gpu.h" #include "msm_gem.h" +#include "msm_mmu.h" struct adreno_info { struct adreno_rev rev; @@ -44,7 +45,7 @@ static const struct adreno_info gpulist[] = { .pfpfw = "a300_pfp.fw", .gmem = SZ_512K, }, { - .rev = ADRENO_REV(3, 3, 0, 0), + .rev = ADRENO_REV(3, 3, 0, ANY_ID), .revn = 330, .name = "A330", .pm4fw = "a330_pm4.fw", @@ -53,6 +54,11 @@ static const struct adreno_info gpulist[] = { }, }; +MODULE_FIRMWARE("a300_pm4.fw"); +MODULE_FIRMWARE("a300_pfp.fw"); +MODULE_FIRMWARE("a330_pm4.fw"); +MODULE_FIRMWARE("a330_pfp.fw"); + #define RB_SIZE SZ_32K #define RB_BLKSIZE 16 @@ -65,7 +71,13 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value) *value = adreno_gpu->info->revn; return 0; case MSM_PARAM_GMEM_SIZE: - *value = adreno_gpu->info->gmem; + *value = adreno_gpu->gmem; + return 0; + case MSM_PARAM_CHIP_ID: + *value = adreno_gpu->rev.patchid | + (adreno_gpu->rev.minor << 8) | + (adreno_gpu->rev.major << 16) | + (adreno_gpu->rev.core << 24); return 0; default: DBG("%s: invalid param: %u", gpu->name, param); @@ -86,7 +98,7 @@ int adreno_hw_init(struct msm_gpu *gpu) gpu_write(gpu, REG_AXXX_CP_RB_CNTL, /* size is log2(quad-words): */ AXXX_CP_RB_CNTL_BUFSZ(ilog2(gpu->rb->size / 8)) | - AXXX_CP_RB_CNTL_BLKSZ(RB_BLKSIZE)); + AXXX_CP_RB_CNTL_BLKSZ(ilog2(RB_BLKSIZE / 8))); /* Setup ringbuffer address: */ gpu_write(gpu, REG_AXXX_CP_RB_BASE, gpu->rb_iova); @@ -219,19 +231,11 @@ void adreno_flush(struct msm_gpu *gpu) void adreno_idle(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); - uint32_t rptr, wptr = get_wptr(gpu->rb); - unsigned long t; - - t = jiffies + ADRENO_IDLE_TIMEOUT; - - /* then wait for CP to drain ringbuffer: */ - do { - rptr = adreno_gpu->memptrs->rptr; - if (rptr == wptr) - return; - } while(time_before(jiffies, t)); + uint32_t wptr = get_wptr(gpu->rb); - DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name); + /* wait for CP to drain ringbuffer: */ + if (spin_until(adreno_gpu->memptrs->rptr == wptr)) + DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name); /* TODO maybe we need to reset GPU here to recover from hang? */ } @@ -254,22 +258,37 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m) } #endif -void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords) +/* would be nice to not have to duplicate the _show() stuff with printk(): */ +void adreno_dump(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); - uint32_t freedwords; - unsigned long t = jiffies + ADRENO_IDLE_TIMEOUT; - do { - uint32_t size = gpu->rb->size / 4; - uint32_t wptr = get_wptr(gpu->rb); - uint32_t rptr = adreno_gpu->memptrs->rptr; - freedwords = (rptr + (size - 1) - wptr) % size; - - if (time_after(jiffies, t)) { - DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name); - break; - } - } while(freedwords < ndwords); + + printk("revision: %d (%d.%d.%d.%d)\n", + adreno_gpu->info->revn, adreno_gpu->rev.core, + adreno_gpu->rev.major, adreno_gpu->rev.minor, + adreno_gpu->rev.patchid); + + printk("fence: %d/%d\n", adreno_gpu->memptrs->fence, + gpu->submitted_fence); + printk("rptr: %d\n", adreno_gpu->memptrs->rptr); + printk("wptr: %d\n", adreno_gpu->memptrs->wptr); + printk("rb wptr: %d\n", get_wptr(gpu->rb)); + +} + +static uint32_t ring_freewords(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + uint32_t size = gpu->rb->size / 4; + uint32_t wptr = get_wptr(gpu->rb); + uint32_t rptr = adreno_gpu->memptrs->rptr; + return (rptr + (size - 1) - wptr) % size; +} + +void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords) +{ + if (spin_until(ring_freewords(gpu) >= ndwords)) + DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name); } static const char *iommu_ports[] = { @@ -286,6 +305,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct adreno_gpu *gpu, const struct adreno_gpu_funcs *funcs, struct adreno_rev rev) { + struct msm_mmu *mmu; int i, ret; /* identify gpu: */ @@ -311,6 +331,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, rev.core, rev.major, rev.minor, rev.patchid); gpu->funcs = funcs; + gpu->gmem = gpu->info->gmem; gpu->rev = rev; ret = request_firmware(&gpu->pm4, gpu->info->pm4fw, drm->dev); @@ -333,10 +354,13 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, if (ret) return ret; - ret = msm_iommu_attach(drm, gpu->base.iommu, - iommu_ports, ARRAY_SIZE(iommu_ports)); - if (ret) - return ret; + mmu = gpu->base.mmu; + if (mmu) { + ret = mmu->funcs->attach(mmu, iommu_ports, + ARRAY_SIZE(iommu_ports)); + if (ret) + return ret; + } gpu->memptrs_bo = msm_gem_new(drm, sizeof(*gpu->memptrs), MSM_BO_UNCACHED); |
