drivers/gpu/drm/radeon/rv730_dpm.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/radeon/rv730_dpm.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/radeon/rv730_dpm.c
Extension
.c
Size
16768 bytes
Lines
506
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

#include "radeon.h"
#include "rv730d.h"
#include "r600_dpm.h"
#include "rv770.h"
#include "rv770_dpm.h"
#include "atom.h"

#define MC_CG_ARB_FREQ_F0           0x0a
#define MC_CG_ARB_FREQ_F1           0x0b
#define MC_CG_ARB_FREQ_F2           0x0c
#define MC_CG_ARB_FREQ_F3           0x0d

int rv730_populate_sclk_value(struct radeon_device *rdev,
			      u32 engine_clock,
			      RV770_SMC_SCLK_VALUE *sclk)
{
	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
	struct atom_clock_dividers dividers;
	u32 spll_func_cntl = pi->clk_regs.rv730.cg_spll_func_cntl;
	u32 spll_func_cntl_2 = pi->clk_regs.rv730.cg_spll_func_cntl_2;
	u32 spll_func_cntl_3 = pi->clk_regs.rv730.cg_spll_func_cntl_3;
	u32 cg_spll_spread_spectrum = pi->clk_regs.rv730.cg_spll_spread_spectrum;
	u32 cg_spll_spread_spectrum_2 = pi->clk_regs.rv730.cg_spll_spread_spectrum_2;
	u64 tmp;
	u32 reference_clock = rdev->clock.spll.reference_freq;
	u32 reference_divider, post_divider;
	u32 fbdiv;
	int ret;

	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
					     engine_clock, false, &dividers);
	if (ret)
		return ret;

	reference_divider = 1 + dividers.ref_div;

	if (dividers.enable_post_div)
		post_divider = ((dividers.post_div >> 4) & 0xf) +
			(dividers.post_div & 0xf) + 2;
	else
		post_divider = 1;

	tmp = (u64) engine_clock * reference_divider * post_divider * 16384;
	do_div(tmp, reference_clock);
	fbdiv = (u32) tmp;

	/* set up registers */
	if (dividers.enable_post_div)
		spll_func_cntl |= SPLL_DIVEN;
	else
		spll_func_cntl &= ~SPLL_DIVEN;
	spll_func_cntl &= ~(SPLL_HILEN_MASK | SPLL_LOLEN_MASK | SPLL_REF_DIV_MASK);
	spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div);
	spll_func_cntl |= SPLL_HILEN((dividers.post_div >> 4) & 0xf);
	spll_func_cntl |= SPLL_LOLEN(dividers.post_div & 0xf);

	spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
	spll_func_cntl_2 |= SCLK_MUX_SEL(2);

	spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK;
	spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv);
	spll_func_cntl_3 |= SPLL_DITHEN;

	if (pi->sclk_ss) {
		struct radeon_atom_ss ss;
		u32 vco_freq = engine_clock * post_divider;

		if (radeon_atombios_get_asic_ss_info(rdev, &ss,
						     ASIC_INTERNAL_ENGINE_SS, vco_freq)) {
			u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate);
			u32 clk_v = ss.percentage * fbdiv / (clk_s * 10000);

			cg_spll_spread_spectrum &= ~CLK_S_MASK;
			cg_spll_spread_spectrum |= CLK_S(clk_s);
			cg_spll_spread_spectrum |= SSEN;

			cg_spll_spread_spectrum_2 &= ~CLK_V_MASK;
			cg_spll_spread_spectrum_2 |= CLK_V(clk_v);
		}
	}

	sclk->sclk_value = cpu_to_be32(engine_clock);
	sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl);
	sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2);
	sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3);
	sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(cg_spll_spread_spectrum);
	sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(cg_spll_spread_spectrum_2);

	return 0;
}

Annotation

Implementation Notes