diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c | 79 | 
1 files changed, 74 insertions, 5 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c index dda29132dfb2..6b7d66b6d4cc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c @@ -121,10 +121,12 @@ static void amdgpu_jpeg_idle_work_handler(struct work_struct *work)  			fences += amdgpu_fence_count_emitted(&adev->jpeg.inst[i].ring_dec[j]);  	} -	if (!fences && !atomic_read(&adev->jpeg.total_submission_cnt)) +	if (!fences && !atomic_read(&adev->jpeg.total_submission_cnt)) { +		mutex_lock(&adev->jpeg.jpeg_pg_lock);  		amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,  						       AMD_PG_STATE_GATE); -	else +		mutex_unlock(&adev->jpeg.jpeg_pg_lock); +	} else  		schedule_delayed_work(&adev->jpeg.idle_work, JPEG_IDLE_TIMEOUT);  } @@ -194,7 +196,8 @@ static int amdgpu_jpeg_dec_set_reg(struct amdgpu_ring *ring, uint32_t handle,  	int i, r;  	r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4, -				     AMDGPU_IB_POOL_DIRECT, &job); +				     AMDGPU_IB_POOL_DIRECT, &job, +				     AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST);  	if (r)  		return r; @@ -368,7 +371,7 @@ static int amdgpu_debugfs_jpeg_sched_mask_set(void *data, u64 val)  	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {  		for (j = 0; j < adev->jpeg.num_jpeg_rings; ++j) {  			ring = &adev->jpeg.inst[i].ring_dec[j]; -			if (val & (1 << ((i * adev->jpeg.num_jpeg_rings) + j))) +			if (val & (BIT_ULL(1) << ((i * adev->jpeg.num_jpeg_rings) + j)))  				ring->sched.ready = true;  			else  				ring->sched.ready = false; @@ -463,7 +466,8 @@ int amdgpu_jpeg_reg_dump_init(struct amdgpu_device *adev,  	adev->jpeg.ip_dump = kcalloc(adev->jpeg.num_jpeg_inst * count,  				     sizeof(uint32_t), GFP_KERNEL);  	if (!adev->jpeg.ip_dump) { -		DRM_ERROR("Failed to allocate memory for JPEG IP Dump\n"); +		dev_err(adev->dev, +			"Failed to allocate memory for JPEG IP Dump\n");  		return -ENOMEM;  	}  	adev->jpeg.reg_list = reg; @@ -536,3 +540,68 @@ void amdgpu_jpeg_print_ip_state(struct amdgpu_ip_block *ip_block, struct drm_pri  			drm_printf(p, "\nInactive Instance:JPEG%d\n", i);  	}  } + +static inline bool amdgpu_jpeg_reg_valid(u32 reg) +{ +	if (reg < JPEG_REG_RANGE_START || reg > JPEG_REG_RANGE_END || +	    (reg >= JPEG_ATOMIC_RANGE_START && reg <= JPEG_ATOMIC_RANGE_END)) +		return false; +	else +		return true; +} + +/** + * amdgpu_jpeg_dec_parse_cs - command submission parser + * + * @parser: Command submission parser context + * @job: the job to parse + * @ib: the IB to parse + * + * Parse the command stream, return -EINVAL for invalid packet, + * 0 otherwise + */ + +int amdgpu_jpeg_dec_parse_cs(struct amdgpu_cs_parser *parser, +			      struct amdgpu_job *job, +			      struct amdgpu_ib *ib) +{ +	u32 i, reg, res, cond, type; +	struct amdgpu_device *adev = parser->adev; + +	for (i = 0; i < ib->length_dw ; i += 2) { +		reg  = CP_PACKETJ_GET_REG(ib->ptr[i]); +		res  = CP_PACKETJ_GET_RES(ib->ptr[i]); +		cond = CP_PACKETJ_GET_COND(ib->ptr[i]); +		type = CP_PACKETJ_GET_TYPE(ib->ptr[i]); + +		if (res) /* only support 0 at the moment */ +			return -EINVAL; + +		switch (type) { +		case PACKETJ_TYPE0: +			if (cond != PACKETJ_CONDITION_CHECK0 || +			    !amdgpu_jpeg_reg_valid(reg)) { +				dev_err(adev->dev, "Invalid packet [0x%08x]!\n", ib->ptr[i]); +				return -EINVAL; +			} +			break; +		case PACKETJ_TYPE3: +			if (cond != PACKETJ_CONDITION_CHECK3 || +			    !amdgpu_jpeg_reg_valid(reg)) { +				dev_err(adev->dev, "Invalid packet [0x%08x]!\n", ib->ptr[i]); +				return -EINVAL; +			} +			break; +		case PACKETJ_TYPE6: +			if (ib->ptr[i] == CP_PACKETJ_NOP) +				continue; +			dev_err(adev->dev, "Invalid packet [0x%08x]!\n", ib->ptr[i]); +			return -EINVAL; +		default: +			dev_err(adev->dev, "Unknown packet type %d !\n", type); +			return -EINVAL; +		} +	} + +	return 0; +} | 
