diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 196 | 
1 files changed, 176 insertions, 20 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index a563328e3dae..1c97244e0d74 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -37,14 +37,16 @@  #define FIRMWARE_RAVEN		"amdgpu/raven_vcn.bin"  #define FIRMWARE_PICASSO	"amdgpu/picasso_vcn.bin"  #define FIRMWARE_RAVEN2		"amdgpu/raven2_vcn.bin" -#define FIRMWARE_ARCTURUS 	"amdgpu/arcturus_vcn.bin" -#define FIRMWARE_RENOIR 	"amdgpu/renoir_vcn.bin" -#define FIRMWARE_GREEN_SARDINE 	"amdgpu/green_sardine_vcn.bin" -#define FIRMWARE_NAVI10 	"amdgpu/navi10_vcn.bin" -#define FIRMWARE_NAVI14 	"amdgpu/navi14_vcn.bin" -#define FIRMWARE_NAVI12 	"amdgpu/navi12_vcn.bin" -#define FIRMWARE_SIENNA_CICHLID 	"amdgpu/sienna_cichlid_vcn.bin" -#define FIRMWARE_NAVY_FLOUNDER 	"amdgpu/navy_flounder_vcn.bin" +#define FIRMWARE_ARCTURUS	"amdgpu/arcturus_vcn.bin" +#define FIRMWARE_RENOIR		"amdgpu/renoir_vcn.bin" +#define FIRMWARE_GREEN_SARDINE	"amdgpu/green_sardine_vcn.bin" +#define FIRMWARE_NAVI10		"amdgpu/navi10_vcn.bin" +#define FIRMWARE_NAVI14		"amdgpu/navi14_vcn.bin" +#define FIRMWARE_NAVI12		"amdgpu/navi12_vcn.bin" +#define FIRMWARE_SIENNA_CICHLID	"amdgpu/sienna_cichlid_vcn.bin" +#define FIRMWARE_NAVY_FLOUNDER	"amdgpu/navy_flounder_vcn.bin" +#define FIRMWARE_VANGOGH	"amdgpu/vangogh_vcn.bin" +#define FIRMWARE_DIMGREY_CAVEFISH	"amdgpu/dimgrey_cavefish_vcn.bin"  MODULE_FIRMWARE(FIRMWARE_RAVEN);  MODULE_FIRMWARE(FIRMWARE_PICASSO); @@ -57,6 +59,8 @@ MODULE_FIRMWARE(FIRMWARE_NAVI14);  MODULE_FIRMWARE(FIRMWARE_NAVI12);  MODULE_FIRMWARE(FIRMWARE_SIENNA_CICHLID);  MODULE_FIRMWARE(FIRMWARE_NAVY_FLOUNDER); +MODULE_FIRMWARE(FIRMWARE_VANGOGH); +MODULE_FIRMWARE(FIRMWARE_DIMGREY_CAVEFISH);  static void amdgpu_vcn_idle_work_handler(struct work_struct *work); @@ -130,6 +134,15 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)  		    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))  			adev->vcn.indirect_sram = true;  		break; +	case CHIP_VANGOGH: +		fw_name = FIRMWARE_VANGOGH; +		break; +	case CHIP_DIMGREY_CAVEFISH: +		fw_name = FIRMWARE_DIMGREY_CAVEFISH; +		if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) && +		    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)) +			adev->vcn.indirect_sram = true; +		break;  	default:  		return -EINVAL;  	} @@ -319,6 +332,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)  		container_of(work, struct amdgpu_device, vcn.idle_work.work);  	unsigned int fences = 0, fence[AMDGPU_MAX_VCN_INSTANCES] = {0};  	unsigned int i, j; +	int r = 0;  	for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {  		if (adev->vcn.harvest_config & (1 << j)) @@ -345,8 +359,13 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)  	}  	if (!fences && !atomic_read(&adev->vcn.total_submission_cnt)) { +		amdgpu_gfx_off_ctrl(adev, true);  		amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,  		       AMD_PG_STATE_GATE); +		r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO, +				false); +		if (r) +			dev_warn(adev->dev, "(%d) failed to disable video power profile mode\n", r);  	} else {  		schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT);  	} @@ -355,9 +374,17 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)  void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)  {  	struct amdgpu_device *adev = ring->adev; +	int r = 0;  	atomic_inc(&adev->vcn.total_submission_cnt); -	cancel_delayed_work_sync(&adev->vcn.idle_work); + +	if (!cancel_delayed_work_sync(&adev->vcn.idle_work)) { +		amdgpu_gfx_off_ctrl(adev, false); +		r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO, +				true); +		if (r) +			dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r); +	}  	mutex_lock(&adev->vcn.vcn_pg_lock);  	amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN, @@ -429,6 +456,37 @@ int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)  	return r;  } +int amdgpu_vcn_dec_sw_ring_test_ring(struct amdgpu_ring *ring) +{ +	struct amdgpu_device *adev = ring->adev; +	uint32_t rptr; +	unsigned int i; +	int r; + +	if (amdgpu_sriov_vf(adev)) +		return 0; + +	r = amdgpu_ring_alloc(ring, 16); +	if (r) +		return r; + +	rptr = amdgpu_ring_get_rptr(ring); + +	amdgpu_ring_write(ring, VCN_DEC_SW_CMD_END); +	amdgpu_ring_commit(ring); + +	for (i = 0; i < adev->usec_timeout; i++) { +		if (amdgpu_ring_get_rptr(ring) != rptr) +			break; +		udelay(1); +	} + +	if (i >= adev->usec_timeout) +		r = -ETIMEDOUT; + +	return r; +} +  static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,  				   struct amdgpu_bo *bo,  				   struct dma_fence **fence) @@ -483,16 +541,16 @@ err:  }  static int amdgpu_vcn_dec_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, -			      struct dma_fence **fence) +					 struct amdgpu_bo **bo)  {  	struct amdgpu_device *adev = ring->adev; -	struct amdgpu_bo *bo = NULL;  	uint32_t *msg;  	int r, i; +	*bo = NULL;  	r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE,  				      AMDGPU_GEM_DOMAIN_VRAM, -				      &bo, NULL, (void **)&msg); +				      bo, NULL, (void **)&msg);  	if (r)  		return r; @@ -513,20 +571,20 @@ static int amdgpu_vcn_dec_get_create_msg(struct amdgpu_ring *ring, uint32_t hand  	for (i = 14; i < 1024; ++i)  		msg[i] = cpu_to_le32(0x0); -	return amdgpu_vcn_dec_send_msg(ring, bo, fence); +	return 0;  }  static int amdgpu_vcn_dec_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, -			       struct dma_fence **fence) +					  struct amdgpu_bo **bo)  {  	struct amdgpu_device *adev = ring->adev; -	struct amdgpu_bo *bo = NULL;  	uint32_t *msg;  	int r, i; +	*bo = NULL;  	r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE,  				      AMDGPU_GEM_DOMAIN_VRAM, -				      &bo, NULL, (void **)&msg); +				      bo, NULL, (void **)&msg);  	if (r)  		return r; @@ -539,19 +597,117 @@ static int amdgpu_vcn_dec_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han  	for (i = 6; i < 1024; ++i)  		msg[i] = cpu_to_le32(0x0); -	return amdgpu_vcn_dec_send_msg(ring, bo, fence); +	return 0;  }  int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout)  { -	struct dma_fence *fence; +	struct dma_fence *fence = NULL; +	struct amdgpu_bo *bo;  	long r; -	r = amdgpu_vcn_dec_get_create_msg(ring, 1, NULL); +	r = amdgpu_vcn_dec_get_create_msg(ring, 1, &bo); +	if (r) +		goto error; + +	r = amdgpu_vcn_dec_send_msg(ring, bo, NULL); +	if (r) +		goto error; +	r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &bo); +	if (r) +		goto error; + +	r = amdgpu_vcn_dec_send_msg(ring, bo, &fence); +	if (r) +		goto error; + +	r = dma_fence_wait_timeout(fence, false, timeout); +	if (r == 0) +		r = -ETIMEDOUT; +	else if (r > 0) +		r = 0; + +	dma_fence_put(fence); +error: +	return r; +} + +static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring, +				   struct amdgpu_bo *bo, +				   struct dma_fence **fence) +{ +	struct amdgpu_vcn_decode_buffer *decode_buffer = NULL; +	const unsigned int ib_size_dw = 64; +	struct amdgpu_device *adev = ring->adev; +	struct dma_fence *f = NULL; +	struct amdgpu_job *job; +	struct amdgpu_ib *ib; +	uint64_t addr; +	int i, r; + +	r = amdgpu_job_alloc_with_ib(adev, ib_size_dw * 4, +				AMDGPU_IB_POOL_DIRECT, &job); +	if (r) +		goto err; + +	ib = &job->ibs[0]; +	addr = amdgpu_bo_gpu_offset(bo); +	ib->length_dw = 0; + +	ib->ptr[ib->length_dw++] = sizeof(struct amdgpu_vcn_decode_buffer) + 8; +	ib->ptr[ib->length_dw++] = cpu_to_le32(AMDGPU_VCN_IB_FLAG_DECODE_BUFFER); +	decode_buffer = (struct amdgpu_vcn_decode_buffer *)&(ib->ptr[ib->length_dw]); +	ib->length_dw += sizeof(struct amdgpu_vcn_decode_buffer) / 4; +	memset(decode_buffer, 0, sizeof(struct amdgpu_vcn_decode_buffer)); + +	decode_buffer->valid_buf_flag |= cpu_to_le32(AMDGPU_VCN_CMD_FLAG_MSG_BUFFER); +	decode_buffer->msg_buffer_address_hi = cpu_to_le32(addr >> 32); +	decode_buffer->msg_buffer_address_lo = cpu_to_le32(addr); + +	for (i = ib->length_dw; i < ib_size_dw; ++i) +		ib->ptr[i] = 0x0; + +	r = amdgpu_job_submit_direct(job, ring, &f); +	if (r) +		goto err_free; + +	amdgpu_bo_fence(bo, f, false); +	amdgpu_bo_unreserve(bo); +	amdgpu_bo_unref(&bo); + +	if (fence) +		*fence = dma_fence_get(f); +	dma_fence_put(f); + +	return 0; + +err_free: +	amdgpu_job_free(job); + +err: +	amdgpu_bo_unreserve(bo); +	amdgpu_bo_unref(&bo); +	return r; +} + +int amdgpu_vcn_dec_sw_ring_test_ib(struct amdgpu_ring *ring, long timeout) +{ +	struct dma_fence *fence = NULL; +	struct amdgpu_bo *bo; +	long r; + +	r = amdgpu_vcn_dec_get_create_msg(ring, 1, &bo); +	if (r) +		goto error; + +	r = amdgpu_vcn_dec_sw_send_msg(ring, bo, NULL); +	if (r) +		goto error; +	r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &bo);  	if (r)  		goto error; -	r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &fence); +	r = amdgpu_vcn_dec_sw_send_msg(ring, bo, &fence);  	if (r)  		goto error; | 
