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

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
Extension
.c
Size
71065 bytes
Lines
2213
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 (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) {
			atomic_inc(&v->dpg_enc_submission_cnt);
			new_state.fw_based = VCN_DPG_STATE__PAUSE;
		} else {
			unsigned int fences = 0;
			unsigned int i;

			for (i = 0; i < v->num_enc_rings; ++i)
				fences += amdgpu_fence_count_emitted(&v->ring_enc[i]);

			if (fences || atomic_read(&v->dpg_enc_submission_cnt))
				new_state.fw_based = VCN_DPG_STATE__PAUSE;
			else
				new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
		}
		v->pause_dpg_mode(v, &new_state);
	}
	mutex_unlock(&adev->vcn.inst[0].vcn_pg_lock);
	amdgpu_vcn_get_profile(adev);
}

static void vcn_v2_5_ring_end_use(struct amdgpu_ring *ring)
{
	struct amdgpu_device *adev = ring->adev;

	/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
	if (ring->adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
	    ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC &&
	    !adev->vcn.inst[ring->me].using_unified_queue)
		atomic_dec(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt);

	atomic_dec(&adev->vcn.inst[0].total_submission_cnt);

	schedule_delayed_work(&adev->vcn.inst[0].idle_work,
			      VCN_IDLE_TIMEOUT);
}

/**
 * vcn_v2_5_early_init - set function pointers and load microcode
 *
 * @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
 *
 * Set ring and irq function pointers
 * Load microcode from filesystem
 */
static int vcn_v2_5_early_init(struct amdgpu_ip_block *ip_block)
{
	struct amdgpu_device *adev = ip_block->adev;
	int i, r;

	if (amdgpu_sriov_vf(adev)) {
		adev->vcn.num_vcn_inst = 2;
		adev->vcn.harvest_config = 0;
		for (i = 0; i < adev->vcn.num_vcn_inst; i++)
			adev->vcn.inst[i].num_enc_rings = 1;
	} else {
		u32 harvest;
		int i;

		for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
			harvest = RREG32_SOC15(VCN, i, mmCC_UVD_HARVESTING);
			if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK)
				adev->vcn.harvest_config |= 1 << i;
			adev->vcn.inst[i].num_enc_rings = 2;
		}
		if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 |
						 AMDGPU_VCN_HARVEST_VCN1))
			/* both instances are harvested, disable the block */
			return -ENOENT;
	}

	vcn_v2_5_set_dec_ring_funcs(adev);
	vcn_v2_5_set_enc_ring_funcs(adev);
	vcn_v2_5_set_irq_funcs(adev);
	vcn_v2_5_set_ras_funcs(adev);

	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
		adev->vcn.inst[i].set_pg_state = vcn_v2_5_set_pg_state;

		r = amdgpu_vcn_early_init(adev, i);
		if (r)
			return r;
	}

	return 0;
}

/**
 * vcn_v2_5_sw_init - sw init for VCN block
 *

Annotation

Implementation Notes