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);  | 
