File Index
Files and directories
Sign in
FILE

vlv_clock.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/i915/display/vlv_clock.c C
 1// SPDX-License-Identifier: MIT
 2/* Copyright © 2025 Intel Corporation */
 3
 4#include <drm/drm_print.h>
 5
 6#include "intel_display_core.h"
 7#include "intel_display_types.h"
 8#include "vlv_clock.h"
 9#include "vlv_sideband.h"
10
11/*
12 * FIXME: The caching of hpll_freq and czclk_freq relies on the first calls
13 * occurring at a time when they can actually be read. This appears to be the
14 * case, but is somewhat fragile. Make the initialization explicit at a point
15 * where they can be reliably read.
16 */
17
18/* returns HPLL frequency in kHz */
19int vlv_clock_get_hpll_vco(struct drm_device *drm)
20{
21	struct intel_display *display = to_intel_display(drm);
22	int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
23
24	if (!display->vlv_clock.hpll_freq) {
25		vlv_cck_get(drm);
26		/* Obtain SKU information */
27		hpll_freq = vlv_cck_read(drm, CCK_FUSE_REG) &
28			CCK_FUSE_HPLL_FREQ_MASK;
29		vlv_cck_put(drm);
30
31		display->vlv_clock.hpll_freq = vco_freq[hpll_freq] * 1000;
32
33		drm_dbg_kms(drm, "HPLL frequency: %d kHz\n", display->vlv_clock.hpll_freq);
34	}
35
36	return display->vlv_clock.hpll_freq;
37}
38
39static int vlv_clock_get_cck(struct drm_device *drm,
40			     const char *name, u32 reg, int ref_freq)
41{
42	u32 val;
43	int divider;
44
45	vlv_cck_get(drm);
46	val = vlv_cck_read(drm, reg);
47	vlv_cck_put(drm);
48
49	divider = val & CCK_FREQUENCY_VALUES;
50
51	drm_WARN(drm, (val & CCK_FREQUENCY_STATUS) !=
52		 (divider << CCK_FREQUENCY_STATUS_SHIFT),
53		 "%s change in progress\n", name);
54
55	return DIV_ROUND_CLOSEST(ref_freq << 1, divider + 1);
56}
57
58int vlv_clock_get_hrawclk(struct drm_device *drm)
59{
60	/* RAWCLK_FREQ_VLV register updated from power well code */
61	return vlv_clock_get_cck(drm, "hrawclk", CCK_DISPLAY_REF_CLOCK_CONTROL,
62				 vlv_clock_get_hpll_vco(drm));
63}
64
65int vlv_clock_get_czclk(struct drm_device *drm)
66{
67	struct intel_display *display = to_intel_display(drm);
68
69	if (!display->vlv_clock.czclk_freq) {
70		display->vlv_clock.czclk_freq = vlv_clock_get_cck(drm, "czclk", CCK_CZ_CLOCK_CONTROL,
71								  vlv_clock_get_hpll_vco(drm));
72		drm_dbg_kms(drm, "CZ clock rate: %d kHz\n", display->vlv_clock.czclk_freq);
73	}
74
75	return display->vlv_clock.czclk_freq;
76}
77
78int vlv_clock_get_cdclk(struct drm_device *drm)
79{
80	return vlv_clock_get_cck(drm, "cdclk", CCK_DISPLAY_CLOCK_CONTROL,
81				 vlv_clock_get_hpll_vco(drm));
82}
83
84int vlv_clock_get_gpll(struct drm_device *drm)
85{
86	return vlv_clock_get_cck(drm, "GPLL ref", CCK_GPLL_CLOCK_CONTROL,
87				 vlv_clock_get_czclk(drm));
88}
~/ Read-only file preview.