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

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
Extension
.c
Size
50045 bytes
Lines
1653
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 (harvest & UVD_PG0_CC_UVD_HARVESTING__UVD_DISABLE_MASK) {
				adev->uvd.harvest_config |= 1 << i;
			}
		}
		if (adev->uvd.harvest_config == (AMDGPU_UVD_HARVEST_UVD0 |
						 AMDGPU_UVD_HARVEST_UVD1))
			/* both instances are harvested, disable the block */
			return -ENOENT;
	} else {
		adev->uvd.num_uvd_inst = 1;
	}

	if (amdgpu_sriov_vf(adev))
		adev->uvd.num_enc_rings = 1;
	else
		adev->uvd.num_enc_rings = 2;
	uvd_v7_0_set_ring_funcs(adev);
	uvd_v7_0_set_enc_ring_funcs(adev);
	uvd_v7_0_set_irq_funcs(adev);

	return 0;
}

static int uvd_v7_0_sw_init(struct amdgpu_ip_block *ip_block)
{
	struct amdgpu_ring *ring;

	int i, j, r;
	struct amdgpu_device *adev = ip_block->adev;

	for (j = 0; j < adev->uvd.num_uvd_inst; j++) {
		if (adev->uvd.harvest_config & (1 << j))
			continue;
		/* UVD TRAP */
		r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_uvds[j], UVD_7_0__SRCID__UVD_SYSTEM_MESSAGE_INTERRUPT, &adev->uvd.inst[j].irq);
		if (r)
			return r;

		/* UVD ENC TRAP */
		for (i = 0; i < adev->uvd.num_enc_rings; ++i) {
			r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_uvds[j], i + UVD_7_0__SRCID__UVD_ENC_GEN_PURP, &adev->uvd.inst[j].irq);
			if (r)
				return r;
		}
	}

	r = amdgpu_uvd_sw_init(adev);
	if (r)
		return r;

	if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
		const struct common_firmware_header *hdr;
		hdr = (const struct common_firmware_header *)adev->uvd.fw->data;
		adev->firmware.ucode[AMDGPU_UCODE_ID_UVD].ucode_id = AMDGPU_UCODE_ID_UVD;
		adev->firmware.ucode[AMDGPU_UCODE_ID_UVD].fw = adev->uvd.fw;
		adev->firmware.fw_size +=
			ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);

		if (adev->uvd.num_uvd_inst == UVD7_MAX_HW_INSTANCES_VEGA20) {
			adev->firmware.ucode[AMDGPU_UCODE_ID_UVD1].ucode_id = AMDGPU_UCODE_ID_UVD1;
			adev->firmware.ucode[AMDGPU_UCODE_ID_UVD1].fw = adev->uvd.fw;
			adev->firmware.fw_size +=
				ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
		}
		drm_info(adev_to_drm(adev), "PSP loading UVD firmware\n");
	}

	for (j = 0; j < adev->uvd.num_uvd_inst; j++) {
		if (adev->uvd.harvest_config & (1 << j))
			continue;
		if (!amdgpu_sriov_vf(adev)) {
			ring = &adev->uvd.inst[j].ring;
			ring->vm_hub = AMDGPU_MMHUB0(0);
			sprintf(ring->name, "uvd_%d", ring->me);
			r = amdgpu_ring_init(adev, ring, 512,
					     &adev->uvd.inst[j].irq, 0,
					     AMDGPU_RING_PRIO_DEFAULT, NULL);
			if (r)
				return r;
		}

		for (i = 0; i < adev->uvd.num_enc_rings; ++i) {
			ring = &adev->uvd.inst[j].ring_enc[i];
			ring->vm_hub = AMDGPU_MMHUB0(0);
			sprintf(ring->name, "uvd_enc_%d.%d", ring->me, i);
			if (amdgpu_sriov_vf(adev)) {
				ring->use_doorbell = true;

				/* currently only use the first enconding ring for
				 * sriov, so set unused location for other unused rings.

Annotation

Implementation Notes