xref: /openbmc/linux/drivers/gpu/drm/i915/display/intel_cdclk.c (revision c845428b7a9157523103100806bc8130d64769c8)
1df0566a6SJani Nikula /*
2df0566a6SJani Nikula  * Copyright © 2006-2017 Intel Corporation
3df0566a6SJani Nikula  *
4df0566a6SJani Nikula  * Permission is hereby granted, free of charge, to any person obtaining a
5df0566a6SJani Nikula  * copy of this software and associated documentation files (the "Software"),
6df0566a6SJani Nikula  * to deal in the Software without restriction, including without limitation
7df0566a6SJani Nikula  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8df0566a6SJani Nikula  * and/or sell copies of the Software, and to permit persons to whom the
9df0566a6SJani Nikula  * Software is furnished to do so, subject to the following conditions:
10df0566a6SJani Nikula  *
11df0566a6SJani Nikula  * The above copyright notice and this permission notice (including the next
12df0566a6SJani Nikula  * paragraph) shall be included in all copies or substantial portions of the
13df0566a6SJani Nikula  * Software.
14df0566a6SJani Nikula  *
15df0566a6SJani Nikula  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16df0566a6SJani Nikula  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17df0566a6SJani Nikula  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18df0566a6SJani Nikula  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19df0566a6SJani Nikula  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20df0566a6SJani Nikula  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21df0566a6SJani Nikula  * DEALINGS IN THE SOFTWARE.
22df0566a6SJani Nikula  */
23df0566a6SJani Nikula 
24cd191546SStanislav Lisovskiy #include <linux/time.h>
25cac91e67SStanislav Lisovskiy 
26f3b603deSVille Syrjälä #include "hsw_ips.h"
27801543b2SJani Nikula #include "i915_reg.h"
28fe4709a8SVille Syrjälä #include "intel_atomic.h"
29754d6275SJani Nikula #include "intel_atomic_plane.h"
30112a87c4SKai Vehmanen #include "intel_audio.h"
31cac91e67SStanislav Lisovskiy #include "intel_bw.h"
32df0566a6SJani Nikula #include "intel_cdclk.h"
33fd2b94a5SJani Nikula #include "intel_crtc.h"
347785ae0bSVille Syrjälä #include "intel_de.h"
351d455f8dSJani Nikula #include "intel_display_types.h"
36e30e6c7bSMatt Roper #include "intel_mchbar_regs.h"
377e470f10SJani Nikula #include "intel_pci_config.h"
384dd4375bSJani Nikula #include "intel_pcode.h"
3917c1a4b7SVille Syrjälä #include "intel_psr.h"
408290bceeSStanislav Lisovskiy #include "intel_vdsc.h"
411eecf31eSJani Nikula #include "vlv_sideband.h"
42df0566a6SJani Nikula 
43df0566a6SJani Nikula /**
44df0566a6SJani Nikula  * DOC: CDCLK / RAWCLK
45df0566a6SJani Nikula  *
46df0566a6SJani Nikula  * The display engine uses several different clocks to do its work. There
47df0566a6SJani Nikula  * are two main clocks involved that aren't directly related to the actual
48df0566a6SJani Nikula  * pixel clock or any symbol/bit clock of the actual output port. These
49df0566a6SJani Nikula  * are the core display clock (CDCLK) and RAWCLK.
50df0566a6SJani Nikula  *
51df0566a6SJani Nikula  * CDCLK clocks most of the display pipe logic, and thus its frequency
52df0566a6SJani Nikula  * must be high enough to support the rate at which pixels are flowing
53df0566a6SJani Nikula  * through the pipes. Downscaling must also be accounted as that increases
54df0566a6SJani Nikula  * the effective pixel rate.
55df0566a6SJani Nikula  *
56df0566a6SJani Nikula  * On several platforms the CDCLK frequency can be changed dynamically
57df0566a6SJani Nikula  * to minimize power consumption for a given display configuration.
58df0566a6SJani Nikula  * Typically changes to the CDCLK frequency require all the display pipes
59df0566a6SJani Nikula  * to be shut down while the frequency is being changed.
60df0566a6SJani Nikula  *
61df0566a6SJani Nikula  * On SKL+ the DMC will toggle the CDCLK off/on during DC5/6 entry/exit.
62df0566a6SJani Nikula  * DMC will not change the active CDCLK frequency however, so that part
63df0566a6SJani Nikula  * will still be performed by the driver directly.
64df0566a6SJani Nikula  *
65df0566a6SJani Nikula  * RAWCLK is a fixed frequency clock, often used by various auxiliary
66df0566a6SJani Nikula  * blocks such as AUX CH or backlight PWM. Hence the only thing we
67df0566a6SJani Nikula  * really need to know about RAWCLK is its frequency so that various
68df0566a6SJani Nikula  * dividers can be programmed correctly.
69df0566a6SJani Nikula  */
70df0566a6SJani Nikula 
71a908db6dSJani Nikula struct intel_cdclk_funcs {
72a908db6dSJani Nikula 	void (*get_cdclk)(struct drm_i915_private *i915,
73a908db6dSJani Nikula 			  struct intel_cdclk_config *cdclk_config);
74a908db6dSJani Nikula 	void (*set_cdclk)(struct drm_i915_private *i915,
75a908db6dSJani Nikula 			  const struct intel_cdclk_config *cdclk_config,
76a908db6dSJani Nikula 			  enum pipe pipe);
77a908db6dSJani Nikula 	int (*modeset_calc_cdclk)(struct intel_cdclk_state *state);
78a908db6dSJani Nikula 	u8 (*calc_voltage_level)(int cdclk);
79a908db6dSJani Nikula };
80a908db6dSJani Nikula 
intel_cdclk_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)8144892ffaSDave Airlie void intel_cdclk_get_cdclk(struct drm_i915_private *dev_priv,
8244892ffaSDave Airlie 			   struct intel_cdclk_config *cdclk_config)
8344892ffaSDave Airlie {
84986531bdSJani Nikula 	dev_priv->display.funcs.cdclk->get_cdclk(dev_priv, cdclk_config);
8544892ffaSDave Airlie }
8644892ffaSDave Airlie 
intel_cdclk_set_cdclk(struct drm_i915_private * dev_priv,const struct intel_cdclk_config * cdclk_config,enum pipe pipe)8744892ffaSDave Airlie static void intel_cdclk_set_cdclk(struct drm_i915_private *dev_priv,
8844892ffaSDave Airlie 				  const struct intel_cdclk_config *cdclk_config,
8944892ffaSDave Airlie 				  enum pipe pipe)
9044892ffaSDave Airlie {
91986531bdSJani Nikula 	dev_priv->display.funcs.cdclk->set_cdclk(dev_priv, cdclk_config, pipe);
9244892ffaSDave Airlie }
9344892ffaSDave Airlie 
intel_cdclk_modeset_calc_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_config)9444892ffaSDave Airlie static int intel_cdclk_modeset_calc_cdclk(struct drm_i915_private *dev_priv,
9544892ffaSDave Airlie 					  struct intel_cdclk_state *cdclk_config)
9644892ffaSDave Airlie {
97986531bdSJani Nikula 	return dev_priv->display.funcs.cdclk->modeset_calc_cdclk(cdclk_config);
9844892ffaSDave Airlie }
9944892ffaSDave Airlie 
intel_cdclk_calc_voltage_level(struct drm_i915_private * dev_priv,int cdclk)10044892ffaSDave Airlie static u8 intel_cdclk_calc_voltage_level(struct drm_i915_private *dev_priv,
10144892ffaSDave Airlie 					 int cdclk)
10244892ffaSDave Airlie {
103986531bdSJani Nikula 	return dev_priv->display.funcs.cdclk->calc_voltage_level(cdclk);
10444892ffaSDave Airlie }
10544892ffaSDave Airlie 
fixed_133mhz_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)106df0566a6SJani Nikula static void fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv,
1070bb94e03SVille Syrjälä 				   struct intel_cdclk_config *cdclk_config)
108df0566a6SJani Nikula {
1090bb94e03SVille Syrjälä 	cdclk_config->cdclk = 133333;
110df0566a6SJani Nikula }
111df0566a6SJani Nikula 
fixed_200mhz_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)112df0566a6SJani Nikula static void fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv,
1130bb94e03SVille Syrjälä 				   struct intel_cdclk_config *cdclk_config)
114df0566a6SJani Nikula {
1150bb94e03SVille Syrjälä 	cdclk_config->cdclk = 200000;
116df0566a6SJani Nikula }
117df0566a6SJani Nikula 
fixed_266mhz_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)118df0566a6SJani Nikula static void fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv,
1190bb94e03SVille Syrjälä 				   struct intel_cdclk_config *cdclk_config)
120df0566a6SJani Nikula {
1210bb94e03SVille Syrjälä 	cdclk_config->cdclk = 266667;
122df0566a6SJani Nikula }
123df0566a6SJani Nikula 
fixed_333mhz_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)124df0566a6SJani Nikula static void fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv,
1250bb94e03SVille Syrjälä 				   struct intel_cdclk_config *cdclk_config)
126df0566a6SJani Nikula {
1270bb94e03SVille Syrjälä 	cdclk_config->cdclk = 333333;
128df0566a6SJani Nikula }
129df0566a6SJani Nikula 
fixed_400mhz_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)130df0566a6SJani Nikula static void fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv,
1310bb94e03SVille Syrjälä 				   struct intel_cdclk_config *cdclk_config)
132df0566a6SJani Nikula {
1330bb94e03SVille Syrjälä 	cdclk_config->cdclk = 400000;
134df0566a6SJani Nikula }
135df0566a6SJani Nikula 
fixed_450mhz_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)136df0566a6SJani Nikula static void fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv,
1370bb94e03SVille Syrjälä 				   struct intel_cdclk_config *cdclk_config)
138df0566a6SJani Nikula {
1390bb94e03SVille Syrjälä 	cdclk_config->cdclk = 450000;
140df0566a6SJani Nikula }
141df0566a6SJani Nikula 
i85x_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)142df0566a6SJani Nikula static void i85x_get_cdclk(struct drm_i915_private *dev_priv,
1430bb94e03SVille Syrjälä 			   struct intel_cdclk_config *cdclk_config)
144df0566a6SJani Nikula {
1458ff5446aSThomas Zimmermann 	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
146df0566a6SJani Nikula 	u16 hpllcc = 0;
147df0566a6SJani Nikula 
148df0566a6SJani Nikula 	/*
149df0566a6SJani Nikula 	 * 852GM/852GMV only supports 133 MHz and the HPLLCC
150df0566a6SJani Nikula 	 * encoding is different :(
151df0566a6SJani Nikula 	 * FIXME is this the right way to detect 852GM/852GMV?
152df0566a6SJani Nikula 	 */
153df0566a6SJani Nikula 	if (pdev->revision == 0x1) {
1540bb94e03SVille Syrjälä 		cdclk_config->cdclk = 133333;
155df0566a6SJani Nikula 		return;
156df0566a6SJani Nikula 	}
157df0566a6SJani Nikula 
158df0566a6SJani Nikula 	pci_bus_read_config_word(pdev->bus,
159df0566a6SJani Nikula 				 PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
160df0566a6SJani Nikula 
161df0566a6SJani Nikula 	/* Assume that the hardware is in the high speed state.  This
162df0566a6SJani Nikula 	 * should be the default.
163df0566a6SJani Nikula 	 */
164df0566a6SJani Nikula 	switch (hpllcc & GC_CLOCK_CONTROL_MASK) {
165df0566a6SJani Nikula 	case GC_CLOCK_133_200:
166df0566a6SJani Nikula 	case GC_CLOCK_133_200_2:
167df0566a6SJani Nikula 	case GC_CLOCK_100_200:
1680bb94e03SVille Syrjälä 		cdclk_config->cdclk = 200000;
169df0566a6SJani Nikula 		break;
170df0566a6SJani Nikula 	case GC_CLOCK_166_250:
1710bb94e03SVille Syrjälä 		cdclk_config->cdclk = 250000;
172df0566a6SJani Nikula 		break;
173df0566a6SJani Nikula 	case GC_CLOCK_100_133:
1740bb94e03SVille Syrjälä 		cdclk_config->cdclk = 133333;
175df0566a6SJani Nikula 		break;
176df0566a6SJani Nikula 	case GC_CLOCK_133_266:
177df0566a6SJani Nikula 	case GC_CLOCK_133_266_2:
178df0566a6SJani Nikula 	case GC_CLOCK_166_266:
1790bb94e03SVille Syrjälä 		cdclk_config->cdclk = 266667;
180df0566a6SJani Nikula 		break;
181df0566a6SJani Nikula 	}
182df0566a6SJani Nikula }
183df0566a6SJani Nikula 
i915gm_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)184df0566a6SJani Nikula static void i915gm_get_cdclk(struct drm_i915_private *dev_priv,
1850bb94e03SVille Syrjälä 			     struct intel_cdclk_config *cdclk_config)
186df0566a6SJani Nikula {
1878ff5446aSThomas Zimmermann 	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
188df0566a6SJani Nikula 	u16 gcfgc = 0;
189df0566a6SJani Nikula 
190df0566a6SJani Nikula 	pci_read_config_word(pdev, GCFGC, &gcfgc);
191df0566a6SJani Nikula 
192df0566a6SJani Nikula 	if (gcfgc & GC_LOW_FREQUENCY_ENABLE) {
1930bb94e03SVille Syrjälä 		cdclk_config->cdclk = 133333;
194df0566a6SJani Nikula 		return;
195df0566a6SJani Nikula 	}
196df0566a6SJani Nikula 
197df0566a6SJani Nikula 	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
198df0566a6SJani Nikula 	case GC_DISPLAY_CLOCK_333_320_MHZ:
1990bb94e03SVille Syrjälä 		cdclk_config->cdclk = 333333;
200df0566a6SJani Nikula 		break;
201df0566a6SJani Nikula 	default:
202df0566a6SJani Nikula 	case GC_DISPLAY_CLOCK_190_200_MHZ:
2030bb94e03SVille Syrjälä 		cdclk_config->cdclk = 190000;
204df0566a6SJani Nikula 		break;
205df0566a6SJani Nikula 	}
206df0566a6SJani Nikula }
207df0566a6SJani Nikula 
i945gm_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)208df0566a6SJani Nikula static void i945gm_get_cdclk(struct drm_i915_private *dev_priv,
2090bb94e03SVille Syrjälä 			     struct intel_cdclk_config *cdclk_config)
210df0566a6SJani Nikula {
2118ff5446aSThomas Zimmermann 	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
212df0566a6SJani Nikula 	u16 gcfgc = 0;
213df0566a6SJani Nikula 
214df0566a6SJani Nikula 	pci_read_config_word(pdev, GCFGC, &gcfgc);
215df0566a6SJani Nikula 
216df0566a6SJani Nikula 	if (gcfgc & GC_LOW_FREQUENCY_ENABLE) {
2170bb94e03SVille Syrjälä 		cdclk_config->cdclk = 133333;
218df0566a6SJani Nikula 		return;
219df0566a6SJani Nikula 	}
220df0566a6SJani Nikula 
221df0566a6SJani Nikula 	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
222df0566a6SJani Nikula 	case GC_DISPLAY_CLOCK_333_320_MHZ:
2230bb94e03SVille Syrjälä 		cdclk_config->cdclk = 320000;
224df0566a6SJani Nikula 		break;
225df0566a6SJani Nikula 	default:
226df0566a6SJani Nikula 	case GC_DISPLAY_CLOCK_190_200_MHZ:
2270bb94e03SVille Syrjälä 		cdclk_config->cdclk = 200000;
228df0566a6SJani Nikula 		break;
229df0566a6SJani Nikula 	}
230df0566a6SJani Nikula }
231df0566a6SJani Nikula 
intel_hpll_vco(struct drm_i915_private * dev_priv)232df0566a6SJani Nikula static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
233df0566a6SJani Nikula {
234df0566a6SJani Nikula 	static const unsigned int blb_vco[8] = {
235df0566a6SJani Nikula 		[0] = 3200000,
236df0566a6SJani Nikula 		[1] = 4000000,
237df0566a6SJani Nikula 		[2] = 5333333,
238df0566a6SJani Nikula 		[3] = 4800000,
239df0566a6SJani Nikula 		[4] = 6400000,
240df0566a6SJani Nikula 	};
241df0566a6SJani Nikula 	static const unsigned int pnv_vco[8] = {
242df0566a6SJani Nikula 		[0] = 3200000,
243df0566a6SJani Nikula 		[1] = 4000000,
244df0566a6SJani Nikula 		[2] = 5333333,
245df0566a6SJani Nikula 		[3] = 4800000,
246df0566a6SJani Nikula 		[4] = 2666667,
247df0566a6SJani Nikula 	};
248df0566a6SJani Nikula 	static const unsigned int cl_vco[8] = {
249df0566a6SJani Nikula 		[0] = 3200000,
250df0566a6SJani Nikula 		[1] = 4000000,
251df0566a6SJani Nikula 		[2] = 5333333,
252df0566a6SJani Nikula 		[3] = 6400000,
253df0566a6SJani Nikula 		[4] = 3333333,
254df0566a6SJani Nikula 		[5] = 3566667,
255df0566a6SJani Nikula 		[6] = 4266667,
256df0566a6SJani Nikula 	};
257df0566a6SJani Nikula 	static const unsigned int elk_vco[8] = {
258df0566a6SJani Nikula 		[0] = 3200000,
259df0566a6SJani Nikula 		[1] = 4000000,
260df0566a6SJani Nikula 		[2] = 5333333,
261df0566a6SJani Nikula 		[3] = 4800000,
262df0566a6SJani Nikula 	};
263df0566a6SJani Nikula 	static const unsigned int ctg_vco[8] = {
264df0566a6SJani Nikula 		[0] = 3200000,
265df0566a6SJani Nikula 		[1] = 4000000,
266df0566a6SJani Nikula 		[2] = 5333333,
267df0566a6SJani Nikula 		[3] = 6400000,
268df0566a6SJani Nikula 		[4] = 2666667,
269df0566a6SJani Nikula 		[5] = 4266667,
270df0566a6SJani Nikula 	};
271df0566a6SJani Nikula 	const unsigned int *vco_table;
272df0566a6SJani Nikula 	unsigned int vco;
273df0566a6SJani Nikula 	u8 tmp = 0;
274df0566a6SJani Nikula 
275df0566a6SJani Nikula 	/* FIXME other chipsets? */
276df0566a6SJani Nikula 	if (IS_GM45(dev_priv))
277df0566a6SJani Nikula 		vco_table = ctg_vco;
278df0566a6SJani Nikula 	else if (IS_G45(dev_priv))
279df0566a6SJani Nikula 		vco_table = elk_vco;
280df0566a6SJani Nikula 	else if (IS_I965GM(dev_priv))
281df0566a6SJani Nikula 		vco_table = cl_vco;
282df0566a6SJani Nikula 	else if (IS_PINEVIEW(dev_priv))
283df0566a6SJani Nikula 		vco_table = pnv_vco;
284df0566a6SJani Nikula 	else if (IS_G33(dev_priv))
285df0566a6SJani Nikula 		vco_table = blb_vco;
286df0566a6SJani Nikula 	else
287df0566a6SJani Nikula 		return 0;
288df0566a6SJani Nikula 
2893e9f55dfSJani Nikula 	tmp = intel_de_read(dev_priv,
2903e9f55dfSJani Nikula 			    IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv) ? HPLLVCO_MOBILE : HPLLVCO);
291df0566a6SJani Nikula 
292df0566a6SJani Nikula 	vco = vco_table[tmp & 0x7];
293df0566a6SJani Nikula 	if (vco == 0)
29423194610SWambui Karuga 		drm_err(&dev_priv->drm, "Bad HPLL VCO (HPLLVCO=0x%02x)\n",
29523194610SWambui Karuga 			tmp);
296df0566a6SJani Nikula 	else
29723194610SWambui Karuga 		drm_dbg_kms(&dev_priv->drm, "HPLL VCO %u kHz\n", vco);
298df0566a6SJani Nikula 
299df0566a6SJani Nikula 	return vco;
300df0566a6SJani Nikula }
301df0566a6SJani Nikula 
g33_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)302df0566a6SJani Nikula static void g33_get_cdclk(struct drm_i915_private *dev_priv,
3030bb94e03SVille Syrjälä 			  struct intel_cdclk_config *cdclk_config)
304df0566a6SJani Nikula {
3058ff5446aSThomas Zimmermann 	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
306df0566a6SJani Nikula 	static const u8 div_3200[] = { 12, 10,  8,  7, 5, 16 };
307df0566a6SJani Nikula 	static const u8 div_4000[] = { 14, 12, 10,  8, 6, 20 };
308df0566a6SJani Nikula 	static const u8 div_4800[] = { 20, 14, 12, 10, 8, 24 };
309df0566a6SJani Nikula 	static const u8 div_5333[] = { 20, 16, 12, 12, 8, 28 };
310df0566a6SJani Nikula 	const u8 *div_table;
311df0566a6SJani Nikula 	unsigned int cdclk_sel;
312df0566a6SJani Nikula 	u16 tmp = 0;
313df0566a6SJani Nikula 
3140bb94e03SVille Syrjälä 	cdclk_config->vco = intel_hpll_vco(dev_priv);
315df0566a6SJani Nikula 
316df0566a6SJani Nikula 	pci_read_config_word(pdev, GCFGC, &tmp);
317df0566a6SJani Nikula 
318df0566a6SJani Nikula 	cdclk_sel = (tmp >> 4) & 0x7;
319df0566a6SJani Nikula 
320df0566a6SJani Nikula 	if (cdclk_sel >= ARRAY_SIZE(div_3200))
321df0566a6SJani Nikula 		goto fail;
322df0566a6SJani Nikula 
3230bb94e03SVille Syrjälä 	switch (cdclk_config->vco) {
324df0566a6SJani Nikula 	case 3200000:
325df0566a6SJani Nikula 		div_table = div_3200;
326df0566a6SJani Nikula 		break;
327df0566a6SJani Nikula 	case 4000000:
328df0566a6SJani Nikula 		div_table = div_4000;
329df0566a6SJani Nikula 		break;
330df0566a6SJani Nikula 	case 4800000:
331df0566a6SJani Nikula 		div_table = div_4800;
332df0566a6SJani Nikula 		break;
333df0566a6SJani Nikula 	case 5333333:
334df0566a6SJani Nikula 		div_table = div_5333;
335df0566a6SJani Nikula 		break;
336df0566a6SJani Nikula 	default:
337df0566a6SJani Nikula 		goto fail;
338df0566a6SJani Nikula 	}
339df0566a6SJani Nikula 
3400bb94e03SVille Syrjälä 	cdclk_config->cdclk = DIV_ROUND_CLOSEST(cdclk_config->vco,
341df0566a6SJani Nikula 						div_table[cdclk_sel]);
342df0566a6SJani Nikula 	return;
343df0566a6SJani Nikula 
344df0566a6SJani Nikula fail:
34523194610SWambui Karuga 	drm_err(&dev_priv->drm,
34623194610SWambui Karuga 		"Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%08x\n",
3470bb94e03SVille Syrjälä 		cdclk_config->vco, tmp);
3480bb94e03SVille Syrjälä 	cdclk_config->cdclk = 190476;
349df0566a6SJani Nikula }
350df0566a6SJani Nikula 
pnv_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)351df0566a6SJani Nikula static void pnv_get_cdclk(struct drm_i915_private *dev_priv,
3520bb94e03SVille Syrjälä 			  struct intel_cdclk_config *cdclk_config)
353df0566a6SJani Nikula {
3548ff5446aSThomas Zimmermann 	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
355df0566a6SJani Nikula 	u16 gcfgc = 0;
356df0566a6SJani Nikula 
357df0566a6SJani Nikula 	pci_read_config_word(pdev, GCFGC, &gcfgc);
358df0566a6SJani Nikula 
359df0566a6SJani Nikula 	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
360df0566a6SJani Nikula 	case GC_DISPLAY_CLOCK_267_MHZ_PNV:
3610bb94e03SVille Syrjälä 		cdclk_config->cdclk = 266667;
362df0566a6SJani Nikula 		break;
363df0566a6SJani Nikula 	case GC_DISPLAY_CLOCK_333_MHZ_PNV:
3640bb94e03SVille Syrjälä 		cdclk_config->cdclk = 333333;
365df0566a6SJani Nikula 		break;
366df0566a6SJani Nikula 	case GC_DISPLAY_CLOCK_444_MHZ_PNV:
3670bb94e03SVille Syrjälä 		cdclk_config->cdclk = 444444;
368df0566a6SJani Nikula 		break;
369df0566a6SJani Nikula 	case GC_DISPLAY_CLOCK_200_MHZ_PNV:
3700bb94e03SVille Syrjälä 		cdclk_config->cdclk = 200000;
371df0566a6SJani Nikula 		break;
372df0566a6SJani Nikula 	default:
37323194610SWambui Karuga 		drm_err(&dev_priv->drm,
37423194610SWambui Karuga 			"Unknown pnv display core clock 0x%04x\n", gcfgc);
375df561f66SGustavo A. R. Silva 		fallthrough;
376df0566a6SJani Nikula 	case GC_DISPLAY_CLOCK_133_MHZ_PNV:
3770bb94e03SVille Syrjälä 		cdclk_config->cdclk = 133333;
378df0566a6SJani Nikula 		break;
379df0566a6SJani Nikula 	case GC_DISPLAY_CLOCK_167_MHZ_PNV:
3800bb94e03SVille Syrjälä 		cdclk_config->cdclk = 166667;
381df0566a6SJani Nikula 		break;
382df0566a6SJani Nikula 	}
383df0566a6SJani Nikula }
384df0566a6SJani Nikula 
i965gm_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)385df0566a6SJani Nikula static void i965gm_get_cdclk(struct drm_i915_private *dev_priv,
3860bb94e03SVille Syrjälä 			     struct intel_cdclk_config *cdclk_config)
387df0566a6SJani Nikula {
3888ff5446aSThomas Zimmermann 	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
389df0566a6SJani Nikula 	static const u8 div_3200[] = { 16, 10,  8 };
390df0566a6SJani Nikula 	static const u8 div_4000[] = { 20, 12, 10 };
391df0566a6SJani Nikula 	static const u8 div_5333[] = { 24, 16, 14 };
392df0566a6SJani Nikula 	const u8 *div_table;
393df0566a6SJani Nikula 	unsigned int cdclk_sel;
394df0566a6SJani Nikula 	u16 tmp = 0;
395df0566a6SJani Nikula 
3960bb94e03SVille Syrjälä 	cdclk_config->vco = intel_hpll_vco(dev_priv);
397df0566a6SJani Nikula 
398df0566a6SJani Nikula 	pci_read_config_word(pdev, GCFGC, &tmp);
399df0566a6SJani Nikula 
400df0566a6SJani Nikula 	cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
401df0566a6SJani Nikula 
402df0566a6SJani Nikula 	if (cdclk_sel >= ARRAY_SIZE(div_3200))
403df0566a6SJani Nikula 		goto fail;
404df0566a6SJani Nikula 
4050bb94e03SVille Syrjälä 	switch (cdclk_config->vco) {
406df0566a6SJani Nikula 	case 3200000:
407df0566a6SJani Nikula 		div_table = div_3200;
408df0566a6SJani Nikula 		break;
409df0566a6SJani Nikula 	case 4000000:
410df0566a6SJani Nikula 		div_table = div_4000;
411df0566a6SJani Nikula 		break;
412df0566a6SJani Nikula 	case 5333333:
413df0566a6SJani Nikula 		div_table = div_5333;
414df0566a6SJani Nikula 		break;
415df0566a6SJani Nikula 	default:
416df0566a6SJani Nikula 		goto fail;
417df0566a6SJani Nikula 	}
418df0566a6SJani Nikula 
4190bb94e03SVille Syrjälä 	cdclk_config->cdclk = DIV_ROUND_CLOSEST(cdclk_config->vco,
420df0566a6SJani Nikula 						div_table[cdclk_sel]);
421df0566a6SJani Nikula 	return;
422df0566a6SJani Nikula 
423df0566a6SJani Nikula fail:
42423194610SWambui Karuga 	drm_err(&dev_priv->drm,
42523194610SWambui Karuga 		"Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%04x\n",
4260bb94e03SVille Syrjälä 		cdclk_config->vco, tmp);
4270bb94e03SVille Syrjälä 	cdclk_config->cdclk = 200000;
428df0566a6SJani Nikula }
429df0566a6SJani Nikula 
gm45_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)430df0566a6SJani Nikula static void gm45_get_cdclk(struct drm_i915_private *dev_priv,
4310bb94e03SVille Syrjälä 			   struct intel_cdclk_config *cdclk_config)
432df0566a6SJani Nikula {
4338ff5446aSThomas Zimmermann 	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
434df0566a6SJani Nikula 	unsigned int cdclk_sel;
435df0566a6SJani Nikula 	u16 tmp = 0;
436df0566a6SJani Nikula 
4370bb94e03SVille Syrjälä 	cdclk_config->vco = intel_hpll_vco(dev_priv);
438df0566a6SJani Nikula 
439df0566a6SJani Nikula 	pci_read_config_word(pdev, GCFGC, &tmp);
440df0566a6SJani Nikula 
441df0566a6SJani Nikula 	cdclk_sel = (tmp >> 12) & 0x1;
442df0566a6SJani Nikula 
4430bb94e03SVille Syrjälä 	switch (cdclk_config->vco) {
444df0566a6SJani Nikula 	case 2666667:
445df0566a6SJani Nikula 	case 4000000:
446df0566a6SJani Nikula 	case 5333333:
4470bb94e03SVille Syrjälä 		cdclk_config->cdclk = cdclk_sel ? 333333 : 222222;
448df0566a6SJani Nikula 		break;
449df0566a6SJani Nikula 	case 3200000:
4500bb94e03SVille Syrjälä 		cdclk_config->cdclk = cdclk_sel ? 320000 : 228571;
451df0566a6SJani Nikula 		break;
452df0566a6SJani Nikula 	default:
45323194610SWambui Karuga 		drm_err(&dev_priv->drm,
45423194610SWambui Karuga 			"Unable to determine CDCLK. HPLL VCO=%u, CFGC=0x%04x\n",
4550bb94e03SVille Syrjälä 			cdclk_config->vco, tmp);
4560bb94e03SVille Syrjälä 		cdclk_config->cdclk = 222222;
457df0566a6SJani Nikula 		break;
458df0566a6SJani Nikula 	}
459df0566a6SJani Nikula }
460df0566a6SJani Nikula 
hsw_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)461df0566a6SJani Nikula static void hsw_get_cdclk(struct drm_i915_private *dev_priv,
4620bb94e03SVille Syrjälä 			  struct intel_cdclk_config *cdclk_config)
463df0566a6SJani Nikula {
4643e9f55dfSJani Nikula 	u32 lcpll = intel_de_read(dev_priv, LCPLL_CTL);
465df0566a6SJani Nikula 	u32 freq = lcpll & LCPLL_CLK_FREQ_MASK;
466df0566a6SJani Nikula 
467df0566a6SJani Nikula 	if (lcpll & LCPLL_CD_SOURCE_FCLK)
4680bb94e03SVille Syrjälä 		cdclk_config->cdclk = 800000;
4693e9f55dfSJani Nikula 	else if (intel_de_read(dev_priv, FUSE_STRAP) & HSW_CDCLK_LIMIT)
4700bb94e03SVille Syrjälä 		cdclk_config->cdclk = 450000;
471df0566a6SJani Nikula 	else if (freq == LCPLL_CLK_FREQ_450)
4720bb94e03SVille Syrjälä 		cdclk_config->cdclk = 450000;
473927a8e38SDnyaneshwar Bhadane 	else if (IS_HASWELL_ULT(dev_priv))
4740bb94e03SVille Syrjälä 		cdclk_config->cdclk = 337500;
475df0566a6SJani Nikula 	else
4760bb94e03SVille Syrjälä 		cdclk_config->cdclk = 540000;
477df0566a6SJani Nikula }
478df0566a6SJani Nikula 
vlv_calc_cdclk(struct drm_i915_private * dev_priv,int min_cdclk)479df0566a6SJani Nikula static int vlv_calc_cdclk(struct drm_i915_private *dev_priv, int min_cdclk)
480df0566a6SJani Nikula {
481df0566a6SJani Nikula 	int freq_320 = (dev_priv->hpll_freq <<  1) % 320000 != 0 ?
482df0566a6SJani Nikula 		333333 : 320000;
483df0566a6SJani Nikula 
484df0566a6SJani Nikula 	/*
485df0566a6SJani Nikula 	 * We seem to get an unstable or solid color picture at 200MHz.
486df0566a6SJani Nikula 	 * Not sure what's wrong. For now use 200MHz only when all pipes
487df0566a6SJani Nikula 	 * are off.
488df0566a6SJani Nikula 	 */
489df0566a6SJani Nikula 	if (IS_VALLEYVIEW(dev_priv) && min_cdclk > freq_320)
490df0566a6SJani Nikula 		return 400000;
491df0566a6SJani Nikula 	else if (min_cdclk > 266667)
492df0566a6SJani Nikula 		return freq_320;
493df0566a6SJani Nikula 	else if (min_cdclk > 0)
494df0566a6SJani Nikula 		return 266667;
495df0566a6SJani Nikula 	else
496df0566a6SJani Nikula 		return 200000;
497df0566a6SJani Nikula }
498df0566a6SJani Nikula 
vlv_calc_voltage_level(struct drm_i915_private * dev_priv,int cdclk)499df0566a6SJani Nikula static u8 vlv_calc_voltage_level(struct drm_i915_private *dev_priv, int cdclk)
500df0566a6SJani Nikula {
501df0566a6SJani Nikula 	if (IS_VALLEYVIEW(dev_priv)) {
502df0566a6SJani Nikula 		if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
503df0566a6SJani Nikula 			return 2;
504df0566a6SJani Nikula 		else if (cdclk >= 266667)
505df0566a6SJani Nikula 			return 1;
506df0566a6SJani Nikula 		else
507df0566a6SJani Nikula 			return 0;
508df0566a6SJani Nikula 	} else {
509df0566a6SJani Nikula 		/*
510df0566a6SJani Nikula 		 * Specs are full of misinformation, but testing on actual
511df0566a6SJani Nikula 		 * hardware has shown that we just need to write the desired
512df0566a6SJani Nikula 		 * CCK divider into the Punit register.
513df0566a6SJani Nikula 		 */
514df0566a6SJani Nikula 		return DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1;
515df0566a6SJani Nikula 	}
516df0566a6SJani Nikula }
517df0566a6SJani Nikula 
vlv_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)518df0566a6SJani Nikula static void vlv_get_cdclk(struct drm_i915_private *dev_priv,
5190bb94e03SVille Syrjälä 			  struct intel_cdclk_config *cdclk_config)
520df0566a6SJani Nikula {
521df0566a6SJani Nikula 	u32 val;
522df0566a6SJani Nikula 
523df0566a6SJani Nikula 	vlv_iosf_sb_get(dev_priv,
524df0566a6SJani Nikula 			BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT));
525df0566a6SJani Nikula 
5260bb94e03SVille Syrjälä 	cdclk_config->vco = vlv_get_hpll_vco(dev_priv);
5270bb94e03SVille Syrjälä 	cdclk_config->cdclk = vlv_get_cck_clock(dev_priv, "cdclk",
528df0566a6SJani Nikula 						CCK_DISPLAY_CLOCK_CONTROL,
5290bb94e03SVille Syrjälä 						cdclk_config->vco);
530df0566a6SJani Nikula 
531df0566a6SJani Nikula 	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM);
532df0566a6SJani Nikula 
533df0566a6SJani Nikula 	vlv_iosf_sb_put(dev_priv,
534df0566a6SJani Nikula 			BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT));
535df0566a6SJani Nikula 
536df0566a6SJani Nikula 	if (IS_VALLEYVIEW(dev_priv))
5370bb94e03SVille Syrjälä 		cdclk_config->voltage_level = (val & DSPFREQGUAR_MASK) >>
538df0566a6SJani Nikula 			DSPFREQGUAR_SHIFT;
539df0566a6SJani Nikula 	else
5400bb94e03SVille Syrjälä 		cdclk_config->voltage_level = (val & DSPFREQGUAR_MASK_CHV) >>
541df0566a6SJani Nikula 			DSPFREQGUAR_SHIFT_CHV;
542df0566a6SJani Nikula }
543df0566a6SJani Nikula 
vlv_program_pfi_credits(struct drm_i915_private * dev_priv)544df0566a6SJani Nikula static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
545df0566a6SJani Nikula {
546df0566a6SJani Nikula 	unsigned int credits, default_credits;
547df0566a6SJani Nikula 
548df0566a6SJani Nikula 	if (IS_CHERRYVIEW(dev_priv))
549df0566a6SJani Nikula 		default_credits = PFI_CREDIT(12);
550df0566a6SJani Nikula 	else
551df0566a6SJani Nikula 		default_credits = PFI_CREDIT(8);
552df0566a6SJani Nikula 
553d51309b4SJani Nikula 	if (dev_priv->display.cdclk.hw.cdclk >= dev_priv->czclk_freq) {
554df0566a6SJani Nikula 		/* CHV suggested value is 31 or 63 */
555df0566a6SJani Nikula 		if (IS_CHERRYVIEW(dev_priv))
556df0566a6SJani Nikula 			credits = PFI_CREDIT_63;
557df0566a6SJani Nikula 		else
558df0566a6SJani Nikula 			credits = PFI_CREDIT(15);
559df0566a6SJani Nikula 	} else {
560df0566a6SJani Nikula 		credits = default_credits;
561df0566a6SJani Nikula 	}
562df0566a6SJani Nikula 
563df0566a6SJani Nikula 	/*
564df0566a6SJani Nikula 	 * WA - write default credits before re-programming
565df0566a6SJani Nikula 	 * FIXME: should we also set the resend bit here?
566df0566a6SJani Nikula 	 */
5673e9f55dfSJani Nikula 	intel_de_write(dev_priv, GCI_CONTROL,
5683e9f55dfSJani Nikula 		       VGA_FAST_MODE_DISABLE | default_credits);
569df0566a6SJani Nikula 
5703e9f55dfSJani Nikula 	intel_de_write(dev_priv, GCI_CONTROL,
5713e9f55dfSJani Nikula 		       VGA_FAST_MODE_DISABLE | credits | PFI_CREDIT_RESEND);
572df0566a6SJani Nikula 
573df0566a6SJani Nikula 	/*
574df0566a6SJani Nikula 	 * FIXME is this guaranteed to clear
575df0566a6SJani Nikula 	 * immediately or should we poll for it?
576df0566a6SJani Nikula 	 */
577aff35110SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm,
578aff35110SPankaj Bharadiya 		    intel_de_read(dev_priv, GCI_CONTROL) & PFI_CREDIT_RESEND);
579df0566a6SJani Nikula }
580df0566a6SJani Nikula 
vlv_set_cdclk(struct drm_i915_private * dev_priv,const struct intel_cdclk_config * cdclk_config,enum pipe pipe)581df0566a6SJani Nikula static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
5820bb94e03SVille Syrjälä 			  const struct intel_cdclk_config *cdclk_config,
583df0566a6SJani Nikula 			  enum pipe pipe)
584df0566a6SJani Nikula {
5850bb94e03SVille Syrjälä 	int cdclk = cdclk_config->cdclk;
5860bb94e03SVille Syrjälä 	u32 val, cmd = cdclk_config->voltage_level;
587df0566a6SJani Nikula 	intel_wakeref_t wakeref;
588df0566a6SJani Nikula 
589df0566a6SJani Nikula 	switch (cdclk) {
590df0566a6SJani Nikula 	case 400000:
591df0566a6SJani Nikula 	case 333333:
592df0566a6SJani Nikula 	case 320000:
593df0566a6SJani Nikula 	case 266667:
594df0566a6SJani Nikula 	case 200000:
595df0566a6SJani Nikula 		break;
596df0566a6SJani Nikula 	default:
597df0566a6SJani Nikula 		MISSING_CASE(cdclk);
598df0566a6SJani Nikula 		return;
599df0566a6SJani Nikula 	}
600df0566a6SJani Nikula 
601df0566a6SJani Nikula 	/* There are cases where we can end up here with power domains
602df0566a6SJani Nikula 	 * off and a CDCLK frequency other than the minimum, like when
603df0566a6SJani Nikula 	 * issuing a modeset without actually changing any display after
60413ce6092SVille Syrjälä 	 * a system suspend.  So grab the display core domain, which covers
605df0566a6SJani Nikula 	 * the HW blocks needed for the following programming.
606df0566a6SJani Nikula 	 */
60713ce6092SVille Syrjälä 	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE);
608df0566a6SJani Nikula 
609df0566a6SJani Nikula 	vlv_iosf_sb_get(dev_priv,
610df0566a6SJani Nikula 			BIT(VLV_IOSF_SB_CCK) |
611df0566a6SJani Nikula 			BIT(VLV_IOSF_SB_BUNIT) |
612df0566a6SJani Nikula 			BIT(VLV_IOSF_SB_PUNIT));
613df0566a6SJani Nikula 
614df0566a6SJani Nikula 	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM);
615df0566a6SJani Nikula 	val &= ~DSPFREQGUAR_MASK;
616df0566a6SJani Nikula 	val |= (cmd << DSPFREQGUAR_SHIFT);
617df0566a6SJani Nikula 	vlv_punit_write(dev_priv, PUNIT_REG_DSPSSPM, val);
618df0566a6SJani Nikula 	if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) &
619df0566a6SJani Nikula 		      DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT),
620df0566a6SJani Nikula 		     50)) {
62123194610SWambui Karuga 		drm_err(&dev_priv->drm,
62223194610SWambui Karuga 			"timed out waiting for CDclk change\n");
623df0566a6SJani Nikula 	}
624df0566a6SJani Nikula 
625df0566a6SJani Nikula 	if (cdclk == 400000) {
626df0566a6SJani Nikula 		u32 divider;
627df0566a6SJani Nikula 
628df0566a6SJani Nikula 		divider = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1,
629df0566a6SJani Nikula 					    cdclk) - 1;
630df0566a6SJani Nikula 
631df0566a6SJani Nikula 		/* adjust cdclk divider */
632df0566a6SJani Nikula 		val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
633df0566a6SJani Nikula 		val &= ~CCK_FREQUENCY_VALUES;
634df0566a6SJani Nikula 		val |= divider;
635df0566a6SJani Nikula 		vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
636df0566a6SJani Nikula 
637df0566a6SJani Nikula 		if (wait_for((vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL) &
638df0566a6SJani Nikula 			      CCK_FREQUENCY_STATUS) == (divider << CCK_FREQUENCY_STATUS_SHIFT),
639df0566a6SJani Nikula 			     50))
64023194610SWambui Karuga 			drm_err(&dev_priv->drm,
64123194610SWambui Karuga 				"timed out waiting for CDclk change\n");
642df0566a6SJani Nikula 	}
643df0566a6SJani Nikula 
644df0566a6SJani Nikula 	/* adjust self-refresh exit latency value */
645df0566a6SJani Nikula 	val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC);
646df0566a6SJani Nikula 	val &= ~0x7f;
647df0566a6SJani Nikula 
648df0566a6SJani Nikula 	/*
649df0566a6SJani Nikula 	 * For high bandwidth configs, we set a higher latency in the bunit
650df0566a6SJani Nikula 	 * so that the core display fetch happens in time to avoid underruns.
651df0566a6SJani Nikula 	 */
652df0566a6SJani Nikula 	if (cdclk == 400000)
653df0566a6SJani Nikula 		val |= 4500 / 250; /* 4.5 usec */
654df0566a6SJani Nikula 	else
655df0566a6SJani Nikula 		val |= 3000 / 250; /* 3.0 usec */
656df0566a6SJani Nikula 	vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
657df0566a6SJani Nikula 
658df0566a6SJani Nikula 	vlv_iosf_sb_put(dev_priv,
659df0566a6SJani Nikula 			BIT(VLV_IOSF_SB_CCK) |
660df0566a6SJani Nikula 			BIT(VLV_IOSF_SB_BUNIT) |
661df0566a6SJani Nikula 			BIT(VLV_IOSF_SB_PUNIT));
662df0566a6SJani Nikula 
663df0566a6SJani Nikula 	intel_update_cdclk(dev_priv);
664df0566a6SJani Nikula 
665df0566a6SJani Nikula 	vlv_program_pfi_credits(dev_priv);
666df0566a6SJani Nikula 
66713ce6092SVille Syrjälä 	intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
668df0566a6SJani Nikula }
669df0566a6SJani Nikula 
chv_set_cdclk(struct drm_i915_private * dev_priv,const struct intel_cdclk_config * cdclk_config,enum pipe pipe)670df0566a6SJani Nikula static void chv_set_cdclk(struct drm_i915_private *dev_priv,
6710bb94e03SVille Syrjälä 			  const struct intel_cdclk_config *cdclk_config,
672df0566a6SJani Nikula 			  enum pipe pipe)
673df0566a6SJani Nikula {
6740bb94e03SVille Syrjälä 	int cdclk = cdclk_config->cdclk;
6750bb94e03SVille Syrjälä 	u32 val, cmd = cdclk_config->voltage_level;
676df0566a6SJani Nikula 	intel_wakeref_t wakeref;
677df0566a6SJani Nikula 
678df0566a6SJani Nikula 	switch (cdclk) {
679df0566a6SJani Nikula 	case 333333:
680df0566a6SJani Nikula 	case 320000:
681df0566a6SJani Nikula 	case 266667:
682df0566a6SJani Nikula 	case 200000:
683df0566a6SJani Nikula 		break;
684df0566a6SJani Nikula 	default:
685df0566a6SJani Nikula 		MISSING_CASE(cdclk);
686df0566a6SJani Nikula 		return;
687df0566a6SJani Nikula 	}
688df0566a6SJani Nikula 
689df0566a6SJani Nikula 	/* There are cases where we can end up here with power domains
690df0566a6SJani Nikula 	 * off and a CDCLK frequency other than the minimum, like when
691df0566a6SJani Nikula 	 * issuing a modeset without actually changing any display after
69213ce6092SVille Syrjälä 	 * a system suspend.  So grab the display core domain, which covers
693df0566a6SJani Nikula 	 * the HW blocks needed for the following programming.
694df0566a6SJani Nikula 	 */
69513ce6092SVille Syrjälä 	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE);
696df0566a6SJani Nikula 
697df0566a6SJani Nikula 	vlv_punit_get(dev_priv);
698df0566a6SJani Nikula 	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM);
699df0566a6SJani Nikula 	val &= ~DSPFREQGUAR_MASK_CHV;
700df0566a6SJani Nikula 	val |= (cmd << DSPFREQGUAR_SHIFT_CHV);
701df0566a6SJani Nikula 	vlv_punit_write(dev_priv, PUNIT_REG_DSPSSPM, val);
702df0566a6SJani Nikula 	if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) &
703df0566a6SJani Nikula 		      DSPFREQSTAT_MASK_CHV) == (cmd << DSPFREQSTAT_SHIFT_CHV),
704df0566a6SJani Nikula 		     50)) {
70523194610SWambui Karuga 		drm_err(&dev_priv->drm,
70623194610SWambui Karuga 			"timed out waiting for CDclk change\n");
707df0566a6SJani Nikula 	}
708df0566a6SJani Nikula 
709df0566a6SJani Nikula 	vlv_punit_put(dev_priv);
710df0566a6SJani Nikula 
711df0566a6SJani Nikula 	intel_update_cdclk(dev_priv);
712df0566a6SJani Nikula 
713df0566a6SJani Nikula 	vlv_program_pfi_credits(dev_priv);
714df0566a6SJani Nikula 
71513ce6092SVille Syrjälä 	intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
716df0566a6SJani Nikula }
717df0566a6SJani Nikula 
bdw_calc_cdclk(int min_cdclk)718df0566a6SJani Nikula static int bdw_calc_cdclk(int min_cdclk)
719df0566a6SJani Nikula {
720df0566a6SJani Nikula 	if (min_cdclk > 540000)
721df0566a6SJani Nikula 		return 675000;
722df0566a6SJani Nikula 	else if (min_cdclk > 450000)
723df0566a6SJani Nikula 		return 540000;
724df0566a6SJani Nikula 	else if (min_cdclk > 337500)
725df0566a6SJani Nikula 		return 450000;
726df0566a6SJani Nikula 	else
727df0566a6SJani Nikula 		return 337500;
728df0566a6SJani Nikula }
729df0566a6SJani Nikula 
bdw_calc_voltage_level(int cdclk)730df0566a6SJani Nikula static u8 bdw_calc_voltage_level(int cdclk)
731df0566a6SJani Nikula {
732df0566a6SJani Nikula 	switch (cdclk) {
733df0566a6SJani Nikula 	default:
734df0566a6SJani Nikula 	case 337500:
735df0566a6SJani Nikula 		return 2;
736df0566a6SJani Nikula 	case 450000:
737df0566a6SJani Nikula 		return 0;
738df0566a6SJani Nikula 	case 540000:
739df0566a6SJani Nikula 		return 1;
740df0566a6SJani Nikula 	case 675000:
741df0566a6SJani Nikula 		return 3;
742df0566a6SJani Nikula 	}
743df0566a6SJani Nikula }
744df0566a6SJani Nikula 
bdw_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)745df0566a6SJani Nikula static void bdw_get_cdclk(struct drm_i915_private *dev_priv,
7460bb94e03SVille Syrjälä 			  struct intel_cdclk_config *cdclk_config)
747df0566a6SJani Nikula {
7483e9f55dfSJani Nikula 	u32 lcpll = intel_de_read(dev_priv, LCPLL_CTL);
749df0566a6SJani Nikula 	u32 freq = lcpll & LCPLL_CLK_FREQ_MASK;
750df0566a6SJani Nikula 
751df0566a6SJani Nikula 	if (lcpll & LCPLL_CD_SOURCE_FCLK)
7520bb94e03SVille Syrjälä 		cdclk_config->cdclk = 800000;
7533e9f55dfSJani Nikula 	else if (intel_de_read(dev_priv, FUSE_STRAP) & HSW_CDCLK_LIMIT)
7540bb94e03SVille Syrjälä 		cdclk_config->cdclk = 450000;
755df0566a6SJani Nikula 	else if (freq == LCPLL_CLK_FREQ_450)
7560bb94e03SVille Syrjälä 		cdclk_config->cdclk = 450000;
757df0566a6SJani Nikula 	else if (freq == LCPLL_CLK_FREQ_54O_BDW)
7580bb94e03SVille Syrjälä 		cdclk_config->cdclk = 540000;
759df0566a6SJani Nikula 	else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
7600bb94e03SVille Syrjälä 		cdclk_config->cdclk = 337500;
761df0566a6SJani Nikula 	else
7620bb94e03SVille Syrjälä 		cdclk_config->cdclk = 675000;
763df0566a6SJani Nikula 
764df0566a6SJani Nikula 	/*
765df0566a6SJani Nikula 	 * Can't read this out :( Let's assume it's
766df0566a6SJani Nikula 	 * at least what the CDCLK frequency requires.
767df0566a6SJani Nikula 	 */
7680bb94e03SVille Syrjälä 	cdclk_config->voltage_level =
7690bb94e03SVille Syrjälä 		bdw_calc_voltage_level(cdclk_config->cdclk);
770df0566a6SJani Nikula }
771df0566a6SJani Nikula 
bdw_cdclk_freq_sel(int cdclk)772b41df85aSVille Syrjälä static u32 bdw_cdclk_freq_sel(int cdclk)
773b41df85aSVille Syrjälä {
774b41df85aSVille Syrjälä 	switch (cdclk) {
775b41df85aSVille Syrjälä 	default:
776b41df85aSVille Syrjälä 		MISSING_CASE(cdclk);
777b41df85aSVille Syrjälä 		fallthrough;
778b41df85aSVille Syrjälä 	case 337500:
779b41df85aSVille Syrjälä 		return LCPLL_CLK_FREQ_337_5_BDW;
780b41df85aSVille Syrjälä 	case 450000:
781b41df85aSVille Syrjälä 		return LCPLL_CLK_FREQ_450;
782b41df85aSVille Syrjälä 	case 540000:
783b41df85aSVille Syrjälä 		return LCPLL_CLK_FREQ_54O_BDW;
784b41df85aSVille Syrjälä 	case 675000:
785b41df85aSVille Syrjälä 		return LCPLL_CLK_FREQ_675_BDW;
786b41df85aSVille Syrjälä 	}
787b41df85aSVille Syrjälä }
788b41df85aSVille Syrjälä 
bdw_set_cdclk(struct drm_i915_private * dev_priv,const struct intel_cdclk_config * cdclk_config,enum pipe pipe)789df0566a6SJani Nikula static void bdw_set_cdclk(struct drm_i915_private *dev_priv,
7900bb94e03SVille Syrjälä 			  const struct intel_cdclk_config *cdclk_config,
791df0566a6SJani Nikula 			  enum pipe pipe)
792df0566a6SJani Nikula {
7930bb94e03SVille Syrjälä 	int cdclk = cdclk_config->cdclk;
794df0566a6SJani Nikula 	int ret;
795df0566a6SJani Nikula 
796aff35110SPankaj Bharadiya 	if (drm_WARN(&dev_priv->drm,
797aff35110SPankaj Bharadiya 		     (intel_de_read(dev_priv, LCPLL_CTL) &
798df0566a6SJani Nikula 		      (LCPLL_PLL_DISABLE | LCPLL_PLL_LOCK |
799df0566a6SJani Nikula 		       LCPLL_CD_CLOCK_DISABLE | LCPLL_ROOT_CD_CLOCK_DISABLE |
800df0566a6SJani Nikula 		       LCPLL_CD2X_CLOCK_DISABLE | LCPLL_POWER_DOWN_ALLOW |
801df0566a6SJani Nikula 		       LCPLL_CD_SOURCE_FCLK)) != LCPLL_PLL_LOCK,
802df0566a6SJani Nikula 		     "trying to change cdclk frequency with cdclk not enabled\n"))
803df0566a6SJani Nikula 		return;
804df0566a6SJani Nikula 
805ee421bb4SAshutosh Dixit 	ret = snb_pcode_write(&dev_priv->uncore, BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ, 0x0);
806df0566a6SJani Nikula 	if (ret) {
80723194610SWambui Karuga 		drm_err(&dev_priv->drm,
80823194610SWambui Karuga 			"failed to inform pcode about cdclk change\n");
809df0566a6SJani Nikula 		return;
810df0566a6SJani Nikula 	}
811df0566a6SJani Nikula 
812fb12fbb1SVille Syrjälä 	intel_de_rmw(dev_priv, LCPLL_CTL,
813fb12fbb1SVille Syrjälä 		     0, LCPLL_CD_SOURCE_FCLK);
814df0566a6SJani Nikula 
815df0566a6SJani Nikula 	/*
816df0566a6SJani Nikula 	 * According to the spec, it should be enough to poll for this 1 us.
817df0566a6SJani Nikula 	 * However, extensive testing shows that this can take longer.
818df0566a6SJani Nikula 	 */
8193e9f55dfSJani Nikula 	if (wait_for_us(intel_de_read(dev_priv, LCPLL_CTL) &
820df0566a6SJani Nikula 			LCPLL_CD_SOURCE_FCLK_DONE, 100))
82123194610SWambui Karuga 		drm_err(&dev_priv->drm, "Switching to FCLK failed\n");
822df0566a6SJani Nikula 
823fb12fbb1SVille Syrjälä 	intel_de_rmw(dev_priv, LCPLL_CTL,
824fb12fbb1SVille Syrjälä 		     LCPLL_CLK_FREQ_MASK, bdw_cdclk_freq_sel(cdclk));
825df0566a6SJani Nikula 
826fb12fbb1SVille Syrjälä 	intel_de_rmw(dev_priv, LCPLL_CTL,
827fb12fbb1SVille Syrjälä 		     LCPLL_CD_SOURCE_FCLK, 0);
828df0566a6SJani Nikula 
8293e9f55dfSJani Nikula 	if (wait_for_us((intel_de_read(dev_priv, LCPLL_CTL) &
830df0566a6SJani Nikula 			 LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
83123194610SWambui Karuga 		drm_err(&dev_priv->drm, "Switching back to LCPLL failed\n");
832df0566a6SJani Nikula 
833ee421bb4SAshutosh Dixit 	snb_pcode_write(&dev_priv->uncore, HSW_PCODE_DE_WRITE_FREQ_REQ,
8340bb94e03SVille Syrjälä 			cdclk_config->voltage_level);
835df0566a6SJani Nikula 
8363e9f55dfSJani Nikula 	intel_de_write(dev_priv, CDCLK_FREQ,
8373e9f55dfSJani Nikula 		       DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
838df0566a6SJani Nikula 
839df0566a6SJani Nikula 	intel_update_cdclk(dev_priv);
840df0566a6SJani Nikula }
841df0566a6SJani Nikula 
skl_calc_cdclk(int min_cdclk,int vco)842df0566a6SJani Nikula static int skl_calc_cdclk(int min_cdclk, int vco)
843df0566a6SJani Nikula {
844df0566a6SJani Nikula 	if (vco == 8640000) {
845df0566a6SJani Nikula 		if (min_cdclk > 540000)
846df0566a6SJani Nikula 			return 617143;
847df0566a6SJani Nikula 		else if (min_cdclk > 432000)
848df0566a6SJani Nikula 			return 540000;
849df0566a6SJani Nikula 		else if (min_cdclk > 308571)
850df0566a6SJani Nikula 			return 432000;
851df0566a6SJani Nikula 		else
852df0566a6SJani Nikula 			return 308571;
853df0566a6SJani Nikula 	} else {
854df0566a6SJani Nikula 		if (min_cdclk > 540000)
855df0566a6SJani Nikula 			return 675000;
856df0566a6SJani Nikula 		else if (min_cdclk > 450000)
857df0566a6SJani Nikula 			return 540000;
858df0566a6SJani Nikula 		else if (min_cdclk > 337500)
859df0566a6SJani Nikula 			return 450000;
860df0566a6SJani Nikula 		else
861df0566a6SJani Nikula 			return 337500;
862df0566a6SJani Nikula 	}
863df0566a6SJani Nikula }
864df0566a6SJani Nikula 
skl_calc_voltage_level(int cdclk)865df0566a6SJani Nikula static u8 skl_calc_voltage_level(int cdclk)
866df0566a6SJani Nikula {
867df0566a6SJani Nikula 	if (cdclk > 540000)
868df0566a6SJani Nikula 		return 3;
869df0566a6SJani Nikula 	else if (cdclk > 450000)
870df0566a6SJani Nikula 		return 2;
871df0566a6SJani Nikula 	else if (cdclk > 337500)
872df0566a6SJani Nikula 		return 1;
873df0566a6SJani Nikula 	else
874df0566a6SJani Nikula 		return 0;
875df0566a6SJani Nikula }
876df0566a6SJani Nikula 
skl_dpll0_update(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)877df0566a6SJani Nikula static void skl_dpll0_update(struct drm_i915_private *dev_priv,
8780bb94e03SVille Syrjälä 			     struct intel_cdclk_config *cdclk_config)
879df0566a6SJani Nikula {
880df0566a6SJani Nikula 	u32 val;
881df0566a6SJani Nikula 
8820bb94e03SVille Syrjälä 	cdclk_config->ref = 24000;
8830bb94e03SVille Syrjälä 	cdclk_config->vco = 0;
884df0566a6SJani Nikula 
8853e9f55dfSJani Nikula 	val = intel_de_read(dev_priv, LCPLL1_CTL);
886df0566a6SJani Nikula 	if ((val & LCPLL_PLL_ENABLE) == 0)
887df0566a6SJani Nikula 		return;
888df0566a6SJani Nikula 
889aff35110SPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, (val & LCPLL_PLL_LOCK) == 0))
890df0566a6SJani Nikula 		return;
891df0566a6SJani Nikula 
8923e9f55dfSJani Nikula 	val = intel_de_read(dev_priv, DPLL_CTRL1);
893df0566a6SJani Nikula 
894aff35110SPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm,
895aff35110SPankaj Bharadiya 			(val & (DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) |
896df0566a6SJani Nikula 				DPLL_CTRL1_SSC(SKL_DPLL0) |
897df0566a6SJani Nikula 				DPLL_CTRL1_OVERRIDE(SKL_DPLL0))) !=
898df0566a6SJani Nikula 			DPLL_CTRL1_OVERRIDE(SKL_DPLL0)))
899df0566a6SJani Nikula 		return;
900df0566a6SJani Nikula 
901df0566a6SJani Nikula 	switch (val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) {
902df0566a6SJani Nikula 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, SKL_DPLL0):
903df0566a6SJani Nikula 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0):
904df0566a6SJani Nikula 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0):
905df0566a6SJani Nikula 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0):
9060bb94e03SVille Syrjälä 		cdclk_config->vco = 8100000;
907df0566a6SJani Nikula 		break;
908df0566a6SJani Nikula 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0):
909df0566a6SJani Nikula 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0):
9100bb94e03SVille Syrjälä 		cdclk_config->vco = 8640000;
911df0566a6SJani Nikula 		break;
912df0566a6SJani Nikula 	default:
913df0566a6SJani Nikula 		MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
914df0566a6SJani Nikula 		break;
915df0566a6SJani Nikula 	}
916df0566a6SJani Nikula }
917df0566a6SJani Nikula 
skl_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)918df0566a6SJani Nikula static void skl_get_cdclk(struct drm_i915_private *dev_priv,
9190bb94e03SVille Syrjälä 			  struct intel_cdclk_config *cdclk_config)
920df0566a6SJani Nikula {
921df0566a6SJani Nikula 	u32 cdctl;
922df0566a6SJani Nikula 
9230bb94e03SVille Syrjälä 	skl_dpll0_update(dev_priv, cdclk_config);
924df0566a6SJani Nikula 
9250bb94e03SVille Syrjälä 	cdclk_config->cdclk = cdclk_config->bypass = cdclk_config->ref;
926df0566a6SJani Nikula 
9270bb94e03SVille Syrjälä 	if (cdclk_config->vco == 0)
928df0566a6SJani Nikula 		goto out;
929df0566a6SJani Nikula 
9303e9f55dfSJani Nikula 	cdctl = intel_de_read(dev_priv, CDCLK_CTL);
931df0566a6SJani Nikula 
9320bb94e03SVille Syrjälä 	if (cdclk_config->vco == 8640000) {
933df0566a6SJani Nikula 		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
934df0566a6SJani Nikula 		case CDCLK_FREQ_450_432:
9350bb94e03SVille Syrjälä 			cdclk_config->cdclk = 432000;
936df0566a6SJani Nikula 			break;
937df0566a6SJani Nikula 		case CDCLK_FREQ_337_308:
9380bb94e03SVille Syrjälä 			cdclk_config->cdclk = 308571;
939df0566a6SJani Nikula 			break;
940df0566a6SJani Nikula 		case CDCLK_FREQ_540:
9410bb94e03SVille Syrjälä 			cdclk_config->cdclk = 540000;
942df0566a6SJani Nikula 			break;
943df0566a6SJani Nikula 		case CDCLK_FREQ_675_617:
9440bb94e03SVille Syrjälä 			cdclk_config->cdclk = 617143;
945df0566a6SJani Nikula 			break;
946df0566a6SJani Nikula 		default:
947df0566a6SJani Nikula 			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
948df0566a6SJani Nikula 			break;
949df0566a6SJani Nikula 		}
950df0566a6SJani Nikula 	} else {
951df0566a6SJani Nikula 		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
952df0566a6SJani Nikula 		case CDCLK_FREQ_450_432:
9530bb94e03SVille Syrjälä 			cdclk_config->cdclk = 450000;
954df0566a6SJani Nikula 			break;
955df0566a6SJani Nikula 		case CDCLK_FREQ_337_308:
9560bb94e03SVille Syrjälä 			cdclk_config->cdclk = 337500;
957df0566a6SJani Nikula 			break;
958df0566a6SJani Nikula 		case CDCLK_FREQ_540:
9590bb94e03SVille Syrjälä 			cdclk_config->cdclk = 540000;
960df0566a6SJani Nikula 			break;
961df0566a6SJani Nikula 		case CDCLK_FREQ_675_617:
9620bb94e03SVille Syrjälä 			cdclk_config->cdclk = 675000;
963df0566a6SJani Nikula 			break;
964df0566a6SJani Nikula 		default:
965df0566a6SJani Nikula 			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
966df0566a6SJani Nikula 			break;
967df0566a6SJani Nikula 		}
968df0566a6SJani Nikula 	}
969df0566a6SJani Nikula 
970df0566a6SJani Nikula  out:
971df0566a6SJani Nikula 	/*
972df0566a6SJani Nikula 	 * Can't read this out :( Let's assume it's
973df0566a6SJani Nikula 	 * at least what the CDCLK frequency requires.
974df0566a6SJani Nikula 	 */
9750bb94e03SVille Syrjälä 	cdclk_config->voltage_level =
9760bb94e03SVille Syrjälä 		skl_calc_voltage_level(cdclk_config->cdclk);
977df0566a6SJani Nikula }
978df0566a6SJani Nikula 
979df0566a6SJani Nikula /* convert from kHz to .1 fixpoint MHz with -1MHz offset */
skl_cdclk_decimal(int cdclk)980df0566a6SJani Nikula static int skl_cdclk_decimal(int cdclk)
981df0566a6SJani Nikula {
982df0566a6SJani Nikula 	return DIV_ROUND_CLOSEST(cdclk - 1000, 500);
983df0566a6SJani Nikula }
984df0566a6SJani Nikula 
skl_set_preferred_cdclk_vco(struct drm_i915_private * dev_priv,int vco)985df0566a6SJani Nikula static void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv,
986df0566a6SJani Nikula 					int vco)
987df0566a6SJani Nikula {
988df0566a6SJani Nikula 	bool changed = dev_priv->skl_preferred_vco_freq != vco;
989df0566a6SJani Nikula 
990df0566a6SJani Nikula 	dev_priv->skl_preferred_vco_freq = vco;
991df0566a6SJani Nikula 
992df0566a6SJani Nikula 	if (changed)
993df0566a6SJani Nikula 		intel_update_max_cdclk(dev_priv);
994df0566a6SJani Nikula }
995df0566a6SJani Nikula 
skl_dpll0_link_rate(struct drm_i915_private * dev_priv,int vco)996b41df85aSVille Syrjälä static u32 skl_dpll0_link_rate(struct drm_i915_private *dev_priv, int vco)
997df0566a6SJani Nikula {
998aff35110SPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, vco != 8100000 && vco != 8640000);
999df0566a6SJani Nikula 
1000df0566a6SJani Nikula 	/*
1001df0566a6SJani Nikula 	 * We always enable DPLL0 with the lowest link rate possible, but still
1002df0566a6SJani Nikula 	 * taking into account the VCO required to operate the eDP panel at the
1003df0566a6SJani Nikula 	 * desired frequency. The usual DP link rates operate with a VCO of
1004df0566a6SJani Nikula 	 * 8100 while the eDP 1.4 alternate link rates need a VCO of 8640.
1005df0566a6SJani Nikula 	 * The modeset code is responsible for the selection of the exact link
1006df0566a6SJani Nikula 	 * rate later on, with the constraint of choosing a frequency that
1007df0566a6SJani Nikula 	 * works with vco.
1008df0566a6SJani Nikula 	 */
1009b41df85aSVille Syrjälä 	if (vco == 8640000)
1010b41df85aSVille Syrjälä 		return DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0);
1011b41df85aSVille Syrjälä 	else
1012b41df85aSVille Syrjälä 		return DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, SKL_DPLL0);
1013b41df85aSVille Syrjälä }
1014b41df85aSVille Syrjälä 
skl_dpll0_enable(struct drm_i915_private * dev_priv,int vco)1015b41df85aSVille Syrjälä static void skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
1016b41df85aSVille Syrjälä {
10173b71a9b6SVille Syrjälä 	intel_de_rmw(dev_priv, DPLL_CTRL1,
10183b71a9b6SVille Syrjälä 		     DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) |
10193b71a9b6SVille Syrjälä 		     DPLL_CTRL1_SSC(SKL_DPLL0) |
10203b71a9b6SVille Syrjälä 		     DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0),
10213b71a9b6SVille Syrjälä 		     DPLL_CTRL1_OVERRIDE(SKL_DPLL0) |
10223b71a9b6SVille Syrjälä 		     skl_dpll0_link_rate(dev_priv, vco));
10233e9f55dfSJani Nikula 	intel_de_posting_read(dev_priv, DPLL_CTRL1);
1024df0566a6SJani Nikula 
10253b71a9b6SVille Syrjälä 	intel_de_rmw(dev_priv, LCPLL1_CTL,
10263b71a9b6SVille Syrjälä 		     0, LCPLL_PLL_ENABLE);
1027df0566a6SJani Nikula 
10284cb3b44dSDaniele Ceraolo Spurio 	if (intel_de_wait_for_set(dev_priv, LCPLL1_CTL, LCPLL_PLL_LOCK, 5))
102923194610SWambui Karuga 		drm_err(&dev_priv->drm, "DPLL0 not locked\n");
1030df0566a6SJani Nikula 
1031d51309b4SJani Nikula 	dev_priv->display.cdclk.hw.vco = vco;
1032df0566a6SJani Nikula 
1033df0566a6SJani Nikula 	/* We'll want to keep using the current vco from now on. */
1034df0566a6SJani Nikula 	skl_set_preferred_cdclk_vco(dev_priv, vco);
1035df0566a6SJani Nikula }
1036df0566a6SJani Nikula 
skl_dpll0_disable(struct drm_i915_private * dev_priv)1037df0566a6SJani Nikula static void skl_dpll0_disable(struct drm_i915_private *dev_priv)
1038df0566a6SJani Nikula {
10393b71a9b6SVille Syrjälä 	intel_de_rmw(dev_priv, LCPLL1_CTL,
10403b71a9b6SVille Syrjälä 		     LCPLL_PLL_ENABLE, 0);
10413b71a9b6SVille Syrjälä 
10424cb3b44dSDaniele Ceraolo Spurio 	if (intel_de_wait_for_clear(dev_priv, LCPLL1_CTL, LCPLL_PLL_LOCK, 1))
104323194610SWambui Karuga 		drm_err(&dev_priv->drm, "Couldn't disable DPLL0\n");
1044df0566a6SJani Nikula 
1045d51309b4SJani Nikula 	dev_priv->display.cdclk.hw.vco = 0;
1046df0566a6SJani Nikula }
1047df0566a6SJani Nikula 
skl_cdclk_freq_sel(struct drm_i915_private * dev_priv,int cdclk,int vco)1048b41df85aSVille Syrjälä static u32 skl_cdclk_freq_sel(struct drm_i915_private *dev_priv,
1049b41df85aSVille Syrjälä 			      int cdclk, int vco)
1050b41df85aSVille Syrjälä {
1051b41df85aSVille Syrjälä 	switch (cdclk) {
1052b41df85aSVille Syrjälä 	default:
1053b41df85aSVille Syrjälä 		drm_WARN_ON(&dev_priv->drm,
1054d51309b4SJani Nikula 			    cdclk != dev_priv->display.cdclk.hw.bypass);
1055b41df85aSVille Syrjälä 		drm_WARN_ON(&dev_priv->drm, vco != 0);
1056b41df85aSVille Syrjälä 		fallthrough;
1057b41df85aSVille Syrjälä 	case 308571:
1058b41df85aSVille Syrjälä 	case 337500:
1059b41df85aSVille Syrjälä 		return CDCLK_FREQ_337_308;
1060b41df85aSVille Syrjälä 	case 450000:
1061b41df85aSVille Syrjälä 	case 432000:
1062b41df85aSVille Syrjälä 		return CDCLK_FREQ_450_432;
1063b41df85aSVille Syrjälä 	case 540000:
1064b41df85aSVille Syrjälä 		return CDCLK_FREQ_540;
1065b41df85aSVille Syrjälä 	case 617143:
1066b41df85aSVille Syrjälä 	case 675000:
1067b41df85aSVille Syrjälä 		return CDCLK_FREQ_675_617;
1068b41df85aSVille Syrjälä 	}
1069b41df85aSVille Syrjälä }
1070b41df85aSVille Syrjälä 
skl_set_cdclk(struct drm_i915_private * dev_priv,const struct intel_cdclk_config * cdclk_config,enum pipe pipe)1071df0566a6SJani Nikula static void skl_set_cdclk(struct drm_i915_private *dev_priv,
10720bb94e03SVille Syrjälä 			  const struct intel_cdclk_config *cdclk_config,
1073df0566a6SJani Nikula 			  enum pipe pipe)
1074df0566a6SJani Nikula {
10750bb94e03SVille Syrjälä 	int cdclk = cdclk_config->cdclk;
10760bb94e03SVille Syrjälä 	int vco = cdclk_config->vco;
1077df0566a6SJani Nikula 	u32 freq_select, cdclk_ctl;
1078df0566a6SJani Nikula 	int ret;
1079df0566a6SJani Nikula 
1080df0566a6SJani Nikula 	/*
1081df0566a6SJani Nikula 	 * Based on WA#1183 CDCLK rates 308 and 617MHz CDCLK rates are
1082df0566a6SJani Nikula 	 * unsupported on SKL. In theory this should never happen since only
1083df0566a6SJani Nikula 	 * the eDP1.4 2.16 and 4.32Gbps rates require it, but eDP1.4 is not
1084df0566a6SJani Nikula 	 * supported on SKL either, see the above WA. WARN whenever trying to
1085df0566a6SJani Nikula 	 * use the corresponding VCO freq as that always leads to using the
1086df0566a6SJani Nikula 	 * minimum 308MHz CDCLK.
1087df0566a6SJani Nikula 	 */
1088aff35110SPankaj Bharadiya 	drm_WARN_ON_ONCE(&dev_priv->drm,
1089aff35110SPankaj Bharadiya 			 IS_SKYLAKE(dev_priv) && vco == 8640000);
1090df0566a6SJani Nikula 
1091ee421bb4SAshutosh Dixit 	ret = skl_pcode_request(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL,
1092df0566a6SJani Nikula 				SKL_CDCLK_PREPARE_FOR_CHANGE,
1093df0566a6SJani Nikula 				SKL_CDCLK_READY_FOR_CHANGE,
1094df0566a6SJani Nikula 				SKL_CDCLK_READY_FOR_CHANGE, 3);
1095df0566a6SJani Nikula 	if (ret) {
109623194610SWambui Karuga 		drm_err(&dev_priv->drm,
109723194610SWambui Karuga 			"Failed to inform PCU about cdclk change (%d)\n", ret);
1098df0566a6SJani Nikula 		return;
1099df0566a6SJani Nikula 	}
1100df0566a6SJani Nikula 
1101b41df85aSVille Syrjälä 	freq_select = skl_cdclk_freq_sel(dev_priv, cdclk, vco);
1102df0566a6SJani Nikula 
1103d51309b4SJani Nikula 	if (dev_priv->display.cdclk.hw.vco != 0 &&
1104d51309b4SJani Nikula 	    dev_priv->display.cdclk.hw.vco != vco)
1105df0566a6SJani Nikula 		skl_dpll0_disable(dev_priv);
1106df0566a6SJani Nikula 
11073e9f55dfSJani Nikula 	cdclk_ctl = intel_de_read(dev_priv, CDCLK_CTL);
1108df0566a6SJani Nikula 
1109d51309b4SJani Nikula 	if (dev_priv->display.cdclk.hw.vco != vco) {
1110df0566a6SJani Nikula 		/* Wa Display #1183: skl,kbl,cfl */
1111df0566a6SJani Nikula 		cdclk_ctl &= ~(CDCLK_FREQ_SEL_MASK | CDCLK_FREQ_DECIMAL_MASK);
1112df0566a6SJani Nikula 		cdclk_ctl |= freq_select | skl_cdclk_decimal(cdclk);
11133e9f55dfSJani Nikula 		intel_de_write(dev_priv, CDCLK_CTL, cdclk_ctl);
1114df0566a6SJani Nikula 	}
1115df0566a6SJani Nikula 
1116df0566a6SJani Nikula 	/* Wa Display #1183: skl,kbl,cfl */
1117df0566a6SJani Nikula 	cdclk_ctl |= CDCLK_DIVMUX_CD_OVERRIDE;
11183e9f55dfSJani Nikula 	intel_de_write(dev_priv, CDCLK_CTL, cdclk_ctl);
11193e9f55dfSJani Nikula 	intel_de_posting_read(dev_priv, CDCLK_CTL);
1120df0566a6SJani Nikula 
1121d51309b4SJani Nikula 	if (dev_priv->display.cdclk.hw.vco != vco)
1122df0566a6SJani Nikula 		skl_dpll0_enable(dev_priv, vco);
1123df0566a6SJani Nikula 
1124df0566a6SJani Nikula 	/* Wa Display #1183: skl,kbl,cfl */
1125df0566a6SJani Nikula 	cdclk_ctl &= ~(CDCLK_FREQ_SEL_MASK | CDCLK_FREQ_DECIMAL_MASK);
11263e9f55dfSJani Nikula 	intel_de_write(dev_priv, CDCLK_CTL, cdclk_ctl);
1127df0566a6SJani Nikula 
1128df0566a6SJani Nikula 	cdclk_ctl |= freq_select | skl_cdclk_decimal(cdclk);
11293e9f55dfSJani Nikula 	intel_de_write(dev_priv, CDCLK_CTL, cdclk_ctl);
1130df0566a6SJani Nikula 
1131df0566a6SJani Nikula 	/* Wa Display #1183: skl,kbl,cfl */
1132df0566a6SJani Nikula 	cdclk_ctl &= ~CDCLK_DIVMUX_CD_OVERRIDE;
11333e9f55dfSJani Nikula 	intel_de_write(dev_priv, CDCLK_CTL, cdclk_ctl);
11343e9f55dfSJani Nikula 	intel_de_posting_read(dev_priv, CDCLK_CTL);
1135df0566a6SJani Nikula 
1136df0566a6SJani Nikula 	/* inform PCU of the change */
1137ee421bb4SAshutosh Dixit 	snb_pcode_write(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL,
11380bb94e03SVille Syrjälä 			cdclk_config->voltage_level);
1139df0566a6SJani Nikula 
1140df0566a6SJani Nikula 	intel_update_cdclk(dev_priv);
1141df0566a6SJani Nikula }
1142df0566a6SJani Nikula 
skl_sanitize_cdclk(struct drm_i915_private * dev_priv)1143df0566a6SJani Nikula static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
1144df0566a6SJani Nikula {
1145df0566a6SJani Nikula 	u32 cdctl, expected;
1146df0566a6SJani Nikula 
1147df0566a6SJani Nikula 	/*
1148df0566a6SJani Nikula 	 * check if the pre-os initialized the display
1149df0566a6SJani Nikula 	 * There is SWF18 scratchpad register defined which is set by the
1150df0566a6SJani Nikula 	 * pre-os which can be used by the OS drivers to check the status
1151df0566a6SJani Nikula 	 */
11523e9f55dfSJani Nikula 	if ((intel_de_read(dev_priv, SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
1153df0566a6SJani Nikula 		goto sanitize;
1154df0566a6SJani Nikula 
1155df0566a6SJani Nikula 	intel_update_cdclk(dev_priv);
1156d51309b4SJani Nikula 	intel_cdclk_dump_config(dev_priv, &dev_priv->display.cdclk.hw, "Current CDCLK");
1157df0566a6SJani Nikula 
1158df0566a6SJani Nikula 	/* Is PLL enabled and locked ? */
1159d51309b4SJani Nikula 	if (dev_priv->display.cdclk.hw.vco == 0 ||
1160d51309b4SJani Nikula 	    dev_priv->display.cdclk.hw.cdclk == dev_priv->display.cdclk.hw.bypass)
1161df0566a6SJani Nikula 		goto sanitize;
1162df0566a6SJani Nikula 
1163df0566a6SJani Nikula 	/* DPLL okay; verify the cdclock
1164df0566a6SJani Nikula 	 *
1165df0566a6SJani Nikula 	 * Noticed in some instances that the freq selection is correct but
1166df0566a6SJani Nikula 	 * decimal part is programmed wrong from BIOS where pre-os does not
1167df0566a6SJani Nikula 	 * enable display. Verify the same as well.
1168df0566a6SJani Nikula 	 */
11693e9f55dfSJani Nikula 	cdctl = intel_de_read(dev_priv, CDCLK_CTL);
1170df0566a6SJani Nikula 	expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
1171d51309b4SJani Nikula 		skl_cdclk_decimal(dev_priv->display.cdclk.hw.cdclk);
1172df0566a6SJani Nikula 	if (cdctl == expected)
1173df0566a6SJani Nikula 		/* All well; nothing to sanitize */
1174df0566a6SJani Nikula 		return;
1175df0566a6SJani Nikula 
1176df0566a6SJani Nikula sanitize:
117723194610SWambui Karuga 	drm_dbg_kms(&dev_priv->drm, "Sanitizing cdclk programmed by pre-os\n");
1178df0566a6SJani Nikula 
1179df0566a6SJani Nikula 	/* force cdclk programming */
1180d51309b4SJani Nikula 	dev_priv->display.cdclk.hw.cdclk = 0;
1181df0566a6SJani Nikula 	/* force full PLL disable + enable */
1182d51309b4SJani Nikula 	dev_priv->display.cdclk.hw.vco = -1;
1183df0566a6SJani Nikula }
1184df0566a6SJani Nikula 
skl_cdclk_init_hw(struct drm_i915_private * dev_priv)1185ed645eeeSVille Syrjälä static void skl_cdclk_init_hw(struct drm_i915_private *dev_priv)
1186df0566a6SJani Nikula {
11870bb94e03SVille Syrjälä 	struct intel_cdclk_config cdclk_config;
1188df0566a6SJani Nikula 
1189df0566a6SJani Nikula 	skl_sanitize_cdclk(dev_priv);
1190df0566a6SJani Nikula 
1191d51309b4SJani Nikula 	if (dev_priv->display.cdclk.hw.cdclk != 0 &&
1192d51309b4SJani Nikula 	    dev_priv->display.cdclk.hw.vco != 0) {
1193df0566a6SJani Nikula 		/*
1194df0566a6SJani Nikula 		 * Use the current vco as our initial
1195df0566a6SJani Nikula 		 * guess as to what the preferred vco is.
1196df0566a6SJani Nikula 		 */
1197df0566a6SJani Nikula 		if (dev_priv->skl_preferred_vco_freq == 0)
1198df0566a6SJani Nikula 			skl_set_preferred_cdclk_vco(dev_priv,
1199d51309b4SJani Nikula 						    dev_priv->display.cdclk.hw.vco);
1200df0566a6SJani Nikula 		return;
1201df0566a6SJani Nikula 	}
1202df0566a6SJani Nikula 
1203d51309b4SJani Nikula 	cdclk_config = dev_priv->display.cdclk.hw;
1204df0566a6SJani Nikula 
12050bb94e03SVille Syrjälä 	cdclk_config.vco = dev_priv->skl_preferred_vco_freq;
12060bb94e03SVille Syrjälä 	if (cdclk_config.vco == 0)
12070bb94e03SVille Syrjälä 		cdclk_config.vco = 8100000;
12080bb94e03SVille Syrjälä 	cdclk_config.cdclk = skl_calc_cdclk(0, cdclk_config.vco);
12090bb94e03SVille Syrjälä 	cdclk_config.voltage_level = skl_calc_voltage_level(cdclk_config.cdclk);
1210df0566a6SJani Nikula 
12110bb94e03SVille Syrjälä 	skl_set_cdclk(dev_priv, &cdclk_config, INVALID_PIPE);
1212df0566a6SJani Nikula }
1213df0566a6SJani Nikula 
skl_cdclk_uninit_hw(struct drm_i915_private * dev_priv)1214ed645eeeSVille Syrjälä static void skl_cdclk_uninit_hw(struct drm_i915_private *dev_priv)
1215df0566a6SJani Nikula {
1216d51309b4SJani Nikula 	struct intel_cdclk_config cdclk_config = dev_priv->display.cdclk.hw;
1217df0566a6SJani Nikula 
12180bb94e03SVille Syrjälä 	cdclk_config.cdclk = cdclk_config.bypass;
12190bb94e03SVille Syrjälä 	cdclk_config.vco = 0;
12200bb94e03SVille Syrjälä 	cdclk_config.voltage_level = skl_calc_voltage_level(cdclk_config.cdclk);
1221df0566a6SJani Nikula 
12220bb94e03SVille Syrjälä 	skl_set_cdclk(dev_priv, &cdclk_config, INVALID_PIPE);
1223df0566a6SJani Nikula }
1224df0566a6SJani Nikula 
12252bebea57SJani Nikula struct intel_cdclk_vals {
12262bebea57SJani Nikula 	u32 cdclk;
12272bebea57SJani Nikula 	u16 refclk;
12282bebea57SJani Nikula 	u16 waveform;
12292bebea57SJani Nikula 	u8 divider;	/* CD2X divider * 2 */
12302bebea57SJani Nikula 	u8 ratio;
12312bebea57SJani Nikula };
12322bebea57SJani Nikula 
1233736da811SMatt Roper static const struct intel_cdclk_vals bxt_cdclk_table[] = {
1234736da811SMatt Roper 	{ .refclk = 19200, .cdclk = 144000, .divider = 8, .ratio = 60 },
1235736da811SMatt Roper 	{ .refclk = 19200, .cdclk = 288000, .divider = 4, .ratio = 60 },
1236736da811SMatt Roper 	{ .refclk = 19200, .cdclk = 384000, .divider = 3, .ratio = 60 },
1237736da811SMatt Roper 	{ .refclk = 19200, .cdclk = 576000, .divider = 2, .ratio = 60 },
1238736da811SMatt Roper 	{ .refclk = 19200, .cdclk = 624000, .divider = 2, .ratio = 65 },
1239736da811SMatt Roper 	{}
1240736da811SMatt Roper };
1241736da811SMatt Roper 
1242736da811SMatt Roper static const struct intel_cdclk_vals glk_cdclk_table[] = {
1243736da811SMatt Roper 	{ .refclk = 19200, .cdclk =  79200, .divider = 8, .ratio = 33 },
1244736da811SMatt Roper 	{ .refclk = 19200, .cdclk = 158400, .divider = 4, .ratio = 33 },
1245736da811SMatt Roper 	{ .refclk = 19200, .cdclk = 316800, .divider = 2, .ratio = 33 },
1246736da811SMatt Roper 	{}
1247736da811SMatt Roper };
1248736da811SMatt Roper 
1249736da811SMatt Roper static const struct intel_cdclk_vals icl_cdclk_table[] = {
1250736da811SMatt Roper 	{ .refclk = 19200, .cdclk = 172800, .divider = 2, .ratio = 18 },
1251736da811SMatt Roper 	{ .refclk = 19200, .cdclk = 192000, .divider = 2, .ratio = 20 },
1252736da811SMatt Roper 	{ .refclk = 19200, .cdclk = 307200, .divider = 2, .ratio = 32 },
1253736da811SMatt Roper 	{ .refclk = 19200, .cdclk = 326400, .divider = 4, .ratio = 68 },
1254736da811SMatt Roper 	{ .refclk = 19200, .cdclk = 556800, .divider = 2, .ratio = 58 },
1255736da811SMatt Roper 	{ .refclk = 19200, .cdclk = 652800, .divider = 2, .ratio = 68 },
1256736da811SMatt Roper 
1257736da811SMatt Roper 	{ .refclk = 24000, .cdclk = 180000, .divider = 2, .ratio = 15 },
1258736da811SMatt Roper 	{ .refclk = 24000, .cdclk = 192000, .divider = 2, .ratio = 16 },
1259736da811SMatt Roper 	{ .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 },
1260736da811SMatt Roper 	{ .refclk = 24000, .cdclk = 324000, .divider = 4, .ratio = 54 },
1261736da811SMatt Roper 	{ .refclk = 24000, .cdclk = 552000, .divider = 2, .ratio = 46 },
1262736da811SMatt Roper 	{ .refclk = 24000, .cdclk = 648000, .divider = 2, .ratio = 54 },
1263736da811SMatt Roper 
1264736da811SMatt Roper 	{ .refclk = 38400, .cdclk = 172800, .divider = 2, .ratio =  9 },
1265736da811SMatt Roper 	{ .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 10 },
1266736da811SMatt Roper 	{ .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16 },
1267736da811SMatt Roper 	{ .refclk = 38400, .cdclk = 326400, .divider = 4, .ratio = 34 },
1268736da811SMatt Roper 	{ .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29 },
1269736da811SMatt Roper 	{ .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34 },
1270736da811SMatt Roper 	{}
1271736da811SMatt Roper };
1272736da811SMatt Roper 
1273693260cfSMatt Roper static const struct intel_cdclk_vals rkl_cdclk_table[] = {
1274693260cfSMatt Roper 	{ .refclk = 19200, .cdclk = 172800, .divider = 4, .ratio =  36 },
1275693260cfSMatt Roper 	{ .refclk = 19200, .cdclk = 192000, .divider = 4, .ratio =  40 },
1276693260cfSMatt Roper 	{ .refclk = 19200, .cdclk = 307200, .divider = 4, .ratio =  64 },
1277693260cfSMatt Roper 	{ .refclk = 19200, .cdclk = 326400, .divider = 8, .ratio = 136 },
1278693260cfSMatt Roper 	{ .refclk = 19200, .cdclk = 556800, .divider = 4, .ratio = 116 },
1279693260cfSMatt Roper 	{ .refclk = 19200, .cdclk = 652800, .divider = 4, .ratio = 136 },
1280693260cfSMatt Roper 
1281693260cfSMatt Roper 	{ .refclk = 24000, .cdclk = 180000, .divider = 4, .ratio =  30 },
1282693260cfSMatt Roper 	{ .refclk = 24000, .cdclk = 192000, .divider = 4, .ratio =  32 },
1283693260cfSMatt Roper 	{ .refclk = 24000, .cdclk = 312000, .divider = 4, .ratio =  52 },
1284693260cfSMatt Roper 	{ .refclk = 24000, .cdclk = 324000, .divider = 8, .ratio = 108 },
1285693260cfSMatt Roper 	{ .refclk = 24000, .cdclk = 552000, .divider = 4, .ratio =  92 },
1286693260cfSMatt Roper 	{ .refclk = 24000, .cdclk = 648000, .divider = 4, .ratio = 108 },
1287693260cfSMatt Roper 
1288693260cfSMatt Roper 	{ .refclk = 38400, .cdclk = 172800, .divider = 4, .ratio = 18 },
1289693260cfSMatt Roper 	{ .refclk = 38400, .cdclk = 192000, .divider = 4, .ratio = 20 },
1290693260cfSMatt Roper 	{ .refclk = 38400, .cdclk = 307200, .divider = 4, .ratio = 32 },
1291693260cfSMatt Roper 	{ .refclk = 38400, .cdclk = 326400, .divider = 8, .ratio = 68 },
1292693260cfSMatt Roper 	{ .refclk = 38400, .cdclk = 556800, .divider = 4, .ratio = 58 },
1293693260cfSMatt Roper 	{ .refclk = 38400, .cdclk = 652800, .divider = 4, .ratio = 68 },
1294693260cfSMatt Roper 	{}
1295693260cfSMatt Roper };
1296693260cfSMatt Roper 
12972680bea7SJosé Roberto de Souza static const struct intel_cdclk_vals adlp_a_step_cdclk_table[] = {
12982680bea7SJosé Roberto de Souza 	{ .refclk = 19200, .cdclk = 307200, .divider = 2, .ratio = 32 },
12992680bea7SJosé Roberto de Souza 	{ .refclk = 19200, .cdclk = 556800, .divider = 2, .ratio = 58 },
13002680bea7SJosé Roberto de Souza 	{ .refclk = 19200, .cdclk = 652800, .divider = 2, .ratio = 68 },
13012680bea7SJosé Roberto de Souza 
13022680bea7SJosé Roberto de Souza 	{ .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 },
13032680bea7SJosé Roberto de Souza 	{ .refclk = 24000, .cdclk = 552000, .divider = 2, .ratio = 46 },
13042680bea7SJosé Roberto de Souza 	{ .refclk = 24400, .cdclk = 648000, .divider = 2, .ratio = 54 },
13052680bea7SJosé Roberto de Souza 
13062680bea7SJosé Roberto de Souza 	{ .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16 },
13072680bea7SJosé Roberto de Souza 	{ .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29 },
13082680bea7SJosé Roberto de Souza 	{ .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34 },
13092680bea7SJosé Roberto de Souza 	{}
13102680bea7SJosé Roberto de Souza };
13112680bea7SJosé Roberto de Souza 
1312626426ffSAnusha Srivatsa static const struct intel_cdclk_vals adlp_cdclk_table[] = {
1313626426ffSAnusha Srivatsa 	{ .refclk = 19200, .cdclk = 172800, .divider = 3, .ratio = 27 },
1314626426ffSAnusha Srivatsa 	{ .refclk = 19200, .cdclk = 192000, .divider = 2, .ratio = 20 },
1315626426ffSAnusha Srivatsa 	{ .refclk = 19200, .cdclk = 307200, .divider = 2, .ratio = 32 },
1316626426ffSAnusha Srivatsa 	{ .refclk = 19200, .cdclk = 556800, .divider = 2, .ratio = 58 },
1317626426ffSAnusha Srivatsa 	{ .refclk = 19200, .cdclk = 652800, .divider = 2, .ratio = 68 },
1318626426ffSAnusha Srivatsa 
1319626426ffSAnusha Srivatsa 	{ .refclk = 24000, .cdclk = 176000, .divider = 3, .ratio = 22 },
1320626426ffSAnusha Srivatsa 	{ .refclk = 24000, .cdclk = 192000, .divider = 2, .ratio = 16 },
1321626426ffSAnusha Srivatsa 	{ .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 },
1322626426ffSAnusha Srivatsa 	{ .refclk = 24000, .cdclk = 552000, .divider = 2, .ratio = 46 },
13232b6f7e39SChaitanya Kumar Borah 	{ .refclk = 24000, .cdclk = 648000, .divider = 2, .ratio = 54 },
1324626426ffSAnusha Srivatsa 
1325626426ffSAnusha Srivatsa 	{ .refclk = 38400, .cdclk = 179200, .divider = 3, .ratio = 14 },
1326626426ffSAnusha Srivatsa 	{ .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 10 },
1327626426ffSAnusha Srivatsa 	{ .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16 },
1328626426ffSAnusha Srivatsa 	{ .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29 },
1329626426ffSAnusha Srivatsa 	{ .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34 },
1330626426ffSAnusha Srivatsa 	{}
1331626426ffSAnusha Srivatsa };
1332626426ffSAnusha Srivatsa 
133306f1b06dSChaitanya Kumar Borah static const struct intel_cdclk_vals rplu_cdclk_table[] = {
133406f1b06dSChaitanya Kumar Borah 	{ .refclk = 19200, .cdclk = 172800, .divider = 3, .ratio = 27 },
133506f1b06dSChaitanya Kumar Borah 	{ .refclk = 19200, .cdclk = 192000, .divider = 2, .ratio = 20 },
133606f1b06dSChaitanya Kumar Borah 	{ .refclk = 19200, .cdclk = 307200, .divider = 2, .ratio = 32 },
133706f1b06dSChaitanya Kumar Borah 	{ .refclk = 19200, .cdclk = 480000, .divider = 2, .ratio = 50 },
133806f1b06dSChaitanya Kumar Borah 	{ .refclk = 19200, .cdclk = 556800, .divider = 2, .ratio = 58 },
133906f1b06dSChaitanya Kumar Borah 	{ .refclk = 19200, .cdclk = 652800, .divider = 2, .ratio = 68 },
134006f1b06dSChaitanya Kumar Borah 
134106f1b06dSChaitanya Kumar Borah 	{ .refclk = 24000, .cdclk = 176000, .divider = 3, .ratio = 22 },
134206f1b06dSChaitanya Kumar Borah 	{ .refclk = 24000, .cdclk = 192000, .divider = 2, .ratio = 16 },
134306f1b06dSChaitanya Kumar Borah 	{ .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 },
134406f1b06dSChaitanya Kumar Borah 	{ .refclk = 24000, .cdclk = 480000, .divider = 2, .ratio = 40 },
134506f1b06dSChaitanya Kumar Borah 	{ .refclk = 24000, .cdclk = 552000, .divider = 2, .ratio = 46 },
134606f1b06dSChaitanya Kumar Borah 	{ .refclk = 24000, .cdclk = 648000, .divider = 2, .ratio = 54 },
134706f1b06dSChaitanya Kumar Borah 
134806f1b06dSChaitanya Kumar Borah 	{ .refclk = 38400, .cdclk = 179200, .divider = 3, .ratio = 14 },
134906f1b06dSChaitanya Kumar Borah 	{ .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 10 },
135006f1b06dSChaitanya Kumar Borah 	{ .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16 },
135106f1b06dSChaitanya Kumar Borah 	{ .refclk = 38400, .cdclk = 480000, .divider = 2, .ratio = 25 },
135206f1b06dSChaitanya Kumar Borah 	{ .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29 },
135306f1b06dSChaitanya Kumar Borah 	{ .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34 },
135406f1b06dSChaitanya Kumar Borah 	{}
135506f1b06dSChaitanya Kumar Borah };
135606f1b06dSChaitanya Kumar Borah 
13571f3e84c4SMatt Roper static const struct intel_cdclk_vals dg2_cdclk_table[] = {
13582fb352faSMika Kahola 	{ .refclk = 38400, .cdclk = 163200, .divider = 2, .ratio = 34, .waveform = 0x8888 },
13592fb352faSMika Kahola 	{ .refclk = 38400, .cdclk = 204000, .divider = 2, .ratio = 34, .waveform = 0x9248 },
13602fb352faSMika Kahola 	{ .refclk = 38400, .cdclk = 244800, .divider = 2, .ratio = 34, .waveform = 0xa4a4 },
13612fb352faSMika Kahola 	{ .refclk = 38400, .cdclk = 285600, .divider = 2, .ratio = 34, .waveform = 0xa54a },
13622fb352faSMika Kahola 	{ .refclk = 38400, .cdclk = 326400, .divider = 2, .ratio = 34, .waveform = 0xaaaa },
13632fb352faSMika Kahola 	{ .refclk = 38400, .cdclk = 367200, .divider = 2, .ratio = 34, .waveform = 0xad5a },
13642fb352faSMika Kahola 	{ .refclk = 38400, .cdclk = 408000, .divider = 2, .ratio = 34, .waveform = 0xb6b6 },
13652fb352faSMika Kahola 	{ .refclk = 38400, .cdclk = 448800, .divider = 2, .ratio = 34, .waveform = 0xdbb6 },
13662fb352faSMika Kahola 	{ .refclk = 38400, .cdclk = 489600, .divider = 2, .ratio = 34, .waveform = 0xeeee },
13672fb352faSMika Kahola 	{ .refclk = 38400, .cdclk = 530400, .divider = 2, .ratio = 34, .waveform = 0xf7de },
13682fb352faSMika Kahola 	{ .refclk = 38400, .cdclk = 571200, .divider = 2, .ratio = 34, .waveform = 0xfefe },
13692fb352faSMika Kahola 	{ .refclk = 38400, .cdclk = 612000, .divider = 2, .ratio = 34, .waveform = 0xfffe },
13702fb352faSMika Kahola 	{ .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34, .waveform = 0xffff },
13711f3e84c4SMatt Roper 	{}
13721f3e84c4SMatt Roper };
13731f3e84c4SMatt Roper 
137486c0ef72SAnusha Srivatsa static const struct intel_cdclk_vals mtl_cdclk_table[] = {
137586c0ef72SAnusha Srivatsa 	{ .refclk = 38400, .cdclk = 172800, .divider = 2, .ratio = 16, .waveform = 0xad5a },
137686c0ef72SAnusha Srivatsa 	{ .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 16, .waveform = 0xb6b6 },
137786c0ef72SAnusha Srivatsa 	{ .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16, .waveform = 0x0000 },
137886c0ef72SAnusha Srivatsa 	{ .refclk = 38400, .cdclk = 480000, .divider = 2, .ratio = 25, .waveform = 0x0000 },
137986c0ef72SAnusha Srivatsa 	{ .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29, .waveform = 0x0000 },
138086c0ef72SAnusha Srivatsa 	{ .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34, .waveform = 0x0000 },
138186c0ef72SAnusha Srivatsa 	{}
138286c0ef72SAnusha Srivatsa };
138386c0ef72SAnusha Srivatsa 
bxt_calc_cdclk(struct drm_i915_private * dev_priv,int min_cdclk)1384736da811SMatt Roper static int bxt_calc_cdclk(struct drm_i915_private *dev_priv, int min_cdclk)
1385df0566a6SJani Nikula {
1386d51309b4SJani Nikula 	const struct intel_cdclk_vals *table = dev_priv->display.cdclk.table;
1387736da811SMatt Roper 	int i;
1388736da811SMatt Roper 
1389736da811SMatt Roper 	for (i = 0; table[i].refclk; i++)
1390d51309b4SJani Nikula 		if (table[i].refclk == dev_priv->display.cdclk.hw.ref &&
1391736da811SMatt Roper 		    table[i].cdclk >= min_cdclk)
1392736da811SMatt Roper 			return table[i].cdclk;
1393736da811SMatt Roper 
1394aff35110SPankaj Bharadiya 	drm_WARN(&dev_priv->drm, 1,
1395aff35110SPankaj Bharadiya 		 "Cannot satisfy minimum cdclk %d with refclk %u\n",
1396d51309b4SJani Nikula 		 min_cdclk, dev_priv->display.cdclk.hw.ref);
1397736da811SMatt Roper 	return 0;
1398df0566a6SJani Nikula }
1399df0566a6SJani Nikula 
bxt_calc_cdclk_pll_vco(struct drm_i915_private * dev_priv,int cdclk)1400736da811SMatt Roper static int bxt_calc_cdclk_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
1401df0566a6SJani Nikula {
1402d51309b4SJani Nikula 	const struct intel_cdclk_vals *table = dev_priv->display.cdclk.table;
1403736da811SMatt Roper 	int i;
1404736da811SMatt Roper 
1405d51309b4SJani Nikula 	if (cdclk == dev_priv->display.cdclk.hw.bypass)
1406736da811SMatt Roper 		return 0;
1407736da811SMatt Roper 
1408736da811SMatt Roper 	for (i = 0; table[i].refclk; i++)
1409d51309b4SJani Nikula 		if (table[i].refclk == dev_priv->display.cdclk.hw.ref &&
1410736da811SMatt Roper 		    table[i].cdclk == cdclk)
1411d51309b4SJani Nikula 			return dev_priv->display.cdclk.hw.ref * table[i].ratio;
1412736da811SMatt Roper 
1413aff35110SPankaj Bharadiya 	drm_WARN(&dev_priv->drm, 1, "cdclk %d not valid for refclk %u\n",
1414d51309b4SJani Nikula 		 cdclk, dev_priv->display.cdclk.hw.ref);
1415736da811SMatt Roper 	return 0;
1416df0566a6SJani Nikula }
1417df0566a6SJani Nikula 
bxt_calc_voltage_level(int cdclk)1418df0566a6SJani Nikula static u8 bxt_calc_voltage_level(int cdclk)
1419df0566a6SJani Nikula {
1420df0566a6SJani Nikula 	return DIV_ROUND_UP(cdclk, 25000);
1421df0566a6SJani Nikula }
1422df0566a6SJani Nikula 
icl_calc_voltage_level(int cdclk)142371dc367eSMatt Roper static u8 icl_calc_voltage_level(int cdclk)
142471dc367eSMatt Roper {
142571dc367eSMatt Roper 	if (cdclk > 556800)
142671dc367eSMatt Roper 		return 2;
142771dc367eSMatt Roper 	else if (cdclk > 312000)
142871dc367eSMatt Roper 		return 1;
142971dc367eSMatt Roper 	else
143071dc367eSMatt Roper 		return 0;
143171dc367eSMatt Roper }
143271dc367eSMatt Roper 
ehl_calc_voltage_level(int cdclk)143371dc367eSMatt Roper static u8 ehl_calc_voltage_level(int cdclk)
143471dc367eSMatt Roper {
1435d1474838SMatt Roper 	if (cdclk > 326400)
1436d1474838SMatt Roper 		return 3;
1437d1474838SMatt Roper 	else if (cdclk > 312000)
143871dc367eSMatt Roper 		return 2;
143971dc367eSMatt Roper 	else if (cdclk > 180000)
144071dc367eSMatt Roper 		return 1;
144171dc367eSMatt Roper 	else
144271dc367eSMatt Roper 		return 0;
144371dc367eSMatt Roper }
144471dc367eSMatt Roper 
tgl_calc_voltage_level(int cdclk)14450fde0b1dSMatt Roper static u8 tgl_calc_voltage_level(int cdclk)
14460fde0b1dSMatt Roper {
14470fde0b1dSMatt Roper 	if (cdclk > 556800)
14480fde0b1dSMatt Roper 		return 3;
14490fde0b1dSMatt Roper 	else if (cdclk > 326400)
14500fde0b1dSMatt Roper 		return 2;
14510fde0b1dSMatt Roper 	else if (cdclk > 312000)
14520fde0b1dSMatt Roper 		return 1;
14530fde0b1dSMatt Roper 	else
14540fde0b1dSMatt Roper 		return 0;
14550fde0b1dSMatt Roper }
14560fde0b1dSMatt Roper 
rplu_calc_voltage_level(int cdclk)14575a3c46b8SChaitanya Kumar Borah static u8 rplu_calc_voltage_level(int cdclk)
14585a3c46b8SChaitanya Kumar Borah {
14595a3c46b8SChaitanya Kumar Borah 	if (cdclk > 556800)
14605a3c46b8SChaitanya Kumar Borah 		return 3;
14615a3c46b8SChaitanya Kumar Borah 	else if (cdclk > 480000)
14625a3c46b8SChaitanya Kumar Borah 		return 2;
14635a3c46b8SChaitanya Kumar Borah 	else if (cdclk > 312000)
14645a3c46b8SChaitanya Kumar Borah 		return 1;
14655a3c46b8SChaitanya Kumar Borah 	else
14665a3c46b8SChaitanya Kumar Borah 		return 0;
14675a3c46b8SChaitanya Kumar Borah }
14685a3c46b8SChaitanya Kumar Borah 
icl_readout_refclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)146971dc367eSMatt Roper static void icl_readout_refclk(struct drm_i915_private *dev_priv,
14700bb94e03SVille Syrjälä 			       struct intel_cdclk_config *cdclk_config)
147171dc367eSMatt Roper {
14723e9f55dfSJani Nikula 	u32 dssm = intel_de_read(dev_priv, SKL_DSSM) & ICL_DSSM_CDCLK_PLL_REFCLK_MASK;
147371dc367eSMatt Roper 
147471dc367eSMatt Roper 	switch (dssm) {
147571dc367eSMatt Roper 	default:
147671dc367eSMatt Roper 		MISSING_CASE(dssm);
1477df561f66SGustavo A. R. Silva 		fallthrough;
147871dc367eSMatt Roper 	case ICL_DSSM_CDCLK_PLL_REFCLK_24MHz:
14790bb94e03SVille Syrjälä 		cdclk_config->ref = 24000;
148071dc367eSMatt Roper 		break;
148171dc367eSMatt Roper 	case ICL_DSSM_CDCLK_PLL_REFCLK_19_2MHz:
14820bb94e03SVille Syrjälä 		cdclk_config->ref = 19200;
148371dc367eSMatt Roper 		break;
148471dc367eSMatt Roper 	case ICL_DSSM_CDCLK_PLL_REFCLK_38_4MHz:
14850bb94e03SVille Syrjälä 		cdclk_config->ref = 38400;
148671dc367eSMatt Roper 		break;
148771dc367eSMatt Roper 	}
148871dc367eSMatt Roper }
148971dc367eSMatt Roper 
bxt_de_pll_readout(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)149071dc367eSMatt Roper static void bxt_de_pll_readout(struct drm_i915_private *dev_priv,
14910bb94e03SVille Syrjälä 			       struct intel_cdclk_config *cdclk_config)
149271dc367eSMatt Roper {
149371dc367eSMatt Roper 	u32 val, ratio;
149471dc367eSMatt Roper 
14951f3e84c4SMatt Roper 	if (IS_DG2(dev_priv))
14961f3e84c4SMatt Roper 		cdclk_config->ref = 38400;
14971f3e84c4SMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 11)
14980bb94e03SVille Syrjälä 		icl_readout_refclk(dev_priv, cdclk_config);
149971dc367eSMatt Roper 	else
15000bb94e03SVille Syrjälä 		cdclk_config->ref = 19200;
1501df0566a6SJani Nikula 
15023e9f55dfSJani Nikula 	val = intel_de_read(dev_priv, BXT_DE_PLL_ENABLE);
150371dc367eSMatt Roper 	if ((val & BXT_DE_PLL_PLL_ENABLE) == 0 ||
150471dc367eSMatt Roper 	    (val & BXT_DE_PLL_LOCK) == 0) {
150571dc367eSMatt Roper 		/*
150671dc367eSMatt Roper 		 * CDCLK PLL is disabled, the VCO/ratio doesn't matter, but
150771dc367eSMatt Roper 		 * setting it to zero is a way to signal that.
150871dc367eSMatt Roper 		 */
15090bb94e03SVille Syrjälä 		cdclk_config->vco = 0;
1510df0566a6SJani Nikula 		return;
151171dc367eSMatt Roper 	}
1512df0566a6SJani Nikula 
151371dc367eSMatt Roper 	/*
15141d89509aSLucas De Marchi 	 * DISPLAY_VER >= 11 have the ratio directly in the PLL enable register,
15151d89509aSLucas De Marchi 	 * gen9lp had it in a separate PLL control register.
151671dc367eSMatt Roper 	 */
15171d89509aSLucas De Marchi 	if (DISPLAY_VER(dev_priv) >= 11)
15181d89509aSLucas De Marchi 		ratio = val & ICL_CDCLK_PLL_RATIO_MASK;
151971dc367eSMatt Roper 	else
15203e9f55dfSJani Nikula 		ratio = intel_de_read(dev_priv, BXT_DE_PLL_CTL) & BXT_DE_PLL_RATIO_MASK;
1521df0566a6SJani Nikula 
15220bb94e03SVille Syrjälä 	cdclk_config->vco = ratio * cdclk_config->ref;
1523df0566a6SJani Nikula }
1524df0566a6SJani Nikula 
bxt_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_config * cdclk_config)1525df0566a6SJani Nikula static void bxt_get_cdclk(struct drm_i915_private *dev_priv,
15260bb94e03SVille Syrjälä 			  struct intel_cdclk_config *cdclk_config)
1527df0566a6SJani Nikula {
152877ab3a1eSMika Kahola 	u32 squash_ctl = 0;
1529df0566a6SJani Nikula 	u32 divider;
1530df0566a6SJani Nikula 	int div;
1531df0566a6SJani Nikula 
15320bb94e03SVille Syrjälä 	bxt_de_pll_readout(dev_priv, cdclk_config);
153374689ddfSVille Syrjälä 
1534005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
15350bb94e03SVille Syrjälä 		cdclk_config->bypass = cdclk_config->ref / 2;
1536005e9537SMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 11)
15370bb94e03SVille Syrjälä 		cdclk_config->bypass = 50000;
153871dc367eSMatt Roper 	else
15390bb94e03SVille Syrjälä 		cdclk_config->bypass = cdclk_config->ref;
1540df0566a6SJani Nikula 
15410bb94e03SVille Syrjälä 	if (cdclk_config->vco == 0) {
15420bb94e03SVille Syrjälä 		cdclk_config->cdclk = cdclk_config->bypass;
1543df0566a6SJani Nikula 		goto out;
154471dc367eSMatt Roper 	}
1545df0566a6SJani Nikula 
15463e9f55dfSJani Nikula 	divider = intel_de_read(dev_priv, CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
1547df0566a6SJani Nikula 
1548df0566a6SJani Nikula 	switch (divider) {
1549df0566a6SJani Nikula 	case BXT_CDCLK_CD2X_DIV_SEL_1:
1550df0566a6SJani Nikula 		div = 2;
1551df0566a6SJani Nikula 		break;
1552df0566a6SJani Nikula 	case BXT_CDCLK_CD2X_DIV_SEL_1_5:
1553df0566a6SJani Nikula 		div = 3;
1554df0566a6SJani Nikula 		break;
1555df0566a6SJani Nikula 	case BXT_CDCLK_CD2X_DIV_SEL_2:
1556df0566a6SJani Nikula 		div = 4;
1557df0566a6SJani Nikula 		break;
1558df0566a6SJani Nikula 	case BXT_CDCLK_CD2X_DIV_SEL_4:
1559df0566a6SJani Nikula 		div = 8;
1560df0566a6SJani Nikula 		break;
1561df0566a6SJani Nikula 	default:
1562df0566a6SJani Nikula 		MISSING_CASE(divider);
1563df0566a6SJani Nikula 		return;
1564df0566a6SJani Nikula 	}
1565df0566a6SJani Nikula 
15661d32f5d6SAnusha Srivatsa 	if (HAS_CDCLK_SQUASH(dev_priv))
156777ab3a1eSMika Kahola 		squash_ctl = intel_de_read(dev_priv, CDCLK_SQUASH_CTL);
156877ab3a1eSMika Kahola 
156977ab3a1eSMika Kahola 	if (squash_ctl & CDCLK_SQUASH_ENABLE) {
157077ab3a1eSMika Kahola 		u16 waveform;
157177ab3a1eSMika Kahola 		int size;
157277ab3a1eSMika Kahola 
157377ab3a1eSMika Kahola 		size = REG_FIELD_GET(CDCLK_SQUASH_WINDOW_SIZE_MASK, squash_ctl) + 1;
157477ab3a1eSMika Kahola 		waveform = REG_FIELD_GET(CDCLK_SQUASH_WAVEFORM_MASK, squash_ctl) >> (16 - size);
157577ab3a1eSMika Kahola 
157677ab3a1eSMika Kahola 		cdclk_config->cdclk = DIV_ROUND_CLOSEST(hweight16(waveform) *
157777ab3a1eSMika Kahola 							cdclk_config->vco, size * div);
157877ab3a1eSMika Kahola 	} else {
15790bb94e03SVille Syrjälä 		cdclk_config->cdclk = DIV_ROUND_CLOSEST(cdclk_config->vco, div);
158077ab3a1eSMika Kahola 	}
1581df0566a6SJani Nikula 
1582df0566a6SJani Nikula  out:
1583df0566a6SJani Nikula 	/*
1584df0566a6SJani Nikula 	 * Can't read this out :( Let's assume it's
1585df0566a6SJani Nikula 	 * at least what the CDCLK frequency requires.
1586df0566a6SJani Nikula 	 */
15870bb94e03SVille Syrjälä 	cdclk_config->voltage_level =
158844892ffaSDave Airlie 		intel_cdclk_calc_voltage_level(dev_priv, cdclk_config->cdclk);
1589df0566a6SJani Nikula }
1590df0566a6SJani Nikula 
bxt_de_pll_disable(struct drm_i915_private * dev_priv)1591df0566a6SJani Nikula static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
1592df0566a6SJani Nikula {
15933e9f55dfSJani Nikula 	intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, 0);
1594df0566a6SJani Nikula 
1595df0566a6SJani Nikula 	/* Timeout 200us */
15964cb3b44dSDaniele Ceraolo Spurio 	if (intel_de_wait_for_clear(dev_priv,
15974cb3b44dSDaniele Ceraolo Spurio 				    BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 1))
159823194610SWambui Karuga 		drm_err(&dev_priv->drm, "timeout waiting for DE PLL unlock\n");
1599df0566a6SJani Nikula 
1600d51309b4SJani Nikula 	dev_priv->display.cdclk.hw.vco = 0;
1601df0566a6SJani Nikula }
1602df0566a6SJani Nikula 
bxt_de_pll_enable(struct drm_i915_private * dev_priv,int vco)1603df0566a6SJani Nikula static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
1604df0566a6SJani Nikula {
1605d51309b4SJani Nikula 	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->display.cdclk.hw.ref);
1606df0566a6SJani Nikula 
1607468f9e8dSVille Syrjälä 	intel_de_rmw(dev_priv, BXT_DE_PLL_CTL,
1608468f9e8dSVille Syrjälä 		     BXT_DE_PLL_RATIO_MASK, BXT_DE_PLL_RATIO(ratio));
1609df0566a6SJani Nikula 
16103e9f55dfSJani Nikula 	intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, BXT_DE_PLL_PLL_ENABLE);
1611df0566a6SJani Nikula 
1612df0566a6SJani Nikula 	/* Timeout 200us */
16134cb3b44dSDaniele Ceraolo Spurio 	if (intel_de_wait_for_set(dev_priv,
16144cb3b44dSDaniele Ceraolo Spurio 				  BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 1))
161523194610SWambui Karuga 		drm_err(&dev_priv->drm, "timeout waiting for DE PLL lock\n");
1616df0566a6SJani Nikula 
1617d51309b4SJani Nikula 	dev_priv->display.cdclk.hw.vco = vco;
1618df0566a6SJani Nikula }
1619df0566a6SJani Nikula 
icl_cdclk_pll_disable(struct drm_i915_private * dev_priv)16201d89509aSLucas De Marchi static void icl_cdclk_pll_disable(struct drm_i915_private *dev_priv)
16211cbcd3b4SMatt Roper {
1622468f9e8dSVille Syrjälä 	intel_de_rmw(dev_priv, BXT_DE_PLL_ENABLE,
1623468f9e8dSVille Syrjälä 		     BXT_DE_PLL_PLL_ENABLE, 0);
16241cbcd3b4SMatt Roper 
16251cbcd3b4SMatt Roper 	/* Timeout 200us */
16267973cff7SVille Syrjälä 	if (intel_de_wait_for_clear(dev_priv, BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 1))
16277973cff7SVille Syrjälä 		drm_err(&dev_priv->drm, "timeout waiting for CDCLK PLL unlock\n");
16281cbcd3b4SMatt Roper 
1629d51309b4SJani Nikula 	dev_priv->display.cdclk.hw.vco = 0;
16301cbcd3b4SMatt Roper }
16311cbcd3b4SMatt Roper 
icl_cdclk_pll_enable(struct drm_i915_private * dev_priv,int vco)16321d89509aSLucas De Marchi static void icl_cdclk_pll_enable(struct drm_i915_private *dev_priv, int vco)
16331cbcd3b4SMatt Roper {
1634d51309b4SJani Nikula 	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->display.cdclk.hw.ref);
16351cbcd3b4SMatt Roper 	u32 val;
16361cbcd3b4SMatt Roper 
16371d89509aSLucas De Marchi 	val = ICL_CDCLK_PLL_RATIO(ratio);
16383e9f55dfSJani Nikula 	intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
16391cbcd3b4SMatt Roper 
16401cbcd3b4SMatt Roper 	val |= BXT_DE_PLL_PLL_ENABLE;
16413e9f55dfSJani Nikula 	intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
16421cbcd3b4SMatt Roper 
16431cbcd3b4SMatt Roper 	/* Timeout 200us */
16447973cff7SVille Syrjälä 	if (intel_de_wait_for_set(dev_priv, BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 1))
16457973cff7SVille Syrjälä 		drm_err(&dev_priv->drm, "timeout waiting for CDCLK PLL lock\n");
16461cbcd3b4SMatt Roper 
1647d51309b4SJani Nikula 	dev_priv->display.cdclk.hw.vco = vco;
16481cbcd3b4SMatt Roper }
16491cbcd3b4SMatt Roper 
adlp_cdclk_pll_crawl(struct drm_i915_private * dev_priv,int vco)1650d62686baSStanislav Lisovskiy static void adlp_cdclk_pll_crawl(struct drm_i915_private *dev_priv, int vco)
1651d62686baSStanislav Lisovskiy {
1652d51309b4SJani Nikula 	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->display.cdclk.hw.ref);
1653d62686baSStanislav Lisovskiy 	u32 val;
1654d62686baSStanislav Lisovskiy 
1655d62686baSStanislav Lisovskiy 	/* Write PLL ratio without disabling */
16561d89509aSLucas De Marchi 	val = ICL_CDCLK_PLL_RATIO(ratio) | BXT_DE_PLL_PLL_ENABLE;
1657d62686baSStanislav Lisovskiy 	intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
1658d62686baSStanislav Lisovskiy 
1659d62686baSStanislav Lisovskiy 	/* Submit freq change request */
1660d62686baSStanislav Lisovskiy 	val |= BXT_DE_PLL_FREQ_REQ;
1661d62686baSStanislav Lisovskiy 	intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
1662d62686baSStanislav Lisovskiy 
1663d62686baSStanislav Lisovskiy 	/* Timeout 200us */
1664d62686baSStanislav Lisovskiy 	if (intel_de_wait_for_set(dev_priv, BXT_DE_PLL_ENABLE,
1665d62686baSStanislav Lisovskiy 				  BXT_DE_PLL_LOCK | BXT_DE_PLL_FREQ_REQ_ACK, 1))
1666c9b06cc2SJani Nikula 		drm_err(&dev_priv->drm, "timeout waiting for FREQ change request ack\n");
1667d62686baSStanislav Lisovskiy 
1668d62686baSStanislav Lisovskiy 	val &= ~BXT_DE_PLL_FREQ_REQ;
1669d62686baSStanislav Lisovskiy 	intel_de_write(dev_priv, BXT_DE_PLL_ENABLE, val);
1670d62686baSStanislav Lisovskiy 
1671d51309b4SJani Nikula 	dev_priv->display.cdclk.hw.vco = vco;
1672d62686baSStanislav Lisovskiy }
1673d62686baSStanislav Lisovskiy 
bxt_cdclk_cd2x_pipe(struct drm_i915_private * dev_priv,enum pipe pipe)16740a12e437SVille Syrjälä static u32 bxt_cdclk_cd2x_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
16750a12e437SVille Syrjälä {
1676005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
16770a12e437SVille Syrjälä 		if (pipe == INVALID_PIPE)
16780a12e437SVille Syrjälä 			return TGL_CDCLK_CD2X_PIPE_NONE;
16790a12e437SVille Syrjälä 		else
16800a12e437SVille Syrjälä 			return TGL_CDCLK_CD2X_PIPE(pipe);
1681005e9537SMatt Roper 	} else if (DISPLAY_VER(dev_priv) >= 11) {
16820a12e437SVille Syrjälä 		if (pipe == INVALID_PIPE)
16830a12e437SVille Syrjälä 			return ICL_CDCLK_CD2X_PIPE_NONE;
16840a12e437SVille Syrjälä 		else
16850a12e437SVille Syrjälä 			return ICL_CDCLK_CD2X_PIPE(pipe);
16860a12e437SVille Syrjälä 	} else {
16870a12e437SVille Syrjälä 		if (pipe == INVALID_PIPE)
16880a12e437SVille Syrjälä 			return BXT_CDCLK_CD2X_PIPE_NONE;
16890a12e437SVille Syrjälä 		else
16900a12e437SVille Syrjälä 			return BXT_CDCLK_CD2X_PIPE(pipe);
16910a12e437SVille Syrjälä 	}
16920a12e437SVille Syrjälä }
16930a12e437SVille Syrjälä 
bxt_cdclk_cd2x_div_sel(struct drm_i915_private * dev_priv,int cdclk,int vco)1694b41df85aSVille Syrjälä static u32 bxt_cdclk_cd2x_div_sel(struct drm_i915_private *dev_priv,
1695b41df85aSVille Syrjälä 				  int cdclk, int vco)
1696b41df85aSVille Syrjälä {
1697b41df85aSVille Syrjälä 	/* cdclk = vco / 2 / div{1,1.5,2,4} */
1698b41df85aSVille Syrjälä 	switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
1699b41df85aSVille Syrjälä 	default:
1700b41df85aSVille Syrjälä 		drm_WARN_ON(&dev_priv->drm,
1701d51309b4SJani Nikula 			    cdclk != dev_priv->display.cdclk.hw.bypass);
1702b41df85aSVille Syrjälä 		drm_WARN_ON(&dev_priv->drm, vco != 0);
1703b41df85aSVille Syrjälä 		fallthrough;
1704b41df85aSVille Syrjälä 	case 2:
1705b41df85aSVille Syrjälä 		return BXT_CDCLK_CD2X_DIV_SEL_1;
1706b41df85aSVille Syrjälä 	case 3:
1707b41df85aSVille Syrjälä 		return BXT_CDCLK_CD2X_DIV_SEL_1_5;
1708b41df85aSVille Syrjälä 	case 4:
1709b41df85aSVille Syrjälä 		return BXT_CDCLK_CD2X_DIV_SEL_2;
1710b41df85aSVille Syrjälä 	case 8:
1711b41df85aSVille Syrjälä 		return BXT_CDCLK_CD2X_DIV_SEL_4;
1712b41df85aSVille Syrjälä 	}
1713b41df85aSVille Syrjälä }
1714b41df85aSVille Syrjälä 
cdclk_squash_waveform(struct drm_i915_private * dev_priv,int cdclk)17152060a689SMika Kahola static u32 cdclk_squash_waveform(struct drm_i915_private *dev_priv,
17162060a689SMika Kahola 				 int cdclk)
17172060a689SMika Kahola {
1718d51309b4SJani Nikula 	const struct intel_cdclk_vals *table = dev_priv->display.cdclk.table;
17192060a689SMika Kahola 	int i;
17202060a689SMika Kahola 
1721d51309b4SJani Nikula 	if (cdclk == dev_priv->display.cdclk.hw.bypass)
17222060a689SMika Kahola 		return 0;
17232060a689SMika Kahola 
17242060a689SMika Kahola 	for (i = 0; table[i].refclk; i++)
1725d51309b4SJani Nikula 		if (table[i].refclk == dev_priv->display.cdclk.hw.ref &&
17262060a689SMika Kahola 		    table[i].cdclk == cdclk)
17272060a689SMika Kahola 			return table[i].waveform;
17282060a689SMika Kahola 
17292060a689SMika Kahola 	drm_WARN(&dev_priv->drm, 1, "cdclk %d not valid for refclk %u\n",
1730d51309b4SJani Nikula 		 cdclk, dev_priv->display.cdclk.hw.ref);
17312060a689SMika Kahola 
17322060a689SMika Kahola 	return 0xffff;
17332060a689SMika Kahola }
17342060a689SMika Kahola 
icl_cdclk_pll_update(struct drm_i915_private * i915,int vco)17356688b6b1SAnusha Srivatsa static void icl_cdclk_pll_update(struct drm_i915_private *i915, int vco)
17366688b6b1SAnusha Srivatsa {
17376688b6b1SAnusha Srivatsa 	if (i915->display.cdclk.hw.vco != 0 &&
17386688b6b1SAnusha Srivatsa 	    i915->display.cdclk.hw.vco != vco)
17396688b6b1SAnusha Srivatsa 		icl_cdclk_pll_disable(i915);
17406688b6b1SAnusha Srivatsa 
17416688b6b1SAnusha Srivatsa 	if (i915->display.cdclk.hw.vco != vco)
17426688b6b1SAnusha Srivatsa 		icl_cdclk_pll_enable(i915, vco);
17436688b6b1SAnusha Srivatsa }
17446688b6b1SAnusha Srivatsa 
bxt_cdclk_pll_update(struct drm_i915_private * i915,int vco)17456688b6b1SAnusha Srivatsa static void bxt_cdclk_pll_update(struct drm_i915_private *i915, int vco)
17466688b6b1SAnusha Srivatsa {
17476688b6b1SAnusha Srivatsa 	if (i915->display.cdclk.hw.vco != 0 &&
17486688b6b1SAnusha Srivatsa 	    i915->display.cdclk.hw.vco != vco)
17496688b6b1SAnusha Srivatsa 		bxt_de_pll_disable(i915);
17506688b6b1SAnusha Srivatsa 
17516688b6b1SAnusha Srivatsa 	if (i915->display.cdclk.hw.vco != vco)
17526688b6b1SAnusha Srivatsa 		bxt_de_pll_enable(i915, vco);
17536688b6b1SAnusha Srivatsa }
17546688b6b1SAnusha Srivatsa 
dg2_cdclk_squash_program(struct drm_i915_private * i915,u16 waveform)1755fcfe55f2SAnusha Srivatsa static void dg2_cdclk_squash_program(struct drm_i915_private *i915,
1756fcfe55f2SAnusha Srivatsa 				     u16 waveform)
1757fcfe55f2SAnusha Srivatsa {
1758fcfe55f2SAnusha Srivatsa 	u32 squash_ctl = 0;
1759fcfe55f2SAnusha Srivatsa 
1760fcfe55f2SAnusha Srivatsa 	if (waveform)
1761fcfe55f2SAnusha Srivatsa 		squash_ctl = CDCLK_SQUASH_ENABLE |
1762fcfe55f2SAnusha Srivatsa 			     CDCLK_SQUASH_WINDOW_SIZE(0xf) | waveform;
1763fcfe55f2SAnusha Srivatsa 
1764fcfe55f2SAnusha Srivatsa 	intel_de_write(i915, CDCLK_SQUASH_CTL, squash_ctl);
1765fcfe55f2SAnusha Srivatsa }
1766fcfe55f2SAnusha Srivatsa 
cdclk_pll_is_unknown(unsigned int vco)17679a0a4ec5SAnusha Srivatsa static bool cdclk_pll_is_unknown(unsigned int vco)
17689a0a4ec5SAnusha Srivatsa {
17699a0a4ec5SAnusha Srivatsa 	/*
17709a0a4ec5SAnusha Srivatsa 	 * Ensure driver does not take the crawl path for the
17719a0a4ec5SAnusha Srivatsa 	 * case when the vco is set to ~0 in the
17729a0a4ec5SAnusha Srivatsa 	 * sanitize path.
17739a0a4ec5SAnusha Srivatsa 	 */
17749a0a4ec5SAnusha Srivatsa 	return vco == ~0;
17759a0a4ec5SAnusha Srivatsa }
17769a0a4ec5SAnusha Srivatsa 
cdclk_squash_divider(u16 waveform)177725e0e5aeSVille Syrjälä static int cdclk_squash_divider(u16 waveform)
177825e0e5aeSVille Syrjälä {
177925e0e5aeSVille Syrjälä 	return hweight16(waveform ?: 0xffff);
178025e0e5aeSVille Syrjälä }
178125e0e5aeSVille Syrjälä 
cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private * i915,const struct intel_cdclk_config * old_cdclk_config,const struct intel_cdclk_config * new_cdclk_config,struct intel_cdclk_config * mid_cdclk_config)178225e0e5aeSVille Syrjälä static bool cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private *i915,
178325e0e5aeSVille Syrjälä 						    const struct intel_cdclk_config *old_cdclk_config,
178425e0e5aeSVille Syrjälä 						    const struct intel_cdclk_config *new_cdclk_config,
178525e0e5aeSVille Syrjälä 						    struct intel_cdclk_config *mid_cdclk_config)
178625e0e5aeSVille Syrjälä {
178725e0e5aeSVille Syrjälä 	u16 old_waveform, new_waveform, mid_waveform;
178825e0e5aeSVille Syrjälä 	int size = 16;
178925e0e5aeSVille Syrjälä 	int div = 2;
179025e0e5aeSVille Syrjälä 
179125e0e5aeSVille Syrjälä 	/* Return if PLL is in an unknown state, force a complete disable and re-enable. */
179225e0e5aeSVille Syrjälä 	if (cdclk_pll_is_unknown(old_cdclk_config->vco))
179325e0e5aeSVille Syrjälä 		return false;
179425e0e5aeSVille Syrjälä 
179525e0e5aeSVille Syrjälä 	/* Return if both Squash and Crawl are not present */
179625e0e5aeSVille Syrjälä 	if (!HAS_CDCLK_CRAWL(i915) || !HAS_CDCLK_SQUASH(i915))
179725e0e5aeSVille Syrjälä 		return false;
179825e0e5aeSVille Syrjälä 
179925e0e5aeSVille Syrjälä 	old_waveform = cdclk_squash_waveform(i915, old_cdclk_config->cdclk);
180025e0e5aeSVille Syrjälä 	new_waveform = cdclk_squash_waveform(i915, new_cdclk_config->cdclk);
180125e0e5aeSVille Syrjälä 
180225e0e5aeSVille Syrjälä 	/* Return if Squash only or Crawl only is the desired action */
180325e0e5aeSVille Syrjälä 	if (old_cdclk_config->vco == 0 || new_cdclk_config->vco == 0 ||
180425e0e5aeSVille Syrjälä 	    old_cdclk_config->vco == new_cdclk_config->vco ||
180525e0e5aeSVille Syrjälä 	    old_waveform == new_waveform)
180625e0e5aeSVille Syrjälä 		return false;
180725e0e5aeSVille Syrjälä 
180825e0e5aeSVille Syrjälä 	*mid_cdclk_config = *new_cdclk_config;
180925e0e5aeSVille Syrjälä 
181025e0e5aeSVille Syrjälä 	/*
181125e0e5aeSVille Syrjälä 	 * Populate the mid_cdclk_config accordingly.
181225e0e5aeSVille Syrjälä 	 * - If moving to a higher cdclk, the desired action is squashing.
181325e0e5aeSVille Syrjälä 	 * The mid cdclk config should have the new (squash) waveform.
181425e0e5aeSVille Syrjälä 	 * - If moving to a lower cdclk, the desired action is crawling.
181525e0e5aeSVille Syrjälä 	 * The mid cdclk config should have the new vco.
181625e0e5aeSVille Syrjälä 	 */
181725e0e5aeSVille Syrjälä 
181825e0e5aeSVille Syrjälä 	if (cdclk_squash_divider(new_waveform) > cdclk_squash_divider(old_waveform)) {
181925e0e5aeSVille Syrjälä 		mid_cdclk_config->vco = old_cdclk_config->vco;
182025e0e5aeSVille Syrjälä 		mid_waveform = new_waveform;
182125e0e5aeSVille Syrjälä 	} else {
182225e0e5aeSVille Syrjälä 		mid_cdclk_config->vco = new_cdclk_config->vco;
182325e0e5aeSVille Syrjälä 		mid_waveform = old_waveform;
182425e0e5aeSVille Syrjälä 	}
182525e0e5aeSVille Syrjälä 
182625e0e5aeSVille Syrjälä 	mid_cdclk_config->cdclk = DIV_ROUND_CLOSEST(cdclk_squash_divider(mid_waveform) *
182725e0e5aeSVille Syrjälä 						    mid_cdclk_config->vco, size * div);
182825e0e5aeSVille Syrjälä 
182925e0e5aeSVille Syrjälä 	/* make sure the mid clock came out sane */
183025e0e5aeSVille Syrjälä 
183125e0e5aeSVille Syrjälä 	drm_WARN_ON(&i915->drm, mid_cdclk_config->cdclk <
183225e0e5aeSVille Syrjälä 		    min(old_cdclk_config->cdclk, new_cdclk_config->cdclk));
183325e0e5aeSVille Syrjälä 	drm_WARN_ON(&i915->drm, mid_cdclk_config->cdclk >
183425e0e5aeSVille Syrjälä 		    i915->display.cdclk.max_cdclk_freq);
183525e0e5aeSVille Syrjälä 	drm_WARN_ON(&i915->drm, cdclk_squash_waveform(i915, mid_cdclk_config->cdclk) !=
183625e0e5aeSVille Syrjälä 		    mid_waveform);
183725e0e5aeSVille Syrjälä 
183825e0e5aeSVille Syrjälä 	return true;
183925e0e5aeSVille Syrjälä }
184025e0e5aeSVille Syrjälä 
pll_enable_wa_needed(struct drm_i915_private * dev_priv)184133d0c67dSStanislav Lisovskiy static bool pll_enable_wa_needed(struct drm_i915_private *dev_priv)
184233d0c67dSStanislav Lisovskiy {
184333d0c67dSStanislav Lisovskiy 	return ((IS_DG2(dev_priv) || IS_METEORLAKE(dev_priv)) &&
184433d0c67dSStanislav Lisovskiy 		dev_priv->display.cdclk.hw.vco > 0 &&
184533d0c67dSStanislav Lisovskiy 		HAS_CDCLK_SQUASH(dev_priv));
184633d0c67dSStanislav Lisovskiy }
184733d0c67dSStanislav Lisovskiy 
_bxt_set_cdclk(struct drm_i915_private * dev_priv,const struct intel_cdclk_config * cdclk_config,enum pipe pipe)184825e0e5aeSVille Syrjälä static void _bxt_set_cdclk(struct drm_i915_private *dev_priv,
18490bb94e03SVille Syrjälä 			   const struct intel_cdclk_config *cdclk_config,
1850df0566a6SJani Nikula 			   enum pipe pipe)
1851df0566a6SJani Nikula {
18520bb94e03SVille Syrjälä 	int cdclk = cdclk_config->cdclk;
18530bb94e03SVille Syrjälä 	int vco = cdclk_config->vco;
1854b41df85aSVille Syrjälä 	u32 val;
18552060a689SMika Kahola 	u16 waveform;
18562060a689SMika Kahola 	int clock;
18571cbcd3b4SMatt Roper 
18589a0a4ec5SAnusha Srivatsa 	if (HAS_CDCLK_CRAWL(dev_priv) && dev_priv->display.cdclk.hw.vco > 0 && vco > 0 &&
18599a0a4ec5SAnusha Srivatsa 	    !cdclk_pll_is_unknown(dev_priv->display.cdclk.hw.vco)) {
1860d51309b4SJani Nikula 		if (dev_priv->display.cdclk.hw.vco != vco)
1861d62686baSStanislav Lisovskiy 			adlp_cdclk_pll_crawl(dev_priv, vco);
186233d0c67dSStanislav Lisovskiy 	} else if (DISPLAY_VER(dev_priv) >= 11) {
186333d0c67dSStanislav Lisovskiy 		/* wa_15010685871: dg2, mtl */
186433d0c67dSStanislav Lisovskiy 		if (pll_enable_wa_needed(dev_priv))
186533d0c67dSStanislav Lisovskiy 			dg2_cdclk_squash_program(dev_priv, 0);
186633d0c67dSStanislav Lisovskiy 
18676688b6b1SAnusha Srivatsa 		icl_cdclk_pll_update(dev_priv, vco);
186833d0c67dSStanislav Lisovskiy 	} else
18696688b6b1SAnusha Srivatsa 		bxt_cdclk_pll_update(dev_priv, vco);
1870df0566a6SJani Nikula 
18712060a689SMika Kahola 	waveform = cdclk_squash_waveform(dev_priv, cdclk);
18722060a689SMika Kahola 
18732060a689SMika Kahola 	if (waveform)
18742060a689SMika Kahola 		clock = vco / 2;
18752060a689SMika Kahola 	else
18762060a689SMika Kahola 		clock = cdclk;
18772060a689SMika Kahola 
1878fcfe55f2SAnusha Srivatsa 	if (HAS_CDCLK_SQUASH(dev_priv))
1879fcfe55f2SAnusha Srivatsa 		dg2_cdclk_squash_program(dev_priv, waveform);
18802060a689SMika Kahola 
18812060a689SMika Kahola 	val = bxt_cdclk_cd2x_div_sel(dev_priv, clock, vco) |
1882b41df85aSVille Syrjälä 		bxt_cdclk_cd2x_pipe(dev_priv, pipe) |
1883b41df85aSVille Syrjälä 		skl_cdclk_decimal(cdclk);
18841cbcd3b4SMatt Roper 
1885df0566a6SJani Nikula 	/*
1886df0566a6SJani Nikula 	 * Disable SSA Precharge when CD clock frequency < 500 MHz,
1887df0566a6SJani Nikula 	 * enable otherwise.
1888df0566a6SJani Nikula 	 */
18892446e1d6SMatt Roper 	if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
18902446e1d6SMatt Roper 	    cdclk >= 500000)
1891df0566a6SJani Nikula 		val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
18923e9f55dfSJani Nikula 	intel_de_write(dev_priv, CDCLK_CTL, val);
1893df0566a6SJani Nikula 
1894df0566a6SJani Nikula 	if (pipe != INVALID_PIPE)
1895f35ed346SJani Nikula 		intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(dev_priv, pipe));
189625e0e5aeSVille Syrjälä }
1897df0566a6SJani Nikula 
bxt_set_cdclk(struct drm_i915_private * dev_priv,const struct intel_cdclk_config * cdclk_config,enum pipe pipe)189825e0e5aeSVille Syrjälä static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
189925e0e5aeSVille Syrjälä 			  const struct intel_cdclk_config *cdclk_config,
190025e0e5aeSVille Syrjälä 			  enum pipe pipe)
190125e0e5aeSVille Syrjälä {
190225e0e5aeSVille Syrjälä 	struct intel_cdclk_config mid_cdclk_config;
190325e0e5aeSVille Syrjälä 	int cdclk = cdclk_config->cdclk;
190425e0e5aeSVille Syrjälä 	int ret = 0;
190525e0e5aeSVille Syrjälä 
190625e0e5aeSVille Syrjälä 	/*
190725e0e5aeSVille Syrjälä 	 * Inform power controller of upcoming frequency change.
190825e0e5aeSVille Syrjälä 	 * Display versions 14 and beyond do not follow the PUnit
190925e0e5aeSVille Syrjälä 	 * mailbox communication, skip
191025e0e5aeSVille Syrjälä 	 * this step.
191125e0e5aeSVille Syrjälä 	 */
1912b9279e9bSStanislav Lisovskiy 	if (DISPLAY_VER(dev_priv) >= 14 || IS_DG2(dev_priv))
191325e0e5aeSVille Syrjälä 		/* NOOP */;
1914b9279e9bSStanislav Lisovskiy 	else if (DISPLAY_VER(dev_priv) >= 11)
191525e0e5aeSVille Syrjälä 		ret = skl_pcode_request(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL,
191625e0e5aeSVille Syrjälä 					SKL_CDCLK_PREPARE_FOR_CHANGE,
191725e0e5aeSVille Syrjälä 					SKL_CDCLK_READY_FOR_CHANGE,
191825e0e5aeSVille Syrjälä 					SKL_CDCLK_READY_FOR_CHANGE, 3);
191925e0e5aeSVille Syrjälä 	else
192025e0e5aeSVille Syrjälä 		/*
192125e0e5aeSVille Syrjälä 		 * BSpec requires us to wait up to 150usec, but that leads to
192225e0e5aeSVille Syrjälä 		 * timeouts; the 2ms used here is based on experiment.
192325e0e5aeSVille Syrjälä 		 */
192425e0e5aeSVille Syrjälä 		ret = snb_pcode_write_timeout(&dev_priv->uncore,
192525e0e5aeSVille Syrjälä 					      HSW_PCODE_DE_WRITE_FREQ_REQ,
192625e0e5aeSVille Syrjälä 					      0x80000000, 150, 2);
192725e0e5aeSVille Syrjälä 
192825e0e5aeSVille Syrjälä 	if (ret) {
192925e0e5aeSVille Syrjälä 		drm_err(&dev_priv->drm,
193025e0e5aeSVille Syrjälä 			"Failed to inform PCU about cdclk change (err %d, freq %d)\n",
193125e0e5aeSVille Syrjälä 			ret, cdclk);
193225e0e5aeSVille Syrjälä 		return;
193325e0e5aeSVille Syrjälä 	}
193425e0e5aeSVille Syrjälä 
193525e0e5aeSVille Syrjälä 	if (cdclk_compute_crawl_and_squash_midpoint(dev_priv, &dev_priv->display.cdclk.hw,
193625e0e5aeSVille Syrjälä 						    cdclk_config, &mid_cdclk_config)) {
193725e0e5aeSVille Syrjälä 		_bxt_set_cdclk(dev_priv, &mid_cdclk_config, pipe);
193825e0e5aeSVille Syrjälä 		_bxt_set_cdclk(dev_priv, cdclk_config, pipe);
193925e0e5aeSVille Syrjälä 	} else {
194025e0e5aeSVille Syrjälä 		_bxt_set_cdclk(dev_priv, cdclk_config, pipe);
194125e0e5aeSVille Syrjälä 	}
194225e0e5aeSVille Syrjälä 
194325e0e5aeSVille Syrjälä 	if (DISPLAY_VER(dev_priv) >= 14)
194425e0e5aeSVille Syrjälä 		/*
194525e0e5aeSVille Syrjälä 		 * NOOP - No Pcode communication needed for
194625e0e5aeSVille Syrjälä 		 * Display versions 14 and beyond
194725e0e5aeSVille Syrjälä 		 */;
1948ceb0cc3bSStanislav Lisovskiy 	else if (DISPLAY_VER(dev_priv) >= 11 && !IS_DG2(dev_priv))
1949ee421bb4SAshutosh Dixit 		ret = snb_pcode_write(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL,
19500bb94e03SVille Syrjälä 				      cdclk_config->voltage_level);
1951ceb0cc3bSStanislav Lisovskiy 	if (DISPLAY_VER(dev_priv) < 11) {
1952df0566a6SJani Nikula 		/*
1953df0566a6SJani Nikula 		 * The timeout isn't specified, the 2ms used here is based on
1954df0566a6SJani Nikula 		 * experiment.
19551cbcd3b4SMatt Roper 		 * FIXME: Waiting for the request completion could be delayed
19561cbcd3b4SMatt Roper 		 * until the next PCODE request based on BSpec.
1957df0566a6SJani Nikula 		 */
1958ee421bb4SAshutosh Dixit 		ret = snb_pcode_write_timeout(&dev_priv->uncore,
1959df0566a6SJani Nikula 					      HSW_PCODE_DE_WRITE_FREQ_REQ,
19600bb94e03SVille Syrjälä 					      cdclk_config->voltage_level,
19611cbcd3b4SMatt Roper 					      150, 2);
1962ceb0cc3bSStanislav Lisovskiy 	}
1963df0566a6SJani Nikula 	if (ret) {
196423194610SWambui Karuga 		drm_err(&dev_priv->drm,
196523194610SWambui Karuga 			"PCode CDCLK freq set failed, (err %d, freq %d)\n",
1966df0566a6SJani Nikula 			ret, cdclk);
1967df0566a6SJani Nikula 		return;
1968df0566a6SJani Nikula 	}
1969df0566a6SJani Nikula 
1970df0566a6SJani Nikula 	intel_update_cdclk(dev_priv);
19711cbcd3b4SMatt Roper 
19721d89509aSLucas De Marchi 	if (DISPLAY_VER(dev_priv) >= 11)
19731cbcd3b4SMatt Roper 		/*
19741cbcd3b4SMatt Roper 		 * Can't read out the voltage level :(
19751cbcd3b4SMatt Roper 		 * Let's just assume everything is as expected.
19761cbcd3b4SMatt Roper 		 */
1977d51309b4SJani Nikula 		dev_priv->display.cdclk.hw.voltage_level = cdclk_config->voltage_level;
1978df0566a6SJani Nikula }
1979df0566a6SJani Nikula 
bxt_sanitize_cdclk(struct drm_i915_private * dev_priv)1980df0566a6SJani Nikula static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
1981df0566a6SJani Nikula {
1982df0566a6SJani Nikula 	u32 cdctl, expected;
1983ba884a41SMika Kahola 	int cdclk, clock, vco;
1984df0566a6SJani Nikula 
1985df0566a6SJani Nikula 	intel_update_cdclk(dev_priv);
1986d51309b4SJani Nikula 	intel_cdclk_dump_config(dev_priv, &dev_priv->display.cdclk.hw, "Current CDCLK");
1987df0566a6SJani Nikula 
1988d51309b4SJani Nikula 	if (dev_priv->display.cdclk.hw.vco == 0 ||
1989d51309b4SJani Nikula 	    dev_priv->display.cdclk.hw.cdclk == dev_priv->display.cdclk.hw.bypass)
1990df0566a6SJani Nikula 		goto sanitize;
1991df0566a6SJani Nikula 
1992df0566a6SJani Nikula 	/* DPLL okay; verify the cdclock
1993df0566a6SJani Nikula 	 *
1994df0566a6SJani Nikula 	 * Some BIOS versions leave an incorrect decimal frequency value and
1995df0566a6SJani Nikula 	 * set reserved MBZ bits in CDCLK_CTL at least during exiting from S4,
1996df0566a6SJani Nikula 	 * so sanitize this register.
1997df0566a6SJani Nikula 	 */
19983e9f55dfSJani Nikula 	cdctl = intel_de_read(dev_priv, CDCLK_CTL);
1999df0566a6SJani Nikula 	/*
2000df0566a6SJani Nikula 	 * Let's ignore the pipe field, since BIOS could have configured the
2001df0566a6SJani Nikula 	 * dividers both synching to an active pipe, or asynchronously
2002df0566a6SJani Nikula 	 * (PIPE_NONE).
2003df0566a6SJani Nikula 	 */
20040a12e437SVille Syrjälä 	cdctl &= ~bxt_cdclk_cd2x_pipe(dev_priv, INVALID_PIPE);
2005df0566a6SJani Nikula 
20068f9f717dSMatt Roper 	/* Make sure this is a legal cdclk value for the platform */
2007d51309b4SJani Nikula 	cdclk = bxt_calc_cdclk(dev_priv, dev_priv->display.cdclk.hw.cdclk);
2008d51309b4SJani Nikula 	if (cdclk != dev_priv->display.cdclk.hw.cdclk)
20098f9f717dSMatt Roper 		goto sanitize;
20108f9f717dSMatt Roper 
20118f9f717dSMatt Roper 	/* Make sure the VCO is correct for the cdclk */
20128f9f717dSMatt Roper 	vco = bxt_calc_cdclk_pll_vco(dev_priv, cdclk);
2013d51309b4SJani Nikula 	if (vco != dev_priv->display.cdclk.hw.vco)
20148f9f717dSMatt Roper 		goto sanitize;
20158f9f717dSMatt Roper 
20168f9f717dSMatt Roper 	expected = skl_cdclk_decimal(cdclk);
20178f9f717dSMatt Roper 
20188f9f717dSMatt Roper 	/* Figure out what CD2X divider we should be using for this cdclk */
20191d32f5d6SAnusha Srivatsa 	if (HAS_CDCLK_SQUASH(dev_priv))
2020d51309b4SJani Nikula 		clock = dev_priv->display.cdclk.hw.vco / 2;
2021ba884a41SMika Kahola 	else
2022d51309b4SJani Nikula 		clock = dev_priv->display.cdclk.hw.cdclk;
2023ba884a41SMika Kahola 
2024ba884a41SMika Kahola 	expected |= bxt_cdclk_cd2x_div_sel(dev_priv, clock,
2025d51309b4SJani Nikula 					   dev_priv->display.cdclk.hw.vco);
20268f9f717dSMatt Roper 
2027df0566a6SJani Nikula 	/*
2028df0566a6SJani Nikula 	 * Disable SSA Precharge when CD clock frequency < 500 MHz,
2029df0566a6SJani Nikula 	 * enable otherwise.
2030df0566a6SJani Nikula 	 */
20312446e1d6SMatt Roper 	if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
2032d51309b4SJani Nikula 	    dev_priv->display.cdclk.hw.cdclk >= 500000)
2033df0566a6SJani Nikula 		expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
2034df0566a6SJani Nikula 
2035df0566a6SJani Nikula 	if (cdctl == expected)
2036df0566a6SJani Nikula 		/* All well; nothing to sanitize */
2037df0566a6SJani Nikula 		return;
2038df0566a6SJani Nikula 
2039df0566a6SJani Nikula sanitize:
204023194610SWambui Karuga 	drm_dbg_kms(&dev_priv->drm, "Sanitizing cdclk programmed by pre-os\n");
2041df0566a6SJani Nikula 
2042df0566a6SJani Nikula 	/* force cdclk programming */
2043d51309b4SJani Nikula 	dev_priv->display.cdclk.hw.cdclk = 0;
2044df0566a6SJani Nikula 
2045df0566a6SJani Nikula 	/* force full PLL disable + enable */
2046d51309b4SJani Nikula 	dev_priv->display.cdclk.hw.vco = -1;
2047df0566a6SJani Nikula }
2048df0566a6SJani Nikula 
bxt_cdclk_init_hw(struct drm_i915_private * dev_priv)2049ed645eeeSVille Syrjälä static void bxt_cdclk_init_hw(struct drm_i915_private *dev_priv)
2050df0566a6SJani Nikula {
20510bb94e03SVille Syrjälä 	struct intel_cdclk_config cdclk_config;
2052df0566a6SJani Nikula 
2053df0566a6SJani Nikula 	bxt_sanitize_cdclk(dev_priv);
2054df0566a6SJani Nikula 
2055d51309b4SJani Nikula 	if (dev_priv->display.cdclk.hw.cdclk != 0 &&
2056d51309b4SJani Nikula 	    dev_priv->display.cdclk.hw.vco != 0)
2057df0566a6SJani Nikula 		return;
2058df0566a6SJani Nikula 
2059d51309b4SJani Nikula 	cdclk_config = dev_priv->display.cdclk.hw;
2060df0566a6SJani Nikula 
2061df0566a6SJani Nikula 	/*
2062df0566a6SJani Nikula 	 * FIXME:
2063df0566a6SJani Nikula 	 * - The initial CDCLK needs to be read from VBT.
2064df0566a6SJani Nikula 	 *   Need to make this change after VBT has changes for BXT.
2065df0566a6SJani Nikula 	 */
20660bb94e03SVille Syrjälä 	cdclk_config.cdclk = bxt_calc_cdclk(dev_priv, 0);
20670bb94e03SVille Syrjälä 	cdclk_config.vco = bxt_calc_cdclk_pll_vco(dev_priv, cdclk_config.cdclk);
20680bb94e03SVille Syrjälä 	cdclk_config.voltage_level =
206944892ffaSDave Airlie 		intel_cdclk_calc_voltage_level(dev_priv, cdclk_config.cdclk);
2070df0566a6SJani Nikula 
20710bb94e03SVille Syrjälä 	bxt_set_cdclk(dev_priv, &cdclk_config, INVALID_PIPE);
2072df0566a6SJani Nikula }
2073df0566a6SJani Nikula 
bxt_cdclk_uninit_hw(struct drm_i915_private * dev_priv)2074ed645eeeSVille Syrjälä static void bxt_cdclk_uninit_hw(struct drm_i915_private *dev_priv)
2075df0566a6SJani Nikula {
2076d51309b4SJani Nikula 	struct intel_cdclk_config cdclk_config = dev_priv->display.cdclk.hw;
2077df0566a6SJani Nikula 
20780bb94e03SVille Syrjälä 	cdclk_config.cdclk = cdclk_config.bypass;
20790bb94e03SVille Syrjälä 	cdclk_config.vco = 0;
20800bb94e03SVille Syrjälä 	cdclk_config.voltage_level =
208144892ffaSDave Airlie 		intel_cdclk_calc_voltage_level(dev_priv, cdclk_config.cdclk);
2082df0566a6SJani Nikula 
20830bb94e03SVille Syrjälä 	bxt_set_cdclk(dev_priv, &cdclk_config, INVALID_PIPE);
2084df0566a6SJani Nikula }
2085df0566a6SJani Nikula 
2086df0566a6SJani Nikula /**
2087ed645eeeSVille Syrjälä  * intel_cdclk_init_hw - Initialize CDCLK hardware
2088df0566a6SJani Nikula  * @i915: i915 device
2089df0566a6SJani Nikula  *
2090d51309b4SJani Nikula  * Initialize CDCLK. This consists mainly of initializing dev_priv->display.cdclk.hw and
2091df0566a6SJani Nikula  * sanitizing the state of the hardware if needed. This is generally done only
2092df0566a6SJani Nikula  * during the display core initialization sequence, after which the DMC will
2093df0566a6SJani Nikula  * take care of turning CDCLK off/on as needed.
2094df0566a6SJani Nikula  */
intel_cdclk_init_hw(struct drm_i915_private * i915)2095ed645eeeSVille Syrjälä void intel_cdclk_init_hw(struct drm_i915_private *i915)
2096df0566a6SJani Nikula {
20972446e1d6SMatt Roper 	if (DISPLAY_VER(i915) >= 10 || IS_BROXTON(i915))
2098ed645eeeSVille Syrjälä 		bxt_cdclk_init_hw(i915);
209993e7e61eSLucas De Marchi 	else if (DISPLAY_VER(i915) == 9)
2100ed645eeeSVille Syrjälä 		skl_cdclk_init_hw(i915);
2101df0566a6SJani Nikula }
2102df0566a6SJani Nikula 
2103df0566a6SJani Nikula /**
2104ed645eeeSVille Syrjälä  * intel_cdclk_uninit_hw - Uninitialize CDCLK hardware
2105df0566a6SJani Nikula  * @i915: i915 device
2106df0566a6SJani Nikula  *
2107df0566a6SJani Nikula  * Uninitialize CDCLK. This is done only during the display core
2108df0566a6SJani Nikula  * uninitialization sequence.
2109df0566a6SJani Nikula  */
intel_cdclk_uninit_hw(struct drm_i915_private * i915)2110ed645eeeSVille Syrjälä void intel_cdclk_uninit_hw(struct drm_i915_private *i915)
2111df0566a6SJani Nikula {
21122446e1d6SMatt Roper 	if (DISPLAY_VER(i915) >= 10 || IS_BROXTON(i915))
2113ed645eeeSVille Syrjälä 		bxt_cdclk_uninit_hw(i915);
211493e7e61eSLucas De Marchi 	else if (DISPLAY_VER(i915) == 9)
2115ed645eeeSVille Syrjälä 		skl_cdclk_uninit_hw(i915);
2116df0566a6SJani Nikula }
2117df0566a6SJani Nikula 
intel_cdclk_can_crawl_and_squash(struct drm_i915_private * i915,const struct intel_cdclk_config * a,const struct intel_cdclk_config * b)211825e0e5aeSVille Syrjälä static bool intel_cdclk_can_crawl_and_squash(struct drm_i915_private *i915,
211925e0e5aeSVille Syrjälä 					     const struct intel_cdclk_config *a,
212025e0e5aeSVille Syrjälä 					     const struct intel_cdclk_config *b)
212125e0e5aeSVille Syrjälä {
212225e0e5aeSVille Syrjälä 	u16 old_waveform;
212325e0e5aeSVille Syrjälä 	u16 new_waveform;
212425e0e5aeSVille Syrjälä 
212525e0e5aeSVille Syrjälä 	drm_WARN_ON(&i915->drm, cdclk_pll_is_unknown(a->vco));
212625e0e5aeSVille Syrjälä 
212725e0e5aeSVille Syrjälä 	if (a->vco == 0 || b->vco == 0)
212825e0e5aeSVille Syrjälä 		return false;
212925e0e5aeSVille Syrjälä 
213025e0e5aeSVille Syrjälä 	if (!HAS_CDCLK_CRAWL(i915) || !HAS_CDCLK_SQUASH(i915))
213125e0e5aeSVille Syrjälä 		return false;
213225e0e5aeSVille Syrjälä 
213325e0e5aeSVille Syrjälä 	old_waveform = cdclk_squash_waveform(i915, a->cdclk);
213425e0e5aeSVille Syrjälä 	new_waveform = cdclk_squash_waveform(i915, b->cdclk);
213525e0e5aeSVille Syrjälä 
213625e0e5aeSVille Syrjälä 	return a->vco != b->vco &&
213725e0e5aeSVille Syrjälä 	       old_waveform != new_waveform;
213825e0e5aeSVille Syrjälä }
213925e0e5aeSVille Syrjälä 
intel_cdclk_can_crawl(struct drm_i915_private * dev_priv,const struct intel_cdclk_config * a,const struct intel_cdclk_config * b)2140d62686baSStanislav Lisovskiy static bool intel_cdclk_can_crawl(struct drm_i915_private *dev_priv,
2141d62686baSStanislav Lisovskiy 				  const struct intel_cdclk_config *a,
2142d62686baSStanislav Lisovskiy 				  const struct intel_cdclk_config *b)
2143d62686baSStanislav Lisovskiy {
2144d62686baSStanislav Lisovskiy 	int a_div, b_div;
2145d62686baSStanislav Lisovskiy 
2146eafaa3e9SMatt Roper 	if (!HAS_CDCLK_CRAWL(dev_priv))
2147d62686baSStanislav Lisovskiy 		return false;
2148d62686baSStanislav Lisovskiy 
2149d62686baSStanislav Lisovskiy 	/*
2150d62686baSStanislav Lisovskiy 	 * The vco and cd2x divider will change independently
2151d62686baSStanislav Lisovskiy 	 * from each, so we disallow cd2x change when crawling.
2152d62686baSStanislav Lisovskiy 	 */
2153d62686baSStanislav Lisovskiy 	a_div = DIV_ROUND_CLOSEST(a->vco, a->cdclk);
2154d62686baSStanislav Lisovskiy 	b_div = DIV_ROUND_CLOSEST(b->vco, b->cdclk);
2155d62686baSStanislav Lisovskiy 
2156d62686baSStanislav Lisovskiy 	return a->vco != 0 && b->vco != 0 &&
2157d62686baSStanislav Lisovskiy 		a->vco != b->vco &&
2158d62686baSStanislav Lisovskiy 		a_div == b_div &&
2159d62686baSStanislav Lisovskiy 		a->ref == b->ref;
2160d62686baSStanislav Lisovskiy }
2161d62686baSStanislav Lisovskiy 
intel_cdclk_can_squash(struct drm_i915_private * dev_priv,const struct intel_cdclk_config * a,const struct intel_cdclk_config * b)2162d4a23930SVille Syrjälä static bool intel_cdclk_can_squash(struct drm_i915_private *dev_priv,
2163d4a23930SVille Syrjälä 				   const struct intel_cdclk_config *a,
2164d4a23930SVille Syrjälä 				   const struct intel_cdclk_config *b)
2165d4a23930SVille Syrjälä {
2166d4a23930SVille Syrjälä 	/*
2167d4a23930SVille Syrjälä 	 * FIXME should store a bit more state in intel_cdclk_config
2168d4a23930SVille Syrjälä 	 * to differentiate squasher vs. cd2x divider properly. For
2169d4a23930SVille Syrjälä 	 * the moment all platforms with squasher use a fixed cd2x
2170d4a23930SVille Syrjälä 	 * divider.
2171d4a23930SVille Syrjälä 	 */
21721d32f5d6SAnusha Srivatsa 	if (!HAS_CDCLK_SQUASH(dev_priv))
2173d4a23930SVille Syrjälä 		return false;
2174d4a23930SVille Syrjälä 
2175d4a23930SVille Syrjälä 	return a->cdclk != b->cdclk &&
2176d4a23930SVille Syrjälä 		a->vco != 0 &&
2177d4a23930SVille Syrjälä 		a->vco == b->vco &&
2178d4a23930SVille Syrjälä 		a->ref == b->ref;
2179d4a23930SVille Syrjälä }
2180d4a23930SVille Syrjälä 
2181df0566a6SJani Nikula /**
21820bb94e03SVille Syrjälä  * intel_cdclk_needs_modeset - Determine if changong between the CDCLK
21830bb94e03SVille Syrjälä  *                             configurations requires a modeset on all pipes
21840bb94e03SVille Syrjälä  * @a: first CDCLK configuration
21850bb94e03SVille Syrjälä  * @b: second CDCLK configuration
2186df0566a6SJani Nikula  *
2187df0566a6SJani Nikula  * Returns:
21880bb94e03SVille Syrjälä  * True if changing between the two CDCLK configurations
21890bb94e03SVille Syrjälä  * requires all pipes to be off, false if not.
2190df0566a6SJani Nikula  */
intel_cdclk_needs_modeset(const struct intel_cdclk_config * a,const struct intel_cdclk_config * b)21910bb94e03SVille Syrjälä bool intel_cdclk_needs_modeset(const struct intel_cdclk_config *a,
21920bb94e03SVille Syrjälä 			       const struct intel_cdclk_config *b)
2193df0566a6SJani Nikula {
2194df0566a6SJani Nikula 	return a->cdclk != b->cdclk ||
2195df0566a6SJani Nikula 		a->vco != b->vco ||
2196df0566a6SJani Nikula 		a->ref != b->ref;
2197df0566a6SJani Nikula }
2198df0566a6SJani Nikula 
2199df0566a6SJani Nikula /**
22000bb94e03SVille Syrjälä  * intel_cdclk_can_cd2x_update - Determine if changing between the two CDCLK
22010bb94e03SVille Syrjälä  *                               configurations requires only a cd2x divider update
22020bb94e03SVille Syrjälä  * @dev_priv: i915 device
22030bb94e03SVille Syrjälä  * @a: first CDCLK configuration
22040bb94e03SVille Syrjälä  * @b: second CDCLK configuration
2205df0566a6SJani Nikula  *
2206df0566a6SJani Nikula  * Returns:
22070bb94e03SVille Syrjälä  * True if changing between the two CDCLK configurations
22080bb94e03SVille Syrjälä  * can be done with just a cd2x divider update, false if not.
2209df0566a6SJani Nikula  */
intel_cdclk_can_cd2x_update(struct drm_i915_private * dev_priv,const struct intel_cdclk_config * a,const struct intel_cdclk_config * b)221065c88a86SVille Syrjälä static bool intel_cdclk_can_cd2x_update(struct drm_i915_private *dev_priv,
22110bb94e03SVille Syrjälä 					const struct intel_cdclk_config *a,
22120bb94e03SVille Syrjälä 					const struct intel_cdclk_config *b)
2213df0566a6SJani Nikula {
2214df0566a6SJani Nikula 	/* Older hw doesn't have the capability */
22152446e1d6SMatt Roper 	if (DISPLAY_VER(dev_priv) < 10 && !IS_BROXTON(dev_priv))
2216df0566a6SJani Nikula 		return false;
2217df0566a6SJani Nikula 
2218d4a23930SVille Syrjälä 	/*
2219d4a23930SVille Syrjälä 	 * FIXME should store a bit more state in intel_cdclk_config
2220d4a23930SVille Syrjälä 	 * to differentiate squasher vs. cd2x divider properly. For
2221d4a23930SVille Syrjälä 	 * the moment all platforms with squasher use a fixed cd2x
2222d4a23930SVille Syrjälä 	 * divider.
2223d4a23930SVille Syrjälä 	 */
22241d32f5d6SAnusha Srivatsa 	if (HAS_CDCLK_SQUASH(dev_priv))
2225d4a23930SVille Syrjälä 		return false;
2226d4a23930SVille Syrjälä 
2227df0566a6SJani Nikula 	return a->cdclk != b->cdclk &&
2228d4a23930SVille Syrjälä 		a->vco != 0 &&
2229df0566a6SJani Nikula 		a->vco == b->vco &&
2230df0566a6SJani Nikula 		a->ref == b->ref;
2231df0566a6SJani Nikula }
2232df0566a6SJani Nikula 
2233df0566a6SJani Nikula /**
22340bb94e03SVille Syrjälä  * intel_cdclk_changed - Determine if two CDCLK configurations are different
22350bb94e03SVille Syrjälä  * @a: first CDCLK configuration
22360bb94e03SVille Syrjälä  * @b: second CDCLK configuration
2237df0566a6SJani Nikula  *
2238df0566a6SJani Nikula  * Returns:
22390bb94e03SVille Syrjälä  * True if the CDCLK configurations don't match, false if they do.
2240df0566a6SJani Nikula  */
intel_cdclk_changed(const struct intel_cdclk_config * a,const struct intel_cdclk_config * b)22410bb94e03SVille Syrjälä static bool intel_cdclk_changed(const struct intel_cdclk_config *a,
22420bb94e03SVille Syrjälä 				const struct intel_cdclk_config *b)
2243df0566a6SJani Nikula {
2244df0566a6SJani Nikula 	return intel_cdclk_needs_modeset(a, b) ||
2245df0566a6SJani Nikula 		a->voltage_level != b->voltage_level;
2246df0566a6SJani Nikula }
2247df0566a6SJani Nikula 
intel_cdclk_dump_config(struct drm_i915_private * i915,const struct intel_cdclk_config * cdclk_config,const char * context)2248140f70aeSJani Nikula void intel_cdclk_dump_config(struct drm_i915_private *i915,
2249140f70aeSJani Nikula 			     const struct intel_cdclk_config *cdclk_config,
2250df0566a6SJani Nikula 			     const char *context)
2251df0566a6SJani Nikula {
2252140f70aeSJani Nikula 	drm_dbg_kms(&i915->drm, "%s %d kHz, VCO %d kHz, ref %d kHz, bypass %d kHz, voltage level %d\n",
22530bb94e03SVille Syrjälä 		    context, cdclk_config->cdclk, cdclk_config->vco,
22540bb94e03SVille Syrjälä 		    cdclk_config->ref, cdclk_config->bypass,
22550bb94e03SVille Syrjälä 		    cdclk_config->voltage_level);
2256df0566a6SJani Nikula }
2257df0566a6SJani Nikula 
intel_pcode_notify(struct drm_i915_private * i915,u8 voltage_level,u8 active_pipe_count,u16 cdclk,bool cdclk_update_valid,bool pipe_count_update_valid)2258ceb0cc3bSStanislav Lisovskiy static void intel_pcode_notify(struct drm_i915_private *i915,
2259ceb0cc3bSStanislav Lisovskiy 			       u8 voltage_level,
2260ceb0cc3bSStanislav Lisovskiy 			       u8 active_pipe_count,
2261ceb0cc3bSStanislav Lisovskiy 			       u16 cdclk,
2262ceb0cc3bSStanislav Lisovskiy 			       bool cdclk_update_valid,
2263ceb0cc3bSStanislav Lisovskiy 			       bool pipe_count_update_valid)
2264ceb0cc3bSStanislav Lisovskiy {
2265ceb0cc3bSStanislav Lisovskiy 	int ret;
2266ceb0cc3bSStanislav Lisovskiy 	u32 update_mask = 0;
2267ceb0cc3bSStanislav Lisovskiy 
2268ceb0cc3bSStanislav Lisovskiy 	if (!IS_DG2(i915))
2269ceb0cc3bSStanislav Lisovskiy 		return;
2270ceb0cc3bSStanislav Lisovskiy 
2271ceb0cc3bSStanislav Lisovskiy 	update_mask = DISPLAY_TO_PCODE_UPDATE_MASK(cdclk, active_pipe_count, voltage_level);
2272ceb0cc3bSStanislav Lisovskiy 
2273ceb0cc3bSStanislav Lisovskiy 	if (cdclk_update_valid)
2274ceb0cc3bSStanislav Lisovskiy 		update_mask |= DISPLAY_TO_PCODE_CDCLK_VALID;
2275ceb0cc3bSStanislav Lisovskiy 
2276ceb0cc3bSStanislav Lisovskiy 	if (pipe_count_update_valid)
2277ceb0cc3bSStanislav Lisovskiy 		update_mask |= DISPLAY_TO_PCODE_PIPE_COUNT_VALID;
2278ceb0cc3bSStanislav Lisovskiy 
2279ceb0cc3bSStanislav Lisovskiy 	ret = skl_pcode_request(&i915->uncore, SKL_PCODE_CDCLK_CONTROL,
2280ceb0cc3bSStanislav Lisovskiy 				SKL_CDCLK_PREPARE_FOR_CHANGE |
2281ceb0cc3bSStanislav Lisovskiy 				update_mask,
2282ceb0cc3bSStanislav Lisovskiy 				SKL_CDCLK_READY_FOR_CHANGE,
2283ceb0cc3bSStanislav Lisovskiy 				SKL_CDCLK_READY_FOR_CHANGE, 3);
2284ceb0cc3bSStanislav Lisovskiy 	if (ret)
2285ceb0cc3bSStanislav Lisovskiy 		drm_err(&i915->drm,
2286ceb0cc3bSStanislav Lisovskiy 			"Failed to inform PCU about display config (err %d)\n",
2287ceb0cc3bSStanislav Lisovskiy 			ret);
2288ceb0cc3bSStanislav Lisovskiy }
2289ceb0cc3bSStanislav Lisovskiy 
2290df0566a6SJani Nikula /**
22910bb94e03SVille Syrjälä  * intel_set_cdclk - Push the CDCLK configuration to the hardware
2292df0566a6SJani Nikula  * @dev_priv: i915 device
22930bb94e03SVille Syrjälä  * @cdclk_config: new CDCLK configuration
2294df0566a6SJani Nikula  * @pipe: pipe with which to synchronize the update
2295df0566a6SJani Nikula  *
2296df0566a6SJani Nikula  * Program the hardware based on the passed in CDCLK state,
2297df0566a6SJani Nikula  * if necessary.
2298df0566a6SJani Nikula  */
intel_set_cdclk(struct drm_i915_private * dev_priv,const struct intel_cdclk_config * cdclk_config,enum pipe pipe)2299df0566a6SJani Nikula static void intel_set_cdclk(struct drm_i915_private *dev_priv,
23000bb94e03SVille Syrjälä 			    const struct intel_cdclk_config *cdclk_config,
2301df0566a6SJani Nikula 			    enum pipe pipe)
2302df0566a6SJani Nikula {
2303bb9ca240SVille Syrjälä 	struct intel_encoder *encoder;
2304bb9ca240SVille Syrjälä 
2305d51309b4SJani Nikula 	if (!intel_cdclk_changed(&dev_priv->display.cdclk.hw, cdclk_config))
2306df0566a6SJani Nikula 		return;
2307df0566a6SJani Nikula 
2308986531bdSJani Nikula 	if (drm_WARN_ON_ONCE(&dev_priv->drm, !dev_priv->display.funcs.cdclk->set_cdclk))
2309df0566a6SJani Nikula 		return;
2310df0566a6SJani Nikula 
2311140f70aeSJani Nikula 	intel_cdclk_dump_config(dev_priv, cdclk_config, "Changing CDCLK to");
2312df0566a6SJani Nikula 
231317c1a4b7SVille Syrjälä 	for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) {
231417c1a4b7SVille Syrjälä 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
231517c1a4b7SVille Syrjälä 
231617c1a4b7SVille Syrjälä 		intel_psr_pause(intel_dp);
231717c1a4b7SVille Syrjälä 	}
231817c1a4b7SVille Syrjälä 
2319112a87c4SKai Vehmanen 	intel_audio_cdclk_change_pre(dev_priv);
2320112a87c4SKai Vehmanen 
2321bb9ca240SVille Syrjälä 	/*
2322bb9ca240SVille Syrjälä 	 * Lock aux/gmbus while we change cdclk in case those
2323bb9ca240SVille Syrjälä 	 * functions use cdclk. Not all platforms/ports do,
2324bb9ca240SVille Syrjälä 	 * but we'll lock them all for simplicity.
2325bb9ca240SVille Syrjälä 	 */
2326203eb5a9SJani Nikula 	mutex_lock(&dev_priv->display.gmbus.mutex);
2327bb9ca240SVille Syrjälä 	for_each_intel_dp(&dev_priv->drm, encoder) {
2328bb9ca240SVille Syrjälä 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
2329bb9ca240SVille Syrjälä 
2330bb9ca240SVille Syrjälä 		mutex_lock_nest_lock(&intel_dp->aux.hw_mutex,
2331203eb5a9SJani Nikula 				     &dev_priv->display.gmbus.mutex);
2332bb9ca240SVille Syrjälä 	}
2333bb9ca240SVille Syrjälä 
233444892ffaSDave Airlie 	intel_cdclk_set_cdclk(dev_priv, cdclk_config, pipe);
2335df0566a6SJani Nikula 
2336bb9ca240SVille Syrjälä 	for_each_intel_dp(&dev_priv->drm, encoder) {
2337bb9ca240SVille Syrjälä 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
2338bb9ca240SVille Syrjälä 
2339bb9ca240SVille Syrjälä 		mutex_unlock(&intel_dp->aux.hw_mutex);
2340bb9ca240SVille Syrjälä 	}
2341203eb5a9SJani Nikula 	mutex_unlock(&dev_priv->display.gmbus.mutex);
2342bb9ca240SVille Syrjälä 
234317c1a4b7SVille Syrjälä 	for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) {
234417c1a4b7SVille Syrjälä 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
234517c1a4b7SVille Syrjälä 
234617c1a4b7SVille Syrjälä 		intel_psr_resume(intel_dp);
234717c1a4b7SVille Syrjälä 	}
234817c1a4b7SVille Syrjälä 
2349112a87c4SKai Vehmanen 	intel_audio_cdclk_change_post(dev_priv);
2350112a87c4SKai Vehmanen 
2351aff35110SPankaj Bharadiya 	if (drm_WARN(&dev_priv->drm,
2352d51309b4SJani Nikula 		     intel_cdclk_changed(&dev_priv->display.cdclk.hw, cdclk_config),
2353df0566a6SJani Nikula 		     "cdclk state doesn't match!\n")) {
2354d51309b4SJani Nikula 		intel_cdclk_dump_config(dev_priv, &dev_priv->display.cdclk.hw, "[hw state]");
2355140f70aeSJani Nikula 		intel_cdclk_dump_config(dev_priv, cdclk_config, "[sw state]");
2356df0566a6SJani Nikula 	}
2357df0566a6SJani Nikula }
2358df0566a6SJani Nikula 
intel_cdclk_pcode_pre_notify(struct intel_atomic_state * state)2359ceb0cc3bSStanislav Lisovskiy static void intel_cdclk_pcode_pre_notify(struct intel_atomic_state *state)
2360ceb0cc3bSStanislav Lisovskiy {
2361ceb0cc3bSStanislav Lisovskiy 	struct drm_i915_private *i915 = to_i915(state->base.dev);
2362ceb0cc3bSStanislav Lisovskiy 	const struct intel_cdclk_state *old_cdclk_state =
2363ceb0cc3bSStanislav Lisovskiy 		intel_atomic_get_old_cdclk_state(state);
2364ceb0cc3bSStanislav Lisovskiy 	const struct intel_cdclk_state *new_cdclk_state =
2365ceb0cc3bSStanislav Lisovskiy 		intel_atomic_get_new_cdclk_state(state);
2366ceb0cc3bSStanislav Lisovskiy 	unsigned int cdclk = 0; u8 voltage_level, num_active_pipes = 0;
2367ceb0cc3bSStanislav Lisovskiy 	bool change_cdclk, update_pipe_count;
2368ceb0cc3bSStanislav Lisovskiy 
2369ceb0cc3bSStanislav Lisovskiy 	if (!intel_cdclk_changed(&old_cdclk_state->actual,
2370ceb0cc3bSStanislav Lisovskiy 				 &new_cdclk_state->actual) &&
2371ceb0cc3bSStanislav Lisovskiy 				 new_cdclk_state->active_pipes ==
2372ceb0cc3bSStanislav Lisovskiy 				 old_cdclk_state->active_pipes)
2373ceb0cc3bSStanislav Lisovskiy 		return;
2374ceb0cc3bSStanislav Lisovskiy 
2375ceb0cc3bSStanislav Lisovskiy 	/* According to "Sequence Before Frequency Change", voltage level set to 0x3 */
2376ceb0cc3bSStanislav Lisovskiy 	voltage_level = DISPLAY_TO_PCODE_VOLTAGE_MAX;
2377ceb0cc3bSStanislav Lisovskiy 
2378ceb0cc3bSStanislav Lisovskiy 	change_cdclk = new_cdclk_state->actual.cdclk != old_cdclk_state->actual.cdclk;
2379ceb0cc3bSStanislav Lisovskiy 	update_pipe_count = hweight8(new_cdclk_state->active_pipes) >
2380ceb0cc3bSStanislav Lisovskiy 			    hweight8(old_cdclk_state->active_pipes);
2381ceb0cc3bSStanislav Lisovskiy 
2382ceb0cc3bSStanislav Lisovskiy 	/*
2383ceb0cc3bSStanislav Lisovskiy 	 * According to "Sequence Before Frequency Change",
2384ceb0cc3bSStanislav Lisovskiy 	 * if CDCLK is increasing, set bits 25:16 to upcoming CDCLK,
2385ceb0cc3bSStanislav Lisovskiy 	 * if CDCLK is decreasing or not changing, set bits 25:16 to current CDCLK,
2386ceb0cc3bSStanislav Lisovskiy 	 * which basically means we choose the maximum of old and new CDCLK, if we know both
2387ceb0cc3bSStanislav Lisovskiy 	 */
2388ceb0cc3bSStanislav Lisovskiy 	if (change_cdclk)
2389ceb0cc3bSStanislav Lisovskiy 		cdclk = max(new_cdclk_state->actual.cdclk, old_cdclk_state->actual.cdclk);
2390ceb0cc3bSStanislav Lisovskiy 
2391ceb0cc3bSStanislav Lisovskiy 	/*
2392ceb0cc3bSStanislav Lisovskiy 	 * According to "Sequence For Pipe Count Change",
2393ceb0cc3bSStanislav Lisovskiy 	 * if pipe count is increasing, set bits 25:16 to upcoming pipe count
2394ceb0cc3bSStanislav Lisovskiy 	 * (power well is enabled)
2395ceb0cc3bSStanislav Lisovskiy 	 * no action if it is decreasing, before the change
2396ceb0cc3bSStanislav Lisovskiy 	 */
2397ceb0cc3bSStanislav Lisovskiy 	if (update_pipe_count)
2398ceb0cc3bSStanislav Lisovskiy 		num_active_pipes = hweight8(new_cdclk_state->active_pipes);
2399ceb0cc3bSStanislav Lisovskiy 
2400ceb0cc3bSStanislav Lisovskiy 	intel_pcode_notify(i915, voltage_level, num_active_pipes, cdclk,
2401ceb0cc3bSStanislav Lisovskiy 			   change_cdclk, update_pipe_count);
2402ceb0cc3bSStanislav Lisovskiy }
2403ceb0cc3bSStanislav Lisovskiy 
intel_cdclk_pcode_post_notify(struct intel_atomic_state * state)2404ceb0cc3bSStanislav Lisovskiy static void intel_cdclk_pcode_post_notify(struct intel_atomic_state *state)
2405ceb0cc3bSStanislav Lisovskiy {
2406ceb0cc3bSStanislav Lisovskiy 	struct drm_i915_private *i915 = to_i915(state->base.dev);
2407ceb0cc3bSStanislav Lisovskiy 	const struct intel_cdclk_state *new_cdclk_state =
2408ceb0cc3bSStanislav Lisovskiy 		intel_atomic_get_new_cdclk_state(state);
2409ceb0cc3bSStanislav Lisovskiy 	const struct intel_cdclk_state *old_cdclk_state =
2410ceb0cc3bSStanislav Lisovskiy 		intel_atomic_get_old_cdclk_state(state);
2411ceb0cc3bSStanislav Lisovskiy 	unsigned int cdclk = 0; u8 voltage_level, num_active_pipes = 0;
2412ceb0cc3bSStanislav Lisovskiy 	bool update_cdclk, update_pipe_count;
2413ceb0cc3bSStanislav Lisovskiy 
2414ceb0cc3bSStanislav Lisovskiy 	/* According to "Sequence After Frequency Change", set voltage to used level */
2415ceb0cc3bSStanislav Lisovskiy 	voltage_level = new_cdclk_state->actual.voltage_level;
2416ceb0cc3bSStanislav Lisovskiy 
2417ceb0cc3bSStanislav Lisovskiy 	update_cdclk = new_cdclk_state->actual.cdclk != old_cdclk_state->actual.cdclk;
2418ceb0cc3bSStanislav Lisovskiy 	update_pipe_count = hweight8(new_cdclk_state->active_pipes) <
2419ceb0cc3bSStanislav Lisovskiy 			    hweight8(old_cdclk_state->active_pipes);
2420ceb0cc3bSStanislav Lisovskiy 
2421ceb0cc3bSStanislav Lisovskiy 	/*
2422ceb0cc3bSStanislav Lisovskiy 	 * According to "Sequence After Frequency Change",
2423ceb0cc3bSStanislav Lisovskiy 	 * set bits 25:16 to current CDCLK
2424ceb0cc3bSStanislav Lisovskiy 	 */
2425ceb0cc3bSStanislav Lisovskiy 	if (update_cdclk)
2426ceb0cc3bSStanislav Lisovskiy 		cdclk = new_cdclk_state->actual.cdclk;
2427ceb0cc3bSStanislav Lisovskiy 
2428ceb0cc3bSStanislav Lisovskiy 	/*
2429ceb0cc3bSStanislav Lisovskiy 	 * According to "Sequence For Pipe Count Change",
2430ceb0cc3bSStanislav Lisovskiy 	 * if pipe count is decreasing, set bits 25:16 to current pipe count,
2431ceb0cc3bSStanislav Lisovskiy 	 * after the change(power well is disabled)
2432ceb0cc3bSStanislav Lisovskiy 	 * no action if it is increasing, after the change
2433ceb0cc3bSStanislav Lisovskiy 	 */
2434ceb0cc3bSStanislav Lisovskiy 	if (update_pipe_count)
2435ceb0cc3bSStanislav Lisovskiy 		num_active_pipes = hweight8(new_cdclk_state->active_pipes);
2436ceb0cc3bSStanislav Lisovskiy 
2437ceb0cc3bSStanislav Lisovskiy 	intel_pcode_notify(i915, voltage_level, num_active_pipes, cdclk,
2438ceb0cc3bSStanislav Lisovskiy 			   update_cdclk, update_pipe_count);
2439ceb0cc3bSStanislav Lisovskiy }
2440ceb0cc3bSStanislav Lisovskiy 
2441df0566a6SJani Nikula /**
24425604e9ceSVille Syrjälä  * intel_set_cdclk_pre_plane_update - Push the CDCLK state to the hardware
24435604e9ceSVille Syrjälä  * @state: intel atomic state
2444df0566a6SJani Nikula  *
24455604e9ceSVille Syrjälä  * Program the hardware before updating the HW plane state based on the
24465604e9ceSVille Syrjälä  * new CDCLK state, if necessary.
2447df0566a6SJani Nikula  */
2448df0566a6SJani Nikula void
intel_set_cdclk_pre_plane_update(struct intel_atomic_state * state)24495604e9ceSVille Syrjälä intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state)
2450df0566a6SJani Nikula {
2451ceb0cc3bSStanislav Lisovskiy 	struct drm_i915_private *i915 = to_i915(state->base.dev);
245228a30b45SVille Syrjälä 	const struct intel_cdclk_state *old_cdclk_state =
245328a30b45SVille Syrjälä 		intel_atomic_get_old_cdclk_state(state);
245428a30b45SVille Syrjälä 	const struct intel_cdclk_state *new_cdclk_state =
245528a30b45SVille Syrjälä 		intel_atomic_get_new_cdclk_state(state);
2456*51cc733fSVille Syrjälä 	struct intel_cdclk_config cdclk_config;
2457*51cc733fSVille Syrjälä 	enum pipe pipe;
24585604e9ceSVille Syrjälä 
245928a30b45SVille Syrjälä 	if (!intel_cdclk_changed(&old_cdclk_state->actual,
246028a30b45SVille Syrjälä 				 &new_cdclk_state->actual))
246128a30b45SVille Syrjälä 		return;
246228a30b45SVille Syrjälä 
2463ceb0cc3bSStanislav Lisovskiy 	if (IS_DG2(i915))
2464ceb0cc3bSStanislav Lisovskiy 		intel_cdclk_pcode_pre_notify(state);
2465ceb0cc3bSStanislav Lisovskiy 
2466*51cc733fSVille Syrjälä 	if (new_cdclk_state->disable_pipes) {
2467*51cc733fSVille Syrjälä 		cdclk_config = new_cdclk_state->actual;
2468*51cc733fSVille Syrjälä 		pipe = INVALID_PIPE;
2469*51cc733fSVille Syrjälä 	} else {
2470*51cc733fSVille Syrjälä 		if (new_cdclk_state->actual.cdclk >= old_cdclk_state->actual.cdclk) {
2471*51cc733fSVille Syrjälä 			cdclk_config = new_cdclk_state->actual;
2472*51cc733fSVille Syrjälä 			pipe = new_cdclk_state->pipe;
2473*51cc733fSVille Syrjälä 		} else {
2474*51cc733fSVille Syrjälä 			cdclk_config = old_cdclk_state->actual;
2475*51cc733fSVille Syrjälä 			pipe = INVALID_PIPE;
2476*51cc733fSVille Syrjälä 		}
2477*51cc733fSVille Syrjälä 
2478*51cc733fSVille Syrjälä 		cdclk_config.voltage_level = max(new_cdclk_state->actual.voltage_level,
2479*51cc733fSVille Syrjälä 						 old_cdclk_state->actual.voltage_level);
2480*51cc733fSVille Syrjälä 	}
2481*51cc733fSVille Syrjälä 
2482ceb0cc3bSStanislav Lisovskiy 	drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
248328a30b45SVille Syrjälä 
2484*51cc733fSVille Syrjälä 	intel_set_cdclk(i915, &cdclk_config, pipe);
248528a30b45SVille Syrjälä }
2486df0566a6SJani Nikula 
2487df0566a6SJani Nikula /**
24885604e9ceSVille Syrjälä  * intel_set_cdclk_post_plane_update - Push the CDCLK state to the hardware
24895604e9ceSVille Syrjälä  * @state: intel atomic state
2490df0566a6SJani Nikula  *
24910b02f97fSVille Syrjälä  * Program the hardware after updating the HW plane state based on the
24925604e9ceSVille Syrjälä  * new CDCLK state, if necessary.
2493df0566a6SJani Nikula  */
2494df0566a6SJani Nikula void
intel_set_cdclk_post_plane_update(struct intel_atomic_state * state)24955604e9ceSVille Syrjälä intel_set_cdclk_post_plane_update(struct intel_atomic_state *state)
2496df0566a6SJani Nikula {
2497ceb0cc3bSStanislav Lisovskiy 	struct drm_i915_private *i915 = to_i915(state->base.dev);
249828a30b45SVille Syrjälä 	const struct intel_cdclk_state *old_cdclk_state =
249928a30b45SVille Syrjälä 		intel_atomic_get_old_cdclk_state(state);
250028a30b45SVille Syrjälä 	const struct intel_cdclk_state *new_cdclk_state =
250128a30b45SVille Syrjälä 		intel_atomic_get_new_cdclk_state(state);
2502*51cc733fSVille Syrjälä 	enum pipe pipe;
25035604e9ceSVille Syrjälä 
250428a30b45SVille Syrjälä 	if (!intel_cdclk_changed(&old_cdclk_state->actual,
250528a30b45SVille Syrjälä 				 &new_cdclk_state->actual))
250628a30b45SVille Syrjälä 		return;
250728a30b45SVille Syrjälä 
2508ceb0cc3bSStanislav Lisovskiy 	if (IS_DG2(i915))
2509ceb0cc3bSStanislav Lisovskiy 		intel_cdclk_pcode_post_notify(state);
2510ceb0cc3bSStanislav Lisovskiy 
2511d1742f77SVille Syrjälä 	if (!new_cdclk_state->disable_pipes &&
2512*51cc733fSVille Syrjälä 	    new_cdclk_state->actual.cdclk < old_cdclk_state->actual.cdclk)
2513*51cc733fSVille Syrjälä 		pipe = new_cdclk_state->pipe;
2514*51cc733fSVille Syrjälä 	else
2515*51cc733fSVille Syrjälä 		pipe = INVALID_PIPE;
2516*51cc733fSVille Syrjälä 
2517ceb0cc3bSStanislav Lisovskiy 	drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
251828a30b45SVille Syrjälä 
2519ceb0cc3bSStanislav Lisovskiy 	intel_set_cdclk(i915, &new_cdclk_state->actual, pipe);
2520df0566a6SJani Nikula }
2521df0566a6SJani Nikula 
intel_pixel_rate_to_cdclk(const struct intel_crtc_state * crtc_state)25223e30d708SVille Syrjälä static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state)
2523df0566a6SJani Nikula {
25242225f3c6SMaarten Lankhorst 	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
25253e30d708SVille Syrjälä 	int pixel_rate = crtc_state->pixel_rate;
25263e30d708SVille Syrjälä 
25272b5a4562SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 10)
2528df0566a6SJani Nikula 		return DIV_ROUND_UP(pixel_rate, 2);
252993e7e61eSLucas De Marchi 	else if (DISPLAY_VER(dev_priv) == 9 ||
2530df0566a6SJani Nikula 		 IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
2531df0566a6SJani Nikula 		return pixel_rate;
2532df0566a6SJani Nikula 	else if (IS_CHERRYVIEW(dev_priv))
2533df0566a6SJani Nikula 		return DIV_ROUND_UP(pixel_rate * 100, 95);
25343e30d708SVille Syrjälä 	else if (crtc_state->double_wide)
25353e30d708SVille Syrjälä 		return DIV_ROUND_UP(pixel_rate * 100, 90 * 2);
2536df0566a6SJani Nikula 	else
2537df0566a6SJani Nikula 		return DIV_ROUND_UP(pixel_rate * 100, 90);
2538df0566a6SJani Nikula }
2539df0566a6SJani Nikula 
intel_planes_min_cdclk(const struct intel_crtc_state * crtc_state)2540bb6ae9e6SVille Syrjälä static int intel_planes_min_cdclk(const struct intel_crtc_state *crtc_state)
2541bb6ae9e6SVille Syrjälä {
25422225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
2543bb6ae9e6SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2544bb6ae9e6SVille Syrjälä 	struct intel_plane *plane;
2545bb6ae9e6SVille Syrjälä 	int min_cdclk = 0;
2546bb6ae9e6SVille Syrjälä 
2547bb6ae9e6SVille Syrjälä 	for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane)
2548bb6ae9e6SVille Syrjälä 		min_cdclk = max(crtc_state->min_cdclk[plane->id], min_cdclk);
2549bb6ae9e6SVille Syrjälä 
2550bb6ae9e6SVille Syrjälä 	return min_cdclk;
2551bb6ae9e6SVille Syrjälä }
2552bb6ae9e6SVille Syrjälä 
intel_crtc_compute_min_cdclk(const struct intel_crtc_state * crtc_state)2553df0566a6SJani Nikula int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
2554df0566a6SJani Nikula {
2555df0566a6SJani Nikula 	struct drm_i915_private *dev_priv =
25562225f3c6SMaarten Lankhorst 		to_i915(crtc_state->uapi.crtc->dev);
2557df0566a6SJani Nikula 	int min_cdclk;
2558df0566a6SJani Nikula 
25591326a92cSMaarten Lankhorst 	if (!crtc_state->hw.enable)
2560df0566a6SJani Nikula 		return 0;
2561df0566a6SJani Nikula 
25623e30d708SVille Syrjälä 	min_cdclk = intel_pixel_rate_to_cdclk(crtc_state);
2563df0566a6SJani Nikula 
2564df0566a6SJani Nikula 	/* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
2565df0566a6SJani Nikula 	if (IS_BROADWELL(dev_priv) && hsw_crtc_state_ips_capable(crtc_state))
2566df0566a6SJani Nikula 		min_cdclk = DIV_ROUND_UP(min_cdclk * 100, 95);
2567df0566a6SJani Nikula 
2568df0566a6SJani Nikula 	/* BSpec says "Do not use DisplayPort with CDCLK less than 432 MHz,
2569df0566a6SJani Nikula 	 * audio enabled, port width x4, and link rate HBR2 (5.4 GHz), or else
2570df0566a6SJani Nikula 	 * there may be audio corruption or screen corruption." This cdclk
2571df0566a6SJani Nikula 	 * restriction for GLK is 316.8 MHz.
2572df0566a6SJani Nikula 	 */
2573df0566a6SJani Nikula 	if (intel_crtc_has_dp_encoder(crtc_state) &&
2574df0566a6SJani Nikula 	    crtc_state->has_audio &&
2575df0566a6SJani Nikula 	    crtc_state->port_clock >= 540000 &&
2576df0566a6SJani Nikula 	    crtc_state->lane_count == 4) {
257793e7e61eSLucas De Marchi 		if (DISPLAY_VER(dev_priv) == 10) {
25781d89509aSLucas De Marchi 			/* Display WA #1145: glk */
2579df0566a6SJani Nikula 			min_cdclk = max(316800, min_cdclk);
258093e7e61eSLucas De Marchi 		} else if (DISPLAY_VER(dev_priv) == 9 || IS_BROADWELL(dev_priv)) {
2581df0566a6SJani Nikula 			/* Display WA #1144: skl,bxt */
2582df0566a6SJani Nikula 			min_cdclk = max(432000, min_cdclk);
2583df0566a6SJani Nikula 		}
2584df0566a6SJani Nikula 	}
2585df0566a6SJani Nikula 
2586df0566a6SJani Nikula 	/*
2587df0566a6SJani Nikula 	 * According to BSpec, "The CD clock frequency must be at least twice
2588df0566a6SJani Nikula 	 * the frequency of the Azalia BCLK." and BCLK is 96 MHz by default.
2589df0566a6SJani Nikula 	 */
2590005e9537SMatt Roper 	if (crtc_state->has_audio && DISPLAY_VER(dev_priv) >= 9)
2591df0566a6SJani Nikula 		min_cdclk = max(2 * 96000, min_cdclk);
2592df0566a6SJani Nikula 
2593df0566a6SJani Nikula 	/*
2594bffb31f7SVille Syrjälä 	 * "For DP audio configuration, cdclk frequency shall be set to
2595bffb31f7SVille Syrjälä 	 *  meet the following requirements:
2596bffb31f7SVille Syrjälä 	 *  DP Link Frequency(MHz) | Cdclk frequency(MHz)
2597bffb31f7SVille Syrjälä 	 *  270                    | 320 or higher
2598bffb31f7SVille Syrjälä 	 *  162                    | 200 or higher"
2599bffb31f7SVille Syrjälä 	 */
2600bffb31f7SVille Syrjälä 	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
2601bffb31f7SVille Syrjälä 	    intel_crtc_has_dp_encoder(crtc_state) && crtc_state->has_audio)
2602bffb31f7SVille Syrjälä 		min_cdclk = max(crtc_state->port_clock, min_cdclk);
2603bffb31f7SVille Syrjälä 
2604bffb31f7SVille Syrjälä 	/*
2605df0566a6SJani Nikula 	 * On Valleyview some DSI panels lose (v|h)sync when the clock is lower
2606df0566a6SJani Nikula 	 * than 320000KHz.
2607df0566a6SJani Nikula 	 */
2608df0566a6SJani Nikula 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) &&
2609df0566a6SJani Nikula 	    IS_VALLEYVIEW(dev_priv))
2610df0566a6SJani Nikula 		min_cdclk = max(320000, min_cdclk);
2611df0566a6SJani Nikula 
2612df0566a6SJani Nikula 	/*
2613df0566a6SJani Nikula 	 * On Geminilake once the CDCLK gets as low as 79200
2614df0566a6SJani Nikula 	 * picture gets unstable, despite that values are
2615df0566a6SJani Nikula 	 * correct for DSI PLL and DE PLL.
2616df0566a6SJani Nikula 	 */
2617df0566a6SJani Nikula 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) &&
2618df0566a6SJani Nikula 	    IS_GEMINILAKE(dev_priv))
2619df0566a6SJani Nikula 		min_cdclk = max(158400, min_cdclk);
2620df0566a6SJani Nikula 
2621bb6ae9e6SVille Syrjälä 	/* Account for additional needs from the planes */
2622bb6ae9e6SVille Syrjälä 	min_cdclk = max(intel_planes_min_cdclk(crtc_state), min_cdclk);
2623bb6ae9e6SVille Syrjälä 
262446d53e27SStanislav Lisovskiy 	/*
26252a764b7cSVandita Kulkarni 	 * When we decide to use only one VDSC engine, since
26262a764b7cSVandita Kulkarni 	 * each VDSC operates with 1 ppc throughput, pixel clock
26272a764b7cSVandita Kulkarni 	 * cannot be higher than the VDSC clock (cdclk)
26288290bceeSStanislav Lisovskiy 	 * If there 2 VDSC engines, then pixel clock can't be higher than
26298290bceeSStanislav Lisovskiy 	 * VDSC clock(cdclk) * 2 and so on.
2630fe01883fSLee Shawn C 	 */
26318290bceeSStanislav Lisovskiy 	if (crtc_state->dsc.compression_enable) {
26328290bceeSStanislav Lisovskiy 		int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
26338290bceeSStanislav Lisovskiy 
26348290bceeSStanislav Lisovskiy 		min_cdclk = max_t(int, min_cdclk,
26358290bceeSStanislav Lisovskiy 				  DIV_ROUND_UP(crtc_state->pixel_rate,
26368290bceeSStanislav Lisovskiy 					       num_vdsc_instances));
26378290bceeSStanislav Lisovskiy 	}
2638fe01883fSLee Shawn C 
2639fe01883fSLee Shawn C 	/*
2640859161b9SStanislav Lisovskiy 	 * HACK. Currently for TGL/DG2 platforms we calculate
264146d53e27SStanislav Lisovskiy 	 * min_cdclk initially based on pixel_rate divided
264246d53e27SStanislav Lisovskiy 	 * by 2, accounting for also plane requirements,
264346d53e27SStanislav Lisovskiy 	 * however in some cases the lowest possible CDCLK
264446d53e27SStanislav Lisovskiy 	 * doesn't work and causing the underruns.
264546d53e27SStanislav Lisovskiy 	 * Explicitly stating here that this seems to be currently
264646d53e27SStanislav Lisovskiy 	 * rather a Hack, than final solution.
264746d53e27SStanislav Lisovskiy 	 */
2648859161b9SStanislav Lisovskiy 	if (IS_TIGERLAKE(dev_priv) || IS_DG2(dev_priv)) {
26493fe4818eSStanislav Lisovskiy 		/*
26503fe4818eSStanislav Lisovskiy 		 * Clamp to max_cdclk_freq in case pixel rate is higher,
26513fe4818eSStanislav Lisovskiy 		 * in order not to break an 8K, but still leave W/A at place.
26523fe4818eSStanislav Lisovskiy 		 */
26533fe4818eSStanislav Lisovskiy 		min_cdclk = max_t(int, min_cdclk,
26543fe4818eSStanislav Lisovskiy 				  min_t(int, crtc_state->pixel_rate,
2655d51309b4SJani Nikula 					dev_priv->display.cdclk.max_cdclk_freq));
26563fe4818eSStanislav Lisovskiy 	}
265746d53e27SStanislav Lisovskiy 
2658df0566a6SJani Nikula 	return min_cdclk;
2659df0566a6SJani Nikula }
2660df0566a6SJani Nikula 
intel_compute_min_cdclk(struct intel_cdclk_state * cdclk_state)266128a30b45SVille Syrjälä static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
2662df0566a6SJani Nikula {
266328a30b45SVille Syrjälä 	struct intel_atomic_state *state = cdclk_state->base.state;
266419aefbc7SStanislav Lisovskiy 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
26655ac860ccSVille Syrjälä 	const struct intel_bw_state *bw_state;
2666df0566a6SJani Nikula 	struct intel_crtc *crtc;
2667df0566a6SJani Nikula 	struct intel_crtc_state *crtc_state;
2668df0566a6SJani Nikula 	int min_cdclk, i;
266919aefbc7SStanislav Lisovskiy 	enum pipe pipe;
2670df0566a6SJani Nikula 
2671df0566a6SJani Nikula 	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
26721d5a95b5SVille Syrjälä 		int ret;
26731d5a95b5SVille Syrjälä 
2674df0566a6SJani Nikula 		min_cdclk = intel_crtc_compute_min_cdclk(crtc_state);
2675df0566a6SJani Nikula 		if (min_cdclk < 0)
2676df0566a6SJani Nikula 			return min_cdclk;
2677df0566a6SJani Nikula 
26786499f925SVille Syrjälä 		if (cdclk_state->min_cdclk[crtc->pipe] == min_cdclk)
26791d5a95b5SVille Syrjälä 			continue;
26801d5a95b5SVille Syrjälä 
26816499f925SVille Syrjälä 		cdclk_state->min_cdclk[crtc->pipe] = min_cdclk;
26821d5a95b5SVille Syrjälä 
268328a30b45SVille Syrjälä 		ret = intel_atomic_lock_global_state(&cdclk_state->base);
26841d5a95b5SVille Syrjälä 		if (ret)
26851d5a95b5SVille Syrjälä 			return ret;
2686df0566a6SJani Nikula 	}
2687df0566a6SJani Nikula 
26885ac860ccSVille Syrjälä 	bw_state = intel_atomic_get_new_bw_state(state);
26895ac860ccSVille Syrjälä 	if (bw_state) {
26905ac860ccSVille Syrjälä 		min_cdclk = intel_bw_min_cdclk(dev_priv, bw_state);
26915ac860ccSVille Syrjälä 
26925ac860ccSVille Syrjälä 		if (cdclk_state->bw_min_cdclk != min_cdclk) {
26935ac860ccSVille Syrjälä 			int ret;
26945ac860ccSVille Syrjälä 
26955ac860ccSVille Syrjälä 			cdclk_state->bw_min_cdclk = min_cdclk;
26965ac860ccSVille Syrjälä 
26975ac860ccSVille Syrjälä 			ret = intel_atomic_lock_global_state(&cdclk_state->base);
26985ac860ccSVille Syrjälä 			if (ret)
26995ac860ccSVille Syrjälä 				return ret;
27005ac860ccSVille Syrjälä 		}
27015ac860ccSVille Syrjälä 	}
27025ac860ccSVille Syrjälä 
27035ac860ccSVille Syrjälä 	min_cdclk = max(cdclk_state->force_min_cdclk,
27045ac860ccSVille Syrjälä 			cdclk_state->bw_min_cdclk);
27055ac860ccSVille Syrjälä 	for_each_pipe(dev_priv, pipe)
270619aefbc7SStanislav Lisovskiy 		min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk);
2707cd191546SStanislav Lisovskiy 
27088722d668SVille Syrjälä 	/*
27098722d668SVille Syrjälä 	 * Avoid glk_force_audio_cdclk() causing excessive screen
27108722d668SVille Syrjälä 	 * blinking when multiple pipes are active by making sure
27118722d668SVille Syrjälä 	 * CDCLK frequency is always high enough for audio. With a
27128722d668SVille Syrjälä 	 * single active pipe we can always change CDCLK frequency
27138722d668SVille Syrjälä 	 * by changing the cd2x divider (see glk_cdclk_table[]) and
27148722d668SVille Syrjälä 	 * thus a full modeset won't be needed then.
27158722d668SVille Syrjälä 	 */
27168722d668SVille Syrjälä 	if (IS_GEMINILAKE(dev_priv) && cdclk_state->active_pipes &&
27178722d668SVille Syrjälä 	    !is_power_of_2(cdclk_state->active_pipes))
27188722d668SVille Syrjälä 		min_cdclk = max(2 * 96000, min_cdclk);
27198722d668SVille Syrjälä 
2720d51309b4SJani Nikula 	if (min_cdclk > dev_priv->display.cdclk.max_cdclk_freq) {
27215ac860ccSVille Syrjälä 		drm_dbg_kms(&dev_priv->drm,
27225ac860ccSVille Syrjälä 			    "required cdclk (%d kHz) exceeds max (%d kHz)\n",
2723d51309b4SJani Nikula 			    min_cdclk, dev_priv->display.cdclk.max_cdclk_freq);
27245ac860ccSVille Syrjälä 		return -EINVAL;
2725cd191546SStanislav Lisovskiy 	}
2726df0566a6SJani Nikula 
2727df0566a6SJani Nikula 	return min_cdclk;
2728df0566a6SJani Nikula }
2729df0566a6SJani Nikula 
2730df0566a6SJani Nikula /*
2731933122ccSVille Syrjälä  * Account for port clock min voltage level requirements.
27321d89509aSLucas De Marchi  * This only really does something on DISPLA_VER >= 11 but can be
2733933122ccSVille Syrjälä  * called on earlier platforms as well.
2734933122ccSVille Syrjälä  *
2735df0566a6SJani Nikula  * Note that this functions assumes that 0 is
2736df0566a6SJani Nikula  * the lowest voltage value, and higher values
2737df0566a6SJani Nikula  * correspond to increasingly higher voltages.
2738df0566a6SJani Nikula  *
2739df0566a6SJani Nikula  * Should that relationship no longer hold on
2740df0566a6SJani Nikula  * future platforms this code will need to be
2741df0566a6SJani Nikula  * adjusted.
2742df0566a6SJani Nikula  */
bxt_compute_min_voltage_level(struct intel_cdclk_state * cdclk_state)274328a30b45SVille Syrjälä static int bxt_compute_min_voltage_level(struct intel_cdclk_state *cdclk_state)
2744df0566a6SJani Nikula {
274528a30b45SVille Syrjälä 	struct intel_atomic_state *state = cdclk_state->base.state;
2746df0566a6SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
2747df0566a6SJani Nikula 	struct intel_crtc *crtc;
2748df0566a6SJani Nikula 	struct intel_crtc_state *crtc_state;
2749df0566a6SJani Nikula 	u8 min_voltage_level;
2750df0566a6SJani Nikula 	int i;
2751df0566a6SJani Nikula 	enum pipe pipe;
2752df0566a6SJani Nikula 
2753df0566a6SJani Nikula 	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
27541d5a95b5SVille Syrjälä 		int ret;
27551d5a95b5SVille Syrjälä 
27561326a92cSMaarten Lankhorst 		if (crtc_state->hw.enable)
27571d5a95b5SVille Syrjälä 			min_voltage_level = crtc_state->min_voltage_level;
2758df0566a6SJani Nikula 		else
27591d5a95b5SVille Syrjälä 			min_voltage_level = 0;
27601d5a95b5SVille Syrjälä 
27616499f925SVille Syrjälä 		if (cdclk_state->min_voltage_level[crtc->pipe] == min_voltage_level)
27621d5a95b5SVille Syrjälä 			continue;
27631d5a95b5SVille Syrjälä 
27646499f925SVille Syrjälä 		cdclk_state->min_voltage_level[crtc->pipe] = min_voltage_level;
27651d5a95b5SVille Syrjälä 
276628a30b45SVille Syrjälä 		ret = intel_atomic_lock_global_state(&cdclk_state->base);
27671d5a95b5SVille Syrjälä 		if (ret)
27681d5a95b5SVille Syrjälä 			return ret;
2769df0566a6SJani Nikula 	}
2770df0566a6SJani Nikula 
2771df0566a6SJani Nikula 	min_voltage_level = 0;
2772df0566a6SJani Nikula 	for_each_pipe(dev_priv, pipe)
27731965de63SVille Syrjälä 		min_voltage_level = max(cdclk_state->min_voltage_level[pipe],
2774df0566a6SJani Nikula 					min_voltage_level);
2775df0566a6SJani Nikula 
2776df0566a6SJani Nikula 	return min_voltage_level;
2777df0566a6SJani Nikula }
2778df0566a6SJani Nikula 
vlv_modeset_calc_cdclk(struct intel_cdclk_state * cdclk_state)277928a30b45SVille Syrjälä static int vlv_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state)
2780df0566a6SJani Nikula {
278128a30b45SVille Syrjälä 	struct intel_atomic_state *state = cdclk_state->base.state;
2782df0566a6SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
2783df0566a6SJani Nikula 	int min_cdclk, cdclk;
2784df0566a6SJani Nikula 
278528a30b45SVille Syrjälä 	min_cdclk = intel_compute_min_cdclk(cdclk_state);
2786df0566a6SJani Nikula 	if (min_cdclk < 0)
2787df0566a6SJani Nikula 		return min_cdclk;
2788df0566a6SJani Nikula 
2789df0566a6SJani Nikula 	cdclk = vlv_calc_cdclk(dev_priv, min_cdclk);
2790df0566a6SJani Nikula 
27911965de63SVille Syrjälä 	cdclk_state->logical.cdclk = cdclk;
27921965de63SVille Syrjälä 	cdclk_state->logical.voltage_level =
2793df0566a6SJani Nikula 		vlv_calc_voltage_level(dev_priv, cdclk);
2794df0566a6SJani Nikula 
27950c2d5512SVille Syrjälä 	if (!cdclk_state->active_pipes) {
27961965de63SVille Syrjälä 		cdclk = vlv_calc_cdclk(dev_priv, cdclk_state->force_min_cdclk);
2797df0566a6SJani Nikula 
27981965de63SVille Syrjälä 		cdclk_state->actual.cdclk = cdclk;
27991965de63SVille Syrjälä 		cdclk_state->actual.voltage_level =
2800df0566a6SJani Nikula 			vlv_calc_voltage_level(dev_priv, cdclk);
2801df0566a6SJani Nikula 	} else {
28021965de63SVille Syrjälä 		cdclk_state->actual = cdclk_state->logical;
2803df0566a6SJani Nikula 	}
2804df0566a6SJani Nikula 
2805df0566a6SJani Nikula 	return 0;
2806df0566a6SJani Nikula }
2807df0566a6SJani Nikula 
bdw_modeset_calc_cdclk(struct intel_cdclk_state * cdclk_state)280828a30b45SVille Syrjälä static int bdw_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state)
2809df0566a6SJani Nikula {
2810df0566a6SJani Nikula 	int min_cdclk, cdclk;
2811df0566a6SJani Nikula 
281228a30b45SVille Syrjälä 	min_cdclk = intel_compute_min_cdclk(cdclk_state);
2813df0566a6SJani Nikula 	if (min_cdclk < 0)
2814df0566a6SJani Nikula 		return min_cdclk;
2815df0566a6SJani Nikula 
2816df0566a6SJani Nikula 	cdclk = bdw_calc_cdclk(min_cdclk);
2817df0566a6SJani Nikula 
28181965de63SVille Syrjälä 	cdclk_state->logical.cdclk = cdclk;
28191965de63SVille Syrjälä 	cdclk_state->logical.voltage_level =
2820df0566a6SJani Nikula 		bdw_calc_voltage_level(cdclk);
2821df0566a6SJani Nikula 
28220c2d5512SVille Syrjälä 	if (!cdclk_state->active_pipes) {
28231965de63SVille Syrjälä 		cdclk = bdw_calc_cdclk(cdclk_state->force_min_cdclk);
2824df0566a6SJani Nikula 
28251965de63SVille Syrjälä 		cdclk_state->actual.cdclk = cdclk;
28261965de63SVille Syrjälä 		cdclk_state->actual.voltage_level =
2827df0566a6SJani Nikula 			bdw_calc_voltage_level(cdclk);
2828df0566a6SJani Nikula 	} else {
28291965de63SVille Syrjälä 		cdclk_state->actual = cdclk_state->logical;
2830df0566a6SJani Nikula 	}
2831df0566a6SJani Nikula 
2832df0566a6SJani Nikula 	return 0;
2833df0566a6SJani Nikula }
2834df0566a6SJani Nikula 
skl_dpll0_vco(struct intel_cdclk_state * cdclk_state)283528a30b45SVille Syrjälä static int skl_dpll0_vco(struct intel_cdclk_state *cdclk_state)
2836df0566a6SJani Nikula {
283728a30b45SVille Syrjälä 	struct intel_atomic_state *state = cdclk_state->base.state;
2838df0566a6SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
2839df0566a6SJani Nikula 	struct intel_crtc *crtc;
2840df0566a6SJani Nikula 	struct intel_crtc_state *crtc_state;
2841df0566a6SJani Nikula 	int vco, i;
2842df0566a6SJani Nikula 
28431965de63SVille Syrjälä 	vco = cdclk_state->logical.vco;
2844df0566a6SJani Nikula 	if (!vco)
2845df0566a6SJani Nikula 		vco = dev_priv->skl_preferred_vco_freq;
2846df0566a6SJani Nikula 
2847df0566a6SJani Nikula 	for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
28481326a92cSMaarten Lankhorst 		if (!crtc_state->hw.enable)
2849df0566a6SJani Nikula 			continue;
2850df0566a6SJani Nikula 
2851df0566a6SJani Nikula 		if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
2852df0566a6SJani Nikula 			continue;
2853df0566a6SJani Nikula 
2854df0566a6SJani Nikula 		/*
2855df0566a6SJani Nikula 		 * DPLL0 VCO may need to be adjusted to get the correct
2856df0566a6SJani Nikula 		 * clock for eDP. This will affect cdclk as well.
2857df0566a6SJani Nikula 		 */
2858df0566a6SJani Nikula 		switch (crtc_state->port_clock / 2) {
2859df0566a6SJani Nikula 		case 108000:
2860df0566a6SJani Nikula 		case 216000:
2861df0566a6SJani Nikula 			vco = 8640000;
2862df0566a6SJani Nikula 			break;
2863df0566a6SJani Nikula 		default:
2864df0566a6SJani Nikula 			vco = 8100000;
2865df0566a6SJani Nikula 			break;
2866df0566a6SJani Nikula 		}
2867df0566a6SJani Nikula 	}
2868df0566a6SJani Nikula 
2869df0566a6SJani Nikula 	return vco;
2870df0566a6SJani Nikula }
2871df0566a6SJani Nikula 
skl_modeset_calc_cdclk(struct intel_cdclk_state * cdclk_state)287228a30b45SVille Syrjälä static int skl_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state)
2873df0566a6SJani Nikula {
2874df0566a6SJani Nikula 	int min_cdclk, cdclk, vco;
2875df0566a6SJani Nikula 
287628a30b45SVille Syrjälä 	min_cdclk = intel_compute_min_cdclk(cdclk_state);
2877df0566a6SJani Nikula 	if (min_cdclk < 0)
2878df0566a6SJani Nikula 		return min_cdclk;
2879df0566a6SJani Nikula 
288028a30b45SVille Syrjälä 	vco = skl_dpll0_vco(cdclk_state);
2881df0566a6SJani Nikula 
2882df0566a6SJani Nikula 	cdclk = skl_calc_cdclk(min_cdclk, vco);
2883df0566a6SJani Nikula 
28841965de63SVille Syrjälä 	cdclk_state->logical.vco = vco;
28851965de63SVille Syrjälä 	cdclk_state->logical.cdclk = cdclk;
28861965de63SVille Syrjälä 	cdclk_state->logical.voltage_level =
2887df0566a6SJani Nikula 		skl_calc_voltage_level(cdclk);
2888df0566a6SJani Nikula 
28890c2d5512SVille Syrjälä 	if (!cdclk_state->active_pipes) {
28901965de63SVille Syrjälä 		cdclk = skl_calc_cdclk(cdclk_state->force_min_cdclk, vco);
2891df0566a6SJani Nikula 
28921965de63SVille Syrjälä 		cdclk_state->actual.vco = vco;
28931965de63SVille Syrjälä 		cdclk_state->actual.cdclk = cdclk;
28941965de63SVille Syrjälä 		cdclk_state->actual.voltage_level =
2895df0566a6SJani Nikula 			skl_calc_voltage_level(cdclk);
2896df0566a6SJani Nikula 	} else {
28971965de63SVille Syrjälä 		cdclk_state->actual = cdclk_state->logical;
2898df0566a6SJani Nikula 	}
2899df0566a6SJani Nikula 
2900df0566a6SJani Nikula 	return 0;
2901df0566a6SJani Nikula }
2902df0566a6SJani Nikula 
bxt_modeset_calc_cdclk(struct intel_cdclk_state * cdclk_state)290328a30b45SVille Syrjälä static int bxt_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state)
2904df0566a6SJani Nikula {
290528a30b45SVille Syrjälä 	struct intel_atomic_state *state = cdclk_state->base.state;
2906df0566a6SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
29071d5a95b5SVille Syrjälä 	int min_cdclk, min_voltage_level, cdclk, vco;
2908df0566a6SJani Nikula 
290928a30b45SVille Syrjälä 	min_cdclk = intel_compute_min_cdclk(cdclk_state);
2910df0566a6SJani Nikula 	if (min_cdclk < 0)
2911df0566a6SJani Nikula 		return min_cdclk;
2912df0566a6SJani Nikula 
291328a30b45SVille Syrjälä 	min_voltage_level = bxt_compute_min_voltage_level(cdclk_state);
29141d5a95b5SVille Syrjälä 	if (min_voltage_level < 0)
29151d5a95b5SVille Syrjälä 		return min_voltage_level;
29161d5a95b5SVille Syrjälä 
2917736da811SMatt Roper 	cdclk = bxt_calc_cdclk(dev_priv, min_cdclk);
2918736da811SMatt Roper 	vco = bxt_calc_cdclk_pll_vco(dev_priv, cdclk);
2919df0566a6SJani Nikula 
29201965de63SVille Syrjälä 	cdclk_state->logical.vco = vco;
29211965de63SVille Syrjälä 	cdclk_state->logical.cdclk = cdclk;
29221965de63SVille Syrjälä 	cdclk_state->logical.voltage_level =
29231d5a95b5SVille Syrjälä 		max_t(int, min_voltage_level,
292444892ffaSDave Airlie 		      intel_cdclk_calc_voltage_level(dev_priv, cdclk));
2925df0566a6SJani Nikula 
29260c2d5512SVille Syrjälä 	if (!cdclk_state->active_pipes) {
29271965de63SVille Syrjälä 		cdclk = bxt_calc_cdclk(dev_priv, cdclk_state->force_min_cdclk);
2928736da811SMatt Roper 		vco = bxt_calc_cdclk_pll_vco(dev_priv, cdclk);
2929df0566a6SJani Nikula 
29301965de63SVille Syrjälä 		cdclk_state->actual.vco = vco;
29311965de63SVille Syrjälä 		cdclk_state->actual.cdclk = cdclk;
29321965de63SVille Syrjälä 		cdclk_state->actual.voltage_level =
293344892ffaSDave Airlie 			intel_cdclk_calc_voltage_level(dev_priv, cdclk);
2934df0566a6SJani Nikula 	} else {
29351965de63SVille Syrjälä 		cdclk_state->actual = cdclk_state->logical;
2936df0566a6SJani Nikula 	}
2937df0566a6SJani Nikula 
2938df0566a6SJani Nikula 	return 0;
2939df0566a6SJani Nikula }
2940df0566a6SJani Nikula 
fixed_modeset_calc_cdclk(struct intel_cdclk_state * cdclk_state)294128a30b45SVille Syrjälä static int fixed_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state)
29423e30d708SVille Syrjälä {
29433e30d708SVille Syrjälä 	int min_cdclk;
29443e30d708SVille Syrjälä 
29453e30d708SVille Syrjälä 	/*
29463e30d708SVille Syrjälä 	 * We can't change the cdclk frequency, but we still want to
29473e30d708SVille Syrjälä 	 * check that the required minimum frequency doesn't exceed
29483e30d708SVille Syrjälä 	 * the actual cdclk frequency.
29493e30d708SVille Syrjälä 	 */
295028a30b45SVille Syrjälä 	min_cdclk = intel_compute_min_cdclk(cdclk_state);
29513e30d708SVille Syrjälä 	if (min_cdclk < 0)
29523e30d708SVille Syrjälä 		return min_cdclk;
29533e30d708SVille Syrjälä 
29543e30d708SVille Syrjälä 	return 0;
29553e30d708SVille Syrjälä }
29563e30d708SVille Syrjälä 
intel_cdclk_duplicate_state(struct intel_global_obj * obj)295728a30b45SVille Syrjälä static struct intel_global_state *intel_cdclk_duplicate_state(struct intel_global_obj *obj)
295828a30b45SVille Syrjälä {
295928a30b45SVille Syrjälä 	struct intel_cdclk_state *cdclk_state;
296028a30b45SVille Syrjälä 
296128a30b45SVille Syrjälä 	cdclk_state = kmemdup(obj->state, sizeof(*cdclk_state), GFP_KERNEL);
296228a30b45SVille Syrjälä 	if (!cdclk_state)
296328a30b45SVille Syrjälä 		return NULL;
296428a30b45SVille Syrjälä 
296528a30b45SVille Syrjälä 	cdclk_state->pipe = INVALID_PIPE;
2966d1742f77SVille Syrjälä 	cdclk_state->disable_pipes = false;
296728a30b45SVille Syrjälä 
296828a30b45SVille Syrjälä 	return &cdclk_state->base;
296928a30b45SVille Syrjälä }
297028a30b45SVille Syrjälä 
intel_cdclk_destroy_state(struct intel_global_obj * obj,struct intel_global_state * state)297128a30b45SVille Syrjälä static void intel_cdclk_destroy_state(struct intel_global_obj *obj,
297228a30b45SVille Syrjälä 				      struct intel_global_state *state)
297328a30b45SVille Syrjälä {
297428a30b45SVille Syrjälä 	kfree(state);
297528a30b45SVille Syrjälä }
297628a30b45SVille Syrjälä 
297728a30b45SVille Syrjälä static const struct intel_global_state_funcs intel_cdclk_funcs = {
297828a30b45SVille Syrjälä 	.atomic_duplicate_state = intel_cdclk_duplicate_state,
297928a30b45SVille Syrjälä 	.atomic_destroy_state = intel_cdclk_destroy_state,
298028a30b45SVille Syrjälä };
298128a30b45SVille Syrjälä 
298228a30b45SVille Syrjälä struct intel_cdclk_state *
intel_atomic_get_cdclk_state(struct intel_atomic_state * state)298328a30b45SVille Syrjälä intel_atomic_get_cdclk_state(struct intel_atomic_state *state)
298428a30b45SVille Syrjälä {
298528a30b45SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
298628a30b45SVille Syrjälä 	struct intel_global_state *cdclk_state;
298728a30b45SVille Syrjälä 
2988d51309b4SJani Nikula 	cdclk_state = intel_atomic_get_global_obj_state(state, &dev_priv->display.cdclk.obj);
298928a30b45SVille Syrjälä 	if (IS_ERR(cdclk_state))
299028a30b45SVille Syrjälä 		return ERR_CAST(cdclk_state);
299128a30b45SVille Syrjälä 
299228a30b45SVille Syrjälä 	return to_intel_cdclk_state(cdclk_state);
299328a30b45SVille Syrjälä }
299428a30b45SVille Syrjälä 
intel_cdclk_atomic_check(struct intel_atomic_state * state,bool * need_cdclk_calc)2995754d6275SJani Nikula int intel_cdclk_atomic_check(struct intel_atomic_state *state,
2996754d6275SJani Nikula 			     bool *need_cdclk_calc)
2997754d6275SJani Nikula {
2998754d6275SJani Nikula 	const struct intel_cdclk_state *old_cdclk_state;
2999754d6275SJani Nikula 	const struct intel_cdclk_state *new_cdclk_state;
3000ace87304SJani Nikula 	struct intel_plane_state __maybe_unused *plane_state;
3001754d6275SJani Nikula 	struct intel_plane *plane;
3002754d6275SJani Nikula 	int ret;
3003754d6275SJani Nikula 	int i;
3004754d6275SJani Nikula 
3005754d6275SJani Nikula 	/*
3006754d6275SJani Nikula 	 * active_planes bitmask has been updated, and potentially affected
3007754d6275SJani Nikula 	 * planes are part of the state. We can now compute the minimum cdclk
3008754d6275SJani Nikula 	 * for each plane.
3009754d6275SJani Nikula 	 */
3010754d6275SJani Nikula 	for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
3011754d6275SJani Nikula 		ret = intel_plane_calc_min_cdclk(state, plane, need_cdclk_calc);
3012754d6275SJani Nikula 		if (ret)
3013754d6275SJani Nikula 			return ret;
3014754d6275SJani Nikula 	}
3015754d6275SJani Nikula 
30165ac860ccSVille Syrjälä 	ret = intel_bw_calc_min_cdclk(state, need_cdclk_calc);
30175ac860ccSVille Syrjälä 	if (ret)
30185ac860ccSVille Syrjälä 		return ret;
30195ac860ccSVille Syrjälä 
3020754d6275SJani Nikula 	old_cdclk_state = intel_atomic_get_old_cdclk_state(state);
3021754d6275SJani Nikula 	new_cdclk_state = intel_atomic_get_new_cdclk_state(state);
3022754d6275SJani Nikula 
3023754d6275SJani Nikula 	if (new_cdclk_state &&
3024754d6275SJani Nikula 	    old_cdclk_state->force_min_cdclk != new_cdclk_state->force_min_cdclk)
3025754d6275SJani Nikula 		*need_cdclk_calc = true;
3026754d6275SJani Nikula 
3027754d6275SJani Nikula 	return 0;
3028754d6275SJani Nikula }
3029754d6275SJani Nikula 
intel_cdclk_init(struct drm_i915_private * dev_priv)303028a30b45SVille Syrjälä int intel_cdclk_init(struct drm_i915_private *dev_priv)
303128a30b45SVille Syrjälä {
303228a30b45SVille Syrjälä 	struct intel_cdclk_state *cdclk_state;
303328a30b45SVille Syrjälä 
303428a30b45SVille Syrjälä 	cdclk_state = kzalloc(sizeof(*cdclk_state), GFP_KERNEL);
303528a30b45SVille Syrjälä 	if (!cdclk_state)
303628a30b45SVille Syrjälä 		return -ENOMEM;
303728a30b45SVille Syrjälä 
3038d51309b4SJani Nikula 	intel_atomic_global_obj_init(dev_priv, &dev_priv->display.cdclk.obj,
303928a30b45SVille Syrjälä 				     &cdclk_state->base, &intel_cdclk_funcs);
304028a30b45SVille Syrjälä 
304128a30b45SVille Syrjälä 	return 0;
304228a30b45SVille Syrjälä }
304328a30b45SVille Syrjälä 
intel_cdclk_need_serialize(struct drm_i915_private * i915,const struct intel_cdclk_state * old_cdclk_state,const struct intel_cdclk_state * new_cdclk_state)3044ceb0cc3bSStanislav Lisovskiy static bool intel_cdclk_need_serialize(struct drm_i915_private *i915,
3045ceb0cc3bSStanislav Lisovskiy 				       const struct intel_cdclk_state *old_cdclk_state,
3046ceb0cc3bSStanislav Lisovskiy 				       const struct intel_cdclk_state *new_cdclk_state)
3047ceb0cc3bSStanislav Lisovskiy {
3048ceb0cc3bSStanislav Lisovskiy 	bool power_well_cnt_changed = hweight8(old_cdclk_state->active_pipes) !=
3049ceb0cc3bSStanislav Lisovskiy 				      hweight8(new_cdclk_state->active_pipes);
3050ceb0cc3bSStanislav Lisovskiy 	bool cdclk_changed = intel_cdclk_changed(&old_cdclk_state->actual,
3051ceb0cc3bSStanislav Lisovskiy 						 &new_cdclk_state->actual);
3052ceb0cc3bSStanislav Lisovskiy 	/*
3053ceb0cc3bSStanislav Lisovskiy 	 * We need to poke hw for gen >= 12, because we notify PCode if
3054ceb0cc3bSStanislav Lisovskiy 	 * pipe power well count changes.
3055ceb0cc3bSStanislav Lisovskiy 	 */
3056ceb0cc3bSStanislav Lisovskiy 	return cdclk_changed || (IS_DG2(i915) && power_well_cnt_changed);
3057ceb0cc3bSStanislav Lisovskiy }
3058ceb0cc3bSStanislav Lisovskiy 
intel_modeset_calc_cdclk(struct intel_atomic_state * state)3059fe4709a8SVille Syrjälä int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
3060fe4709a8SVille Syrjälä {
3061fe4709a8SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
306228a30b45SVille Syrjälä 	const struct intel_cdclk_state *old_cdclk_state;
306328a30b45SVille Syrjälä 	struct intel_cdclk_state *new_cdclk_state;
3064d62686baSStanislav Lisovskiy 	enum pipe pipe = INVALID_PIPE;
3065fe4709a8SVille Syrjälä 	int ret;
3066fe4709a8SVille Syrjälä 
306728a30b45SVille Syrjälä 	new_cdclk_state = intel_atomic_get_cdclk_state(state);
306828a30b45SVille Syrjälä 	if (IS_ERR(new_cdclk_state))
306928a30b45SVille Syrjälä 		return PTR_ERR(new_cdclk_state);
307054f09d23SVille Syrjälä 
307128a30b45SVille Syrjälä 	old_cdclk_state = intel_atomic_get_old_cdclk_state(state);
307254f09d23SVille Syrjälä 
30730c2d5512SVille Syrjälä 	new_cdclk_state->active_pipes =
30740c2d5512SVille Syrjälä 		intel_calc_active_pipes(state, old_cdclk_state->active_pipes);
30750c2d5512SVille Syrjälä 
307644892ffaSDave Airlie 	ret = intel_cdclk_modeset_calc_cdclk(dev_priv, new_cdclk_state);
3077fe4709a8SVille Syrjälä 	if (ret)
3078fe4709a8SVille Syrjälä 		return ret;
3079fe4709a8SVille Syrjälä 
3080ceb0cc3bSStanislav Lisovskiy 	if (intel_cdclk_need_serialize(dev_priv, old_cdclk_state, new_cdclk_state)) {
30811d5a95b5SVille Syrjälä 		/*
30821d5a95b5SVille Syrjälä 		 * Also serialize commits across all crtcs
30831d5a95b5SVille Syrjälä 		 * if the actual hw needs to be poked.
30841d5a95b5SVille Syrjälä 		 */
308528a30b45SVille Syrjälä 		ret = intel_atomic_serialize_global_state(&new_cdclk_state->base);
30861d5a95b5SVille Syrjälä 		if (ret)
3087fe4709a8SVille Syrjälä 			return ret;
30880c2d5512SVille Syrjälä 	} else if (old_cdclk_state->active_pipes != new_cdclk_state->active_pipes ||
3089dc98f50fSVille Syrjälä 		   old_cdclk_state->force_min_cdclk != new_cdclk_state->force_min_cdclk ||
30900c2d5512SVille Syrjälä 		   intel_cdclk_changed(&old_cdclk_state->logical,
30911965de63SVille Syrjälä 				       &new_cdclk_state->logical)) {
309228a30b45SVille Syrjälä 		ret = intel_atomic_lock_global_state(&new_cdclk_state->base);
30931d5a95b5SVille Syrjälä 		if (ret)
30941d5a95b5SVille Syrjälä 			return ret;
30951d5a95b5SVille Syrjälä 	} else {
30961d5a95b5SVille Syrjälä 		return 0;
3097fe4709a8SVille Syrjälä 	}
3098fe4709a8SVille Syrjälä 
30990c2d5512SVille Syrjälä 	if (is_power_of_2(new_cdclk_state->active_pipes) &&
310065c88a86SVille Syrjälä 	    intel_cdclk_can_cd2x_update(dev_priv,
31011965de63SVille Syrjälä 					&old_cdclk_state->actual,
31021965de63SVille Syrjälä 					&new_cdclk_state->actual)) {
3103fe4709a8SVille Syrjälä 		struct intel_crtc *crtc;
3104fe4709a8SVille Syrjälä 		struct intel_crtc_state *crtc_state;
3105fe4709a8SVille Syrjälä 
31060c2d5512SVille Syrjälä 		pipe = ilog2(new_cdclk_state->active_pipes);
31077794b6deSJani Nikula 		crtc = intel_crtc_for_pipe(dev_priv, pipe);
31081d5a95b5SVille Syrjälä 
31091d5a95b5SVille Syrjälä 		crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
31101d5a95b5SVille Syrjälä 		if (IS_ERR(crtc_state))
31111d5a95b5SVille Syrjälä 			return PTR_ERR(crtc_state);
31121d5a95b5SVille Syrjälä 
3113882ecff7SVille Syrjälä 		if (intel_crtc_needs_modeset(crtc_state))
3114fe4709a8SVille Syrjälä 			pipe = INVALID_PIPE;
3115fe4709a8SVille Syrjälä 	}
3116fe4709a8SVille Syrjälä 
311725e0e5aeSVille Syrjälä 	if (intel_cdclk_can_crawl_and_squash(dev_priv,
311825e0e5aeSVille Syrjälä 					     &old_cdclk_state->actual,
311925e0e5aeSVille Syrjälä 					     &new_cdclk_state->actual)) {
312025e0e5aeSVille Syrjälä 		drm_dbg_kms(&dev_priv->drm,
312125e0e5aeSVille Syrjälä 			    "Can change cdclk via crawling and squashing\n");
312225e0e5aeSVille Syrjälä 	} else if (intel_cdclk_can_squash(dev_priv,
3123d4a23930SVille Syrjälä 					&old_cdclk_state->actual,
3124d4a23930SVille Syrjälä 					&new_cdclk_state->actual)) {
3125d4a23930SVille Syrjälä 		drm_dbg_kms(&dev_priv->drm,
3126c74b644fSAnusha Srivatsa 			    "Can change cdclk via squashing\n");
3127d4a23930SVille Syrjälä 	} else if (intel_cdclk_can_crawl(dev_priv,
3128d62686baSStanislav Lisovskiy 					 &old_cdclk_state->actual,
3129d62686baSStanislav Lisovskiy 					 &new_cdclk_state->actual)) {
3130d62686baSStanislav Lisovskiy 		drm_dbg_kms(&dev_priv->drm,
3131c74b644fSAnusha Srivatsa 			    "Can change cdclk via crawling\n");
3132d62686baSStanislav Lisovskiy 	} else if (pipe != INVALID_PIPE) {
31331965de63SVille Syrjälä 		new_cdclk_state->pipe = pipe;
31346c066f4cSVille Syrjälä 
313523194610SWambui Karuga 		drm_dbg_kms(&dev_priv->drm,
3136d62686baSStanislav Lisovskiy 			    "Can change cdclk cd2x divider with pipe %c active\n",
31376c066f4cSVille Syrjälä 			    pipe_name(pipe));
31381965de63SVille Syrjälä 	} else if (intel_cdclk_needs_modeset(&old_cdclk_state->actual,
31391965de63SVille Syrjälä 					     &new_cdclk_state->actual)) {
31401d5a95b5SVille Syrjälä 		/* All pipes must be switched off while we change the cdclk. */
31410c316114SVille Syrjälä 		ret = intel_modeset_all_pipes(state, "CDCLK change");
3142fe4709a8SVille Syrjälä 		if (ret)
3143fe4709a8SVille Syrjälä 			return ret;
3144fe4709a8SVille Syrjälä 
3145d1742f77SVille Syrjälä 		new_cdclk_state->disable_pipes = true;
3146d1742f77SVille Syrjälä 
314723194610SWambui Karuga 		drm_dbg_kms(&dev_priv->drm,
314823194610SWambui Karuga 			    "Modeset required for cdclk change\n");
3149fe4709a8SVille Syrjälä 	}
3150fe4709a8SVille Syrjälä 
315123194610SWambui Karuga 	drm_dbg_kms(&dev_priv->drm,
315223194610SWambui Karuga 		    "New cdclk calculated to be logical %u kHz, actual %u kHz\n",
31531965de63SVille Syrjälä 		    new_cdclk_state->logical.cdclk,
31541965de63SVille Syrjälä 		    new_cdclk_state->actual.cdclk);
315523194610SWambui Karuga 	drm_dbg_kms(&dev_priv->drm,
315623194610SWambui Karuga 		    "New voltage level calculated to be logical %u, actual %u\n",
31571965de63SVille Syrjälä 		    new_cdclk_state->logical.voltage_level,
31581965de63SVille Syrjälä 		    new_cdclk_state->actual.voltage_level);
3159fe4709a8SVille Syrjälä 
3160fe4709a8SVille Syrjälä 	return 0;
3161fe4709a8SVille Syrjälä }
3162fe4709a8SVille Syrjälä 
intel_compute_max_dotclk(struct drm_i915_private * dev_priv)3163df0566a6SJani Nikula static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
3164df0566a6SJani Nikula {
3165d51309b4SJani Nikula 	int max_cdclk_freq = dev_priv->display.cdclk.max_cdclk_freq;
3166df0566a6SJani Nikula 
31672b5a4562SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 10)
3168df0566a6SJani Nikula 		return 2 * max_cdclk_freq;
316993e7e61eSLucas De Marchi 	else if (DISPLAY_VER(dev_priv) == 9 ||
3170df0566a6SJani Nikula 		 IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
3171df0566a6SJani Nikula 		return max_cdclk_freq;
3172df0566a6SJani Nikula 	else if (IS_CHERRYVIEW(dev_priv))
3173df0566a6SJani Nikula 		return max_cdclk_freq*95/100;
3174005e9537SMatt Roper 	else if (DISPLAY_VER(dev_priv) < 4)
3175df0566a6SJani Nikula 		return 2*max_cdclk_freq*90/100;
3176df0566a6SJani Nikula 	else
3177df0566a6SJani Nikula 		return max_cdclk_freq*90/100;
3178df0566a6SJani Nikula }
3179df0566a6SJani Nikula 
3180df0566a6SJani Nikula /**
3181df0566a6SJani Nikula  * intel_update_max_cdclk - Determine the maximum support CDCLK frequency
3182df0566a6SJani Nikula  * @dev_priv: i915 device
3183df0566a6SJani Nikula  *
3184df0566a6SJani Nikula  * Determine the maximum CDCLK frequency the platform supports, and also
3185df0566a6SJani Nikula  * derive the maximum dot clock frequency the maximum CDCLK frequency
3186df0566a6SJani Nikula  * allows.
3187df0566a6SJani Nikula  */
intel_update_max_cdclk(struct drm_i915_private * dev_priv)3188df0566a6SJani Nikula void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
3189df0566a6SJani Nikula {
31900c65dc06SDnyaneshwar Bhadane 	if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) {
3191d51309b4SJani Nikula 		if (dev_priv->display.cdclk.hw.ref == 24000)
3192d51309b4SJani Nikula 			dev_priv->display.cdclk.max_cdclk_freq = 552000;
31936e63790eSJosé Roberto de Souza 		else
3194d51309b4SJani Nikula 			dev_priv->display.cdclk.max_cdclk_freq = 556800;
3195005e9537SMatt Roper 	} else if (DISPLAY_VER(dev_priv) >= 11) {
3196d51309b4SJani Nikula 		if (dev_priv->display.cdclk.hw.ref == 24000)
3197d51309b4SJani Nikula 			dev_priv->display.cdclk.max_cdclk_freq = 648000;
3198df0566a6SJani Nikula 		else
3199d51309b4SJani Nikula 			dev_priv->display.cdclk.max_cdclk_freq = 652800;
32002446e1d6SMatt Roper 	} else if (IS_GEMINILAKE(dev_priv)) {
3201d51309b4SJani Nikula 		dev_priv->display.cdclk.max_cdclk_freq = 316800;
32022446e1d6SMatt Roper 	} else if (IS_BROXTON(dev_priv)) {
3203d51309b4SJani Nikula 		dev_priv->display.cdclk.max_cdclk_freq = 624000;
320493e7e61eSLucas De Marchi 	} else if (DISPLAY_VER(dev_priv) == 9) {
32053e9f55dfSJani Nikula 		u32 limit = intel_de_read(dev_priv, SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
3206df0566a6SJani Nikula 		int max_cdclk, vco;
3207df0566a6SJani Nikula 
3208df0566a6SJani Nikula 		vco = dev_priv->skl_preferred_vco_freq;
3209aff35110SPankaj Bharadiya 		drm_WARN_ON(&dev_priv->drm, vco != 8100000 && vco != 8640000);
3210df0566a6SJani Nikula 
3211df0566a6SJani Nikula 		/*
3212df0566a6SJani Nikula 		 * Use the lower (vco 8640) cdclk values as a
3213df0566a6SJani Nikula 		 * first guess. skl_calc_cdclk() will correct it
3214df0566a6SJani Nikula 		 * if the preferred vco is 8100 instead.
3215df0566a6SJani Nikula 		 */
3216df0566a6SJani Nikula 		if (limit == SKL_DFSM_CDCLK_LIMIT_675)
3217df0566a6SJani Nikula 			max_cdclk = 617143;
3218df0566a6SJani Nikula 		else if (limit == SKL_DFSM_CDCLK_LIMIT_540)
3219df0566a6SJani Nikula 			max_cdclk = 540000;
3220df0566a6SJani Nikula 		else if (limit == SKL_DFSM_CDCLK_LIMIT_450)
3221df0566a6SJani Nikula 			max_cdclk = 432000;
3222df0566a6SJani Nikula 		else
3223df0566a6SJani Nikula 			max_cdclk = 308571;
3224df0566a6SJani Nikula 
3225d51309b4SJani Nikula 		dev_priv->display.cdclk.max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco);
3226df0566a6SJani Nikula 	} else if (IS_BROADWELL(dev_priv))  {
3227df0566a6SJani Nikula 		/*
3228df0566a6SJani Nikula 		 * FIXME with extra cooling we can allow
3229df0566a6SJani Nikula 		 * 540 MHz for ULX and 675 Mhz for ULT.
3230df0566a6SJani Nikula 		 * How can we know if extra cooling is
3231df0566a6SJani Nikula 		 * available? PCI ID, VTB, something else?
3232df0566a6SJani Nikula 		 */
32333e9f55dfSJani Nikula 		if (intel_de_read(dev_priv, FUSE_STRAP) & HSW_CDCLK_LIMIT)
3234d51309b4SJani Nikula 			dev_priv->display.cdclk.max_cdclk_freq = 450000;
3235c224d89cSDnyaneshwar Bhadane 		else if (IS_BROADWELL_ULX(dev_priv))
3236d51309b4SJani Nikula 			dev_priv->display.cdclk.max_cdclk_freq = 450000;
3237c224d89cSDnyaneshwar Bhadane 		else if (IS_BROADWELL_ULT(dev_priv))
3238d51309b4SJani Nikula 			dev_priv->display.cdclk.max_cdclk_freq = 540000;
3239df0566a6SJani Nikula 		else
3240d51309b4SJani Nikula 			dev_priv->display.cdclk.max_cdclk_freq = 675000;
3241df0566a6SJani Nikula 	} else if (IS_CHERRYVIEW(dev_priv)) {
3242d51309b4SJani Nikula 		dev_priv->display.cdclk.max_cdclk_freq = 320000;
3243df0566a6SJani Nikula 	} else if (IS_VALLEYVIEW(dev_priv)) {
3244d51309b4SJani Nikula 		dev_priv->display.cdclk.max_cdclk_freq = 400000;
3245df0566a6SJani Nikula 	} else {
3246df0566a6SJani Nikula 		/* otherwise assume cdclk is fixed */
3247d51309b4SJani Nikula 		dev_priv->display.cdclk.max_cdclk_freq = dev_priv->display.cdclk.hw.cdclk;
3248df0566a6SJani Nikula 	}
3249df0566a6SJani Nikula 
3250df0566a6SJani Nikula 	dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv);
3251df0566a6SJani Nikula 
325223194610SWambui Karuga 	drm_dbg(&dev_priv->drm, "Max CD clock rate: %d kHz\n",
3253d51309b4SJani Nikula 		dev_priv->display.cdclk.max_cdclk_freq);
3254df0566a6SJani Nikula 
325523194610SWambui Karuga 	drm_dbg(&dev_priv->drm, "Max dotclock rate: %d kHz\n",
3256df0566a6SJani Nikula 		dev_priv->max_dotclk_freq);
3257df0566a6SJani Nikula }
3258df0566a6SJani Nikula 
3259df0566a6SJani Nikula /**
3260df0566a6SJani Nikula  * intel_update_cdclk - Determine the current CDCLK frequency
3261df0566a6SJani Nikula  * @dev_priv: i915 device
3262df0566a6SJani Nikula  *
3263df0566a6SJani Nikula  * Determine the current CDCLK frequency.
3264df0566a6SJani Nikula  */
intel_update_cdclk(struct drm_i915_private * dev_priv)3265df0566a6SJani Nikula void intel_update_cdclk(struct drm_i915_private *dev_priv)
3266df0566a6SJani Nikula {
3267d51309b4SJani Nikula 	intel_cdclk_get_cdclk(dev_priv, &dev_priv->display.cdclk.hw);
3268df0566a6SJani Nikula 
3269df0566a6SJani Nikula 	/*
3270df0566a6SJani Nikula 	 * 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
3271df0566a6SJani Nikula 	 * Programmng [sic] note: bit[9:2] should be programmed to the number
3272df0566a6SJani Nikula 	 * of cdclk that generates 4MHz reference clock freq which is used to
3273df0566a6SJani Nikula 	 * generate GMBus clock. This will vary with the cdclk freq.
3274df0566a6SJani Nikula 	 */
3275df0566a6SJani Nikula 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
32763e9f55dfSJani Nikula 		intel_de_write(dev_priv, GMBUSFREQ_VLV,
3277d51309b4SJani Nikula 			       DIV_ROUND_UP(dev_priv->display.cdclk.hw.cdclk, 1000));
3278df0566a6SJani Nikula }
3279df0566a6SJani Nikula 
dg1_rawclk(struct drm_i915_private * dev_priv)328027a6bc80SMatt Roper static int dg1_rawclk(struct drm_i915_private *dev_priv)
328127a6bc80SMatt Roper {
328227a6bc80SMatt Roper 	/*
328327a6bc80SMatt Roper 	 * DG1 always uses a 38.4 MHz rawclk.  The bspec tells us
328427a6bc80SMatt Roper 	 * "Program Numerator=2, Denominator=4, Divider=37 decimal."
328527a6bc80SMatt Roper 	 */
3286507007fbSJani Nikula 	intel_de_write(dev_priv, PCH_RAWCLK_FREQ,
328727a6bc80SMatt Roper 		       CNP_RAWCLK_DEN(4) | CNP_RAWCLK_DIV(37) | ICP_RAWCLK_NUM(2));
328827a6bc80SMatt Roper 
328927a6bc80SMatt Roper 	return 38400;
329027a6bc80SMatt Roper }
329127a6bc80SMatt Roper 
cnp_rawclk(struct drm_i915_private * dev_priv)3292df0566a6SJani Nikula static int cnp_rawclk(struct drm_i915_private *dev_priv)
3293df0566a6SJani Nikula {
3294df0566a6SJani Nikula 	u32 rawclk;
3295df0566a6SJani Nikula 	int divider, fraction;
3296df0566a6SJani Nikula 
32973e9f55dfSJani Nikula 	if (intel_de_read(dev_priv, SFUSE_STRAP) & SFUSE_STRAP_RAW_FREQUENCY) {
3298df0566a6SJani Nikula 		/* 24 MHz */
3299df0566a6SJani Nikula 		divider = 24000;
3300df0566a6SJani Nikula 		fraction = 0;
3301df0566a6SJani Nikula 	} else {
3302df0566a6SJani Nikula 		/* 19.2 MHz */
3303df0566a6SJani Nikula 		divider = 19000;
3304df0566a6SJani Nikula 		fraction = 200;
3305df0566a6SJani Nikula 	}
3306df0566a6SJani Nikula 
3307df0566a6SJani Nikula 	rawclk = CNP_RAWCLK_DIV(divider / 1000);
3308df0566a6SJani Nikula 	if (fraction) {
3309df0566a6SJani Nikula 		int numerator = 1;
3310df0566a6SJani Nikula 
3311df0566a6SJani Nikula 		rawclk |= CNP_RAWCLK_DEN(DIV_ROUND_CLOSEST(numerator * 1000,
3312df0566a6SJani Nikula 							   fraction) - 1);
3313df0566a6SJani Nikula 		if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
3314df0566a6SJani Nikula 			rawclk |= ICP_RAWCLK_NUM(numerator);
3315df0566a6SJani Nikula 	}
3316df0566a6SJani Nikula 
33173e9f55dfSJani Nikula 	intel_de_write(dev_priv, PCH_RAWCLK_FREQ, rawclk);
3318df0566a6SJani Nikula 	return divider + fraction;
3319df0566a6SJani Nikula }
3320df0566a6SJani Nikula 
pch_rawclk(struct drm_i915_private * dev_priv)3321df0566a6SJani Nikula static int pch_rawclk(struct drm_i915_private *dev_priv)
3322df0566a6SJani Nikula {
33233e9f55dfSJani Nikula 	return (intel_de_read(dev_priv, PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK) * 1000;
3324df0566a6SJani Nikula }
3325df0566a6SJani Nikula 
vlv_hrawclk(struct drm_i915_private * dev_priv)3326df0566a6SJani Nikula static int vlv_hrawclk(struct drm_i915_private *dev_priv)
3327df0566a6SJani Nikula {
3328df0566a6SJani Nikula 	/* RAWCLK_FREQ_VLV register updated from power well code */
3329df0566a6SJani Nikula 	return vlv_get_cck_clock_hpll(dev_priv, "hrawclk",
3330df0566a6SJani Nikula 				      CCK_DISPLAY_REF_CLOCK_CONTROL);
3331df0566a6SJani Nikula }
3332df0566a6SJani Nikula 
i9xx_hrawclk(struct drm_i915_private * dev_priv)3333488e0179SVille Syrjälä static int i9xx_hrawclk(struct drm_i915_private *dev_priv)
3334df0566a6SJani Nikula {
3335df0566a6SJani Nikula 	u32 clkcfg;
3336df0566a6SJani Nikula 
333742ab3305SVille Syrjälä 	/*
333842ab3305SVille Syrjälä 	 * hrawclock is 1/4 the FSB frequency
333942ab3305SVille Syrjälä 	 *
334042ab3305SVille Syrjälä 	 * Note that this only reads the state of the FSB
334142ab3305SVille Syrjälä 	 * straps, not the actual FSB frequency. Some BIOSen
334242ab3305SVille Syrjälä 	 * let you configure each independently. Ideally we'd
334342ab3305SVille Syrjälä 	 * read out the actual FSB frequency but sadly we
334442ab3305SVille Syrjälä 	 * don't know which registers have that information,
334542ab3305SVille Syrjälä 	 * and all the relevant docs have gone to bit heaven :(
334642ab3305SVille Syrjälä 	 */
33476f62bda1SVille Syrjälä 	clkcfg = intel_de_read(dev_priv, CLKCFG) & CLKCFG_FSB_MASK;
33486f62bda1SVille Syrjälä 
3349488e0179SVille Syrjälä 	if (IS_MOBILE(dev_priv)) {
33506f62bda1SVille Syrjälä 		switch (clkcfg) {
3351df0566a6SJani Nikula 		case CLKCFG_FSB_400:
3352df0566a6SJani Nikula 			return 100000;
3353df0566a6SJani Nikula 		case CLKCFG_FSB_533:
3354df0566a6SJani Nikula 			return 133333;
3355df0566a6SJani Nikula 		case CLKCFG_FSB_667:
3356df0566a6SJani Nikula 			return 166667;
3357df0566a6SJani Nikula 		case CLKCFG_FSB_800:
3358df0566a6SJani Nikula 			return 200000;
3359df0566a6SJani Nikula 		case CLKCFG_FSB_1067:
3360df0566a6SJani Nikula 			return 266667;
3361df0566a6SJani Nikula 		case CLKCFG_FSB_1333:
3362df0566a6SJani Nikula 			return 333333;
3363df0566a6SJani Nikula 		default:
3364488e0179SVille Syrjälä 			MISSING_CASE(clkcfg);
3365df0566a6SJani Nikula 			return 133333;
3366df0566a6SJani Nikula 		}
3367488e0179SVille Syrjälä 	} else {
3368488e0179SVille Syrjälä 		switch (clkcfg) {
3369488e0179SVille Syrjälä 		case CLKCFG_FSB_400_ALT:
3370488e0179SVille Syrjälä 			return 100000;
3371488e0179SVille Syrjälä 		case CLKCFG_FSB_533:
3372488e0179SVille Syrjälä 			return 133333;
3373488e0179SVille Syrjälä 		case CLKCFG_FSB_667:
3374488e0179SVille Syrjälä 			return 166667;
3375488e0179SVille Syrjälä 		case CLKCFG_FSB_800:
3376488e0179SVille Syrjälä 			return 200000;
3377488e0179SVille Syrjälä 		case CLKCFG_FSB_1067_ALT:
3378488e0179SVille Syrjälä 			return 266667;
3379488e0179SVille Syrjälä 		case CLKCFG_FSB_1333_ALT:
3380488e0179SVille Syrjälä 			return 333333;
3381488e0179SVille Syrjälä 		case CLKCFG_FSB_1600_ALT:
3382488e0179SVille Syrjälä 			return 400000;
3383488e0179SVille Syrjälä 		default:
3384488e0179SVille Syrjälä 			return 133333;
3385488e0179SVille Syrjälä 		}
3386488e0179SVille Syrjälä 	}
3387df0566a6SJani Nikula }
3388df0566a6SJani Nikula 
3389df0566a6SJani Nikula /**
3390b04002f4SChris Wilson  * intel_read_rawclk - Determine the current RAWCLK frequency
3391df0566a6SJani Nikula  * @dev_priv: i915 device
3392df0566a6SJani Nikula  *
3393df0566a6SJani Nikula  * Determine the current RAWCLK frequency. RAWCLK is a fixed
3394df0566a6SJani Nikula  * frequency clock so this needs to done only once.
3395df0566a6SJani Nikula  */
intel_read_rawclk(struct drm_i915_private * dev_priv)3396b04002f4SChris Wilson u32 intel_read_rawclk(struct drm_i915_private *dev_priv)
3397df0566a6SJani Nikula {
3398b04002f4SChris Wilson 	u32 freq;
3399b04002f4SChris Wilson 
340027a6bc80SMatt Roper 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
340127a6bc80SMatt Roper 		freq = dg1_rawclk(dev_priv);
3402dc35583bSClint Taylor 	else if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTP)
3403dc35583bSClint Taylor 		/*
3404dc35583bSClint Taylor 		 * MTL always uses a 38.4 MHz rawclk.  The bspec tells us
3405dc35583bSClint Taylor 		 * "RAWCLK_FREQ defaults to the values for 38.4 and does
3406dc35583bSClint Taylor 		 * not need to be programmed."
3407dc35583bSClint Taylor 		 */
3408dc35583bSClint Taylor 		freq = 38400;
340927a6bc80SMatt Roper 	else if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
3410b04002f4SChris Wilson 		freq = cnp_rawclk(dev_priv);
3411df0566a6SJani Nikula 	else if (HAS_PCH_SPLIT(dev_priv))
3412b04002f4SChris Wilson 		freq = pch_rawclk(dev_priv);
3413df0566a6SJani Nikula 	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
3414b04002f4SChris Wilson 		freq = vlv_hrawclk(dev_priv);
3415005e9537SMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 3)
3416488e0179SVille Syrjälä 		freq = i9xx_hrawclk(dev_priv);
3417df0566a6SJani Nikula 	else
3418df0566a6SJani Nikula 		/* no rawclk on other platforms, or no need to know it */
3419b04002f4SChris Wilson 		return 0;
3420df0566a6SJani Nikula 
3421b04002f4SChris Wilson 	return freq;
3422df0566a6SJani Nikula }
3423df0566a6SJani Nikula 
i915_cdclk_info_show(struct seq_file * m,void * unused)3424d7c281eeSBhanuprakash Modem static int i915_cdclk_info_show(struct seq_file *m, void *unused)
3425d7c281eeSBhanuprakash Modem {
3426d7c281eeSBhanuprakash Modem 	struct drm_i915_private *i915 = m->private;
3427d7c281eeSBhanuprakash Modem 
3428d7c281eeSBhanuprakash Modem 	seq_printf(m, "Current CD clock frequency: %d kHz\n", i915->display.cdclk.hw.cdclk);
3429d7c281eeSBhanuprakash Modem 	seq_printf(m, "Max CD clock frequency: %d kHz\n", i915->display.cdclk.max_cdclk_freq);
3430d7c281eeSBhanuprakash Modem 	seq_printf(m, "Max pixel clock frequency: %d kHz\n", i915->max_dotclk_freq);
3431d7c281eeSBhanuprakash Modem 
3432d7c281eeSBhanuprakash Modem 	return 0;
3433d7c281eeSBhanuprakash Modem }
3434d7c281eeSBhanuprakash Modem 
3435d7c281eeSBhanuprakash Modem DEFINE_SHOW_ATTRIBUTE(i915_cdclk_info);
3436d7c281eeSBhanuprakash Modem 
intel_cdclk_debugfs_register(struct drm_i915_private * i915)3437d7c281eeSBhanuprakash Modem void intel_cdclk_debugfs_register(struct drm_i915_private *i915)
3438d7c281eeSBhanuprakash Modem {
3439d7c281eeSBhanuprakash Modem 	struct drm_minor *minor = i915->drm.primary;
3440d7c281eeSBhanuprakash Modem 
3441d7c281eeSBhanuprakash Modem 	debugfs_create_file("i915_cdclk_info", 0444, minor->debugfs_root,
3442d7c281eeSBhanuprakash Modem 			    i915, &i915_cdclk_info_fops);
3443d7c281eeSBhanuprakash Modem }
3444d7c281eeSBhanuprakash Modem 
344586c0ef72SAnusha Srivatsa static const struct intel_cdclk_funcs mtl_cdclk_funcs = {
344686c0ef72SAnusha Srivatsa 	.get_cdclk = bxt_get_cdclk,
344786c0ef72SAnusha Srivatsa 	.set_cdclk = bxt_set_cdclk,
344886c0ef72SAnusha Srivatsa 	.modeset_calc_cdclk = bxt_modeset_calc_cdclk,
344986c0ef72SAnusha Srivatsa 	.calc_voltage_level = tgl_calc_voltage_level,
345086c0ef72SAnusha Srivatsa };
345186c0ef72SAnusha Srivatsa 
34525a3c46b8SChaitanya Kumar Borah static const struct intel_cdclk_funcs rplu_cdclk_funcs = {
34535a3c46b8SChaitanya Kumar Borah 	.get_cdclk = bxt_get_cdclk,
34545a3c46b8SChaitanya Kumar Borah 	.set_cdclk = bxt_set_cdclk,
34555a3c46b8SChaitanya Kumar Borah 	.modeset_calc_cdclk = bxt_modeset_calc_cdclk,
34565a3c46b8SChaitanya Kumar Borah 	.calc_voltage_level = rplu_calc_voltage_level,
34575a3c46b8SChaitanya Kumar Borah };
34585a3c46b8SChaitanya Kumar Borah 
3459877d0749SJani Nikula static const struct intel_cdclk_funcs tgl_cdclk_funcs = {
34606b4cd9cbSDave Airlie 	.get_cdclk = bxt_get_cdclk,
34616b4cd9cbSDave Airlie 	.set_cdclk = bxt_set_cdclk,
34626b4cd9cbSDave Airlie 	.modeset_calc_cdclk = bxt_modeset_calc_cdclk,
34636b4cd9cbSDave Airlie 	.calc_voltage_level = tgl_calc_voltage_level,
34646b4cd9cbSDave Airlie };
34656b4cd9cbSDave Airlie 
3466877d0749SJani Nikula static const struct intel_cdclk_funcs ehl_cdclk_funcs = {
34676b4cd9cbSDave Airlie 	.get_cdclk = bxt_get_cdclk,
34686b4cd9cbSDave Airlie 	.set_cdclk = bxt_set_cdclk,
34696b4cd9cbSDave Airlie 	.modeset_calc_cdclk = bxt_modeset_calc_cdclk,
34706b4cd9cbSDave Airlie 	.calc_voltage_level = ehl_calc_voltage_level,
34716b4cd9cbSDave Airlie };
34726b4cd9cbSDave Airlie 
3473877d0749SJani Nikula static const struct intel_cdclk_funcs icl_cdclk_funcs = {
34746b4cd9cbSDave Airlie 	.get_cdclk = bxt_get_cdclk,
34756b4cd9cbSDave Airlie 	.set_cdclk = bxt_set_cdclk,
34766b4cd9cbSDave Airlie 	.modeset_calc_cdclk = bxt_modeset_calc_cdclk,
34776b4cd9cbSDave Airlie 	.calc_voltage_level = icl_calc_voltage_level,
34786b4cd9cbSDave Airlie };
34796b4cd9cbSDave Airlie 
3480877d0749SJani Nikula static const struct intel_cdclk_funcs bxt_cdclk_funcs = {
34816b4cd9cbSDave Airlie 	.get_cdclk = bxt_get_cdclk,
34826b4cd9cbSDave Airlie 	.set_cdclk = bxt_set_cdclk,
34836b4cd9cbSDave Airlie 	.modeset_calc_cdclk = bxt_modeset_calc_cdclk,
34846b4cd9cbSDave Airlie 	.calc_voltage_level = bxt_calc_voltage_level,
34856b4cd9cbSDave Airlie };
34866b4cd9cbSDave Airlie 
3487877d0749SJani Nikula static const struct intel_cdclk_funcs skl_cdclk_funcs = {
34886b4cd9cbSDave Airlie 	.get_cdclk = skl_get_cdclk,
34896b4cd9cbSDave Airlie 	.set_cdclk = skl_set_cdclk,
34906b4cd9cbSDave Airlie 	.modeset_calc_cdclk = skl_modeset_calc_cdclk,
34916b4cd9cbSDave Airlie };
34926b4cd9cbSDave Airlie 
3493877d0749SJani Nikula static const struct intel_cdclk_funcs bdw_cdclk_funcs = {
34946b4cd9cbSDave Airlie 	.get_cdclk = bdw_get_cdclk,
34956b4cd9cbSDave Airlie 	.set_cdclk = bdw_set_cdclk,
34966b4cd9cbSDave Airlie 	.modeset_calc_cdclk = bdw_modeset_calc_cdclk,
34976b4cd9cbSDave Airlie };
34986b4cd9cbSDave Airlie 
3499877d0749SJani Nikula static const struct intel_cdclk_funcs chv_cdclk_funcs = {
35006b4cd9cbSDave Airlie 	.get_cdclk = vlv_get_cdclk,
35016b4cd9cbSDave Airlie 	.set_cdclk = chv_set_cdclk,
35026b4cd9cbSDave Airlie 	.modeset_calc_cdclk = vlv_modeset_calc_cdclk,
35036b4cd9cbSDave Airlie };
35046b4cd9cbSDave Airlie 
3505877d0749SJani Nikula static const struct intel_cdclk_funcs vlv_cdclk_funcs = {
35066b4cd9cbSDave Airlie 	.get_cdclk = vlv_get_cdclk,
35076b4cd9cbSDave Airlie 	.set_cdclk = vlv_set_cdclk,
35086b4cd9cbSDave Airlie 	.modeset_calc_cdclk = vlv_modeset_calc_cdclk,
35096b4cd9cbSDave Airlie };
35106b4cd9cbSDave Airlie 
3511877d0749SJani Nikula static const struct intel_cdclk_funcs hsw_cdclk_funcs = {
35126b4cd9cbSDave Airlie 	.get_cdclk = hsw_get_cdclk,
35136b4cd9cbSDave Airlie 	.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
35146b4cd9cbSDave Airlie };
35156b4cd9cbSDave Airlie 
35166b4cd9cbSDave Airlie /* SNB, IVB, 965G, 945G */
3517877d0749SJani Nikula static const struct intel_cdclk_funcs fixed_400mhz_cdclk_funcs = {
35186b4cd9cbSDave Airlie 	.get_cdclk = fixed_400mhz_get_cdclk,
35196b4cd9cbSDave Airlie 	.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
35206b4cd9cbSDave Airlie };
35216b4cd9cbSDave Airlie 
3522877d0749SJani Nikula static const struct intel_cdclk_funcs ilk_cdclk_funcs = {
35236b4cd9cbSDave Airlie 	.get_cdclk = fixed_450mhz_get_cdclk,
35246b4cd9cbSDave Airlie 	.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
35256b4cd9cbSDave Airlie };
35266b4cd9cbSDave Airlie 
3527877d0749SJani Nikula static const struct intel_cdclk_funcs gm45_cdclk_funcs = {
35286b4cd9cbSDave Airlie 	.get_cdclk = gm45_get_cdclk,
35296b4cd9cbSDave Airlie 	.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
35306b4cd9cbSDave Airlie };
35316b4cd9cbSDave Airlie 
35326b4cd9cbSDave Airlie /* G45 uses G33 */
35336b4cd9cbSDave Airlie 
3534877d0749SJani Nikula static const struct intel_cdclk_funcs i965gm_cdclk_funcs = {
35356b4cd9cbSDave Airlie 	.get_cdclk = i965gm_get_cdclk,
35366b4cd9cbSDave Airlie 	.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
35376b4cd9cbSDave Airlie };
35386b4cd9cbSDave Airlie 
35396b4cd9cbSDave Airlie /* i965G uses fixed 400 */
35406b4cd9cbSDave Airlie 
3541877d0749SJani Nikula static const struct intel_cdclk_funcs pnv_cdclk_funcs = {
35426b4cd9cbSDave Airlie 	.get_cdclk = pnv_get_cdclk,
35436b4cd9cbSDave Airlie 	.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
35446b4cd9cbSDave Airlie };
35456b4cd9cbSDave Airlie 
3546877d0749SJani Nikula static const struct intel_cdclk_funcs g33_cdclk_funcs = {
35476b4cd9cbSDave Airlie 	.get_cdclk = g33_get_cdclk,
35486b4cd9cbSDave Airlie 	.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
35496b4cd9cbSDave Airlie };
35506b4cd9cbSDave Airlie 
3551877d0749SJani Nikula static const struct intel_cdclk_funcs i945gm_cdclk_funcs = {
35526b4cd9cbSDave Airlie 	.get_cdclk = i945gm_get_cdclk,
35536b4cd9cbSDave Airlie 	.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
35546b4cd9cbSDave Airlie };
35556b4cd9cbSDave Airlie 
35566b4cd9cbSDave Airlie /* i945G uses fixed 400 */
35576b4cd9cbSDave Airlie 
3558877d0749SJani Nikula static const struct intel_cdclk_funcs i915gm_cdclk_funcs = {
35596b4cd9cbSDave Airlie 	.get_cdclk = i915gm_get_cdclk,
35606b4cd9cbSDave Airlie 	.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
35616b4cd9cbSDave Airlie };
35626b4cd9cbSDave Airlie 
3563877d0749SJani Nikula static const struct intel_cdclk_funcs i915g_cdclk_funcs = {
35646b4cd9cbSDave Airlie 	.get_cdclk = fixed_333mhz_get_cdclk,
35656b4cd9cbSDave Airlie 	.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
35666b4cd9cbSDave Airlie };
35676b4cd9cbSDave Airlie 
3568877d0749SJani Nikula static const struct intel_cdclk_funcs i865g_cdclk_funcs = {
35696b4cd9cbSDave Airlie 	.get_cdclk = fixed_266mhz_get_cdclk,
35706b4cd9cbSDave Airlie 	.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
35716b4cd9cbSDave Airlie };
35726b4cd9cbSDave Airlie 
3573877d0749SJani Nikula static const struct intel_cdclk_funcs i85x_cdclk_funcs = {
35746b4cd9cbSDave Airlie 	.get_cdclk = i85x_get_cdclk,
35756b4cd9cbSDave Airlie 	.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
35766b4cd9cbSDave Airlie };
35776b4cd9cbSDave Airlie 
3578877d0749SJani Nikula static const struct intel_cdclk_funcs i845g_cdclk_funcs = {
35796b4cd9cbSDave Airlie 	.get_cdclk = fixed_200mhz_get_cdclk,
35806b4cd9cbSDave Airlie 	.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
35816b4cd9cbSDave Airlie };
35826b4cd9cbSDave Airlie 
3583877d0749SJani Nikula static const struct intel_cdclk_funcs i830_cdclk_funcs = {
35846b4cd9cbSDave Airlie 	.get_cdclk = fixed_133mhz_get_cdclk,
35856b4cd9cbSDave Airlie 	.modeset_calc_cdclk = fixed_modeset_calc_cdclk,
35866b4cd9cbSDave Airlie };
35876b4cd9cbSDave Airlie 
3588df0566a6SJani Nikula /**
3589df0566a6SJani Nikula  * intel_init_cdclk_hooks - Initialize CDCLK related modesetting hooks
3590df0566a6SJani Nikula  * @dev_priv: i915 device
3591df0566a6SJani Nikula  */
intel_init_cdclk_hooks(struct drm_i915_private * dev_priv)3592df0566a6SJani Nikula void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
3593df0566a6SJani Nikula {
359486c0ef72SAnusha Srivatsa 	if (IS_METEORLAKE(dev_priv)) {
359586c0ef72SAnusha Srivatsa 		dev_priv->display.funcs.cdclk = &mtl_cdclk_funcs;
359686c0ef72SAnusha Srivatsa 		dev_priv->display.cdclk.table = mtl_cdclk_table;
359786c0ef72SAnusha Srivatsa 	} else if (IS_DG2(dev_priv)) {
3598986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &tgl_cdclk_funcs;
3599d51309b4SJani Nikula 		dev_priv->display.cdclk.table = dg2_cdclk_table;
36001f3e84c4SMatt Roper 	} else if (IS_ALDERLAKE_P(dev_priv)) {
36011d2b8fd9SJosé Roberto de Souza 		/* Wa_22011320316:adl-p[a0] */
3602cc0c986aSDnyaneshwar Bhadane 		if (IS_ALDERLAKE_P(dev_priv) && IS_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) {
3603d51309b4SJani Nikula 			dev_priv->display.cdclk.table = adlp_a_step_cdclk_table;
36045a3c46b8SChaitanya Kumar Borah 			dev_priv->display.funcs.cdclk = &tgl_cdclk_funcs;
3605e5706c04SDnyaneshwar Bhadane 		} else if (IS_RAPTORLAKE_U(dev_priv)) {
360606f1b06dSChaitanya Kumar Borah 			dev_priv->display.cdclk.table = rplu_cdclk_table;
36075a3c46b8SChaitanya Kumar Borah 			dev_priv->display.funcs.cdclk = &rplu_cdclk_funcs;
36085a3c46b8SChaitanya Kumar Borah 		} else {
3609d51309b4SJani Nikula 			dev_priv->display.cdclk.table = adlp_cdclk_table;
36105a3c46b8SChaitanya Kumar Borah 			dev_priv->display.funcs.cdclk = &tgl_cdclk_funcs;
36115a3c46b8SChaitanya Kumar Borah 		}
3612626426ffSAnusha Srivatsa 	} else if (IS_ROCKETLAKE(dev_priv)) {
3613986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &tgl_cdclk_funcs;
3614d51309b4SJani Nikula 		dev_priv->display.cdclk.table = rkl_cdclk_table;
3615005e9537SMatt Roper 	} else if (DISPLAY_VER(dev_priv) >= 12) {
3616986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &tgl_cdclk_funcs;
3617d51309b4SJani Nikula 		dev_priv->display.cdclk.table = icl_cdclk_table;
36180c65dc06SDnyaneshwar Bhadane 	} else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) {
3619986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &ehl_cdclk_funcs;
3620d51309b4SJani Nikula 		dev_priv->display.cdclk.table = icl_cdclk_table;
3621005e9537SMatt Roper 	} else if (DISPLAY_VER(dev_priv) >= 11) {
3622986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &icl_cdclk_funcs;
3623d51309b4SJani Nikula 		dev_priv->display.cdclk.table = icl_cdclk_table;
36242446e1d6SMatt Roper 	} else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
3625986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &bxt_cdclk_funcs;
362643ed2275SChris Wilson 		if (IS_GEMINILAKE(dev_priv))
3627d51309b4SJani Nikula 			dev_priv->display.cdclk.table = glk_cdclk_table;
362843ed2275SChris Wilson 		else
3629d51309b4SJani Nikula 			dev_priv->display.cdclk.table = bxt_cdclk_table;
363093e7e61eSLucas De Marchi 	} else if (DISPLAY_VER(dev_priv) == 9) {
3631986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &skl_cdclk_funcs;
3632df0566a6SJani Nikula 	} else if (IS_BROADWELL(dev_priv)) {
3633986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &bdw_cdclk_funcs;
36346b4cd9cbSDave Airlie 	} else if (IS_HASWELL(dev_priv)) {
3635986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &hsw_cdclk_funcs;
3636df0566a6SJani Nikula 	} else if (IS_CHERRYVIEW(dev_priv)) {
3637986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &chv_cdclk_funcs;
3638df0566a6SJani Nikula 	} else if (IS_VALLEYVIEW(dev_priv)) {
3639986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &vlv_cdclk_funcs;
36406b4cd9cbSDave Airlie 	} else if (IS_SANDYBRIDGE(dev_priv) || IS_IVYBRIDGE(dev_priv)) {
3641986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &fixed_400mhz_cdclk_funcs;
36426b4cd9cbSDave Airlie 	} else if (IS_IRONLAKE(dev_priv)) {
3643986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &ilk_cdclk_funcs;
36446b4cd9cbSDave Airlie 	} else if (IS_GM45(dev_priv)) {
3645986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &gm45_cdclk_funcs;
36466b4cd9cbSDave Airlie 	} else if (IS_G45(dev_priv)) {
3647986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &g33_cdclk_funcs;
36486b4cd9cbSDave Airlie 	} else if (IS_I965GM(dev_priv)) {
3649986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &i965gm_cdclk_funcs;
36506b4cd9cbSDave Airlie 	} else if (IS_I965G(dev_priv)) {
3651986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &fixed_400mhz_cdclk_funcs;
36526b4cd9cbSDave Airlie 	} else if (IS_PINEVIEW(dev_priv)) {
3653986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &pnv_cdclk_funcs;
36546b4cd9cbSDave Airlie 	} else if (IS_G33(dev_priv)) {
3655986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &g33_cdclk_funcs;
36566b4cd9cbSDave Airlie 	} else if (IS_I945GM(dev_priv)) {
3657986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &i945gm_cdclk_funcs;
36586b4cd9cbSDave Airlie 	} else if (IS_I945G(dev_priv)) {
3659986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &fixed_400mhz_cdclk_funcs;
36606b4cd9cbSDave Airlie 	} else if (IS_I915GM(dev_priv)) {
3661986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &i915gm_cdclk_funcs;
36626b4cd9cbSDave Airlie 	} else if (IS_I915G(dev_priv)) {
3663986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &i915g_cdclk_funcs;
36646b4cd9cbSDave Airlie 	} else if (IS_I865G(dev_priv)) {
3665986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &i865g_cdclk_funcs;
36666b4cd9cbSDave Airlie 	} else if (IS_I85X(dev_priv)) {
3667986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &i85x_cdclk_funcs;
36686b4cd9cbSDave Airlie 	} else if (IS_I845G(dev_priv)) {
3669986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &i845g_cdclk_funcs;
36706b4cd9cbSDave Airlie 	} else if (IS_I830(dev_priv)) {
3671986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &i830_cdclk_funcs;
3672df0566a6SJani Nikula 	}
3673df0566a6SJani Nikula 
3674986531bdSJani Nikula 	if (drm_WARN(&dev_priv->drm, !dev_priv->display.funcs.cdclk,
36756b4cd9cbSDave Airlie 		     "Unknown platform. Assuming i830\n"))
3676986531bdSJani Nikula 		dev_priv->display.funcs.cdclk = &i830_cdclk_funcs;
3677df0566a6SJani Nikula }
3678