drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
Extension
.c
Size
30379 bytes
Lines
1214
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (r != 0) {
			DRM_ERROR("Failed setting up VCE run queue.\n");
			return r;
		}
	}

	return 0;
}

/**
 * amdgpu_vce_suspend - unpin VCE fw memory
 *
 * @adev: amdgpu_device pointer
 *
 */
int amdgpu_vce_suspend(struct amdgpu_device *adev)
{
	int i;

	cancel_delayed_work_sync(&adev->vce.idle_work);

	if (adev->vce.vcpu_bo == NULL)
		return 0;

	for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i)
		if (atomic_read(&adev->vce.handles[i]))
			break;

	if (i == AMDGPU_MAX_VCE_HANDLES)
		return 0;

	/* TODO: suspending running encoding sessions isn't supported */
	return -EINVAL;
}

/**
 * amdgpu_vce_resume - pin VCE fw memory
 *
 * @adev: amdgpu_device pointer
 *
 */
int amdgpu_vce_resume(struct amdgpu_device *adev)
{
	const struct common_firmware_header *hdr;
	unsigned int offset;
	int idx;

	if (adev->vce.vcpu_bo == NULL)
		return -EINVAL;

	hdr = (const struct common_firmware_header *)adev->vce.fw->data;
	offset = le32_to_cpu(hdr->ucode_array_offset_bytes);

	if (drm_dev_enter(adev_to_drm(adev), &idx)) {
		memset_io(adev->vce.cpu_addr, 0, amdgpu_bo_size(adev->vce.vcpu_bo));
		memcpy_toio(adev->vce.cpu_addr, adev->vce.fw->data + offset,
			    adev->vce.fw->size - offset);
		drm_dev_exit(idx);
	}

	return 0;
}

/**
 * amdgpu_vce_idle_work_handler - power off VCE
 *
 * @work: pointer to work structure
 *
 * power of VCE when it's not used any more
 */
static void amdgpu_vce_idle_work_handler(struct work_struct *work)
{
	struct amdgpu_device *adev =
		container_of(work, struct amdgpu_device, vce.idle_work.work);
	unsigned int i, count = 0;

	for (i = 0; i < adev->vce.num_rings; i++)
		count += amdgpu_fence_count_emitted(&adev->vce.ring[i]);

	if (count == 0) {
		if (adev->pm.dpm_enabled) {
			amdgpu_dpm_enable_vce(adev, false);
		} else {
			amdgpu_asic_set_vce_clocks(adev, 0, 0);
			amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
							       AMD_PG_STATE_GATE);
			amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
							       AMD_CG_STATE_GATE);
		}
	} else {

Annotation

Implementation Notes