drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c- Extension
.c- Size
- 28881 bytes
- Lines
- 1050
- 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.
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/firmware.hdrm/drm_drv.hamdgpu.hamdgpu_ucode.hamdgpu_vpe.hamdgpu_smu.hsoc15_common.hvpe_v6_1.hvpe_v2_0.h
Detected Declarations
function div16_u16_remfunction complete_integer_division_u16function vpe_u1_8_from_fractionfunction vpe_internal_get_pratiofunction amdgpu_vpe_configure_dpmfunction amdgpu_vpe_psp_update_sramfunction amdgpu_vpe_init_microcodefunction amdgpu_vpe_ring_initfunction amdgpu_vpe_ring_finifunction vpe_early_initfunction vpe_need_dpm0_at_power_downfunction vpe_get_dpm_levelfunction vpe_idle_work_handlerfunction vpe_common_initfunction vpe_sw_initfunction vpe_sw_finifunction vpe_hw_initfunction vpe_hw_finifunction vpe_suspendfunction vpe_resumefunction vpe_ring_insert_nopfunction vpe_get_csa_mc_addrfunction vpe_ring_emit_pred_execfunction vpe_ring_emit_ibfunction vpe_ring_emit_fencefunction vpe_ring_emit_pipeline_syncfunction vpe_ring_emit_wregfunction vpe_ring_emit_reg_waitfunction vpe_ring_emit_vm_flushfunction vpe_ring_init_cond_execfunction vpe_ring_preempt_ibfunction vpe_set_clockgating_statefunction vpe_set_powergating_statefunction vpe_ring_get_rptrfunction vpe_ring_get_wptrfunction vpe_ring_set_wptrfunction vpe_ring_test_ringfunction vpe_ring_test_ibfunction vpe_ring_begin_usefunction vpe_ring_end_usefunction vpe_ring_resetfunction amdgpu_get_vpe_reset_maskfunction amdgpu_vpe_sysfs_reset_mask_initfunction amdgpu_vpe_sysfs_reset_mask_finifunction vpe_set_ring_funcs
Annotated Snippet
if (remainder >= arg2_value) {
res_value |= 1;
remainder -= arg2_value;
}
} while (--i != 0);
}
/* round up LSB */
{
uint16_t summand = (remainder << 1) >= arg2_value;
if ((res_value + summand) > 32767 /* SHRT_MAX */)
return 0;
res_value += summand;
}
return res_value;
}
static uint16_t vpe_internal_get_pratio(uint16_t from_frequency, uint16_t to_frequency)
{
uint16_t pratio = vpe_u1_8_from_fraction(from_frequency, to_frequency);
if (GET_PRATIO_INTEGER_PART(pratio) > 1)
pratio = 0;
return pratio;
}
/*
* VPE has 4 DPM levels from level 0 (lowerest) to 3 (highest),
* VPE FW will dynamically decide which level should be used according to current loading.
*
* Get VPE and SOC clocks from PM, and select the appropriate four clock values,
* calculate the ratios of adjusting from one clock to another.
* The VPE FW can then request the appropriate frequency from the PMFW.
*/
int amdgpu_vpe_configure_dpm(struct amdgpu_vpe *vpe)
{
struct amdgpu_device *adev = vpe->ring.adev;
uint32_t dpm_ctl;
if (adev->pm.dpm_enabled) {
struct dpm_clocks clock_table = { 0 };
struct dpm_clock *VPEClks;
struct dpm_clock *SOCClks;
uint32_t idx;
uint32_t vpeclk_enalbled_num = 0;
uint32_t pratio_vmax_vnorm = 0, pratio_vnorm_vmid = 0, pratio_vmid_vmin = 0;
uint16_t pratio_vmin_freq = 0, pratio_vmid_freq = 0, pratio_vnorm_freq = 0, pratio_vmax_freq = 0;
dpm_ctl = RREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_enable));
dpm_ctl |= 1; /* DPM enablement */
WREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_enable), dpm_ctl);
/* Get VPECLK and SOCCLK */
if (amdgpu_dpm_get_dpm_clock_table(adev, &clock_table)) {
dev_dbg(adev->dev, "%s: get clock failed!\n", __func__);
goto disable_dpm;
}
SOCClks = clock_table.SocClocks;
VPEClks = clock_table.VPEClocks;
/* Comfirm enabled vpe clk num
* Enabled VPE clocks are ordered from low to high in VPEClks
* The highest valid clock index+1 is the number of VPEClks
*/
for (idx = PP_SMU_NUM_VPECLK_DPM_LEVELS; idx && !vpeclk_enalbled_num; idx--)
if (VPEClks[idx-1].Freq)
vpeclk_enalbled_num = idx;
/* vpe dpm only cares 4 levels. */
for (idx = 0; idx < VPE_MAX_DPM_LEVEL; idx++) {
uint32_t soc_dpm_level;
uint32_t min_freq;
if (idx == 0)
soc_dpm_level = 0;
else
soc_dpm_level = (idx * 2) + 1;
/* clamp the max level */
if (soc_dpm_level > vpeclk_enalbled_num - 1)
soc_dpm_level = vpeclk_enalbled_num - 1;
min_freq = (SOCClks[soc_dpm_level].Freq < VPEClks[soc_dpm_level].Freq) ?
SOCClks[soc_dpm_level].Freq : VPEClks[soc_dpm_level].Freq;
Annotation
- Immediate include surface: `linux/firmware.h`, `drm/drm_drv.h`, `amdgpu.h`, `amdgpu_ucode.h`, `amdgpu_vpe.h`, `amdgpu_smu.h`, `soc15_common.h`, `vpe_v6_1.h`.
- Detected declarations: `function div16_u16_rem`, `function complete_integer_division_u16`, `function vpe_u1_8_from_fraction`, `function vpe_internal_get_pratio`, `function amdgpu_vpe_configure_dpm`, `function amdgpu_vpe_psp_update_sram`, `function amdgpu_vpe_init_microcode`, `function amdgpu_vpe_ring_init`, `function amdgpu_vpe_ring_fini`, `function vpe_early_init`.
- Atlas domain: Driver Families / drivers/gpu.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.