drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c
Extension
.c
Size
13591 bytes
Lines
365
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

struct pll_output_params {
	u32 ssc_up_spread;
	u32 mpll_div5_en;
	u32 hdmi_div;
	u32 ana_cp_int;
	u32 ana_cp_prop;
	u32 refclk_postscalar;
	u32 tx_clk_div;
	u32 fracn_quot;
	u32 fracn_rem;
	u32 fracn_den;
	u32 fracn_en;
	u32 pmix_en;
	u32 multiplier;
	int mpll_ana_v2i;
	int ana_freq_vco;
};

static s64 interp(s64 x, s64 x1, s64 x2, s64 y1, s64 y2)
{
	s64 dydx;

	dydx = DIV64_U64_ROUND_UP((y2 - y1) * 100000, (x2 - x1));

	return (y1 + DIV64_U64_ROUND_UP(dydx * (x - x1), 100000));
}

static void get_ana_cp_int_prop(u64 vco_clk,
				u32 refclk_postscalar,
				int mpll_ana_v2i,
				int c, int a,
				const u64 curve_freq_hz[2][8],
				const u64 curve_0[2][8],
				const u64 curve_1[2][8],
				const u64 curve_2[2][8],
				u32 *ana_cp_int,
				u32 *ana_cp_prop)
{
	u64 vco_div_refclk_float;
	u64 curve_0_interpolated;
	u64 curve_2_interpolated;
	u64 curve_1_interpolated;
	u64 curve_2_scaled1;
	u64 curve_2_scaled2;
	u64 adjusted_vco_clk1;
	u64 adjusted_vco_clk2;
	u64 curve_2_scaled_int;
	u64 interpolated_product;
	u64 scaled_interpolated_sqrt;
	u64 scaled_vco_div_refclk1;
	u64 scaled_vco_div_refclk2;
	u64 ana_cp_int_temp;
	u64 temp;

	vco_div_refclk_float = vco_clk * DIV_ROUND_DOWN_ULL(1000000000000ULL, refclk_postscalar);

	/* Interpolate curve values at the target vco_clk frequency */
	curve_0_interpolated = interp(vco_clk, curve_freq_hz[c][a], curve_freq_hz[c][a + 1],
				      curve_0[c][a], curve_0[c][a + 1]);

	curve_2_interpolated = interp(vco_clk, curve_freq_hz[c][a], curve_freq_hz[c][a + 1],
				      curve_2[c][a], curve_2[c][a + 1]);

	curve_1_interpolated = interp(vco_clk, curve_freq_hz[c][a], curve_freq_hz[c][a + 1],
				      curve_1[c][a], curve_1[c][a + 1]);

	curve_1_interpolated = DIV_ROUND_DOWN_ULL(curve_1_interpolated, CURVE1_MULTIPLIER);

	/*
	 * Scale curve_2_interpolated based on mpll_ana_v2i, for integer part
	 * ana_cp_int and for the proportional part ana_cp_prop
	 */
	temp = curve_2_interpolated * (4 - mpll_ana_v2i);
	curve_2_scaled1 = DIV_ROUND_DOWN_ULL(temp, 16000);
	curve_2_scaled2 = DIV_ROUND_DOWN_ULL(temp, 160);

	/* Scale vco_div_refclk for ana_cp_int */
	scaled_vco_div_refclk1 = 112008301 * DIV_ROUND_DOWN_ULL(vco_div_refclk_float, 100000);

	adjusted_vco_clk1 = CURVE2_MULTIPLIER *
			    DIV_ROUND_DOWN_ULL(scaled_vco_div_refclk1, (curve_0_interpolated *
			    DIV_ROUND_DOWN_ULL(curve_1_interpolated, CURVE0_MULTIPLIER)));

	ana_cp_int_temp =
		DIV64_U64_ROUND_CLOSEST(DIV_ROUND_DOWN_ULL(adjusted_vco_clk1, curve_2_scaled1),
					CURVE2_MULTIPLIER);

	*ana_cp_int = clamp(ana_cp_int_temp, 1, 127);

	curve_2_scaled_int = curve_2_scaled1 * (*ana_cp_int);

Annotation

Implementation Notes