xref: /dragonfly/sys/dev/drm/i915/intel_cdclk.c (revision 3f2dd94a)
1a85cb24fSFrançois Tigeot /*
2a85cb24fSFrançois Tigeot  * Copyright © 2006-2017 Intel Corporation
3a85cb24fSFrançois Tigeot  *
4a85cb24fSFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
5a85cb24fSFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
6a85cb24fSFrançois Tigeot  * to deal in the Software without restriction, including without limitation
7a85cb24fSFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8a85cb24fSFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
9a85cb24fSFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
10a85cb24fSFrançois Tigeot  *
11a85cb24fSFrançois Tigeot  * The above copyright notice and this permission notice (including the next
12a85cb24fSFrançois Tigeot  * paragraph) shall be included in all copies or substantial portions of the
13a85cb24fSFrançois Tigeot  * Software.
14a85cb24fSFrançois Tigeot  *
15a85cb24fSFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16a85cb24fSFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17a85cb24fSFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18a85cb24fSFrançois Tigeot  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19a85cb24fSFrançois Tigeot  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20a85cb24fSFrançois Tigeot  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21a85cb24fSFrançois Tigeot  * DEALINGS IN THE SOFTWARE.
22a85cb24fSFrançois Tigeot  */
23a85cb24fSFrançois Tigeot 
24a85cb24fSFrançois Tigeot #include "intel_drv.h"
25a85cb24fSFrançois Tigeot 
26a85cb24fSFrançois Tigeot /**
27a85cb24fSFrançois Tigeot  * DOC: CDCLK / RAWCLK
28a85cb24fSFrançois Tigeot  *
29a85cb24fSFrançois Tigeot  * The display engine uses several different clocks to do its work. There
30a85cb24fSFrançois Tigeot  * are two main clocks involved that aren't directly related to the actual
31a85cb24fSFrançois Tigeot  * pixel clock or any symbol/bit clock of the actual output port. These
32a85cb24fSFrançois Tigeot  * are the core display clock (CDCLK) and RAWCLK.
33a85cb24fSFrançois Tigeot  *
34a85cb24fSFrançois Tigeot  * CDCLK clocks most of the display pipe logic, and thus its frequency
35a85cb24fSFrançois Tigeot  * must be high enough to support the rate at which pixels are flowing
36a85cb24fSFrançois Tigeot  * through the pipes. Downscaling must also be accounted as that increases
37a85cb24fSFrançois Tigeot  * the effective pixel rate.
38a85cb24fSFrançois Tigeot  *
39a85cb24fSFrançois Tigeot  * On several platforms the CDCLK frequency can be changed dynamically
40a85cb24fSFrançois Tigeot  * to minimize power consumption for a given display configuration.
41a85cb24fSFrançois Tigeot  * Typically changes to the CDCLK frequency require all the display pipes
42a85cb24fSFrançois Tigeot  * to be shut down while the frequency is being changed.
43a85cb24fSFrançois Tigeot  *
44a85cb24fSFrançois Tigeot  * On SKL+ the DMC will toggle the CDCLK off/on during DC5/6 entry/exit.
45a85cb24fSFrançois Tigeot  * DMC will not change the active CDCLK frequency however, so that part
46a85cb24fSFrançois Tigeot  * will still be performed by the driver directly.
47a85cb24fSFrançois Tigeot  *
48a85cb24fSFrançois Tigeot  * RAWCLK is a fixed frequency clock, often used by various auxiliary
49a85cb24fSFrançois Tigeot  * blocks such as AUX CH or backlight PWM. Hence the only thing we
50a85cb24fSFrançois Tigeot  * really need to know about RAWCLK is its frequency so that various
51a85cb24fSFrançois Tigeot  * dividers can be programmed correctly.
52a85cb24fSFrançois Tigeot  */
53a85cb24fSFrançois Tigeot 
fixed_133mhz_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)54a85cb24fSFrançois Tigeot static void fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv,
55a85cb24fSFrançois Tigeot 				   struct intel_cdclk_state *cdclk_state)
56a85cb24fSFrançois Tigeot {
57a85cb24fSFrançois Tigeot 	cdclk_state->cdclk = 133333;
58a85cb24fSFrançois Tigeot }
59a85cb24fSFrançois Tigeot 
fixed_200mhz_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)60a85cb24fSFrançois Tigeot static void fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv,
61a85cb24fSFrançois Tigeot 				   struct intel_cdclk_state *cdclk_state)
62a85cb24fSFrançois Tigeot {
63a85cb24fSFrançois Tigeot 	cdclk_state->cdclk = 200000;
64a85cb24fSFrançois Tigeot }
65a85cb24fSFrançois Tigeot 
fixed_266mhz_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)66a85cb24fSFrançois Tigeot static void fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv,
67a85cb24fSFrançois Tigeot 				   struct intel_cdclk_state *cdclk_state)
68a85cb24fSFrançois Tigeot {
69a85cb24fSFrançois Tigeot 	cdclk_state->cdclk = 266667;
70a85cb24fSFrançois Tigeot }
71a85cb24fSFrançois Tigeot 
fixed_333mhz_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)72a85cb24fSFrançois Tigeot static void fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv,
73a85cb24fSFrançois Tigeot 				   struct intel_cdclk_state *cdclk_state)
74a85cb24fSFrançois Tigeot {
75a85cb24fSFrançois Tigeot 	cdclk_state->cdclk = 333333;
76a85cb24fSFrançois Tigeot }
77a85cb24fSFrançois Tigeot 
fixed_400mhz_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)78a85cb24fSFrançois Tigeot static void fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv,
79a85cb24fSFrançois Tigeot 				   struct intel_cdclk_state *cdclk_state)
80a85cb24fSFrançois Tigeot {
81a85cb24fSFrançois Tigeot 	cdclk_state->cdclk = 400000;
82a85cb24fSFrançois Tigeot }
83a85cb24fSFrançois Tigeot 
fixed_450mhz_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)84a85cb24fSFrançois Tigeot static void fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv,
85a85cb24fSFrançois Tigeot 				   struct intel_cdclk_state *cdclk_state)
86a85cb24fSFrançois Tigeot {
87a85cb24fSFrançois Tigeot 	cdclk_state->cdclk = 450000;
88a85cb24fSFrançois Tigeot }
89a85cb24fSFrançois Tigeot 
i85x_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)90a85cb24fSFrançois Tigeot static void i85x_get_cdclk(struct drm_i915_private *dev_priv,
91a85cb24fSFrançois Tigeot 			   struct intel_cdclk_state *cdclk_state)
92a85cb24fSFrançois Tigeot {
93a85cb24fSFrançois Tigeot 	struct pci_dev *pdev = dev_priv->drm.pdev;
94a85cb24fSFrançois Tigeot 	u16 hpllcc = 0;
95a85cb24fSFrançois Tigeot 
96a85cb24fSFrançois Tigeot 	/*
97a85cb24fSFrançois Tigeot 	 * 852GM/852GMV only supports 133 MHz and the HPLLCC
98a85cb24fSFrançois Tigeot 	 * encoding is different :(
99a85cb24fSFrançois Tigeot 	 * FIXME is this the right way to detect 852GM/852GMV?
100a85cb24fSFrançois Tigeot 	 */
101a85cb24fSFrançois Tigeot 	if (pdev->revision == 0x1) {
102a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 133333;
103a85cb24fSFrançois Tigeot 		return;
104a85cb24fSFrançois Tigeot 	}
105a85cb24fSFrançois Tigeot 
106a85cb24fSFrançois Tigeot 	pci_bus_read_config_word(pdev->bus,
107a85cb24fSFrançois Tigeot 				 PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
108a85cb24fSFrançois Tigeot 
109a85cb24fSFrançois Tigeot 	/* Assume that the hardware is in the high speed state.  This
110a85cb24fSFrançois Tigeot 	 * should be the default.
111a85cb24fSFrançois Tigeot 	 */
112a85cb24fSFrançois Tigeot 	switch (hpllcc & GC_CLOCK_CONTROL_MASK) {
113a85cb24fSFrançois Tigeot 	case GC_CLOCK_133_200:
114a85cb24fSFrançois Tigeot 	case GC_CLOCK_133_200_2:
115a85cb24fSFrançois Tigeot 	case GC_CLOCK_100_200:
116a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 200000;
117a85cb24fSFrançois Tigeot 		break;
118a85cb24fSFrançois Tigeot 	case GC_CLOCK_166_250:
119a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 250000;
120a85cb24fSFrançois Tigeot 		break;
121a85cb24fSFrançois Tigeot 	case GC_CLOCK_100_133:
122a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 133333;
123a85cb24fSFrançois Tigeot 		break;
124a85cb24fSFrançois Tigeot 	case GC_CLOCK_133_266:
125a85cb24fSFrançois Tigeot 	case GC_CLOCK_133_266_2:
126a85cb24fSFrançois Tigeot 	case GC_CLOCK_166_266:
127a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 266667;
128a85cb24fSFrançois Tigeot 		break;
129a85cb24fSFrançois Tigeot 	}
130a85cb24fSFrançois Tigeot }
131a85cb24fSFrançois Tigeot 
i915gm_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)132a85cb24fSFrançois Tigeot static void i915gm_get_cdclk(struct drm_i915_private *dev_priv,
133a85cb24fSFrançois Tigeot 			     struct intel_cdclk_state *cdclk_state)
134a85cb24fSFrançois Tigeot {
135a85cb24fSFrançois Tigeot 	struct pci_dev *pdev = dev_priv->drm.pdev;
136a85cb24fSFrançois Tigeot 	u16 gcfgc = 0;
137a85cb24fSFrançois Tigeot 
138a85cb24fSFrançois Tigeot 	pci_read_config_word(pdev, GCFGC, &gcfgc);
139a85cb24fSFrançois Tigeot 
140a85cb24fSFrançois Tigeot 	if (gcfgc & GC_LOW_FREQUENCY_ENABLE) {
141a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 133333;
142a85cb24fSFrançois Tigeot 		return;
143a85cb24fSFrançois Tigeot 	}
144a85cb24fSFrançois Tigeot 
145a85cb24fSFrançois Tigeot 	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
146a85cb24fSFrançois Tigeot 	case GC_DISPLAY_CLOCK_333_320_MHZ:
147a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 333333;
148a85cb24fSFrançois Tigeot 		break;
149a85cb24fSFrançois Tigeot 	default:
150a85cb24fSFrançois Tigeot 	case GC_DISPLAY_CLOCK_190_200_MHZ:
151a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 190000;
152a85cb24fSFrançois Tigeot 		break;
153a85cb24fSFrançois Tigeot 	}
154a85cb24fSFrançois Tigeot }
155a85cb24fSFrançois Tigeot 
i945gm_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)156a85cb24fSFrançois Tigeot static void i945gm_get_cdclk(struct drm_i915_private *dev_priv,
157a85cb24fSFrançois Tigeot 			     struct intel_cdclk_state *cdclk_state)
158a85cb24fSFrançois Tigeot {
159a85cb24fSFrançois Tigeot 	struct pci_dev *pdev = dev_priv->drm.pdev;
160a85cb24fSFrançois Tigeot 	u16 gcfgc = 0;
161a85cb24fSFrançois Tigeot 
162a85cb24fSFrançois Tigeot 	pci_read_config_word(pdev, GCFGC, &gcfgc);
163a85cb24fSFrançois Tigeot 
164a85cb24fSFrançois Tigeot 	if (gcfgc & GC_LOW_FREQUENCY_ENABLE) {
165a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 133333;
166a85cb24fSFrançois Tigeot 		return;
167a85cb24fSFrançois Tigeot 	}
168a85cb24fSFrançois Tigeot 
169a85cb24fSFrançois Tigeot 	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
170a85cb24fSFrançois Tigeot 	case GC_DISPLAY_CLOCK_333_320_MHZ:
171a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 320000;
172a85cb24fSFrançois Tigeot 		break;
173a85cb24fSFrançois Tigeot 	default:
174a85cb24fSFrançois Tigeot 	case GC_DISPLAY_CLOCK_190_200_MHZ:
175a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 200000;
176a85cb24fSFrançois Tigeot 		break;
177a85cb24fSFrançois Tigeot 	}
178a85cb24fSFrançois Tigeot }
179a85cb24fSFrançois Tigeot 
intel_hpll_vco(struct drm_i915_private * dev_priv)180a85cb24fSFrançois Tigeot static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
181a85cb24fSFrançois Tigeot {
182a85cb24fSFrançois Tigeot 	static const unsigned int blb_vco[8] = {
183a85cb24fSFrançois Tigeot 		[0] = 3200000,
184a85cb24fSFrançois Tigeot 		[1] = 4000000,
185a85cb24fSFrançois Tigeot 		[2] = 5333333,
186a85cb24fSFrançois Tigeot 		[3] = 4800000,
187a85cb24fSFrançois Tigeot 		[4] = 6400000,
188a85cb24fSFrançois Tigeot 	};
189a85cb24fSFrançois Tigeot 	static const unsigned int pnv_vco[8] = {
190a85cb24fSFrançois Tigeot 		[0] = 3200000,
191a85cb24fSFrançois Tigeot 		[1] = 4000000,
192a85cb24fSFrançois Tigeot 		[2] = 5333333,
193a85cb24fSFrançois Tigeot 		[3] = 4800000,
194a85cb24fSFrançois Tigeot 		[4] = 2666667,
195a85cb24fSFrançois Tigeot 	};
196a85cb24fSFrançois Tigeot 	static const unsigned int cl_vco[8] = {
197a85cb24fSFrançois Tigeot 		[0] = 3200000,
198a85cb24fSFrançois Tigeot 		[1] = 4000000,
199a85cb24fSFrançois Tigeot 		[2] = 5333333,
200a85cb24fSFrançois Tigeot 		[3] = 6400000,
201a85cb24fSFrançois Tigeot 		[4] = 3333333,
202a85cb24fSFrançois Tigeot 		[5] = 3566667,
203a85cb24fSFrançois Tigeot 		[6] = 4266667,
204a85cb24fSFrançois Tigeot 	};
205a85cb24fSFrançois Tigeot 	static const unsigned int elk_vco[8] = {
206a85cb24fSFrançois Tigeot 		[0] = 3200000,
207a85cb24fSFrançois Tigeot 		[1] = 4000000,
208a85cb24fSFrançois Tigeot 		[2] = 5333333,
209a85cb24fSFrançois Tigeot 		[3] = 4800000,
210a85cb24fSFrançois Tigeot 	};
211a85cb24fSFrançois Tigeot 	static const unsigned int ctg_vco[8] = {
212a85cb24fSFrançois Tigeot 		[0] = 3200000,
213a85cb24fSFrançois Tigeot 		[1] = 4000000,
214a85cb24fSFrançois Tigeot 		[2] = 5333333,
215a85cb24fSFrançois Tigeot 		[3] = 6400000,
216a85cb24fSFrançois Tigeot 		[4] = 2666667,
217a85cb24fSFrançois Tigeot 		[5] = 4266667,
218a85cb24fSFrançois Tigeot 	};
219a85cb24fSFrançois Tigeot 	const unsigned int *vco_table;
220a85cb24fSFrançois Tigeot 	unsigned int vco;
221a85cb24fSFrançois Tigeot 	uint8_t tmp = 0;
222a85cb24fSFrançois Tigeot 
223a85cb24fSFrançois Tigeot 	/* FIXME other chipsets? */
224a85cb24fSFrançois Tigeot 	if (IS_GM45(dev_priv))
225a85cb24fSFrançois Tigeot 		vco_table = ctg_vco;
226a85cb24fSFrançois Tigeot 	else if (IS_G45(dev_priv))
227a85cb24fSFrançois Tigeot 		vco_table = elk_vco;
228a85cb24fSFrançois Tigeot 	else if (IS_I965GM(dev_priv))
229a85cb24fSFrançois Tigeot 		vco_table = cl_vco;
230a85cb24fSFrançois Tigeot 	else if (IS_PINEVIEW(dev_priv))
231a85cb24fSFrançois Tigeot 		vco_table = pnv_vco;
232a85cb24fSFrançois Tigeot 	else if (IS_G33(dev_priv))
233a85cb24fSFrançois Tigeot 		vco_table = blb_vco;
234a85cb24fSFrançois Tigeot 	else
235a85cb24fSFrançois Tigeot 		return 0;
236a85cb24fSFrançois Tigeot 
237a85cb24fSFrançois Tigeot 	tmp = I915_READ(IS_MOBILE(dev_priv) ? HPLLVCO_MOBILE : HPLLVCO);
238a85cb24fSFrançois Tigeot 
239a85cb24fSFrançois Tigeot 	vco = vco_table[tmp & 0x7];
240a85cb24fSFrançois Tigeot 	if (vco == 0)
241a85cb24fSFrançois Tigeot 		DRM_ERROR("Bad HPLL VCO (HPLLVCO=0x%02x)\n", tmp);
242a85cb24fSFrançois Tigeot 	else
243a85cb24fSFrançois Tigeot 		DRM_DEBUG_KMS("HPLL VCO %u kHz\n", vco);
244a85cb24fSFrançois Tigeot 
245a85cb24fSFrançois Tigeot 	return vco;
246a85cb24fSFrançois Tigeot }
247a85cb24fSFrançois Tigeot 
g33_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)248a85cb24fSFrançois Tigeot static void g33_get_cdclk(struct drm_i915_private *dev_priv,
249a85cb24fSFrançois Tigeot 			  struct intel_cdclk_state *cdclk_state)
250a85cb24fSFrançois Tigeot {
251a85cb24fSFrançois Tigeot 	struct pci_dev *pdev = dev_priv->drm.pdev;
252a85cb24fSFrançois Tigeot 	static const uint8_t div_3200[] = { 12, 10,  8,  7, 5, 16 };
253a85cb24fSFrançois Tigeot 	static const uint8_t div_4000[] = { 14, 12, 10,  8, 6, 20 };
254a85cb24fSFrançois Tigeot 	static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 };
255a85cb24fSFrançois Tigeot 	static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 };
256a85cb24fSFrançois Tigeot 	const uint8_t *div_table;
257a85cb24fSFrançois Tigeot 	unsigned int cdclk_sel;
258a85cb24fSFrançois Tigeot 	uint16_t tmp = 0;
259a85cb24fSFrançois Tigeot 
260a85cb24fSFrançois Tigeot 	cdclk_state->vco = intel_hpll_vco(dev_priv);
261a85cb24fSFrançois Tigeot 
262a85cb24fSFrançois Tigeot 	pci_read_config_word(pdev, GCFGC, &tmp);
263a85cb24fSFrançois Tigeot 
264a85cb24fSFrançois Tigeot 	cdclk_sel = (tmp >> 4) & 0x7;
265a85cb24fSFrançois Tigeot 
266a85cb24fSFrançois Tigeot 	if (cdclk_sel >= ARRAY_SIZE(div_3200))
267a85cb24fSFrançois Tigeot 		goto fail;
268a85cb24fSFrançois Tigeot 
269a85cb24fSFrançois Tigeot 	switch (cdclk_state->vco) {
270a85cb24fSFrançois Tigeot 	case 3200000:
271a85cb24fSFrançois Tigeot 		div_table = div_3200;
272a85cb24fSFrançois Tigeot 		break;
273a85cb24fSFrançois Tigeot 	case 4000000:
274a85cb24fSFrançois Tigeot 		div_table = div_4000;
275a85cb24fSFrançois Tigeot 		break;
276a85cb24fSFrançois Tigeot 	case 4800000:
277a85cb24fSFrançois Tigeot 		div_table = div_4800;
278a85cb24fSFrançois Tigeot 		break;
279a85cb24fSFrançois Tigeot 	case 5333333:
280a85cb24fSFrançois Tigeot 		div_table = div_5333;
281a85cb24fSFrançois Tigeot 		break;
282a85cb24fSFrançois Tigeot 	default:
283a85cb24fSFrançois Tigeot 		goto fail;
284a85cb24fSFrançois Tigeot 	}
285a85cb24fSFrançois Tigeot 
286a85cb24fSFrançois Tigeot 	cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco,
287a85cb24fSFrançois Tigeot 					       div_table[cdclk_sel]);
288a85cb24fSFrançois Tigeot 	return;
289a85cb24fSFrançois Tigeot 
290a85cb24fSFrançois Tigeot fail:
291a85cb24fSFrançois Tigeot 	DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%08x\n",
292a85cb24fSFrançois Tigeot 		  cdclk_state->vco, tmp);
293a85cb24fSFrançois Tigeot 	cdclk_state->cdclk = 190476;
294a85cb24fSFrançois Tigeot }
295a85cb24fSFrançois Tigeot 
pnv_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)296a85cb24fSFrançois Tigeot static void pnv_get_cdclk(struct drm_i915_private *dev_priv,
297a85cb24fSFrançois Tigeot 			  struct intel_cdclk_state *cdclk_state)
298a85cb24fSFrançois Tigeot {
299a85cb24fSFrançois Tigeot 	struct pci_dev *pdev = dev_priv->drm.pdev;
300a85cb24fSFrançois Tigeot 	u16 gcfgc = 0;
301a85cb24fSFrançois Tigeot 
302a85cb24fSFrançois Tigeot 	pci_read_config_word(pdev, GCFGC, &gcfgc);
303a85cb24fSFrançois Tigeot 
304a85cb24fSFrançois Tigeot 	switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
305a85cb24fSFrançois Tigeot 	case GC_DISPLAY_CLOCK_267_MHZ_PNV:
306a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 266667;
307a85cb24fSFrançois Tigeot 		break;
308a85cb24fSFrançois Tigeot 	case GC_DISPLAY_CLOCK_333_MHZ_PNV:
309a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 333333;
310a85cb24fSFrançois Tigeot 		break;
311a85cb24fSFrançois Tigeot 	case GC_DISPLAY_CLOCK_444_MHZ_PNV:
312a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 444444;
313a85cb24fSFrançois Tigeot 		break;
314a85cb24fSFrançois Tigeot 	case GC_DISPLAY_CLOCK_200_MHZ_PNV:
315a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 200000;
316a85cb24fSFrançois Tigeot 		break;
317a85cb24fSFrançois Tigeot 	default:
318a85cb24fSFrançois Tigeot 		DRM_ERROR("Unknown pnv display core clock 0x%04x\n", gcfgc);
319a85cb24fSFrançois Tigeot 	case GC_DISPLAY_CLOCK_133_MHZ_PNV:
320a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 133333;
321a85cb24fSFrançois Tigeot 		break;
322a85cb24fSFrançois Tigeot 	case GC_DISPLAY_CLOCK_167_MHZ_PNV:
323a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 166667;
324a85cb24fSFrançois Tigeot 		break;
325a85cb24fSFrançois Tigeot 	}
326a85cb24fSFrançois Tigeot }
327a85cb24fSFrançois Tigeot 
i965gm_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)328a85cb24fSFrançois Tigeot static void i965gm_get_cdclk(struct drm_i915_private *dev_priv,
329a85cb24fSFrançois Tigeot 			     struct intel_cdclk_state *cdclk_state)
330a85cb24fSFrançois Tigeot {
331a85cb24fSFrançois Tigeot 	struct pci_dev *pdev = dev_priv->drm.pdev;
332a85cb24fSFrançois Tigeot 	static const uint8_t div_3200[] = { 16, 10,  8 };
333a85cb24fSFrançois Tigeot 	static const uint8_t div_4000[] = { 20, 12, 10 };
334a85cb24fSFrançois Tigeot 	static const uint8_t div_5333[] = { 24, 16, 14 };
335a85cb24fSFrançois Tigeot 	const uint8_t *div_table;
336a85cb24fSFrançois Tigeot 	unsigned int cdclk_sel;
337a85cb24fSFrançois Tigeot 	uint16_t tmp = 0;
338a85cb24fSFrançois Tigeot 
339a85cb24fSFrançois Tigeot 	cdclk_state->vco = intel_hpll_vco(dev_priv);
340a85cb24fSFrançois Tigeot 
341a85cb24fSFrançois Tigeot 	pci_read_config_word(pdev, GCFGC, &tmp);
342a85cb24fSFrançois Tigeot 
343a85cb24fSFrançois Tigeot 	cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
344a85cb24fSFrançois Tigeot 
345a85cb24fSFrançois Tigeot 	if (cdclk_sel >= ARRAY_SIZE(div_3200))
346a85cb24fSFrançois Tigeot 		goto fail;
347a85cb24fSFrançois Tigeot 
348a85cb24fSFrançois Tigeot 	switch (cdclk_state->vco) {
349a85cb24fSFrançois Tigeot 	case 3200000:
350a85cb24fSFrançois Tigeot 		div_table = div_3200;
351a85cb24fSFrançois Tigeot 		break;
352a85cb24fSFrançois Tigeot 	case 4000000:
353a85cb24fSFrançois Tigeot 		div_table = div_4000;
354a85cb24fSFrançois Tigeot 		break;
355a85cb24fSFrançois Tigeot 	case 5333333:
356a85cb24fSFrançois Tigeot 		div_table = div_5333;
357a85cb24fSFrançois Tigeot 		break;
358a85cb24fSFrançois Tigeot 	default:
359a85cb24fSFrançois Tigeot 		goto fail;
360a85cb24fSFrançois Tigeot 	}
361a85cb24fSFrançois Tigeot 
362a85cb24fSFrançois Tigeot 	cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco,
363a85cb24fSFrançois Tigeot 					       div_table[cdclk_sel]);
364a85cb24fSFrançois Tigeot 	return;
365a85cb24fSFrançois Tigeot 
366a85cb24fSFrançois Tigeot fail:
367a85cb24fSFrançois Tigeot 	DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%04x\n",
368a85cb24fSFrançois Tigeot 		  cdclk_state->vco, tmp);
369a85cb24fSFrançois Tigeot 	cdclk_state->cdclk = 200000;
370a85cb24fSFrançois Tigeot }
371a85cb24fSFrançois Tigeot 
gm45_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)372a85cb24fSFrançois Tigeot static void gm45_get_cdclk(struct drm_i915_private *dev_priv,
373a85cb24fSFrançois Tigeot 			   struct intel_cdclk_state *cdclk_state)
374a85cb24fSFrançois Tigeot {
375a85cb24fSFrançois Tigeot 	struct pci_dev *pdev = dev_priv->drm.pdev;
376a85cb24fSFrançois Tigeot 	unsigned int cdclk_sel;
377a85cb24fSFrançois Tigeot 	uint16_t tmp = 0;
378a85cb24fSFrançois Tigeot 
379a85cb24fSFrançois Tigeot 	cdclk_state->vco = intel_hpll_vco(dev_priv);
380a85cb24fSFrançois Tigeot 
381a85cb24fSFrançois Tigeot 	pci_read_config_word(pdev, GCFGC, &tmp);
382a85cb24fSFrançois Tigeot 
383a85cb24fSFrançois Tigeot 	cdclk_sel = (tmp >> 12) & 0x1;
384a85cb24fSFrançois Tigeot 
385a85cb24fSFrançois Tigeot 	switch (cdclk_state->vco) {
386a85cb24fSFrançois Tigeot 	case 2666667:
387a85cb24fSFrançois Tigeot 	case 4000000:
388a85cb24fSFrançois Tigeot 	case 5333333:
389a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = cdclk_sel ? 333333 : 222222;
390a85cb24fSFrançois Tigeot 		break;
391a85cb24fSFrançois Tigeot 	case 3200000:
392a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = cdclk_sel ? 320000 : 228571;
393a85cb24fSFrançois Tigeot 		break;
394a85cb24fSFrançois Tigeot 	default:
395a85cb24fSFrançois Tigeot 		DRM_ERROR("Unable to determine CDCLK. HPLL VCO=%u, CFGC=0x%04x\n",
396a85cb24fSFrançois Tigeot 			  cdclk_state->vco, tmp);
397a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 222222;
398a85cb24fSFrançois Tigeot 		break;
399a85cb24fSFrançois Tigeot 	}
400a85cb24fSFrançois Tigeot }
401a85cb24fSFrançois Tigeot 
hsw_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)402a85cb24fSFrançois Tigeot static void hsw_get_cdclk(struct drm_i915_private *dev_priv,
403a85cb24fSFrançois Tigeot 			  struct intel_cdclk_state *cdclk_state)
404a85cb24fSFrançois Tigeot {
405a85cb24fSFrançois Tigeot 	uint32_t lcpll = I915_READ(LCPLL_CTL);
406a85cb24fSFrançois Tigeot 	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
407a85cb24fSFrançois Tigeot 
408a85cb24fSFrançois Tigeot 	if (lcpll & LCPLL_CD_SOURCE_FCLK)
409a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 800000;
410a85cb24fSFrançois Tigeot 	else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
411a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 450000;
412a85cb24fSFrançois Tigeot 	else if (freq == LCPLL_CLK_FREQ_450)
413a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 450000;
414a85cb24fSFrançois Tigeot 	else if (IS_HSW_ULT(dev_priv))
415a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 337500;
416a85cb24fSFrançois Tigeot 	else
417a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 540000;
418a85cb24fSFrançois Tigeot }
419a85cb24fSFrançois Tigeot 
vlv_calc_cdclk(struct drm_i915_private * dev_priv,int min_cdclk)420*3f2dd94aSFrançois Tigeot static int vlv_calc_cdclk(struct drm_i915_private *dev_priv, int min_cdclk)
421a85cb24fSFrançois Tigeot {
422a85cb24fSFrançois Tigeot 	int freq_320 = (dev_priv->hpll_freq <<  1) % 320000 != 0 ?
423a85cb24fSFrançois Tigeot 		333333 : 320000;
424a85cb24fSFrançois Tigeot 
425a85cb24fSFrançois Tigeot 	/*
426a85cb24fSFrançois Tigeot 	 * We seem to get an unstable or solid color picture at 200MHz.
427a85cb24fSFrançois Tigeot 	 * Not sure what's wrong. For now use 200MHz only when all pipes
428a85cb24fSFrançois Tigeot 	 * are off.
429a85cb24fSFrançois Tigeot 	 */
430*3f2dd94aSFrançois Tigeot 	if (IS_VALLEYVIEW(dev_priv) && min_cdclk > freq_320)
431a85cb24fSFrançois Tigeot 		return 400000;
432*3f2dd94aSFrançois Tigeot 	else if (min_cdclk > 266667)
433a85cb24fSFrançois Tigeot 		return freq_320;
434*3f2dd94aSFrançois Tigeot 	else if (min_cdclk > 0)
435a85cb24fSFrançois Tigeot 		return 266667;
436a85cb24fSFrançois Tigeot 	else
437a85cb24fSFrançois Tigeot 		return 200000;
438a85cb24fSFrançois Tigeot }
439a85cb24fSFrançois Tigeot 
vlv_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)440a85cb24fSFrançois Tigeot static void vlv_get_cdclk(struct drm_i915_private *dev_priv,
441a85cb24fSFrançois Tigeot 			  struct intel_cdclk_state *cdclk_state)
442a85cb24fSFrançois Tigeot {
443a85cb24fSFrançois Tigeot 	cdclk_state->vco = vlv_get_hpll_vco(dev_priv);
444a85cb24fSFrançois Tigeot 	cdclk_state->cdclk = vlv_get_cck_clock(dev_priv, "cdclk",
445a85cb24fSFrançois Tigeot 					       CCK_DISPLAY_CLOCK_CONTROL,
446a85cb24fSFrançois Tigeot 					       cdclk_state->vco);
447a85cb24fSFrançois Tigeot }
448a85cb24fSFrançois Tigeot 
vlv_program_pfi_credits(struct drm_i915_private * dev_priv)449a85cb24fSFrançois Tigeot static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
450a85cb24fSFrançois Tigeot {
451a85cb24fSFrançois Tigeot 	unsigned int credits, default_credits;
452a85cb24fSFrançois Tigeot 
453a85cb24fSFrançois Tigeot 	if (IS_CHERRYVIEW(dev_priv))
454a85cb24fSFrançois Tigeot 		default_credits = PFI_CREDIT(12);
455a85cb24fSFrançois Tigeot 	else
456a85cb24fSFrançois Tigeot 		default_credits = PFI_CREDIT(8);
457a85cb24fSFrançois Tigeot 
458a85cb24fSFrançois Tigeot 	if (dev_priv->cdclk.hw.cdclk >= dev_priv->czclk_freq) {
459a85cb24fSFrançois Tigeot 		/* CHV suggested value is 31 or 63 */
460a85cb24fSFrançois Tigeot 		if (IS_CHERRYVIEW(dev_priv))
461a85cb24fSFrançois Tigeot 			credits = PFI_CREDIT_63;
462a85cb24fSFrançois Tigeot 		else
463a85cb24fSFrançois Tigeot 			credits = PFI_CREDIT(15);
464a85cb24fSFrançois Tigeot 	} else {
465a85cb24fSFrançois Tigeot 		credits = default_credits;
466a85cb24fSFrançois Tigeot 	}
467a85cb24fSFrançois Tigeot 
468a85cb24fSFrançois Tigeot 	/*
469a85cb24fSFrançois Tigeot 	 * WA - write default credits before re-programming
470a85cb24fSFrançois Tigeot 	 * FIXME: should we also set the resend bit here?
471a85cb24fSFrançois Tigeot 	 */
472a85cb24fSFrançois Tigeot 	I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
473a85cb24fSFrançois Tigeot 		   default_credits);
474a85cb24fSFrançois Tigeot 
475a85cb24fSFrançois Tigeot 	I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
476a85cb24fSFrançois Tigeot 		   credits | PFI_CREDIT_RESEND);
477a85cb24fSFrançois Tigeot 
478a85cb24fSFrançois Tigeot 	/*
479a85cb24fSFrançois Tigeot 	 * FIXME is this guaranteed to clear
480a85cb24fSFrançois Tigeot 	 * immediately or should we poll for it?
481a85cb24fSFrançois Tigeot 	 */
482a85cb24fSFrançois Tigeot 	WARN_ON(I915_READ(GCI_CONTROL) & PFI_CREDIT_RESEND);
483a85cb24fSFrançois Tigeot }
484a85cb24fSFrançois Tigeot 
vlv_set_cdclk(struct drm_i915_private * dev_priv,const struct intel_cdclk_state * cdclk_state)485a85cb24fSFrançois Tigeot static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
486a85cb24fSFrançois Tigeot 			  const struct intel_cdclk_state *cdclk_state)
487a85cb24fSFrançois Tigeot {
488a85cb24fSFrançois Tigeot 	int cdclk = cdclk_state->cdclk;
489a85cb24fSFrançois Tigeot 	u32 val, cmd;
490a85cb24fSFrançois Tigeot 
491a85cb24fSFrançois Tigeot 	/* There are cases where we can end up here with power domains
492a85cb24fSFrançois Tigeot 	 * off and a CDCLK frequency other than the minimum, like when
493a85cb24fSFrançois Tigeot 	 * issuing a modeset without actually changing any display after
494a85cb24fSFrançois Tigeot 	 * a system suspend.  So grab the PIPE-A domain, which covers
495a85cb24fSFrançois Tigeot 	 * the HW blocks needed for the following programming.
496a85cb24fSFrançois Tigeot 	 */
497a85cb24fSFrançois Tigeot 	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
498a85cb24fSFrançois Tigeot 
499a85cb24fSFrançois Tigeot 	if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
500a85cb24fSFrançois Tigeot 		cmd = 2;
501a85cb24fSFrançois Tigeot 	else if (cdclk == 266667)
502a85cb24fSFrançois Tigeot 		cmd = 1;
503a85cb24fSFrançois Tigeot 	else
504a85cb24fSFrançois Tigeot 		cmd = 0;
505a85cb24fSFrançois Tigeot 
506*3f2dd94aSFrançois Tigeot 	mutex_lock(&dev_priv->pcu_lock);
507a85cb24fSFrançois Tigeot 	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
508a85cb24fSFrançois Tigeot 	val &= ~DSPFREQGUAR_MASK;
509a85cb24fSFrançois Tigeot 	val |= (cmd << DSPFREQGUAR_SHIFT);
510a85cb24fSFrançois Tigeot 	vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
511a85cb24fSFrançois Tigeot 	if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
512a85cb24fSFrançois Tigeot 		      DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT),
513a85cb24fSFrançois Tigeot 		     50)) {
514a85cb24fSFrançois Tigeot 		DRM_ERROR("timed out waiting for CDclk change\n");
515a85cb24fSFrançois Tigeot 	}
516*3f2dd94aSFrançois Tigeot 	mutex_unlock(&dev_priv->pcu_lock);
517a85cb24fSFrançois Tigeot 
518a85cb24fSFrançois Tigeot 	mutex_lock(&dev_priv->sb_lock);
519a85cb24fSFrançois Tigeot 
520a85cb24fSFrançois Tigeot 	if (cdclk == 400000) {
521a85cb24fSFrançois Tigeot 		u32 divider;
522a85cb24fSFrançois Tigeot 
523a85cb24fSFrançois Tigeot 		divider = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1,
524a85cb24fSFrançois Tigeot 					    cdclk) - 1;
525a85cb24fSFrançois Tigeot 
526a85cb24fSFrançois Tigeot 		/* adjust cdclk divider */
527a85cb24fSFrançois Tigeot 		val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
528a85cb24fSFrançois Tigeot 		val &= ~CCK_FREQUENCY_VALUES;
529a85cb24fSFrançois Tigeot 		val |= divider;
530a85cb24fSFrançois Tigeot 		vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
531a85cb24fSFrançois Tigeot 
532a85cb24fSFrançois Tigeot 		if (wait_for((vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL) &
533a85cb24fSFrançois Tigeot 			      CCK_FREQUENCY_STATUS) == (divider << CCK_FREQUENCY_STATUS_SHIFT),
534a85cb24fSFrançois Tigeot 			     50))
535a85cb24fSFrançois Tigeot 			DRM_ERROR("timed out waiting for CDclk change\n");
536a85cb24fSFrançois Tigeot 	}
537a85cb24fSFrançois Tigeot 
538a85cb24fSFrançois Tigeot 	/* adjust self-refresh exit latency value */
539a85cb24fSFrançois Tigeot 	val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC);
540a85cb24fSFrançois Tigeot 	val &= ~0x7f;
541a85cb24fSFrançois Tigeot 
542a85cb24fSFrançois Tigeot 	/*
543a85cb24fSFrançois Tigeot 	 * For high bandwidth configs, we set a higher latency in the bunit
544a85cb24fSFrançois Tigeot 	 * so that the core display fetch happens in time to avoid underruns.
545a85cb24fSFrançois Tigeot 	 */
546a85cb24fSFrançois Tigeot 	if (cdclk == 400000)
547a85cb24fSFrançois Tigeot 		val |= 4500 / 250; /* 4.5 usec */
548a85cb24fSFrançois Tigeot 	else
549a85cb24fSFrançois Tigeot 		val |= 3000 / 250; /* 3.0 usec */
550a85cb24fSFrançois Tigeot 	vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
551a85cb24fSFrançois Tigeot 
552a85cb24fSFrançois Tigeot 	mutex_unlock(&dev_priv->sb_lock);
553a85cb24fSFrançois Tigeot 
554a85cb24fSFrançois Tigeot 	intel_update_cdclk(dev_priv);
555a85cb24fSFrançois Tigeot 
556a85cb24fSFrançois Tigeot 	vlv_program_pfi_credits(dev_priv);
557a85cb24fSFrançois Tigeot 
558a85cb24fSFrançois Tigeot 	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
559a85cb24fSFrançois Tigeot }
560a85cb24fSFrançois Tigeot 
chv_set_cdclk(struct drm_i915_private * dev_priv,const struct intel_cdclk_state * cdclk_state)561a85cb24fSFrançois Tigeot static void chv_set_cdclk(struct drm_i915_private *dev_priv,
562a85cb24fSFrançois Tigeot 			  const struct intel_cdclk_state *cdclk_state)
563a85cb24fSFrançois Tigeot {
564a85cb24fSFrançois Tigeot 	int cdclk = cdclk_state->cdclk;
565a85cb24fSFrançois Tigeot 	u32 val, cmd;
566a85cb24fSFrançois Tigeot 
567a85cb24fSFrançois Tigeot 	switch (cdclk) {
568a85cb24fSFrançois Tigeot 	case 333333:
569a85cb24fSFrançois Tigeot 	case 320000:
570a85cb24fSFrançois Tigeot 	case 266667:
571a85cb24fSFrançois Tigeot 	case 200000:
572a85cb24fSFrançois Tigeot 		break;
573a85cb24fSFrançois Tigeot 	default:
574a85cb24fSFrançois Tigeot 		MISSING_CASE(cdclk);
575a85cb24fSFrançois Tigeot 		return;
576a85cb24fSFrançois Tigeot 	}
577a85cb24fSFrançois Tigeot 
578a85cb24fSFrançois Tigeot 	/* There are cases where we can end up here with power domains
579a85cb24fSFrançois Tigeot 	 * off and a CDCLK frequency other than the minimum, like when
580a85cb24fSFrançois Tigeot 	 * issuing a modeset without actually changing any display after
581a85cb24fSFrançois Tigeot 	 * a system suspend.  So grab the PIPE-A domain, which covers
582a85cb24fSFrançois Tigeot 	 * the HW blocks needed for the following programming.
583a85cb24fSFrançois Tigeot 	 */
584a85cb24fSFrançois Tigeot 	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
585a85cb24fSFrançois Tigeot 
586a85cb24fSFrançois Tigeot 	/*
587a85cb24fSFrançois Tigeot 	 * Specs are full of misinformation, but testing on actual
588a85cb24fSFrançois Tigeot 	 * hardware has shown that we just need to write the desired
589a85cb24fSFrançois Tigeot 	 * CCK divider into the Punit register.
590a85cb24fSFrançois Tigeot 	 */
591a85cb24fSFrançois Tigeot 	cmd = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1;
592a85cb24fSFrançois Tigeot 
593*3f2dd94aSFrançois Tigeot 	mutex_lock(&dev_priv->pcu_lock);
594a85cb24fSFrançois Tigeot 	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
595a85cb24fSFrançois Tigeot 	val &= ~DSPFREQGUAR_MASK_CHV;
596a85cb24fSFrançois Tigeot 	val |= (cmd << DSPFREQGUAR_SHIFT_CHV);
597a85cb24fSFrançois Tigeot 	vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
598a85cb24fSFrançois Tigeot 	if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
599a85cb24fSFrançois Tigeot 		      DSPFREQSTAT_MASK_CHV) == (cmd << DSPFREQSTAT_SHIFT_CHV),
600a85cb24fSFrançois Tigeot 		     50)) {
601a85cb24fSFrançois Tigeot 		DRM_ERROR("timed out waiting for CDclk change\n");
602a85cb24fSFrançois Tigeot 	}
603*3f2dd94aSFrançois Tigeot 	mutex_unlock(&dev_priv->pcu_lock);
604a85cb24fSFrançois Tigeot 
605a85cb24fSFrançois Tigeot 	intel_update_cdclk(dev_priv);
606a85cb24fSFrançois Tigeot 
607a85cb24fSFrançois Tigeot 	vlv_program_pfi_credits(dev_priv);
608a85cb24fSFrançois Tigeot 
609a85cb24fSFrançois Tigeot 	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
610a85cb24fSFrançois Tigeot }
611a85cb24fSFrançois Tigeot 
bdw_calc_cdclk(int min_cdclk)612*3f2dd94aSFrançois Tigeot static int bdw_calc_cdclk(int min_cdclk)
613a85cb24fSFrançois Tigeot {
614*3f2dd94aSFrançois Tigeot 	if (min_cdclk > 540000)
615a85cb24fSFrançois Tigeot 		return 675000;
616*3f2dd94aSFrançois Tigeot 	else if (min_cdclk > 450000)
617a85cb24fSFrançois Tigeot 		return 540000;
618*3f2dd94aSFrançois Tigeot 	else if (min_cdclk > 337500)
619a85cb24fSFrançois Tigeot 		return 450000;
620a85cb24fSFrançois Tigeot 	else
621a85cb24fSFrançois Tigeot 		return 337500;
622a85cb24fSFrançois Tigeot }
623a85cb24fSFrançois Tigeot 
bdw_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)624a85cb24fSFrançois Tigeot static void bdw_get_cdclk(struct drm_i915_private *dev_priv,
625a85cb24fSFrançois Tigeot 			  struct intel_cdclk_state *cdclk_state)
626a85cb24fSFrançois Tigeot {
627a85cb24fSFrançois Tigeot 	uint32_t lcpll = I915_READ(LCPLL_CTL);
628a85cb24fSFrançois Tigeot 	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
629a85cb24fSFrançois Tigeot 
630a85cb24fSFrançois Tigeot 	if (lcpll & LCPLL_CD_SOURCE_FCLK)
631a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 800000;
632a85cb24fSFrançois Tigeot 	else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
633a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 450000;
634a85cb24fSFrançois Tigeot 	else if (freq == LCPLL_CLK_FREQ_450)
635a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 450000;
636a85cb24fSFrançois Tigeot 	else if (freq == LCPLL_CLK_FREQ_54O_BDW)
637a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 540000;
638a85cb24fSFrançois Tigeot 	else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
639a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 337500;
640a85cb24fSFrançois Tigeot 	else
641a85cb24fSFrançois Tigeot 		cdclk_state->cdclk = 675000;
642a85cb24fSFrançois Tigeot }
643a85cb24fSFrançois Tigeot 
bdw_set_cdclk(struct drm_i915_private * dev_priv,const struct intel_cdclk_state * cdclk_state)644a85cb24fSFrançois Tigeot static void bdw_set_cdclk(struct drm_i915_private *dev_priv,
645a85cb24fSFrançois Tigeot 			  const struct intel_cdclk_state *cdclk_state)
646a85cb24fSFrançois Tigeot {
647a85cb24fSFrançois Tigeot 	int cdclk = cdclk_state->cdclk;
648a85cb24fSFrançois Tigeot 	uint32_t val, data;
649a85cb24fSFrançois Tigeot 	int ret;
650a85cb24fSFrançois Tigeot 
651a85cb24fSFrançois Tigeot 	if (WARN((I915_READ(LCPLL_CTL) &
652a85cb24fSFrançois Tigeot 		  (LCPLL_PLL_DISABLE | LCPLL_PLL_LOCK |
653a85cb24fSFrançois Tigeot 		   LCPLL_CD_CLOCK_DISABLE | LCPLL_ROOT_CD_CLOCK_DISABLE |
654a85cb24fSFrançois Tigeot 		   LCPLL_CD2X_CLOCK_DISABLE | LCPLL_POWER_DOWN_ALLOW |
655a85cb24fSFrançois Tigeot 		   LCPLL_CD_SOURCE_FCLK)) != LCPLL_PLL_LOCK,
656a85cb24fSFrançois Tigeot 		 "trying to change cdclk frequency with cdclk not enabled\n"))
657a85cb24fSFrançois Tigeot 		return;
658a85cb24fSFrançois Tigeot 
659*3f2dd94aSFrançois Tigeot 	mutex_lock(&dev_priv->pcu_lock);
660a85cb24fSFrançois Tigeot 	ret = sandybridge_pcode_write(dev_priv,
661a85cb24fSFrançois Tigeot 				      BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ, 0x0);
662*3f2dd94aSFrançois Tigeot 	mutex_unlock(&dev_priv->pcu_lock);
663a85cb24fSFrançois Tigeot 	if (ret) {
664a85cb24fSFrançois Tigeot 		DRM_ERROR("failed to inform pcode about cdclk change\n");
665a85cb24fSFrançois Tigeot 		return;
666a85cb24fSFrançois Tigeot 	}
667a85cb24fSFrançois Tigeot 
668a85cb24fSFrançois Tigeot 	val = I915_READ(LCPLL_CTL);
669a85cb24fSFrançois Tigeot 	val |= LCPLL_CD_SOURCE_FCLK;
670a85cb24fSFrançois Tigeot 	I915_WRITE(LCPLL_CTL, val);
671a85cb24fSFrançois Tigeot 
672*3f2dd94aSFrançois Tigeot 	/*
673*3f2dd94aSFrançois Tigeot 	 * According to the spec, it should be enough to poll for this 1 us.
674*3f2dd94aSFrançois Tigeot 	 * However, extensive testing shows that this can take longer.
675*3f2dd94aSFrançois Tigeot 	 */
676a85cb24fSFrançois Tigeot 	if (wait_for_us(I915_READ(LCPLL_CTL) &
677*3f2dd94aSFrançois Tigeot 			LCPLL_CD_SOURCE_FCLK_DONE, 100))
678a85cb24fSFrançois Tigeot 		DRM_ERROR("Switching to FCLK failed\n");
679a85cb24fSFrançois Tigeot 
680a85cb24fSFrançois Tigeot 	val = I915_READ(LCPLL_CTL);
681a85cb24fSFrançois Tigeot 	val &= ~LCPLL_CLK_FREQ_MASK;
682a85cb24fSFrançois Tigeot 
683a85cb24fSFrançois Tigeot 	switch (cdclk) {
684a85cb24fSFrançois Tigeot 	case 450000:
685a85cb24fSFrançois Tigeot 		val |= LCPLL_CLK_FREQ_450;
686a85cb24fSFrançois Tigeot 		data = 0;
687a85cb24fSFrançois Tigeot 		break;
688a85cb24fSFrançois Tigeot 	case 540000:
689a85cb24fSFrançois Tigeot 		val |= LCPLL_CLK_FREQ_54O_BDW;
690a85cb24fSFrançois Tigeot 		data = 1;
691a85cb24fSFrançois Tigeot 		break;
692a85cb24fSFrançois Tigeot 	case 337500:
693a85cb24fSFrançois Tigeot 		val |= LCPLL_CLK_FREQ_337_5_BDW;
694a85cb24fSFrançois Tigeot 		data = 2;
695a85cb24fSFrançois Tigeot 		break;
696a85cb24fSFrançois Tigeot 	case 675000:
697a85cb24fSFrançois Tigeot 		val |= LCPLL_CLK_FREQ_675_BDW;
698a85cb24fSFrançois Tigeot 		data = 3;
699a85cb24fSFrançois Tigeot 		break;
700a85cb24fSFrançois Tigeot 	default:
701a85cb24fSFrançois Tigeot 		WARN(1, "invalid cdclk frequency\n");
702a85cb24fSFrançois Tigeot 		return;
703a85cb24fSFrançois Tigeot 	}
704a85cb24fSFrançois Tigeot 
705a85cb24fSFrançois Tigeot 	I915_WRITE(LCPLL_CTL, val);
706a85cb24fSFrançois Tigeot 
707a85cb24fSFrançois Tigeot 	val = I915_READ(LCPLL_CTL);
708a85cb24fSFrançois Tigeot 	val &= ~LCPLL_CD_SOURCE_FCLK;
709a85cb24fSFrançois Tigeot 	I915_WRITE(LCPLL_CTL, val);
710a85cb24fSFrançois Tigeot 
711a85cb24fSFrançois Tigeot 	if (wait_for_us((I915_READ(LCPLL_CTL) &
712a85cb24fSFrançois Tigeot 			LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
713a85cb24fSFrançois Tigeot 		DRM_ERROR("Switching back to LCPLL failed\n");
714a85cb24fSFrançois Tigeot 
715*3f2dd94aSFrançois Tigeot 	mutex_lock(&dev_priv->pcu_lock);
716a85cb24fSFrançois Tigeot 	sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, data);
717*3f2dd94aSFrançois Tigeot 	mutex_unlock(&dev_priv->pcu_lock);
718a85cb24fSFrançois Tigeot 
719a85cb24fSFrançois Tigeot 	I915_WRITE(CDCLK_FREQ, DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
720a85cb24fSFrançois Tigeot 
721a85cb24fSFrançois Tigeot 	intel_update_cdclk(dev_priv);
722a85cb24fSFrançois Tigeot 
723a85cb24fSFrançois Tigeot 	WARN(cdclk != dev_priv->cdclk.hw.cdclk,
724a85cb24fSFrançois Tigeot 	     "cdclk requested %d kHz but got %d kHz\n",
725a85cb24fSFrançois Tigeot 	     cdclk, dev_priv->cdclk.hw.cdclk);
726a85cb24fSFrançois Tigeot }
727a85cb24fSFrançois Tigeot 
skl_calc_cdclk(int min_cdclk,int vco)728*3f2dd94aSFrançois Tigeot static int skl_calc_cdclk(int min_cdclk, int vco)
729a85cb24fSFrançois Tigeot {
730a85cb24fSFrançois Tigeot 	if (vco == 8640000) {
731*3f2dd94aSFrançois Tigeot 		if (min_cdclk > 540000)
732a85cb24fSFrançois Tigeot 			return 617143;
733*3f2dd94aSFrançois Tigeot 		else if (min_cdclk > 432000)
734a85cb24fSFrançois Tigeot 			return 540000;
735*3f2dd94aSFrançois Tigeot 		else if (min_cdclk > 308571)
736a85cb24fSFrançois Tigeot 			return 432000;
737a85cb24fSFrançois Tigeot 		else
738a85cb24fSFrançois Tigeot 			return 308571;
739a85cb24fSFrançois Tigeot 	} else {
740*3f2dd94aSFrançois Tigeot 		if (min_cdclk > 540000)
741a85cb24fSFrançois Tigeot 			return 675000;
742*3f2dd94aSFrançois Tigeot 		else if (min_cdclk > 450000)
743a85cb24fSFrançois Tigeot 			return 540000;
744*3f2dd94aSFrançois Tigeot 		else if (min_cdclk > 337500)
745a85cb24fSFrançois Tigeot 			return 450000;
746a85cb24fSFrançois Tigeot 		else
747a85cb24fSFrançois Tigeot 			return 337500;
748a85cb24fSFrançois Tigeot 	}
749a85cb24fSFrançois Tigeot }
750a85cb24fSFrançois Tigeot 
skl_dpll0_update(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)751a85cb24fSFrançois Tigeot static void skl_dpll0_update(struct drm_i915_private *dev_priv,
752a85cb24fSFrançois Tigeot 			     struct intel_cdclk_state *cdclk_state)
753a85cb24fSFrançois Tigeot {
754a85cb24fSFrançois Tigeot 	u32 val;
755a85cb24fSFrançois Tigeot 
756a85cb24fSFrançois Tigeot 	cdclk_state->ref = 24000;
757a85cb24fSFrançois Tigeot 	cdclk_state->vco = 0;
758a85cb24fSFrançois Tigeot 
759a85cb24fSFrançois Tigeot 	val = I915_READ(LCPLL1_CTL);
760a85cb24fSFrançois Tigeot 	if ((val & LCPLL_PLL_ENABLE) == 0)
761a85cb24fSFrançois Tigeot 		return;
762a85cb24fSFrançois Tigeot 
763a85cb24fSFrançois Tigeot 	if (WARN_ON((val & LCPLL_PLL_LOCK) == 0))
764a85cb24fSFrançois Tigeot 		return;
765a85cb24fSFrançois Tigeot 
766a85cb24fSFrançois Tigeot 	val = I915_READ(DPLL_CTRL1);
767a85cb24fSFrançois Tigeot 
768a85cb24fSFrançois Tigeot 	if (WARN_ON((val & (DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) |
769a85cb24fSFrançois Tigeot 			    DPLL_CTRL1_SSC(SKL_DPLL0) |
770a85cb24fSFrançois Tigeot 			    DPLL_CTRL1_OVERRIDE(SKL_DPLL0))) !=
771a85cb24fSFrançois Tigeot 		    DPLL_CTRL1_OVERRIDE(SKL_DPLL0)))
772a85cb24fSFrançois Tigeot 		return;
773a85cb24fSFrançois Tigeot 
774a85cb24fSFrançois Tigeot 	switch (val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) {
775a85cb24fSFrançois Tigeot 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, SKL_DPLL0):
776a85cb24fSFrançois Tigeot 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0):
777a85cb24fSFrançois Tigeot 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0):
778a85cb24fSFrançois Tigeot 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0):
779a85cb24fSFrançois Tigeot 		cdclk_state->vco = 8100000;
780a85cb24fSFrançois Tigeot 		break;
781a85cb24fSFrançois Tigeot 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0):
782a85cb24fSFrançois Tigeot 	case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0):
783a85cb24fSFrançois Tigeot 		cdclk_state->vco = 8640000;
784a85cb24fSFrançois Tigeot 		break;
785a85cb24fSFrançois Tigeot 	default:
786a85cb24fSFrançois Tigeot 		MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
787a85cb24fSFrançois Tigeot 		break;
788a85cb24fSFrançois Tigeot 	}
789a85cb24fSFrançois Tigeot }
790a85cb24fSFrançois Tigeot 
skl_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)791a85cb24fSFrançois Tigeot static void skl_get_cdclk(struct drm_i915_private *dev_priv,
792a85cb24fSFrançois Tigeot 			  struct intel_cdclk_state *cdclk_state)
793a85cb24fSFrançois Tigeot {
794a85cb24fSFrançois Tigeot 	u32 cdctl;
795a85cb24fSFrançois Tigeot 
796a85cb24fSFrançois Tigeot 	skl_dpll0_update(dev_priv, cdclk_state);
797a85cb24fSFrançois Tigeot 
798a85cb24fSFrançois Tigeot 	cdclk_state->cdclk = cdclk_state->ref;
799a85cb24fSFrançois Tigeot 
800a85cb24fSFrançois Tigeot 	if (cdclk_state->vco == 0)
801a85cb24fSFrançois Tigeot 		return;
802a85cb24fSFrançois Tigeot 
803a85cb24fSFrançois Tigeot 	cdctl = I915_READ(CDCLK_CTL);
804a85cb24fSFrançois Tigeot 
805a85cb24fSFrançois Tigeot 	if (cdclk_state->vco == 8640000) {
806a85cb24fSFrançois Tigeot 		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
807a85cb24fSFrançois Tigeot 		case CDCLK_FREQ_450_432:
808a85cb24fSFrançois Tigeot 			cdclk_state->cdclk = 432000;
809a85cb24fSFrançois Tigeot 			break;
810a85cb24fSFrançois Tigeot 		case CDCLK_FREQ_337_308:
811a85cb24fSFrançois Tigeot 			cdclk_state->cdclk = 308571;
812a85cb24fSFrançois Tigeot 			break;
813a85cb24fSFrançois Tigeot 		case CDCLK_FREQ_540:
814a85cb24fSFrançois Tigeot 			cdclk_state->cdclk = 540000;
815a85cb24fSFrançois Tigeot 			break;
816a85cb24fSFrançois Tigeot 		case CDCLK_FREQ_675_617:
817a85cb24fSFrançois Tigeot 			cdclk_state->cdclk = 617143;
818a85cb24fSFrançois Tigeot 			break;
819a85cb24fSFrançois Tigeot 		default:
820a85cb24fSFrançois Tigeot 			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
821a85cb24fSFrançois Tigeot 			break;
822a85cb24fSFrançois Tigeot 		}
823a85cb24fSFrançois Tigeot 	} else {
824a85cb24fSFrançois Tigeot 		switch (cdctl & CDCLK_FREQ_SEL_MASK) {
825a85cb24fSFrançois Tigeot 		case CDCLK_FREQ_450_432:
826a85cb24fSFrançois Tigeot 			cdclk_state->cdclk = 450000;
827a85cb24fSFrançois Tigeot 			break;
828a85cb24fSFrançois Tigeot 		case CDCLK_FREQ_337_308:
829a85cb24fSFrançois Tigeot 			cdclk_state->cdclk = 337500;
830a85cb24fSFrançois Tigeot 			break;
831a85cb24fSFrançois Tigeot 		case CDCLK_FREQ_540:
832a85cb24fSFrançois Tigeot 			cdclk_state->cdclk = 540000;
833a85cb24fSFrançois Tigeot 			break;
834a85cb24fSFrançois Tigeot 		case CDCLK_FREQ_675_617:
835a85cb24fSFrançois Tigeot 			cdclk_state->cdclk = 675000;
836a85cb24fSFrançois Tigeot 			break;
837a85cb24fSFrançois Tigeot 		default:
838a85cb24fSFrançois Tigeot 			MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
839a85cb24fSFrançois Tigeot 			break;
840a85cb24fSFrançois Tigeot 		}
841a85cb24fSFrançois Tigeot 	}
842a85cb24fSFrançois Tigeot }
843a85cb24fSFrançois Tigeot 
844a85cb24fSFrançois Tigeot /* convert from kHz to .1 fixpoint MHz with -1MHz offset */
skl_cdclk_decimal(int cdclk)845a85cb24fSFrançois Tigeot static int skl_cdclk_decimal(int cdclk)
846a85cb24fSFrançois Tigeot {
847a85cb24fSFrançois Tigeot 	return DIV_ROUND_CLOSEST(cdclk - 1000, 500);
848a85cb24fSFrançois Tigeot }
849a85cb24fSFrançois Tigeot 
skl_set_preferred_cdclk_vco(struct drm_i915_private * dev_priv,int vco)850a85cb24fSFrançois Tigeot static void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv,
851a85cb24fSFrançois Tigeot 					int vco)
852a85cb24fSFrançois Tigeot {
853a85cb24fSFrançois Tigeot 	bool changed = dev_priv->skl_preferred_vco_freq != vco;
854a85cb24fSFrançois Tigeot 
855a85cb24fSFrançois Tigeot 	dev_priv->skl_preferred_vco_freq = vco;
856a85cb24fSFrançois Tigeot 
857a85cb24fSFrançois Tigeot 	if (changed)
858a85cb24fSFrançois Tigeot 		intel_update_max_cdclk(dev_priv);
859a85cb24fSFrançois Tigeot }
860a85cb24fSFrançois Tigeot 
skl_dpll0_enable(struct drm_i915_private * dev_priv,int vco)861a85cb24fSFrançois Tigeot static void skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
862a85cb24fSFrançois Tigeot {
863a85cb24fSFrançois Tigeot 	u32 val;
864a85cb24fSFrançois Tigeot 
865a85cb24fSFrançois Tigeot 	WARN_ON(vco != 8100000 && vco != 8640000);
866a85cb24fSFrançois Tigeot 
867a85cb24fSFrançois Tigeot 	/*
868a85cb24fSFrançois Tigeot 	 * We always enable DPLL0 with the lowest link rate possible, but still
869a85cb24fSFrançois Tigeot 	 * taking into account the VCO required to operate the eDP panel at the
870a85cb24fSFrançois Tigeot 	 * desired frequency. The usual DP link rates operate with a VCO of
871a85cb24fSFrançois Tigeot 	 * 8100 while the eDP 1.4 alternate link rates need a VCO of 8640.
872a85cb24fSFrançois Tigeot 	 * The modeset code is responsible for the selection of the exact link
873a85cb24fSFrançois Tigeot 	 * rate later on, with the constraint of choosing a frequency that
874a85cb24fSFrançois Tigeot 	 * works with vco.
875a85cb24fSFrançois Tigeot 	 */
876a85cb24fSFrançois Tigeot 	val = I915_READ(DPLL_CTRL1);
877a85cb24fSFrançois Tigeot 
878a85cb24fSFrançois Tigeot 	val &= ~(DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) | DPLL_CTRL1_SSC(SKL_DPLL0) |
879a85cb24fSFrançois Tigeot 		 DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
880a85cb24fSFrançois Tigeot 	val |= DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
881a85cb24fSFrançois Tigeot 	if (vco == 8640000)
882a85cb24fSFrançois Tigeot 		val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,
883a85cb24fSFrançois Tigeot 					    SKL_DPLL0);
884a85cb24fSFrançois Tigeot 	else
885a85cb24fSFrançois Tigeot 		val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,
886a85cb24fSFrançois Tigeot 					    SKL_DPLL0);
887a85cb24fSFrançois Tigeot 
888a85cb24fSFrançois Tigeot 	I915_WRITE(DPLL_CTRL1, val);
889a85cb24fSFrançois Tigeot 	POSTING_READ(DPLL_CTRL1);
890a85cb24fSFrançois Tigeot 
891a85cb24fSFrançois Tigeot 	I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) | LCPLL_PLL_ENABLE);
892a85cb24fSFrançois Tigeot 
893a85cb24fSFrançois Tigeot 	if (intel_wait_for_register(dev_priv,
894a85cb24fSFrançois Tigeot 				    LCPLL1_CTL, LCPLL_PLL_LOCK, LCPLL_PLL_LOCK,
895a85cb24fSFrançois Tigeot 				    5))
896a85cb24fSFrançois Tigeot 		DRM_ERROR("DPLL0 not locked\n");
897a85cb24fSFrançois Tigeot 
898a85cb24fSFrançois Tigeot 	dev_priv->cdclk.hw.vco = vco;
899a85cb24fSFrançois Tigeot 
900a85cb24fSFrançois Tigeot 	/* We'll want to keep using the current vco from now on. */
901a85cb24fSFrançois Tigeot 	skl_set_preferred_cdclk_vco(dev_priv, vco);
902a85cb24fSFrançois Tigeot }
903a85cb24fSFrançois Tigeot 
skl_dpll0_disable(struct drm_i915_private * dev_priv)904a85cb24fSFrançois Tigeot static void skl_dpll0_disable(struct drm_i915_private *dev_priv)
905a85cb24fSFrançois Tigeot {
906a85cb24fSFrançois Tigeot 	I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) & ~LCPLL_PLL_ENABLE);
907a85cb24fSFrançois Tigeot 	if (intel_wait_for_register(dev_priv,
908a85cb24fSFrançois Tigeot 				   LCPLL1_CTL, LCPLL_PLL_LOCK, 0,
909a85cb24fSFrançois Tigeot 				   1))
910a85cb24fSFrançois Tigeot 		DRM_ERROR("Couldn't disable DPLL0\n");
911a85cb24fSFrançois Tigeot 
912a85cb24fSFrançois Tigeot 	dev_priv->cdclk.hw.vco = 0;
913a85cb24fSFrançois Tigeot }
914a85cb24fSFrançois Tigeot 
skl_set_cdclk(struct drm_i915_private * dev_priv,const struct intel_cdclk_state * cdclk_state)915a85cb24fSFrançois Tigeot static void skl_set_cdclk(struct drm_i915_private *dev_priv,
916a85cb24fSFrançois Tigeot 			  const struct intel_cdclk_state *cdclk_state)
917a85cb24fSFrançois Tigeot {
918a85cb24fSFrançois Tigeot 	int cdclk = cdclk_state->cdclk;
919a85cb24fSFrançois Tigeot 	int vco = cdclk_state->vco;
920*3f2dd94aSFrançois Tigeot 	u32 freq_select, pcu_ack, cdclk_ctl;
921a85cb24fSFrançois Tigeot 	int ret;
922a85cb24fSFrançois Tigeot 
923a85cb24fSFrançois Tigeot 	WARN_ON((cdclk == 24000) != (vco == 0));
924a85cb24fSFrançois Tigeot 
925*3f2dd94aSFrançois Tigeot 	mutex_lock(&dev_priv->pcu_lock);
926a85cb24fSFrançois Tigeot 	ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
927a85cb24fSFrançois Tigeot 				SKL_CDCLK_PREPARE_FOR_CHANGE,
928a85cb24fSFrançois Tigeot 				SKL_CDCLK_READY_FOR_CHANGE,
929a85cb24fSFrançois Tigeot 				SKL_CDCLK_READY_FOR_CHANGE, 3);
930*3f2dd94aSFrançois Tigeot 	mutex_unlock(&dev_priv->pcu_lock);
931a85cb24fSFrançois Tigeot 	if (ret) {
932a85cb24fSFrançois Tigeot 		DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n",
933a85cb24fSFrançois Tigeot 			  ret);
934a85cb24fSFrançois Tigeot 		return;
935a85cb24fSFrançois Tigeot 	}
936a85cb24fSFrançois Tigeot 
937*3f2dd94aSFrançois Tigeot 	/* Choose frequency for this cdclk */
938a85cb24fSFrançois Tigeot 	switch (cdclk) {
939a85cb24fSFrançois Tigeot 	case 450000:
940a85cb24fSFrançois Tigeot 	case 432000:
941a85cb24fSFrançois Tigeot 		freq_select = CDCLK_FREQ_450_432;
942a85cb24fSFrançois Tigeot 		pcu_ack = 1;
943a85cb24fSFrançois Tigeot 		break;
944a85cb24fSFrançois Tigeot 	case 540000:
945a85cb24fSFrançois Tigeot 		freq_select = CDCLK_FREQ_540;
946a85cb24fSFrançois Tigeot 		pcu_ack = 2;
947a85cb24fSFrançois Tigeot 		break;
948a85cb24fSFrançois Tigeot 	case 308571:
949a85cb24fSFrançois Tigeot 	case 337500:
950a85cb24fSFrançois Tigeot 	default:
951a85cb24fSFrançois Tigeot 		freq_select = CDCLK_FREQ_337_308;
952a85cb24fSFrançois Tigeot 		pcu_ack = 0;
953a85cb24fSFrançois Tigeot 		break;
954a85cb24fSFrançois Tigeot 	case 617143:
955a85cb24fSFrançois Tigeot 	case 675000:
956a85cb24fSFrançois Tigeot 		freq_select = CDCLK_FREQ_675_617;
957a85cb24fSFrançois Tigeot 		pcu_ack = 3;
958a85cb24fSFrançois Tigeot 		break;
959a85cb24fSFrançois Tigeot 	}
960a85cb24fSFrançois Tigeot 
961a85cb24fSFrançois Tigeot 	if (dev_priv->cdclk.hw.vco != 0 &&
962a85cb24fSFrançois Tigeot 	    dev_priv->cdclk.hw.vco != vco)
963a85cb24fSFrançois Tigeot 		skl_dpll0_disable(dev_priv);
964a85cb24fSFrançois Tigeot 
965*3f2dd94aSFrançois Tigeot 	cdclk_ctl = I915_READ(CDCLK_CTL);
966*3f2dd94aSFrançois Tigeot 
967*3f2dd94aSFrançois Tigeot 	if (dev_priv->cdclk.hw.vco != vco) {
968*3f2dd94aSFrançois Tigeot 		/* Wa Display #1183: skl,kbl,cfl */
969*3f2dd94aSFrançois Tigeot 		cdclk_ctl &= ~(CDCLK_FREQ_SEL_MASK | CDCLK_FREQ_DECIMAL_MASK);
970*3f2dd94aSFrançois Tigeot 		cdclk_ctl |= freq_select | skl_cdclk_decimal(cdclk);
971*3f2dd94aSFrançois Tigeot 		I915_WRITE(CDCLK_CTL, cdclk_ctl);
972*3f2dd94aSFrançois Tigeot 	}
973*3f2dd94aSFrançois Tigeot 
974*3f2dd94aSFrançois Tigeot 	/* Wa Display #1183: skl,kbl,cfl */
975*3f2dd94aSFrançois Tigeot 	cdclk_ctl |= CDCLK_DIVMUX_CD_OVERRIDE;
976*3f2dd94aSFrançois Tigeot 	I915_WRITE(CDCLK_CTL, cdclk_ctl);
977*3f2dd94aSFrançois Tigeot 	POSTING_READ(CDCLK_CTL);
978*3f2dd94aSFrançois Tigeot 
979a85cb24fSFrançois Tigeot 	if (dev_priv->cdclk.hw.vco != vco)
980a85cb24fSFrançois Tigeot 		skl_dpll0_enable(dev_priv, vco);
981a85cb24fSFrançois Tigeot 
982*3f2dd94aSFrançois Tigeot 	/* Wa Display #1183: skl,kbl,cfl */
983*3f2dd94aSFrançois Tigeot 	cdclk_ctl &= ~(CDCLK_FREQ_SEL_MASK | CDCLK_FREQ_DECIMAL_MASK);
984*3f2dd94aSFrançois Tigeot 	I915_WRITE(CDCLK_CTL, cdclk_ctl);
985*3f2dd94aSFrançois Tigeot 
986*3f2dd94aSFrançois Tigeot 	cdclk_ctl |= freq_select | skl_cdclk_decimal(cdclk);
987*3f2dd94aSFrançois Tigeot 	I915_WRITE(CDCLK_CTL, cdclk_ctl);
988*3f2dd94aSFrançois Tigeot 
989*3f2dd94aSFrançois Tigeot 	/* Wa Display #1183: skl,kbl,cfl */
990*3f2dd94aSFrançois Tigeot 	cdclk_ctl &= ~CDCLK_DIVMUX_CD_OVERRIDE;
991*3f2dd94aSFrançois Tigeot 	I915_WRITE(CDCLK_CTL, cdclk_ctl);
992a85cb24fSFrançois Tigeot 	POSTING_READ(CDCLK_CTL);
993a85cb24fSFrançois Tigeot 
994a85cb24fSFrançois Tigeot 	/* inform PCU of the change */
995*3f2dd94aSFrançois Tigeot 	mutex_lock(&dev_priv->pcu_lock);
996a85cb24fSFrançois Tigeot 	sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack);
997*3f2dd94aSFrançois Tigeot 	mutex_unlock(&dev_priv->pcu_lock);
998a85cb24fSFrançois Tigeot 
999a85cb24fSFrançois Tigeot 	intel_update_cdclk(dev_priv);
1000a85cb24fSFrançois Tigeot }
1001a85cb24fSFrançois Tigeot 
skl_sanitize_cdclk(struct drm_i915_private * dev_priv)1002a85cb24fSFrançois Tigeot static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
1003a85cb24fSFrançois Tigeot {
1004a85cb24fSFrançois Tigeot 	uint32_t cdctl, expected;
1005a85cb24fSFrançois Tigeot 
1006a85cb24fSFrançois Tigeot 	/*
1007a85cb24fSFrançois Tigeot 	 * check if the pre-os initialized the display
1008a85cb24fSFrançois Tigeot 	 * There is SWF18 scratchpad register defined which is set by the
1009a85cb24fSFrançois Tigeot 	 * pre-os which can be used by the OS drivers to check the status
1010a85cb24fSFrançois Tigeot 	 */
1011a85cb24fSFrançois Tigeot 	if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
1012a85cb24fSFrançois Tigeot 		goto sanitize;
1013a85cb24fSFrançois Tigeot 
1014a85cb24fSFrançois Tigeot 	intel_update_cdclk(dev_priv);
1015a85cb24fSFrançois Tigeot 	/* Is PLL enabled and locked ? */
1016a85cb24fSFrançois Tigeot 	if (dev_priv->cdclk.hw.vco == 0 ||
1017a85cb24fSFrançois Tigeot 	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
1018a85cb24fSFrançois Tigeot 		goto sanitize;
1019a85cb24fSFrançois Tigeot 
1020a85cb24fSFrançois Tigeot 	/* DPLL okay; verify the cdclock
1021a85cb24fSFrançois Tigeot 	 *
1022a85cb24fSFrançois Tigeot 	 * Noticed in some instances that the freq selection is correct but
1023a85cb24fSFrançois Tigeot 	 * decimal part is programmed wrong from BIOS where pre-os does not
1024a85cb24fSFrançois Tigeot 	 * enable display. Verify the same as well.
1025a85cb24fSFrançois Tigeot 	 */
1026a85cb24fSFrançois Tigeot 	cdctl = I915_READ(CDCLK_CTL);
1027a85cb24fSFrançois Tigeot 	expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
1028a85cb24fSFrançois Tigeot 		skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk);
1029a85cb24fSFrançois Tigeot 	if (cdctl == expected)
1030a85cb24fSFrançois Tigeot 		/* All well; nothing to sanitize */
1031a85cb24fSFrançois Tigeot 		return;
1032a85cb24fSFrançois Tigeot 
1033a85cb24fSFrançois Tigeot sanitize:
1034a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
1035a85cb24fSFrançois Tigeot 
1036a85cb24fSFrançois Tigeot 	/* force cdclk programming */
1037a85cb24fSFrançois Tigeot 	dev_priv->cdclk.hw.cdclk = 0;
1038a85cb24fSFrançois Tigeot 	/* force full PLL disable + enable */
1039a85cb24fSFrançois Tigeot 	dev_priv->cdclk.hw.vco = -1;
1040a85cb24fSFrançois Tigeot }
1041a85cb24fSFrançois Tigeot 
1042a85cb24fSFrançois Tigeot /**
1043a85cb24fSFrançois Tigeot  * skl_init_cdclk - Initialize CDCLK on SKL
1044a85cb24fSFrançois Tigeot  * @dev_priv: i915 device
1045a85cb24fSFrançois Tigeot  *
1046a85cb24fSFrançois Tigeot  * Initialize CDCLK for SKL and derivatives. This is generally
1047a85cb24fSFrançois Tigeot  * done only during the display core initialization sequence,
1048a85cb24fSFrançois Tigeot  * after which the DMC will take care of turning CDCLK off/on
1049a85cb24fSFrançois Tigeot  * as needed.
1050a85cb24fSFrançois Tigeot  */
skl_init_cdclk(struct drm_i915_private * dev_priv)1051a85cb24fSFrançois Tigeot void skl_init_cdclk(struct drm_i915_private *dev_priv)
1052a85cb24fSFrançois Tigeot {
1053a85cb24fSFrançois Tigeot 	struct intel_cdclk_state cdclk_state;
1054a85cb24fSFrançois Tigeot 
1055a85cb24fSFrançois Tigeot 	skl_sanitize_cdclk(dev_priv);
1056a85cb24fSFrançois Tigeot 
1057a85cb24fSFrançois Tigeot 	if (dev_priv->cdclk.hw.cdclk != 0 &&
1058a85cb24fSFrançois Tigeot 	    dev_priv->cdclk.hw.vco != 0) {
1059a85cb24fSFrançois Tigeot 		/*
1060a85cb24fSFrançois Tigeot 		 * Use the current vco as our initial
1061a85cb24fSFrançois Tigeot 		 * guess as to what the preferred vco is.
1062a85cb24fSFrançois Tigeot 		 */
1063a85cb24fSFrançois Tigeot 		if (dev_priv->skl_preferred_vco_freq == 0)
1064a85cb24fSFrançois Tigeot 			skl_set_preferred_cdclk_vco(dev_priv,
1065a85cb24fSFrançois Tigeot 						    dev_priv->cdclk.hw.vco);
1066a85cb24fSFrançois Tigeot 		return;
1067a85cb24fSFrançois Tigeot 	}
1068a85cb24fSFrançois Tigeot 
1069a85cb24fSFrançois Tigeot 	cdclk_state = dev_priv->cdclk.hw;
1070a85cb24fSFrançois Tigeot 
1071a85cb24fSFrançois Tigeot 	cdclk_state.vco = dev_priv->skl_preferred_vco_freq;
1072a85cb24fSFrançois Tigeot 	if (cdclk_state.vco == 0)
1073a85cb24fSFrançois Tigeot 		cdclk_state.vco = 8100000;
1074a85cb24fSFrançois Tigeot 	cdclk_state.cdclk = skl_calc_cdclk(0, cdclk_state.vco);
1075a85cb24fSFrançois Tigeot 
1076a85cb24fSFrançois Tigeot 	skl_set_cdclk(dev_priv, &cdclk_state);
1077a85cb24fSFrançois Tigeot }
1078a85cb24fSFrançois Tigeot 
1079a85cb24fSFrançois Tigeot /**
1080a85cb24fSFrançois Tigeot  * skl_uninit_cdclk - Uninitialize CDCLK on SKL
1081a85cb24fSFrançois Tigeot  * @dev_priv: i915 device
1082a85cb24fSFrançois Tigeot  *
1083a85cb24fSFrançois Tigeot  * Uninitialize CDCLK for SKL and derivatives. This is done only
1084a85cb24fSFrançois Tigeot  * during the display core uninitialization sequence.
1085a85cb24fSFrançois Tigeot  */
skl_uninit_cdclk(struct drm_i915_private * dev_priv)1086a85cb24fSFrançois Tigeot void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
1087a85cb24fSFrançois Tigeot {
1088a85cb24fSFrançois Tigeot 	struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw;
1089a85cb24fSFrançois Tigeot 
1090a85cb24fSFrançois Tigeot 	cdclk_state.cdclk = cdclk_state.ref;
1091a85cb24fSFrançois Tigeot 	cdclk_state.vco = 0;
1092a85cb24fSFrançois Tigeot 
1093a85cb24fSFrançois Tigeot 	skl_set_cdclk(dev_priv, &cdclk_state);
1094a85cb24fSFrançois Tigeot }
1095a85cb24fSFrançois Tigeot 
bxt_calc_cdclk(int min_cdclk)1096*3f2dd94aSFrançois Tigeot static int bxt_calc_cdclk(int min_cdclk)
1097a85cb24fSFrançois Tigeot {
1098*3f2dd94aSFrançois Tigeot 	if (min_cdclk > 576000)
1099a85cb24fSFrançois Tigeot 		return 624000;
1100*3f2dd94aSFrançois Tigeot 	else if (min_cdclk > 384000)
1101a85cb24fSFrançois Tigeot 		return 576000;
1102*3f2dd94aSFrançois Tigeot 	else if (min_cdclk > 288000)
1103a85cb24fSFrançois Tigeot 		return 384000;
1104*3f2dd94aSFrançois Tigeot 	else if (min_cdclk > 144000)
1105a85cb24fSFrançois Tigeot 		return 288000;
1106a85cb24fSFrançois Tigeot 	else
1107a85cb24fSFrançois Tigeot 		return 144000;
1108a85cb24fSFrançois Tigeot }
1109a85cb24fSFrançois Tigeot 
glk_calc_cdclk(int min_cdclk)1110*3f2dd94aSFrançois Tigeot static int glk_calc_cdclk(int min_cdclk)
1111a85cb24fSFrançois Tigeot {
1112*3f2dd94aSFrançois Tigeot 	if (min_cdclk > 158400)
1113a85cb24fSFrançois Tigeot 		return 316800;
1114*3f2dd94aSFrançois Tigeot 	else if (min_cdclk > 79200)
1115a85cb24fSFrançois Tigeot 		return 158400;
1116a85cb24fSFrançois Tigeot 	else
1117a85cb24fSFrançois Tigeot 		return 79200;
1118a85cb24fSFrançois Tigeot }
1119a85cb24fSFrançois Tigeot 
bxt_de_pll_vco(struct drm_i915_private * dev_priv,int cdclk)1120a85cb24fSFrançois Tigeot static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
1121a85cb24fSFrançois Tigeot {
1122a85cb24fSFrançois Tigeot 	int ratio;
1123a85cb24fSFrançois Tigeot 
1124a85cb24fSFrançois Tigeot 	if (cdclk == dev_priv->cdclk.hw.ref)
1125a85cb24fSFrançois Tigeot 		return 0;
1126a85cb24fSFrançois Tigeot 
1127a85cb24fSFrançois Tigeot 	switch (cdclk) {
1128a85cb24fSFrançois Tigeot 	default:
1129a85cb24fSFrançois Tigeot 		MISSING_CASE(cdclk);
1130a85cb24fSFrançois Tigeot 	case 144000:
1131a85cb24fSFrançois Tigeot 	case 288000:
1132a85cb24fSFrançois Tigeot 	case 384000:
1133a85cb24fSFrançois Tigeot 	case 576000:
1134a85cb24fSFrançois Tigeot 		ratio = 60;
1135a85cb24fSFrançois Tigeot 		break;
1136a85cb24fSFrançois Tigeot 	case 624000:
1137a85cb24fSFrançois Tigeot 		ratio = 65;
1138a85cb24fSFrançois Tigeot 		break;
1139a85cb24fSFrançois Tigeot 	}
1140a85cb24fSFrançois Tigeot 
1141a85cb24fSFrançois Tigeot 	return dev_priv->cdclk.hw.ref * ratio;
1142a85cb24fSFrançois Tigeot }
1143a85cb24fSFrançois Tigeot 
glk_de_pll_vco(struct drm_i915_private * dev_priv,int cdclk)1144a85cb24fSFrançois Tigeot static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
1145a85cb24fSFrançois Tigeot {
1146a85cb24fSFrançois Tigeot 	int ratio;
1147a85cb24fSFrançois Tigeot 
1148a85cb24fSFrançois Tigeot 	if (cdclk == dev_priv->cdclk.hw.ref)
1149a85cb24fSFrançois Tigeot 		return 0;
1150a85cb24fSFrançois Tigeot 
1151a85cb24fSFrançois Tigeot 	switch (cdclk) {
1152a85cb24fSFrançois Tigeot 	default:
1153a85cb24fSFrançois Tigeot 		MISSING_CASE(cdclk);
1154a85cb24fSFrançois Tigeot 	case  79200:
1155a85cb24fSFrançois Tigeot 	case 158400:
1156a85cb24fSFrançois Tigeot 	case 316800:
1157a85cb24fSFrançois Tigeot 		ratio = 33;
1158a85cb24fSFrançois Tigeot 		break;
1159a85cb24fSFrançois Tigeot 	}
1160a85cb24fSFrançois Tigeot 
1161a85cb24fSFrançois Tigeot 	return dev_priv->cdclk.hw.ref * ratio;
1162a85cb24fSFrançois Tigeot }
1163a85cb24fSFrançois Tigeot 
bxt_de_pll_update(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)1164a85cb24fSFrançois Tigeot static void bxt_de_pll_update(struct drm_i915_private *dev_priv,
1165a85cb24fSFrançois Tigeot 			      struct intel_cdclk_state *cdclk_state)
1166a85cb24fSFrançois Tigeot {
1167a85cb24fSFrançois Tigeot 	u32 val;
1168a85cb24fSFrançois Tigeot 
1169a85cb24fSFrançois Tigeot 	cdclk_state->ref = 19200;
1170a85cb24fSFrançois Tigeot 	cdclk_state->vco = 0;
1171a85cb24fSFrançois Tigeot 
1172a85cb24fSFrançois Tigeot 	val = I915_READ(BXT_DE_PLL_ENABLE);
1173a85cb24fSFrançois Tigeot 	if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
1174a85cb24fSFrançois Tigeot 		return;
1175a85cb24fSFrançois Tigeot 
1176a85cb24fSFrançois Tigeot 	if (WARN_ON((val & BXT_DE_PLL_LOCK) == 0))
1177a85cb24fSFrançois Tigeot 		return;
1178a85cb24fSFrançois Tigeot 
1179a85cb24fSFrançois Tigeot 	val = I915_READ(BXT_DE_PLL_CTL);
1180a85cb24fSFrançois Tigeot 	cdclk_state->vco = (val & BXT_DE_PLL_RATIO_MASK) * cdclk_state->ref;
1181a85cb24fSFrançois Tigeot }
1182a85cb24fSFrançois Tigeot 
bxt_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)1183a85cb24fSFrançois Tigeot static void bxt_get_cdclk(struct drm_i915_private *dev_priv,
1184a85cb24fSFrançois Tigeot 			  struct intel_cdclk_state *cdclk_state)
1185a85cb24fSFrançois Tigeot {
1186a85cb24fSFrançois Tigeot 	u32 divider;
1187a85cb24fSFrançois Tigeot 	int div;
1188a85cb24fSFrançois Tigeot 
1189a85cb24fSFrançois Tigeot 	bxt_de_pll_update(dev_priv, cdclk_state);
1190a85cb24fSFrançois Tigeot 
1191a85cb24fSFrançois Tigeot 	cdclk_state->cdclk = cdclk_state->ref;
1192a85cb24fSFrançois Tigeot 
1193a85cb24fSFrançois Tigeot 	if (cdclk_state->vco == 0)
1194a85cb24fSFrançois Tigeot 		return;
1195a85cb24fSFrançois Tigeot 
1196a85cb24fSFrançois Tigeot 	divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
1197a85cb24fSFrançois Tigeot 
1198a85cb24fSFrançois Tigeot 	switch (divider) {
1199a85cb24fSFrançois Tigeot 	case BXT_CDCLK_CD2X_DIV_SEL_1:
1200a85cb24fSFrançois Tigeot 		div = 2;
1201a85cb24fSFrançois Tigeot 		break;
1202a85cb24fSFrançois Tigeot 	case BXT_CDCLK_CD2X_DIV_SEL_1_5:
1203a85cb24fSFrançois Tigeot 		WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n");
1204a85cb24fSFrançois Tigeot 		div = 3;
1205a85cb24fSFrançois Tigeot 		break;
1206a85cb24fSFrançois Tigeot 	case BXT_CDCLK_CD2X_DIV_SEL_2:
1207a85cb24fSFrançois Tigeot 		div = 4;
1208a85cb24fSFrançois Tigeot 		break;
1209a85cb24fSFrançois Tigeot 	case BXT_CDCLK_CD2X_DIV_SEL_4:
1210a85cb24fSFrançois Tigeot 		div = 8;
1211a85cb24fSFrançois Tigeot 		break;
1212a85cb24fSFrançois Tigeot 	default:
1213a85cb24fSFrançois Tigeot 		MISSING_CASE(divider);
1214a85cb24fSFrançois Tigeot 		return;
1215a85cb24fSFrançois Tigeot 	}
1216a85cb24fSFrançois Tigeot 
1217a85cb24fSFrançois Tigeot 	cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco, div);
1218a85cb24fSFrançois Tigeot }
1219a85cb24fSFrançois Tigeot 
bxt_de_pll_disable(struct drm_i915_private * dev_priv)1220a85cb24fSFrançois Tigeot static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
1221a85cb24fSFrançois Tigeot {
1222a85cb24fSFrançois Tigeot 	I915_WRITE(BXT_DE_PLL_ENABLE, 0);
1223a85cb24fSFrançois Tigeot 
1224a85cb24fSFrançois Tigeot 	/* Timeout 200us */
1225a85cb24fSFrançois Tigeot 	if (intel_wait_for_register(dev_priv,
1226a85cb24fSFrançois Tigeot 				    BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 0,
1227a85cb24fSFrançois Tigeot 				    1))
1228a85cb24fSFrançois Tigeot 		DRM_ERROR("timeout waiting for DE PLL unlock\n");
1229a85cb24fSFrançois Tigeot 
1230a85cb24fSFrançois Tigeot 	dev_priv->cdclk.hw.vco = 0;
1231a85cb24fSFrançois Tigeot }
1232a85cb24fSFrançois Tigeot 
bxt_de_pll_enable(struct drm_i915_private * dev_priv,int vco)1233a85cb24fSFrançois Tigeot static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
1234a85cb24fSFrançois Tigeot {
1235a85cb24fSFrançois Tigeot 	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk.hw.ref);
1236a85cb24fSFrançois Tigeot 	u32 val;
1237a85cb24fSFrançois Tigeot 
1238a85cb24fSFrançois Tigeot 	val = I915_READ(BXT_DE_PLL_CTL);
1239a85cb24fSFrançois Tigeot 	val &= ~BXT_DE_PLL_RATIO_MASK;
1240a85cb24fSFrançois Tigeot 	val |= BXT_DE_PLL_RATIO(ratio);
1241a85cb24fSFrançois Tigeot 	I915_WRITE(BXT_DE_PLL_CTL, val);
1242a85cb24fSFrançois Tigeot 
1243a85cb24fSFrançois Tigeot 	I915_WRITE(BXT_DE_PLL_ENABLE, BXT_DE_PLL_PLL_ENABLE);
1244a85cb24fSFrançois Tigeot 
1245a85cb24fSFrançois Tigeot 	/* Timeout 200us */
1246a85cb24fSFrançois Tigeot 	if (intel_wait_for_register(dev_priv,
1247a85cb24fSFrançois Tigeot 				    BXT_DE_PLL_ENABLE,
1248a85cb24fSFrançois Tigeot 				    BXT_DE_PLL_LOCK,
1249a85cb24fSFrançois Tigeot 				    BXT_DE_PLL_LOCK,
1250a85cb24fSFrançois Tigeot 				    1))
1251a85cb24fSFrançois Tigeot 		DRM_ERROR("timeout waiting for DE PLL lock\n");
1252a85cb24fSFrançois Tigeot 
1253a85cb24fSFrançois Tigeot 	dev_priv->cdclk.hw.vco = vco;
1254a85cb24fSFrançois Tigeot }
1255a85cb24fSFrançois Tigeot 
bxt_set_cdclk(struct drm_i915_private * dev_priv,const struct intel_cdclk_state * cdclk_state)1256a85cb24fSFrançois Tigeot static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
1257a85cb24fSFrançois Tigeot 			  const struct intel_cdclk_state *cdclk_state)
1258a85cb24fSFrançois Tigeot {
1259a85cb24fSFrançois Tigeot 	int cdclk = cdclk_state->cdclk;
1260a85cb24fSFrançois Tigeot 	int vco = cdclk_state->vco;
1261a85cb24fSFrançois Tigeot 	u32 val, divider;
1262a85cb24fSFrançois Tigeot 	int ret;
1263a85cb24fSFrançois Tigeot 
1264a85cb24fSFrançois Tigeot 	/* cdclk = vco / 2 / div{1,1.5,2,4} */
1265a85cb24fSFrançois Tigeot 	switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
1266a85cb24fSFrançois Tigeot 	case 8:
1267a85cb24fSFrançois Tigeot 		divider = BXT_CDCLK_CD2X_DIV_SEL_4;
1268a85cb24fSFrançois Tigeot 		break;
1269a85cb24fSFrançois Tigeot 	case 4:
1270a85cb24fSFrançois Tigeot 		divider = BXT_CDCLK_CD2X_DIV_SEL_2;
1271a85cb24fSFrançois Tigeot 		break;
1272a85cb24fSFrançois Tigeot 	case 3:
1273a85cb24fSFrançois Tigeot 		WARN(IS_GEMINILAKE(dev_priv), "Unsupported divider\n");
1274a85cb24fSFrançois Tigeot 		divider = BXT_CDCLK_CD2X_DIV_SEL_1_5;
1275a85cb24fSFrançois Tigeot 		break;
1276a85cb24fSFrançois Tigeot 	case 2:
1277a85cb24fSFrançois Tigeot 		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
1278a85cb24fSFrançois Tigeot 		break;
1279a85cb24fSFrançois Tigeot 	default:
1280a85cb24fSFrançois Tigeot 		WARN_ON(cdclk != dev_priv->cdclk.hw.ref);
1281a85cb24fSFrançois Tigeot 		WARN_ON(vco != 0);
1282a85cb24fSFrançois Tigeot 
1283a85cb24fSFrançois Tigeot 		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
1284a85cb24fSFrançois Tigeot 		break;
1285a85cb24fSFrançois Tigeot 	}
1286a85cb24fSFrançois Tigeot 
1287a85cb24fSFrançois Tigeot 	/* Inform power controller of upcoming frequency change */
1288*3f2dd94aSFrançois Tigeot 	mutex_lock(&dev_priv->pcu_lock);
1289a85cb24fSFrançois Tigeot 	ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
1290a85cb24fSFrançois Tigeot 				      0x80000000);
1291*3f2dd94aSFrançois Tigeot 	mutex_unlock(&dev_priv->pcu_lock);
1292a85cb24fSFrançois Tigeot 
1293a85cb24fSFrançois Tigeot 	if (ret) {
1294a85cb24fSFrançois Tigeot 		DRM_ERROR("PCode CDCLK freq change notify failed (err %d, freq %d)\n",
1295a85cb24fSFrançois Tigeot 			  ret, cdclk);
1296a85cb24fSFrançois Tigeot 		return;
1297a85cb24fSFrançois Tigeot 	}
1298a85cb24fSFrançois Tigeot 
1299a85cb24fSFrançois Tigeot 	if (dev_priv->cdclk.hw.vco != 0 &&
1300a85cb24fSFrançois Tigeot 	    dev_priv->cdclk.hw.vco != vco)
1301a85cb24fSFrançois Tigeot 		bxt_de_pll_disable(dev_priv);
1302a85cb24fSFrançois Tigeot 
1303a85cb24fSFrançois Tigeot 	if (dev_priv->cdclk.hw.vco != vco)
1304a85cb24fSFrançois Tigeot 		bxt_de_pll_enable(dev_priv, vco);
1305a85cb24fSFrançois Tigeot 
1306a85cb24fSFrançois Tigeot 	val = divider | skl_cdclk_decimal(cdclk);
1307a85cb24fSFrançois Tigeot 	/*
1308a85cb24fSFrançois Tigeot 	 * FIXME if only the cd2x divider needs changing, it could be done
1309a85cb24fSFrançois Tigeot 	 * without shutting off the pipe (if only one pipe is active).
1310a85cb24fSFrançois Tigeot 	 */
1311a85cb24fSFrançois Tigeot 	val |= BXT_CDCLK_CD2X_PIPE_NONE;
1312a85cb24fSFrançois Tigeot 	/*
1313a85cb24fSFrançois Tigeot 	 * Disable SSA Precharge when CD clock frequency < 500 MHz,
1314a85cb24fSFrançois Tigeot 	 * enable otherwise.
1315a85cb24fSFrançois Tigeot 	 */
1316a85cb24fSFrançois Tigeot 	if (cdclk >= 500000)
1317a85cb24fSFrançois Tigeot 		val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
1318a85cb24fSFrançois Tigeot 	I915_WRITE(CDCLK_CTL, val);
1319a85cb24fSFrançois Tigeot 
1320*3f2dd94aSFrançois Tigeot 	mutex_lock(&dev_priv->pcu_lock);
1321a85cb24fSFrançois Tigeot 	ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
1322a85cb24fSFrançois Tigeot 				      DIV_ROUND_UP(cdclk, 25000));
1323*3f2dd94aSFrançois Tigeot 	mutex_unlock(&dev_priv->pcu_lock);
1324a85cb24fSFrançois Tigeot 
1325a85cb24fSFrançois Tigeot 	if (ret) {
1326a85cb24fSFrançois Tigeot 		DRM_ERROR("PCode CDCLK freq set failed, (err %d, freq %d)\n",
1327a85cb24fSFrançois Tigeot 			  ret, cdclk);
1328a85cb24fSFrançois Tigeot 		return;
1329a85cb24fSFrançois Tigeot 	}
1330a85cb24fSFrançois Tigeot 
1331a85cb24fSFrançois Tigeot 	intel_update_cdclk(dev_priv);
1332a85cb24fSFrançois Tigeot }
1333a85cb24fSFrançois Tigeot 
bxt_sanitize_cdclk(struct drm_i915_private * dev_priv)1334a85cb24fSFrançois Tigeot static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
1335a85cb24fSFrançois Tigeot {
1336a85cb24fSFrançois Tigeot 	u32 cdctl, expected;
1337a85cb24fSFrançois Tigeot 
1338a85cb24fSFrançois Tigeot 	intel_update_cdclk(dev_priv);
1339a85cb24fSFrançois Tigeot 
1340a85cb24fSFrançois Tigeot 	if (dev_priv->cdclk.hw.vco == 0 ||
1341a85cb24fSFrançois Tigeot 	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
1342a85cb24fSFrançois Tigeot 		goto sanitize;
1343a85cb24fSFrançois Tigeot 
1344a85cb24fSFrançois Tigeot 	/* DPLL okay; verify the cdclock
1345a85cb24fSFrançois Tigeot 	 *
1346a85cb24fSFrançois Tigeot 	 * Some BIOS versions leave an incorrect decimal frequency value and
1347a85cb24fSFrançois Tigeot 	 * set reserved MBZ bits in CDCLK_CTL at least during exiting from S4,
1348a85cb24fSFrançois Tigeot 	 * so sanitize this register.
1349a85cb24fSFrançois Tigeot 	 */
1350a85cb24fSFrançois Tigeot 	cdctl = I915_READ(CDCLK_CTL);
1351a85cb24fSFrançois Tigeot 	/*
1352a85cb24fSFrançois Tigeot 	 * Let's ignore the pipe field, since BIOS could have configured the
1353a85cb24fSFrançois Tigeot 	 * dividers both synching to an active pipe, or asynchronously
1354a85cb24fSFrançois Tigeot 	 * (PIPE_NONE).
1355a85cb24fSFrançois Tigeot 	 */
1356a85cb24fSFrançois Tigeot 	cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
1357a85cb24fSFrançois Tigeot 
1358a85cb24fSFrançois Tigeot 	expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) |
1359a85cb24fSFrançois Tigeot 		skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk);
1360a85cb24fSFrançois Tigeot 	/*
1361a85cb24fSFrançois Tigeot 	 * Disable SSA Precharge when CD clock frequency < 500 MHz,
1362a85cb24fSFrançois Tigeot 	 * enable otherwise.
1363a85cb24fSFrançois Tigeot 	 */
1364a85cb24fSFrançois Tigeot 	if (dev_priv->cdclk.hw.cdclk >= 500000)
1365a85cb24fSFrançois Tigeot 		expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
1366a85cb24fSFrançois Tigeot 
1367a85cb24fSFrançois Tigeot 	if (cdctl == expected)
1368a85cb24fSFrançois Tigeot 		/* All well; nothing to sanitize */
1369a85cb24fSFrançois Tigeot 		return;
1370a85cb24fSFrançois Tigeot 
1371a85cb24fSFrançois Tigeot sanitize:
1372a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
1373a85cb24fSFrançois Tigeot 
1374a85cb24fSFrançois Tigeot 	/* force cdclk programming */
1375a85cb24fSFrançois Tigeot 	dev_priv->cdclk.hw.cdclk = 0;
1376a85cb24fSFrançois Tigeot 
1377a85cb24fSFrançois Tigeot 	/* force full PLL disable + enable */
1378a85cb24fSFrançois Tigeot 	dev_priv->cdclk.hw.vco = -1;
1379a85cb24fSFrançois Tigeot }
1380a85cb24fSFrançois Tigeot 
1381a85cb24fSFrançois Tigeot /**
1382a85cb24fSFrançois Tigeot  * bxt_init_cdclk - Initialize CDCLK on BXT
1383a85cb24fSFrançois Tigeot  * @dev_priv: i915 device
1384a85cb24fSFrançois Tigeot  *
1385a85cb24fSFrançois Tigeot  * Initialize CDCLK for BXT and derivatives. This is generally
1386a85cb24fSFrançois Tigeot  * done only during the display core initialization sequence,
1387a85cb24fSFrançois Tigeot  * after which the DMC will take care of turning CDCLK off/on
1388a85cb24fSFrançois Tigeot  * as needed.
1389a85cb24fSFrançois Tigeot  */
bxt_init_cdclk(struct drm_i915_private * dev_priv)1390a85cb24fSFrançois Tigeot void bxt_init_cdclk(struct drm_i915_private *dev_priv)
1391a85cb24fSFrançois Tigeot {
1392a85cb24fSFrançois Tigeot 	struct intel_cdclk_state cdclk_state;
1393a85cb24fSFrançois Tigeot 
1394a85cb24fSFrançois Tigeot 	bxt_sanitize_cdclk(dev_priv);
1395a85cb24fSFrançois Tigeot 
1396a85cb24fSFrançois Tigeot 	if (dev_priv->cdclk.hw.cdclk != 0 &&
1397a85cb24fSFrançois Tigeot 	    dev_priv->cdclk.hw.vco != 0)
1398a85cb24fSFrançois Tigeot 		return;
1399a85cb24fSFrançois Tigeot 
1400a85cb24fSFrançois Tigeot 	cdclk_state = dev_priv->cdclk.hw;
1401a85cb24fSFrançois Tigeot 
1402a85cb24fSFrançois Tigeot 	/*
1403a85cb24fSFrançois Tigeot 	 * FIXME:
1404a85cb24fSFrançois Tigeot 	 * - The initial CDCLK needs to be read from VBT.
1405a85cb24fSFrançois Tigeot 	 *   Need to make this change after VBT has changes for BXT.
1406a85cb24fSFrançois Tigeot 	 */
1407a85cb24fSFrançois Tigeot 	if (IS_GEMINILAKE(dev_priv)) {
1408a85cb24fSFrançois Tigeot 		cdclk_state.cdclk = glk_calc_cdclk(0);
1409a85cb24fSFrançois Tigeot 		cdclk_state.vco = glk_de_pll_vco(dev_priv, cdclk_state.cdclk);
1410a85cb24fSFrançois Tigeot 	} else {
1411a85cb24fSFrançois Tigeot 		cdclk_state.cdclk = bxt_calc_cdclk(0);
1412a85cb24fSFrançois Tigeot 		cdclk_state.vco = bxt_de_pll_vco(dev_priv, cdclk_state.cdclk);
1413a85cb24fSFrançois Tigeot 	}
1414a85cb24fSFrançois Tigeot 
1415a85cb24fSFrançois Tigeot 	bxt_set_cdclk(dev_priv, &cdclk_state);
1416a85cb24fSFrançois Tigeot }
1417a85cb24fSFrançois Tigeot 
1418a85cb24fSFrançois Tigeot /**
1419a85cb24fSFrançois Tigeot  * bxt_uninit_cdclk - Uninitialize CDCLK on BXT
1420a85cb24fSFrançois Tigeot  * @dev_priv: i915 device
1421a85cb24fSFrançois Tigeot  *
1422a85cb24fSFrançois Tigeot  * Uninitialize CDCLK for BXT and derivatives. This is done only
1423a85cb24fSFrançois Tigeot  * during the display core uninitialization sequence.
1424a85cb24fSFrançois Tigeot  */
bxt_uninit_cdclk(struct drm_i915_private * dev_priv)1425a85cb24fSFrançois Tigeot void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
1426a85cb24fSFrançois Tigeot {
1427a85cb24fSFrançois Tigeot 	struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw;
1428a85cb24fSFrançois Tigeot 
1429a85cb24fSFrançois Tigeot 	cdclk_state.cdclk = cdclk_state.ref;
1430a85cb24fSFrançois Tigeot 	cdclk_state.vco = 0;
1431a85cb24fSFrançois Tigeot 
1432a85cb24fSFrançois Tigeot 	bxt_set_cdclk(dev_priv, &cdclk_state);
1433a85cb24fSFrançois Tigeot }
1434a85cb24fSFrançois Tigeot 
cnl_calc_cdclk(int min_cdclk)1435*3f2dd94aSFrançois Tigeot static int cnl_calc_cdclk(int min_cdclk)
1436*3f2dd94aSFrançois Tigeot {
1437*3f2dd94aSFrançois Tigeot 	if (min_cdclk > 336000)
1438*3f2dd94aSFrançois Tigeot 		return 528000;
1439*3f2dd94aSFrançois Tigeot 	else if (min_cdclk > 168000)
1440*3f2dd94aSFrançois Tigeot 		return 336000;
1441*3f2dd94aSFrançois Tigeot 	else
1442*3f2dd94aSFrançois Tigeot 		return 168000;
1443*3f2dd94aSFrançois Tigeot }
1444*3f2dd94aSFrançois Tigeot 
cnl_cdclk_pll_update(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)1445*3f2dd94aSFrançois Tigeot static void cnl_cdclk_pll_update(struct drm_i915_private *dev_priv,
1446*3f2dd94aSFrançois Tigeot 				 struct intel_cdclk_state *cdclk_state)
1447*3f2dd94aSFrançois Tigeot {
1448*3f2dd94aSFrançois Tigeot 	u32 val;
1449*3f2dd94aSFrançois Tigeot 
1450*3f2dd94aSFrançois Tigeot 	if (I915_READ(SKL_DSSM) & CNL_DSSM_CDCLK_PLL_REFCLK_24MHz)
1451*3f2dd94aSFrançois Tigeot 		cdclk_state->ref = 24000;
1452*3f2dd94aSFrançois Tigeot 	else
1453*3f2dd94aSFrançois Tigeot 		cdclk_state->ref = 19200;
1454*3f2dd94aSFrançois Tigeot 
1455*3f2dd94aSFrançois Tigeot 	cdclk_state->vco = 0;
1456*3f2dd94aSFrançois Tigeot 
1457*3f2dd94aSFrançois Tigeot 	val = I915_READ(BXT_DE_PLL_ENABLE);
1458*3f2dd94aSFrançois Tigeot 	if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
1459*3f2dd94aSFrançois Tigeot 		return;
1460*3f2dd94aSFrançois Tigeot 
1461*3f2dd94aSFrançois Tigeot 	if (WARN_ON((val & BXT_DE_PLL_LOCK) == 0))
1462*3f2dd94aSFrançois Tigeot 		return;
1463*3f2dd94aSFrançois Tigeot 
1464*3f2dd94aSFrançois Tigeot 	cdclk_state->vco = (val & CNL_CDCLK_PLL_RATIO_MASK) * cdclk_state->ref;
1465*3f2dd94aSFrançois Tigeot }
1466*3f2dd94aSFrançois Tigeot 
cnl_get_cdclk(struct drm_i915_private * dev_priv,struct intel_cdclk_state * cdclk_state)1467*3f2dd94aSFrançois Tigeot static void cnl_get_cdclk(struct drm_i915_private *dev_priv,
1468*3f2dd94aSFrançois Tigeot 			 struct intel_cdclk_state *cdclk_state)
1469*3f2dd94aSFrançois Tigeot {
1470*3f2dd94aSFrançois Tigeot 	u32 divider;
1471*3f2dd94aSFrançois Tigeot 	int div;
1472*3f2dd94aSFrançois Tigeot 
1473*3f2dd94aSFrançois Tigeot 	cnl_cdclk_pll_update(dev_priv, cdclk_state);
1474*3f2dd94aSFrançois Tigeot 
1475*3f2dd94aSFrançois Tigeot 	cdclk_state->cdclk = cdclk_state->ref;
1476*3f2dd94aSFrançois Tigeot 
1477*3f2dd94aSFrançois Tigeot 	if (cdclk_state->vco == 0)
1478*3f2dd94aSFrançois Tigeot 		return;
1479*3f2dd94aSFrançois Tigeot 
1480*3f2dd94aSFrançois Tigeot 	divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
1481*3f2dd94aSFrançois Tigeot 
1482*3f2dd94aSFrançois Tigeot 	switch (divider) {
1483*3f2dd94aSFrançois Tigeot 	case BXT_CDCLK_CD2X_DIV_SEL_1:
1484*3f2dd94aSFrançois Tigeot 		div = 2;
1485*3f2dd94aSFrançois Tigeot 		break;
1486*3f2dd94aSFrançois Tigeot 	case BXT_CDCLK_CD2X_DIV_SEL_2:
1487*3f2dd94aSFrançois Tigeot 		div = 4;
1488*3f2dd94aSFrançois Tigeot 		break;
1489*3f2dd94aSFrançois Tigeot 	default:
1490*3f2dd94aSFrançois Tigeot 		MISSING_CASE(divider);
1491*3f2dd94aSFrançois Tigeot 		return;
1492*3f2dd94aSFrançois Tigeot 	}
1493*3f2dd94aSFrançois Tigeot 
1494*3f2dd94aSFrançois Tigeot 	cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco, div);
1495*3f2dd94aSFrançois Tigeot }
1496*3f2dd94aSFrançois Tigeot 
cnl_cdclk_pll_disable(struct drm_i915_private * dev_priv)1497*3f2dd94aSFrançois Tigeot static void cnl_cdclk_pll_disable(struct drm_i915_private *dev_priv)
1498*3f2dd94aSFrançois Tigeot {
1499*3f2dd94aSFrançois Tigeot 	u32 val;
1500*3f2dd94aSFrançois Tigeot 
1501*3f2dd94aSFrançois Tigeot 	val = I915_READ(BXT_DE_PLL_ENABLE);
1502*3f2dd94aSFrançois Tigeot 	val &= ~BXT_DE_PLL_PLL_ENABLE;
1503*3f2dd94aSFrançois Tigeot 	I915_WRITE(BXT_DE_PLL_ENABLE, val);
1504*3f2dd94aSFrançois Tigeot 
1505*3f2dd94aSFrançois Tigeot 	/* Timeout 200us */
1506*3f2dd94aSFrançois Tigeot 	if (wait_for((I915_READ(BXT_DE_PLL_ENABLE) & BXT_DE_PLL_LOCK) == 0, 1))
1507*3f2dd94aSFrançois Tigeot 		DRM_ERROR("timout waiting for CDCLK PLL unlock\n");
1508*3f2dd94aSFrançois Tigeot 
1509*3f2dd94aSFrançois Tigeot 	dev_priv->cdclk.hw.vco = 0;
1510*3f2dd94aSFrançois Tigeot }
1511*3f2dd94aSFrançois Tigeot 
cnl_cdclk_pll_enable(struct drm_i915_private * dev_priv,int vco)1512*3f2dd94aSFrançois Tigeot static void cnl_cdclk_pll_enable(struct drm_i915_private *dev_priv, int vco)
1513*3f2dd94aSFrançois Tigeot {
1514*3f2dd94aSFrançois Tigeot 	int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk.hw.ref);
1515*3f2dd94aSFrançois Tigeot 	u32 val;
1516*3f2dd94aSFrançois Tigeot 
1517*3f2dd94aSFrançois Tigeot 	val = CNL_CDCLK_PLL_RATIO(ratio);
1518*3f2dd94aSFrançois Tigeot 	I915_WRITE(BXT_DE_PLL_ENABLE, val);
1519*3f2dd94aSFrançois Tigeot 
1520*3f2dd94aSFrançois Tigeot 	val |= BXT_DE_PLL_PLL_ENABLE;
1521*3f2dd94aSFrançois Tigeot 	I915_WRITE(BXT_DE_PLL_ENABLE, val);
1522*3f2dd94aSFrançois Tigeot 
1523*3f2dd94aSFrançois Tigeot 	/* Timeout 200us */
1524*3f2dd94aSFrançois Tigeot 	if (wait_for((I915_READ(BXT_DE_PLL_ENABLE) & BXT_DE_PLL_LOCK) != 0, 1))
1525*3f2dd94aSFrançois Tigeot 		DRM_ERROR("timout waiting for CDCLK PLL lock\n");
1526*3f2dd94aSFrançois Tigeot 
1527*3f2dd94aSFrançois Tigeot 	dev_priv->cdclk.hw.vco = vco;
1528*3f2dd94aSFrançois Tigeot }
1529*3f2dd94aSFrançois Tigeot 
cnl_set_cdclk(struct drm_i915_private * dev_priv,const struct intel_cdclk_state * cdclk_state)1530*3f2dd94aSFrançois Tigeot static void cnl_set_cdclk(struct drm_i915_private *dev_priv,
1531*3f2dd94aSFrançois Tigeot 			  const struct intel_cdclk_state *cdclk_state)
1532*3f2dd94aSFrançois Tigeot {
1533*3f2dd94aSFrançois Tigeot 	int cdclk = cdclk_state->cdclk;
1534*3f2dd94aSFrançois Tigeot 	int vco = cdclk_state->vco;
1535*3f2dd94aSFrançois Tigeot 	u32 val, divider, pcu_ack;
1536*3f2dd94aSFrançois Tigeot 	int ret;
1537*3f2dd94aSFrançois Tigeot 
1538*3f2dd94aSFrançois Tigeot 	mutex_lock(&dev_priv->pcu_lock);
1539*3f2dd94aSFrançois Tigeot 	ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
1540*3f2dd94aSFrançois Tigeot 				SKL_CDCLK_PREPARE_FOR_CHANGE,
1541*3f2dd94aSFrançois Tigeot 				SKL_CDCLK_READY_FOR_CHANGE,
1542*3f2dd94aSFrançois Tigeot 				SKL_CDCLK_READY_FOR_CHANGE, 3);
1543*3f2dd94aSFrançois Tigeot 	mutex_unlock(&dev_priv->pcu_lock);
1544*3f2dd94aSFrançois Tigeot 	if (ret) {
1545*3f2dd94aSFrançois Tigeot 		DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n",
1546*3f2dd94aSFrançois Tigeot 			  ret);
1547*3f2dd94aSFrançois Tigeot 		return;
1548*3f2dd94aSFrançois Tigeot 	}
1549*3f2dd94aSFrançois Tigeot 
1550*3f2dd94aSFrançois Tigeot 	/* cdclk = vco / 2 / div{1,2} */
1551*3f2dd94aSFrançois Tigeot 	switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
1552*3f2dd94aSFrançois Tigeot 	case 4:
1553*3f2dd94aSFrançois Tigeot 		divider = BXT_CDCLK_CD2X_DIV_SEL_2;
1554*3f2dd94aSFrançois Tigeot 		break;
1555*3f2dd94aSFrançois Tigeot 	case 2:
1556*3f2dd94aSFrançois Tigeot 		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
1557*3f2dd94aSFrançois Tigeot 		break;
1558*3f2dd94aSFrançois Tigeot 	default:
1559*3f2dd94aSFrançois Tigeot 		WARN_ON(cdclk != dev_priv->cdclk.hw.ref);
1560*3f2dd94aSFrançois Tigeot 		WARN_ON(vco != 0);
1561*3f2dd94aSFrançois Tigeot 
1562*3f2dd94aSFrançois Tigeot 		divider = BXT_CDCLK_CD2X_DIV_SEL_1;
1563*3f2dd94aSFrançois Tigeot 		break;
1564*3f2dd94aSFrançois Tigeot 	}
1565*3f2dd94aSFrançois Tigeot 
1566*3f2dd94aSFrançois Tigeot 	switch (cdclk) {
1567*3f2dd94aSFrançois Tigeot 	case 528000:
1568*3f2dd94aSFrançois Tigeot 		pcu_ack = 2;
1569*3f2dd94aSFrançois Tigeot 		break;
1570*3f2dd94aSFrançois Tigeot 	case 336000:
1571*3f2dd94aSFrançois Tigeot 		pcu_ack = 1;
1572*3f2dd94aSFrançois Tigeot 		break;
1573*3f2dd94aSFrançois Tigeot 	case 168000:
1574*3f2dd94aSFrançois Tigeot 	default:
1575*3f2dd94aSFrançois Tigeot 		pcu_ack = 0;
1576*3f2dd94aSFrançois Tigeot 		break;
1577*3f2dd94aSFrançois Tigeot 	}
1578*3f2dd94aSFrançois Tigeot 
1579*3f2dd94aSFrançois Tigeot 	if (dev_priv->cdclk.hw.vco != 0 &&
1580*3f2dd94aSFrançois Tigeot 	    dev_priv->cdclk.hw.vco != vco)
1581*3f2dd94aSFrançois Tigeot 		cnl_cdclk_pll_disable(dev_priv);
1582*3f2dd94aSFrançois Tigeot 
1583*3f2dd94aSFrançois Tigeot 	if (dev_priv->cdclk.hw.vco != vco)
1584*3f2dd94aSFrançois Tigeot 		cnl_cdclk_pll_enable(dev_priv, vco);
1585*3f2dd94aSFrançois Tigeot 
1586*3f2dd94aSFrançois Tigeot 	val = divider | skl_cdclk_decimal(cdclk);
1587*3f2dd94aSFrançois Tigeot 	/*
1588*3f2dd94aSFrançois Tigeot 	 * FIXME if only the cd2x divider needs changing, it could be done
1589*3f2dd94aSFrançois Tigeot 	 * without shutting off the pipe (if only one pipe is active).
1590*3f2dd94aSFrançois Tigeot 	 */
1591*3f2dd94aSFrançois Tigeot 	val |= BXT_CDCLK_CD2X_PIPE_NONE;
1592*3f2dd94aSFrançois Tigeot 	I915_WRITE(CDCLK_CTL, val);
1593*3f2dd94aSFrançois Tigeot 
1594*3f2dd94aSFrançois Tigeot 	/* inform PCU of the change */
1595*3f2dd94aSFrançois Tigeot 	mutex_lock(&dev_priv->pcu_lock);
1596*3f2dd94aSFrançois Tigeot 	sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack);
1597*3f2dd94aSFrançois Tigeot 	mutex_unlock(&dev_priv->pcu_lock);
1598*3f2dd94aSFrançois Tigeot 
1599*3f2dd94aSFrançois Tigeot 	intel_update_cdclk(dev_priv);
1600*3f2dd94aSFrançois Tigeot }
1601*3f2dd94aSFrançois Tigeot 
cnl_cdclk_pll_vco(struct drm_i915_private * dev_priv,int cdclk)1602*3f2dd94aSFrançois Tigeot static int cnl_cdclk_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
1603*3f2dd94aSFrançois Tigeot {
1604*3f2dd94aSFrançois Tigeot 	int ratio;
1605*3f2dd94aSFrançois Tigeot 
1606*3f2dd94aSFrançois Tigeot 	if (cdclk == dev_priv->cdclk.hw.ref)
1607*3f2dd94aSFrançois Tigeot 		return 0;
1608*3f2dd94aSFrançois Tigeot 
1609*3f2dd94aSFrançois Tigeot 	switch (cdclk) {
1610*3f2dd94aSFrançois Tigeot 	default:
1611*3f2dd94aSFrançois Tigeot 		MISSING_CASE(cdclk);
1612*3f2dd94aSFrançois Tigeot 	case 168000:
1613*3f2dd94aSFrançois Tigeot 	case 336000:
1614*3f2dd94aSFrançois Tigeot 		ratio = dev_priv->cdclk.hw.ref == 19200 ? 35 : 28;
1615*3f2dd94aSFrançois Tigeot 		break;
1616*3f2dd94aSFrançois Tigeot 	case 528000:
1617*3f2dd94aSFrançois Tigeot 		ratio = dev_priv->cdclk.hw.ref == 19200 ? 55 : 44;
1618*3f2dd94aSFrançois Tigeot 		break;
1619*3f2dd94aSFrançois Tigeot 	}
1620*3f2dd94aSFrançois Tigeot 
1621*3f2dd94aSFrançois Tigeot 	return dev_priv->cdclk.hw.ref * ratio;
1622*3f2dd94aSFrançois Tigeot }
1623*3f2dd94aSFrançois Tigeot 
cnl_sanitize_cdclk(struct drm_i915_private * dev_priv)1624*3f2dd94aSFrançois Tigeot static void cnl_sanitize_cdclk(struct drm_i915_private *dev_priv)
1625*3f2dd94aSFrançois Tigeot {
1626*3f2dd94aSFrançois Tigeot 	u32 cdctl, expected;
1627*3f2dd94aSFrançois Tigeot 
1628*3f2dd94aSFrançois Tigeot 	intel_update_cdclk(dev_priv);
1629*3f2dd94aSFrançois Tigeot 
1630*3f2dd94aSFrançois Tigeot 	if (dev_priv->cdclk.hw.vco == 0 ||
1631*3f2dd94aSFrançois Tigeot 	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
1632*3f2dd94aSFrançois Tigeot 		goto sanitize;
1633*3f2dd94aSFrançois Tigeot 
1634*3f2dd94aSFrançois Tigeot 	/* DPLL okay; verify the cdclock
1635*3f2dd94aSFrançois Tigeot 	 *
1636*3f2dd94aSFrançois Tigeot 	 * Some BIOS versions leave an incorrect decimal frequency value and
1637*3f2dd94aSFrançois Tigeot 	 * set reserved MBZ bits in CDCLK_CTL at least during exiting from S4,
1638*3f2dd94aSFrançois Tigeot 	 * so sanitize this register.
1639*3f2dd94aSFrançois Tigeot 	 */
1640*3f2dd94aSFrançois Tigeot 	cdctl = I915_READ(CDCLK_CTL);
1641*3f2dd94aSFrançois Tigeot 	/*
1642*3f2dd94aSFrançois Tigeot 	 * Let's ignore the pipe field, since BIOS could have configured the
1643*3f2dd94aSFrançois Tigeot 	 * dividers both synching to an active pipe, or asynchronously
1644*3f2dd94aSFrançois Tigeot 	 * (PIPE_NONE).
1645*3f2dd94aSFrançois Tigeot 	 */
1646*3f2dd94aSFrançois Tigeot 	cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
1647*3f2dd94aSFrançois Tigeot 
1648*3f2dd94aSFrançois Tigeot 	expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) |
1649*3f2dd94aSFrançois Tigeot 		   skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk);
1650*3f2dd94aSFrançois Tigeot 
1651*3f2dd94aSFrançois Tigeot 	if (cdctl == expected)
1652*3f2dd94aSFrançois Tigeot 		/* All well; nothing to sanitize */
1653*3f2dd94aSFrançois Tigeot 		return;
1654*3f2dd94aSFrançois Tigeot 
1655*3f2dd94aSFrançois Tigeot sanitize:
1656*3f2dd94aSFrançois Tigeot 	DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
1657*3f2dd94aSFrançois Tigeot 
1658*3f2dd94aSFrançois Tigeot 	/* force cdclk programming */
1659*3f2dd94aSFrançois Tigeot 	dev_priv->cdclk.hw.cdclk = 0;
1660*3f2dd94aSFrançois Tigeot 
1661*3f2dd94aSFrançois Tigeot 	/* force full PLL disable + enable */
1662*3f2dd94aSFrançois Tigeot 	dev_priv->cdclk.hw.vco = -1;
1663*3f2dd94aSFrançois Tigeot }
1664*3f2dd94aSFrançois Tigeot 
1665*3f2dd94aSFrançois Tigeot /**
1666*3f2dd94aSFrançois Tigeot  * cnl_init_cdclk - Initialize CDCLK on CNL
1667*3f2dd94aSFrançois Tigeot  * @dev_priv: i915 device
1668*3f2dd94aSFrançois Tigeot  *
1669*3f2dd94aSFrançois Tigeot  * Initialize CDCLK for CNL. This is generally
1670*3f2dd94aSFrançois Tigeot  * done only during the display core initialization sequence,
1671*3f2dd94aSFrançois Tigeot  * after which the DMC will take care of turning CDCLK off/on
1672*3f2dd94aSFrançois Tigeot  * as needed.
1673*3f2dd94aSFrançois Tigeot  */
cnl_init_cdclk(struct drm_i915_private * dev_priv)1674*3f2dd94aSFrançois Tigeot void cnl_init_cdclk(struct drm_i915_private *dev_priv)
1675*3f2dd94aSFrançois Tigeot {
1676*3f2dd94aSFrançois Tigeot 	struct intel_cdclk_state cdclk_state;
1677*3f2dd94aSFrançois Tigeot 
1678*3f2dd94aSFrançois Tigeot 	cnl_sanitize_cdclk(dev_priv);
1679*3f2dd94aSFrançois Tigeot 
1680*3f2dd94aSFrançois Tigeot 	if (dev_priv->cdclk.hw.cdclk != 0 &&
1681*3f2dd94aSFrançois Tigeot 	    dev_priv->cdclk.hw.vco != 0)
1682*3f2dd94aSFrançois Tigeot 		return;
1683*3f2dd94aSFrançois Tigeot 
1684*3f2dd94aSFrançois Tigeot 	cdclk_state = dev_priv->cdclk.hw;
1685*3f2dd94aSFrançois Tigeot 
1686*3f2dd94aSFrançois Tigeot 	cdclk_state.cdclk = cnl_calc_cdclk(0);
1687*3f2dd94aSFrançois Tigeot 	cdclk_state.vco = cnl_cdclk_pll_vco(dev_priv, cdclk_state.cdclk);
1688*3f2dd94aSFrançois Tigeot 
1689*3f2dd94aSFrançois Tigeot 	cnl_set_cdclk(dev_priv, &cdclk_state);
1690*3f2dd94aSFrançois Tigeot }
1691*3f2dd94aSFrançois Tigeot 
1692*3f2dd94aSFrançois Tigeot /**
1693*3f2dd94aSFrançois Tigeot  * cnl_uninit_cdclk - Uninitialize CDCLK on CNL
1694*3f2dd94aSFrançois Tigeot  * @dev_priv: i915 device
1695*3f2dd94aSFrançois Tigeot  *
1696*3f2dd94aSFrançois Tigeot  * Uninitialize CDCLK for CNL. This is done only
1697*3f2dd94aSFrançois Tigeot  * during the display core uninitialization sequence.
1698*3f2dd94aSFrançois Tigeot  */
cnl_uninit_cdclk(struct drm_i915_private * dev_priv)1699*3f2dd94aSFrançois Tigeot void cnl_uninit_cdclk(struct drm_i915_private *dev_priv)
1700*3f2dd94aSFrançois Tigeot {
1701*3f2dd94aSFrançois Tigeot 	struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw;
1702*3f2dd94aSFrançois Tigeot 
1703*3f2dd94aSFrançois Tigeot 	cdclk_state.cdclk = cdclk_state.ref;
1704*3f2dd94aSFrançois Tigeot 	cdclk_state.vco = 0;
1705*3f2dd94aSFrançois Tigeot 
1706*3f2dd94aSFrançois Tigeot 	cnl_set_cdclk(dev_priv, &cdclk_state);
1707*3f2dd94aSFrançois Tigeot }
1708*3f2dd94aSFrançois Tigeot 
1709a85cb24fSFrançois Tigeot /**
1710a85cb24fSFrançois Tigeot  * intel_cdclk_state_compare - Determine if two CDCLK states differ
1711a85cb24fSFrançois Tigeot  * @a: first CDCLK state
1712a85cb24fSFrançois Tigeot  * @b: second CDCLK state
1713a85cb24fSFrançois Tigeot  *
1714a85cb24fSFrançois Tigeot  * Returns:
1715a85cb24fSFrançois Tigeot  * True if the CDCLK states are identical, false if they differ.
1716a85cb24fSFrançois Tigeot  */
intel_cdclk_state_compare(const struct intel_cdclk_state * a,const struct intel_cdclk_state * b)1717a85cb24fSFrançois Tigeot bool intel_cdclk_state_compare(const struct intel_cdclk_state *a,
1718a85cb24fSFrançois Tigeot 			       const struct intel_cdclk_state *b)
1719a85cb24fSFrançois Tigeot {
1720a85cb24fSFrançois Tigeot 	return memcmp(a, b, sizeof(*a)) == 0;
1721a85cb24fSFrançois Tigeot }
1722a85cb24fSFrançois Tigeot 
1723a85cb24fSFrançois Tigeot /**
1724a85cb24fSFrançois Tigeot  * intel_set_cdclk - Push the CDCLK state to the hardware
1725a85cb24fSFrançois Tigeot  * @dev_priv: i915 device
1726a85cb24fSFrançois Tigeot  * @cdclk_state: new CDCLK state
1727a85cb24fSFrançois Tigeot  *
1728a85cb24fSFrançois Tigeot  * Program the hardware based on the passed in CDCLK state,
1729a85cb24fSFrançois Tigeot  * if necessary.
1730a85cb24fSFrançois Tigeot  */
intel_set_cdclk(struct drm_i915_private * dev_priv,const struct intel_cdclk_state * cdclk_state)1731a85cb24fSFrançois Tigeot void intel_set_cdclk(struct drm_i915_private *dev_priv,
1732a85cb24fSFrançois Tigeot 		     const struct intel_cdclk_state *cdclk_state)
1733a85cb24fSFrançois Tigeot {
1734a85cb24fSFrançois Tigeot 	if (intel_cdclk_state_compare(&dev_priv->cdclk.hw, cdclk_state))
1735a85cb24fSFrançois Tigeot 		return;
1736a85cb24fSFrançois Tigeot 
1737a85cb24fSFrançois Tigeot 	if (WARN_ON_ONCE(!dev_priv->display.set_cdclk))
1738a85cb24fSFrançois Tigeot 		return;
1739a85cb24fSFrançois Tigeot 
1740a85cb24fSFrançois Tigeot 	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz, VCO %d kHz, ref %d kHz\n",
1741a85cb24fSFrançois Tigeot 			 cdclk_state->cdclk, cdclk_state->vco,
1742a85cb24fSFrançois Tigeot 			 cdclk_state->ref);
1743a85cb24fSFrançois Tigeot 
1744a85cb24fSFrançois Tigeot 	dev_priv->display.set_cdclk(dev_priv, cdclk_state);
1745a85cb24fSFrançois Tigeot }
1746a85cb24fSFrançois Tigeot 
intel_pixel_rate_to_cdclk(struct drm_i915_private * dev_priv,int pixel_rate)1747*3f2dd94aSFrançois Tigeot static int intel_pixel_rate_to_cdclk(struct drm_i915_private *dev_priv,
1748a85cb24fSFrançois Tigeot 				     int pixel_rate)
1749a85cb24fSFrançois Tigeot {
1750*3f2dd94aSFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 10)
1751*3f2dd94aSFrançois Tigeot 		/*
1752*3f2dd94aSFrançois Tigeot 		 * FIXME: Switch to DIV_ROUND_UP(pixel_rate, 2)
1753*3f2dd94aSFrançois Tigeot 		 * once DDI clock voltage requirements are
1754*3f2dd94aSFrançois Tigeot 		 * handled correctly.
1755*3f2dd94aSFrançois Tigeot 		 */
1756*3f2dd94aSFrançois Tigeot 		return pixel_rate;
1757*3f2dd94aSFrançois Tigeot 	else if (IS_GEMINILAKE(dev_priv))
1758*3f2dd94aSFrançois Tigeot 		/*
1759*3f2dd94aSFrançois Tigeot 		 * FIXME: Avoid using a pixel clock that is more than 99% of the cdclk
1760*3f2dd94aSFrançois Tigeot 		 * as a temporary workaround. Use a higher cdclk instead. (Note that
1761*3f2dd94aSFrançois Tigeot 		 * intel_compute_max_dotclk() limits the max pixel clock to 99% of max
1762*3f2dd94aSFrançois Tigeot 		 * cdclk.)
1763*3f2dd94aSFrançois Tigeot 		 */
1764*3f2dd94aSFrançois Tigeot 		return DIV_ROUND_UP(pixel_rate * 100, 2 * 99);
1765*3f2dd94aSFrançois Tigeot 	else if (IS_GEN9(dev_priv) ||
1766*3f2dd94aSFrançois Tigeot 		 IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
1767*3f2dd94aSFrançois Tigeot 		return pixel_rate;
1768*3f2dd94aSFrançois Tigeot 	else if (IS_CHERRYVIEW(dev_priv))
1769*3f2dd94aSFrançois Tigeot 		return DIV_ROUND_UP(pixel_rate * 100, 95);
1770*3f2dd94aSFrançois Tigeot 	else
1771*3f2dd94aSFrançois Tigeot 		return DIV_ROUND_UP(pixel_rate * 100, 90);
1772*3f2dd94aSFrançois Tigeot }
1773*3f2dd94aSFrançois Tigeot 
intel_crtc_compute_min_cdclk(const struct intel_crtc_state * crtc_state)1774*3f2dd94aSFrançois Tigeot int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
1775*3f2dd94aSFrançois Tigeot {
1776a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv =
1777a85cb24fSFrançois Tigeot 		to_i915(crtc_state->base.crtc->dev);
1778*3f2dd94aSFrançois Tigeot 	int min_cdclk;
1779*3f2dd94aSFrançois Tigeot 
1780*3f2dd94aSFrançois Tigeot 	if (!crtc_state->base.enable)
1781*3f2dd94aSFrançois Tigeot 		return 0;
1782*3f2dd94aSFrançois Tigeot 
1783*3f2dd94aSFrançois Tigeot 	min_cdclk = intel_pixel_rate_to_cdclk(dev_priv, crtc_state->pixel_rate);
1784a85cb24fSFrançois Tigeot 
1785a85cb24fSFrançois Tigeot 	/* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
1786a85cb24fSFrançois Tigeot 	if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
1787*3f2dd94aSFrançois Tigeot 		min_cdclk = DIV_ROUND_UP(min_cdclk * 100, 95);
1788a85cb24fSFrançois Tigeot 
1789a85cb24fSFrançois Tigeot 	/* BSpec says "Do not use DisplayPort with CDCLK less than 432 MHz,
1790a85cb24fSFrançois Tigeot 	 * audio enabled, port width x4, and link rate HBR2 (5.4 GHz), or else
1791a85cb24fSFrançois Tigeot 	 * there may be audio corruption or screen corruption." This cdclk
1792*3f2dd94aSFrançois Tigeot 	 * restriction for GLK is 316.8 MHz.
1793a85cb24fSFrançois Tigeot 	 */
1794a85cb24fSFrançois Tigeot 	if (intel_crtc_has_dp_encoder(crtc_state) &&
1795a85cb24fSFrançois Tigeot 	    crtc_state->has_audio &&
1796a85cb24fSFrançois Tigeot 	    crtc_state->port_clock >= 540000 &&
1797a85cb24fSFrançois Tigeot 	    crtc_state->lane_count == 4) {
1798*3f2dd94aSFrançois Tigeot 		if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv)) {
1799*3f2dd94aSFrançois Tigeot 			/* Display WA #1145: glk,cnl */
1800*3f2dd94aSFrançois Tigeot 			min_cdclk = max(316800, min_cdclk);
1801*3f2dd94aSFrançois Tigeot 		} else if (IS_GEN9(dev_priv) || IS_BROADWELL(dev_priv)) {
1802*3f2dd94aSFrançois Tigeot 			/* Display WA #1144: skl,bxt */
1803*3f2dd94aSFrançois Tigeot 			min_cdclk = max(432000, min_cdclk);
1804*3f2dd94aSFrançois Tigeot 		}
1805a85cb24fSFrançois Tigeot 	}
1806a85cb24fSFrançois Tigeot 
1807a85cb24fSFrançois Tigeot 	/* According to BSpec, "The CD clock frequency must be at least twice
1808a85cb24fSFrançois Tigeot 	 * the frequency of the Azalia BCLK." and BCLK is 96 MHz by default.
1809a85cb24fSFrançois Tigeot 	 */
1810*3f2dd94aSFrançois Tigeot 	if (crtc_state->has_audio && INTEL_GEN(dev_priv) >= 9)
1811*3f2dd94aSFrançois Tigeot 		min_cdclk = max(2 * 96000, min_cdclk);
1812*3f2dd94aSFrançois Tigeot 
1813*3f2dd94aSFrançois Tigeot 	if (min_cdclk > dev_priv->max_cdclk_freq) {
1814*3f2dd94aSFrançois Tigeot 		DRM_DEBUG_KMS("required cdclk (%d kHz) exceeds max (%d kHz)\n",
1815*3f2dd94aSFrançois Tigeot 			      min_cdclk, dev_priv->max_cdclk_freq);
1816*3f2dd94aSFrançois Tigeot 		return -EINVAL;
1817a85cb24fSFrançois Tigeot 	}
1818a85cb24fSFrançois Tigeot 
1819*3f2dd94aSFrançois Tigeot 	return min_cdclk;
1820a85cb24fSFrançois Tigeot }
1821a85cb24fSFrançois Tigeot 
intel_compute_min_cdclk(struct drm_atomic_state * state)1822*3f2dd94aSFrançois Tigeot static int intel_compute_min_cdclk(struct drm_atomic_state *state)
1823a85cb24fSFrançois Tigeot {
1824a85cb24fSFrançois Tigeot 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
1825a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(state->dev);
1826*3f2dd94aSFrançois Tigeot 	struct intel_crtc *crtc;
1827a85cb24fSFrançois Tigeot 	struct intel_crtc_state *crtc_state;
1828*3f2dd94aSFrançois Tigeot 	int min_cdclk, i;
1829a85cb24fSFrançois Tigeot 	enum i915_pipe pipe;
1830a85cb24fSFrançois Tigeot 
1831*3f2dd94aSFrançois Tigeot 	memcpy(intel_state->min_cdclk, dev_priv->min_cdclk,
1832*3f2dd94aSFrançois Tigeot 	       sizeof(intel_state->min_cdclk));
1833a85cb24fSFrançois Tigeot 
1834*3f2dd94aSFrançois Tigeot 	for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) {
1835*3f2dd94aSFrançois Tigeot 		min_cdclk = intel_crtc_compute_min_cdclk(crtc_state);
1836*3f2dd94aSFrançois Tigeot 		if (min_cdclk < 0)
1837*3f2dd94aSFrançois Tigeot 			return min_cdclk;
1838a85cb24fSFrançois Tigeot 
1839*3f2dd94aSFrançois Tigeot 		intel_state->min_cdclk[i] = min_cdclk;
1840a85cb24fSFrançois Tigeot 	}
1841a85cb24fSFrançois Tigeot 
1842*3f2dd94aSFrançois Tigeot 	min_cdclk = 0;
1843a85cb24fSFrançois Tigeot 	for_each_pipe(dev_priv, pipe)
1844*3f2dd94aSFrançois Tigeot 		min_cdclk = max(intel_state->min_cdclk[pipe], min_cdclk);
1845a85cb24fSFrançois Tigeot 
1846*3f2dd94aSFrançois Tigeot 	return min_cdclk;
1847a85cb24fSFrançois Tigeot }
1848a85cb24fSFrançois Tigeot 
vlv_modeset_calc_cdclk(struct drm_atomic_state * state)1849a85cb24fSFrançois Tigeot static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state)
1850a85cb24fSFrançois Tigeot {
1851a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(state->dev);
1852*3f2dd94aSFrançois Tigeot 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
1853*3f2dd94aSFrançois Tigeot 	int min_cdclk, cdclk;
1854a85cb24fSFrançois Tigeot 
1855*3f2dd94aSFrançois Tigeot 	min_cdclk = intel_compute_min_cdclk(state);
1856*3f2dd94aSFrançois Tigeot 	if (min_cdclk < 0)
1857*3f2dd94aSFrançois Tigeot 		return min_cdclk;
1858a85cb24fSFrançois Tigeot 
1859*3f2dd94aSFrançois Tigeot 	cdclk = vlv_calc_cdclk(dev_priv, min_cdclk);
1860a85cb24fSFrançois Tigeot 
1861a85cb24fSFrançois Tigeot 	intel_state->cdclk.logical.cdclk = cdclk;
1862a85cb24fSFrançois Tigeot 
1863a85cb24fSFrançois Tigeot 	if (!intel_state->active_crtcs) {
1864a85cb24fSFrançois Tigeot 		cdclk = vlv_calc_cdclk(dev_priv, 0);
1865a85cb24fSFrançois Tigeot 
1866a85cb24fSFrançois Tigeot 		intel_state->cdclk.actual.cdclk = cdclk;
1867a85cb24fSFrançois Tigeot 	} else {
1868a85cb24fSFrançois Tigeot 		intel_state->cdclk.actual =
1869a85cb24fSFrançois Tigeot 			intel_state->cdclk.logical;
1870a85cb24fSFrançois Tigeot 	}
1871a85cb24fSFrançois Tigeot 
1872a85cb24fSFrançois Tigeot 	return 0;
1873a85cb24fSFrançois Tigeot }
1874a85cb24fSFrançois Tigeot 
bdw_modeset_calc_cdclk(struct drm_atomic_state * state)1875a85cb24fSFrançois Tigeot static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
1876a85cb24fSFrançois Tigeot {
1877a85cb24fSFrançois Tigeot 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
1878*3f2dd94aSFrançois Tigeot 	int min_cdclk, cdclk;
1879*3f2dd94aSFrançois Tigeot 
1880*3f2dd94aSFrançois Tigeot 	min_cdclk = intel_compute_min_cdclk(state);
1881*3f2dd94aSFrançois Tigeot 	if (min_cdclk < 0)
1882*3f2dd94aSFrançois Tigeot 		return min_cdclk;
1883a85cb24fSFrançois Tigeot 
1884a85cb24fSFrançois Tigeot 	/*
1885a85cb24fSFrançois Tigeot 	 * FIXME should also account for plane ratio
1886a85cb24fSFrançois Tigeot 	 * once 64bpp pixel formats are supported.
1887a85cb24fSFrançois Tigeot 	 */
1888*3f2dd94aSFrançois Tigeot 	cdclk = bdw_calc_cdclk(min_cdclk);
1889a85cb24fSFrançois Tigeot 
1890a85cb24fSFrançois Tigeot 	intel_state->cdclk.logical.cdclk = cdclk;
1891a85cb24fSFrançois Tigeot 
1892a85cb24fSFrançois Tigeot 	if (!intel_state->active_crtcs) {
1893a85cb24fSFrançois Tigeot 		cdclk = bdw_calc_cdclk(0);
1894a85cb24fSFrançois Tigeot 
1895a85cb24fSFrançois Tigeot 		intel_state->cdclk.actual.cdclk = cdclk;
1896a85cb24fSFrançois Tigeot 	} else {
1897a85cb24fSFrançois Tigeot 		intel_state->cdclk.actual =
1898a85cb24fSFrançois Tigeot 			intel_state->cdclk.logical;
1899a85cb24fSFrançois Tigeot 	}
1900a85cb24fSFrançois Tigeot 
1901a85cb24fSFrançois Tigeot 	return 0;
1902a85cb24fSFrançois Tigeot }
1903a85cb24fSFrançois Tigeot 
skl_modeset_calc_cdclk(struct drm_atomic_state * state)1904a85cb24fSFrançois Tigeot static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
1905a85cb24fSFrançois Tigeot {
1906a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(state->dev);
1907*3f2dd94aSFrançois Tigeot 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
1908*3f2dd94aSFrançois Tigeot 	int min_cdclk, cdclk, vco;
1909*3f2dd94aSFrançois Tigeot 
1910*3f2dd94aSFrançois Tigeot 	min_cdclk = intel_compute_min_cdclk(state);
1911*3f2dd94aSFrançois Tigeot 	if (min_cdclk < 0)
1912*3f2dd94aSFrançois Tigeot 		return min_cdclk;
1913a85cb24fSFrançois Tigeot 
1914a85cb24fSFrançois Tigeot 	vco = intel_state->cdclk.logical.vco;
1915a85cb24fSFrançois Tigeot 	if (!vco)
1916a85cb24fSFrançois Tigeot 		vco = dev_priv->skl_preferred_vco_freq;
1917a85cb24fSFrançois Tigeot 
1918a85cb24fSFrançois Tigeot 	/*
1919a85cb24fSFrançois Tigeot 	 * FIXME should also account for plane ratio
1920a85cb24fSFrançois Tigeot 	 * once 64bpp pixel formats are supported.
1921a85cb24fSFrançois Tigeot 	 */
1922*3f2dd94aSFrançois Tigeot 	cdclk = skl_calc_cdclk(min_cdclk, vco);
1923a85cb24fSFrançois Tigeot 
1924a85cb24fSFrançois Tigeot 	intel_state->cdclk.logical.vco = vco;
1925a85cb24fSFrançois Tigeot 	intel_state->cdclk.logical.cdclk = cdclk;
1926a85cb24fSFrançois Tigeot 
1927a85cb24fSFrançois Tigeot 	if (!intel_state->active_crtcs) {
1928a85cb24fSFrançois Tigeot 		cdclk = skl_calc_cdclk(0, vco);
1929a85cb24fSFrançois Tigeot 
1930a85cb24fSFrançois Tigeot 		intel_state->cdclk.actual.vco = vco;
1931a85cb24fSFrançois Tigeot 		intel_state->cdclk.actual.cdclk = cdclk;
1932a85cb24fSFrançois Tigeot 	} else {
1933a85cb24fSFrançois Tigeot 		intel_state->cdclk.actual =
1934a85cb24fSFrançois Tigeot 			intel_state->cdclk.logical;
1935a85cb24fSFrançois Tigeot 	}
1936a85cb24fSFrançois Tigeot 
1937a85cb24fSFrançois Tigeot 	return 0;
1938a85cb24fSFrançois Tigeot }
1939a85cb24fSFrançois Tigeot 
bxt_modeset_calc_cdclk(struct drm_atomic_state * state)1940a85cb24fSFrançois Tigeot static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
1941a85cb24fSFrançois Tigeot {
1942a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(state->dev);
1943*3f2dd94aSFrançois Tigeot 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
1944*3f2dd94aSFrançois Tigeot 	int min_cdclk, cdclk, vco;
1945*3f2dd94aSFrançois Tigeot 
1946*3f2dd94aSFrançois Tigeot 	min_cdclk = intel_compute_min_cdclk(state);
1947*3f2dd94aSFrançois Tigeot 	if (min_cdclk < 0)
1948*3f2dd94aSFrançois Tigeot 		return min_cdclk;
1949a85cb24fSFrançois Tigeot 
1950a85cb24fSFrançois Tigeot 	if (IS_GEMINILAKE(dev_priv)) {
1951*3f2dd94aSFrançois Tigeot 		cdclk = glk_calc_cdclk(min_cdclk);
1952a85cb24fSFrançois Tigeot 		vco = glk_de_pll_vco(dev_priv, cdclk);
1953a85cb24fSFrançois Tigeot 	} else {
1954*3f2dd94aSFrançois Tigeot 		cdclk = bxt_calc_cdclk(min_cdclk);
1955a85cb24fSFrançois Tigeot 		vco = bxt_de_pll_vco(dev_priv, cdclk);
1956a85cb24fSFrançois Tigeot 	}
1957a85cb24fSFrançois Tigeot 
1958a85cb24fSFrançois Tigeot 	intel_state->cdclk.logical.vco = vco;
1959a85cb24fSFrançois Tigeot 	intel_state->cdclk.logical.cdclk = cdclk;
1960a85cb24fSFrançois Tigeot 
1961a85cb24fSFrançois Tigeot 	if (!intel_state->active_crtcs) {
1962a85cb24fSFrançois Tigeot 		if (IS_GEMINILAKE(dev_priv)) {
1963a85cb24fSFrançois Tigeot 			cdclk = glk_calc_cdclk(0);
1964a85cb24fSFrançois Tigeot 			vco = glk_de_pll_vco(dev_priv, cdclk);
1965a85cb24fSFrançois Tigeot 		} else {
1966a85cb24fSFrançois Tigeot 			cdclk = bxt_calc_cdclk(0);
1967a85cb24fSFrançois Tigeot 			vco = bxt_de_pll_vco(dev_priv, cdclk);
1968a85cb24fSFrançois Tigeot 		}
1969a85cb24fSFrançois Tigeot 
1970a85cb24fSFrançois Tigeot 		intel_state->cdclk.actual.vco = vco;
1971a85cb24fSFrançois Tigeot 		intel_state->cdclk.actual.cdclk = cdclk;
1972a85cb24fSFrançois Tigeot 	} else {
1973a85cb24fSFrançois Tigeot 		intel_state->cdclk.actual =
1974a85cb24fSFrançois Tigeot 			intel_state->cdclk.logical;
1975a85cb24fSFrançois Tigeot 	}
1976a85cb24fSFrançois Tigeot 
1977a85cb24fSFrançois Tigeot 	return 0;
1978a85cb24fSFrançois Tigeot }
1979a85cb24fSFrançois Tigeot 
cnl_modeset_calc_cdclk(struct drm_atomic_state * state)1980*3f2dd94aSFrançois Tigeot static int cnl_modeset_calc_cdclk(struct drm_atomic_state *state)
1981*3f2dd94aSFrançois Tigeot {
1982*3f2dd94aSFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(state->dev);
1983*3f2dd94aSFrançois Tigeot 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
1984*3f2dd94aSFrançois Tigeot 	int min_cdclk, cdclk, vco;
1985*3f2dd94aSFrançois Tigeot 
1986*3f2dd94aSFrançois Tigeot 	min_cdclk = intel_compute_min_cdclk(state);
1987*3f2dd94aSFrançois Tigeot 	if (min_cdclk < 0)
1988*3f2dd94aSFrançois Tigeot 		return min_cdclk;
1989*3f2dd94aSFrançois Tigeot 
1990*3f2dd94aSFrançois Tigeot 	cdclk = cnl_calc_cdclk(min_cdclk);
1991*3f2dd94aSFrançois Tigeot 	vco = cnl_cdclk_pll_vco(dev_priv, cdclk);
1992*3f2dd94aSFrançois Tigeot 
1993*3f2dd94aSFrançois Tigeot 	intel_state->cdclk.logical.vco = vco;
1994*3f2dd94aSFrançois Tigeot 	intel_state->cdclk.logical.cdclk = cdclk;
1995*3f2dd94aSFrançois Tigeot 
1996*3f2dd94aSFrançois Tigeot 	if (!intel_state->active_crtcs) {
1997*3f2dd94aSFrançois Tigeot 		cdclk = cnl_calc_cdclk(0);
1998*3f2dd94aSFrançois Tigeot 		vco = cnl_cdclk_pll_vco(dev_priv, cdclk);
1999*3f2dd94aSFrançois Tigeot 
2000*3f2dd94aSFrançois Tigeot 		intel_state->cdclk.actual.vco = vco;
2001*3f2dd94aSFrançois Tigeot 		intel_state->cdclk.actual.cdclk = cdclk;
2002*3f2dd94aSFrançois Tigeot 	} else {
2003*3f2dd94aSFrançois Tigeot 		intel_state->cdclk.actual =
2004*3f2dd94aSFrançois Tigeot 			intel_state->cdclk.logical;
2005*3f2dd94aSFrançois Tigeot 	}
2006*3f2dd94aSFrançois Tigeot 
2007*3f2dd94aSFrançois Tigeot 	return 0;
2008*3f2dd94aSFrançois Tigeot }
2009*3f2dd94aSFrançois Tigeot 
intel_compute_max_dotclk(struct drm_i915_private * dev_priv)2010a85cb24fSFrançois Tigeot static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
2011a85cb24fSFrançois Tigeot {
2012a85cb24fSFrançois Tigeot 	int max_cdclk_freq = dev_priv->max_cdclk_freq;
2013a85cb24fSFrançois Tigeot 
2014*3f2dd94aSFrançois Tigeot 	if (INTEL_GEN(dev_priv) >= 10)
2015*3f2dd94aSFrançois Tigeot 		/*
2016*3f2dd94aSFrançois Tigeot 		 * FIXME: Allow '2 * max_cdclk_freq'
2017*3f2dd94aSFrançois Tigeot 		 * once DDI clock voltage requirements are
2018*3f2dd94aSFrançois Tigeot 		 * handled correctly.
2019*3f2dd94aSFrançois Tigeot 		 */
2020*3f2dd94aSFrançois Tigeot 		return max_cdclk_freq;
2021*3f2dd94aSFrançois Tigeot 	else if (IS_GEMINILAKE(dev_priv))
2022*3f2dd94aSFrançois Tigeot 		/*
2023*3f2dd94aSFrançois Tigeot 		 * FIXME: Limiting to 99% as a temporary workaround. See
2024*3f2dd94aSFrançois Tigeot 		 * intel_min_cdclk() for details.
2025*3f2dd94aSFrançois Tigeot 		 */
2026*3f2dd94aSFrançois Tigeot 		return 2 * max_cdclk_freq * 99 / 100;
2027*3f2dd94aSFrançois Tigeot 	else if (IS_GEN9(dev_priv) ||
2028*3f2dd94aSFrançois Tigeot 		 IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
2029a85cb24fSFrançois Tigeot 		return max_cdclk_freq;
2030a85cb24fSFrançois Tigeot 	else if (IS_CHERRYVIEW(dev_priv))
2031a85cb24fSFrançois Tigeot 		return max_cdclk_freq*95/100;
2032a85cb24fSFrançois Tigeot 	else if (INTEL_INFO(dev_priv)->gen < 4)
2033a85cb24fSFrançois Tigeot 		return 2*max_cdclk_freq*90/100;
2034a85cb24fSFrançois Tigeot 	else
2035a85cb24fSFrançois Tigeot 		return max_cdclk_freq*90/100;
2036a85cb24fSFrançois Tigeot }
2037a85cb24fSFrançois Tigeot 
2038a85cb24fSFrançois Tigeot /**
2039a85cb24fSFrançois Tigeot  * intel_update_max_cdclk - Determine the maximum support CDCLK frequency
2040a85cb24fSFrançois Tigeot  * @dev_priv: i915 device
2041a85cb24fSFrançois Tigeot  *
2042a85cb24fSFrançois Tigeot  * Determine the maximum CDCLK frequency the platform supports, and also
2043a85cb24fSFrançois Tigeot  * derive the maximum dot clock frequency the maximum CDCLK frequency
2044a85cb24fSFrançois Tigeot  * allows.
2045a85cb24fSFrançois Tigeot  */
intel_update_max_cdclk(struct drm_i915_private * dev_priv)2046a85cb24fSFrançois Tigeot void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
2047a85cb24fSFrançois Tigeot {
2048*3f2dd94aSFrançois Tigeot 	if (IS_CANNONLAKE(dev_priv)) {
2049*3f2dd94aSFrançois Tigeot 		dev_priv->max_cdclk_freq = 528000;
2050*3f2dd94aSFrançois Tigeot 	} else if (IS_GEN9_BC(dev_priv)) {
2051a85cb24fSFrançois Tigeot 		u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
2052a85cb24fSFrançois Tigeot 		int max_cdclk, vco;
2053a85cb24fSFrançois Tigeot 
2054a85cb24fSFrançois Tigeot 		vco = dev_priv->skl_preferred_vco_freq;
2055a85cb24fSFrançois Tigeot 		WARN_ON(vco != 8100000 && vco != 8640000);
2056a85cb24fSFrançois Tigeot 
2057a85cb24fSFrançois Tigeot 		/*
2058a85cb24fSFrançois Tigeot 		 * Use the lower (vco 8640) cdclk values as a
2059a85cb24fSFrançois Tigeot 		 * first guess. skl_calc_cdclk() will correct it
2060a85cb24fSFrançois Tigeot 		 * if the preferred vco is 8100 instead.
2061a85cb24fSFrançois Tigeot 		 */
2062a85cb24fSFrançois Tigeot 		if (limit == SKL_DFSM_CDCLK_LIMIT_675)
2063a85cb24fSFrançois Tigeot 			max_cdclk = 617143;
2064a85cb24fSFrançois Tigeot 		else if (limit == SKL_DFSM_CDCLK_LIMIT_540)
2065a85cb24fSFrançois Tigeot 			max_cdclk = 540000;
2066a85cb24fSFrançois Tigeot 		else if (limit == SKL_DFSM_CDCLK_LIMIT_450)
2067a85cb24fSFrançois Tigeot 			max_cdclk = 432000;
2068a85cb24fSFrançois Tigeot 		else
2069a85cb24fSFrançois Tigeot 			max_cdclk = 308571;
2070a85cb24fSFrançois Tigeot 
2071a85cb24fSFrançois Tigeot 		dev_priv->max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco);
2072a85cb24fSFrançois Tigeot 	} else if (IS_GEMINILAKE(dev_priv)) {
2073a85cb24fSFrançois Tigeot 		dev_priv->max_cdclk_freq = 316800;
2074a85cb24fSFrançois Tigeot 	} else if (IS_BROXTON(dev_priv)) {
2075a85cb24fSFrançois Tigeot 		dev_priv->max_cdclk_freq = 624000;
2076a85cb24fSFrançois Tigeot 	} else if (IS_BROADWELL(dev_priv))  {
2077a85cb24fSFrançois Tigeot 		/*
2078a85cb24fSFrançois Tigeot 		 * FIXME with extra cooling we can allow
2079a85cb24fSFrançois Tigeot 		 * 540 MHz for ULX and 675 Mhz for ULT.
2080a85cb24fSFrançois Tigeot 		 * How can we know if extra cooling is
2081a85cb24fSFrançois Tigeot 		 * available? PCI ID, VTB, something else?
2082a85cb24fSFrançois Tigeot 		 */
2083a85cb24fSFrançois Tigeot 		if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
2084a85cb24fSFrançois Tigeot 			dev_priv->max_cdclk_freq = 450000;
2085a85cb24fSFrançois Tigeot 		else if (IS_BDW_ULX(dev_priv))
2086a85cb24fSFrançois Tigeot 			dev_priv->max_cdclk_freq = 450000;
2087a85cb24fSFrançois Tigeot 		else if (IS_BDW_ULT(dev_priv))
2088a85cb24fSFrançois Tigeot 			dev_priv->max_cdclk_freq = 540000;
2089a85cb24fSFrançois Tigeot 		else
2090a85cb24fSFrançois Tigeot 			dev_priv->max_cdclk_freq = 675000;
2091a85cb24fSFrançois Tigeot 	} else if (IS_CHERRYVIEW(dev_priv)) {
2092a85cb24fSFrançois Tigeot 		dev_priv->max_cdclk_freq = 320000;
2093a85cb24fSFrançois Tigeot 	} else if (IS_VALLEYVIEW(dev_priv)) {
2094a85cb24fSFrançois Tigeot 		dev_priv->max_cdclk_freq = 400000;
2095a85cb24fSFrançois Tigeot 	} else {
2096a85cb24fSFrançois Tigeot 		/* otherwise assume cdclk is fixed */
2097a85cb24fSFrançois Tigeot 		dev_priv->max_cdclk_freq = dev_priv->cdclk.hw.cdclk;
2098a85cb24fSFrançois Tigeot 	}
2099a85cb24fSFrançois Tigeot 
2100a85cb24fSFrançois Tigeot 	dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv);
2101a85cb24fSFrançois Tigeot 
2102a85cb24fSFrançois Tigeot 	DRM_DEBUG_DRIVER("Max CD clock rate: %d kHz\n",
2103a85cb24fSFrançois Tigeot 			 dev_priv->max_cdclk_freq);
2104a85cb24fSFrançois Tigeot 
2105a85cb24fSFrançois Tigeot 	DRM_DEBUG_DRIVER("Max dotclock rate: %d kHz\n",
2106a85cb24fSFrançois Tigeot 			 dev_priv->max_dotclk_freq);
2107a85cb24fSFrançois Tigeot }
2108a85cb24fSFrançois Tigeot 
2109a85cb24fSFrançois Tigeot /**
2110a85cb24fSFrançois Tigeot  * intel_update_cdclk - Determine the current CDCLK frequency
2111a85cb24fSFrançois Tigeot  * @dev_priv: i915 device
2112a85cb24fSFrançois Tigeot  *
2113a85cb24fSFrançois Tigeot  * Determine the current CDCLK frequency.
2114a85cb24fSFrançois Tigeot  */
intel_update_cdclk(struct drm_i915_private * dev_priv)2115a85cb24fSFrançois Tigeot void intel_update_cdclk(struct drm_i915_private *dev_priv)
2116a85cb24fSFrançois Tigeot {
2117a85cb24fSFrançois Tigeot 	dev_priv->display.get_cdclk(dev_priv, &dev_priv->cdclk.hw);
2118a85cb24fSFrançois Tigeot 
2119a85cb24fSFrançois Tigeot 	DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
2120a85cb24fSFrançois Tigeot 			 dev_priv->cdclk.hw.cdclk, dev_priv->cdclk.hw.vco,
2121a85cb24fSFrançois Tigeot 			 dev_priv->cdclk.hw.ref);
2122a85cb24fSFrançois Tigeot 
2123a85cb24fSFrançois Tigeot 	/*
2124a85cb24fSFrançois Tigeot 	 * 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
2125a85cb24fSFrançois Tigeot 	 * Programmng [sic] note: bit[9:2] should be programmed to the number
2126a85cb24fSFrançois Tigeot 	 * of cdclk that generates 4MHz reference clock freq which is used to
2127a85cb24fSFrançois Tigeot 	 * generate GMBus clock. This will vary with the cdclk freq.
2128a85cb24fSFrançois Tigeot 	 */
2129a85cb24fSFrançois Tigeot 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
2130a85cb24fSFrançois Tigeot 		I915_WRITE(GMBUSFREQ_VLV,
2131a85cb24fSFrançois Tigeot 			   DIV_ROUND_UP(dev_priv->cdclk.hw.cdclk, 1000));
2132a85cb24fSFrançois Tigeot }
2133a85cb24fSFrançois Tigeot 
cnp_rawclk(struct drm_i915_private * dev_priv)2134*3f2dd94aSFrançois Tigeot static int cnp_rawclk(struct drm_i915_private *dev_priv)
2135*3f2dd94aSFrançois Tigeot {
2136*3f2dd94aSFrançois Tigeot 	u32 rawclk;
2137*3f2dd94aSFrançois Tigeot 	int divider, fraction;
2138*3f2dd94aSFrançois Tigeot 
2139*3f2dd94aSFrançois Tigeot 	if (I915_READ(SFUSE_STRAP) & SFUSE_STRAP_RAW_FREQUENCY) {
2140*3f2dd94aSFrançois Tigeot 		/* 24 MHz */
2141*3f2dd94aSFrançois Tigeot 		divider = 24000;
2142*3f2dd94aSFrançois Tigeot 		fraction = 0;
2143*3f2dd94aSFrançois Tigeot 	} else {
2144*3f2dd94aSFrançois Tigeot 		/* 19.2 MHz */
2145*3f2dd94aSFrançois Tigeot 		divider = 19000;
2146*3f2dd94aSFrançois Tigeot 		fraction = 200;
2147*3f2dd94aSFrançois Tigeot 	}
2148*3f2dd94aSFrançois Tigeot 
2149*3f2dd94aSFrançois Tigeot 	rawclk = CNP_RAWCLK_DIV((divider / 1000) - 1);
2150*3f2dd94aSFrançois Tigeot 	if (fraction)
2151*3f2dd94aSFrançois Tigeot 		rawclk |= CNP_RAWCLK_FRAC(DIV_ROUND_CLOSEST(1000,
2152*3f2dd94aSFrançois Tigeot 							    fraction) - 1);
2153*3f2dd94aSFrançois Tigeot 
2154*3f2dd94aSFrançois Tigeot 	I915_WRITE(PCH_RAWCLK_FREQ, rawclk);
2155*3f2dd94aSFrançois Tigeot 	return divider + fraction;
2156*3f2dd94aSFrançois Tigeot }
2157*3f2dd94aSFrançois Tigeot 
pch_rawclk(struct drm_i915_private * dev_priv)2158a85cb24fSFrançois Tigeot static int pch_rawclk(struct drm_i915_private *dev_priv)
2159a85cb24fSFrançois Tigeot {
2160a85cb24fSFrançois Tigeot 	return (I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK) * 1000;
2161a85cb24fSFrançois Tigeot }
2162a85cb24fSFrançois Tigeot 
vlv_hrawclk(struct drm_i915_private * dev_priv)2163a85cb24fSFrançois Tigeot static int vlv_hrawclk(struct drm_i915_private *dev_priv)
2164a85cb24fSFrançois Tigeot {
2165a85cb24fSFrançois Tigeot 	/* RAWCLK_FREQ_VLV register updated from power well code */
2166a85cb24fSFrançois Tigeot 	return vlv_get_cck_clock_hpll(dev_priv, "hrawclk",
2167a85cb24fSFrançois Tigeot 				      CCK_DISPLAY_REF_CLOCK_CONTROL);
2168a85cb24fSFrançois Tigeot }
2169a85cb24fSFrançois Tigeot 
g4x_hrawclk(struct drm_i915_private * dev_priv)2170a85cb24fSFrançois Tigeot static int g4x_hrawclk(struct drm_i915_private *dev_priv)
2171a85cb24fSFrançois Tigeot {
2172a85cb24fSFrançois Tigeot 	uint32_t clkcfg;
2173a85cb24fSFrançois Tigeot 
2174a85cb24fSFrançois Tigeot 	/* hrawclock is 1/4 the FSB frequency */
2175a85cb24fSFrançois Tigeot 	clkcfg = I915_READ(CLKCFG);
2176a85cb24fSFrançois Tigeot 	switch (clkcfg & CLKCFG_FSB_MASK) {
2177a85cb24fSFrançois Tigeot 	case CLKCFG_FSB_400:
2178a85cb24fSFrançois Tigeot 		return 100000;
2179a85cb24fSFrançois Tigeot 	case CLKCFG_FSB_533:
2180a85cb24fSFrançois Tigeot 		return 133333;
2181a85cb24fSFrançois Tigeot 	case CLKCFG_FSB_667:
2182a85cb24fSFrançois Tigeot 		return 166667;
2183a85cb24fSFrançois Tigeot 	case CLKCFG_FSB_800:
2184a85cb24fSFrançois Tigeot 		return 200000;
2185a85cb24fSFrançois Tigeot 	case CLKCFG_FSB_1067:
2186a85cb24fSFrançois Tigeot 	case CLKCFG_FSB_1067_ALT:
2187a85cb24fSFrançois Tigeot 		return 266667;
2188a85cb24fSFrançois Tigeot 	case CLKCFG_FSB_1333:
2189a85cb24fSFrançois Tigeot 	case CLKCFG_FSB_1333_ALT:
2190a85cb24fSFrançois Tigeot 		return 333333;
2191a85cb24fSFrançois Tigeot 	default:
2192a85cb24fSFrançois Tigeot 		return 133333;
2193a85cb24fSFrançois Tigeot 	}
2194a85cb24fSFrançois Tigeot }
2195a85cb24fSFrançois Tigeot 
2196a85cb24fSFrançois Tigeot /**
2197a85cb24fSFrançois Tigeot  * intel_update_rawclk - Determine the current RAWCLK frequency
2198a85cb24fSFrançois Tigeot  * @dev_priv: i915 device
2199a85cb24fSFrançois Tigeot  *
2200a85cb24fSFrançois Tigeot  * Determine the current RAWCLK frequency. RAWCLK is a fixed
2201a85cb24fSFrançois Tigeot  * frequency clock so this needs to done only once.
2202a85cb24fSFrançois Tigeot  */
intel_update_rawclk(struct drm_i915_private * dev_priv)2203a85cb24fSFrançois Tigeot void intel_update_rawclk(struct drm_i915_private *dev_priv)
2204a85cb24fSFrançois Tigeot {
2205*3f2dd94aSFrançois Tigeot 
2206*3f2dd94aSFrançois Tigeot 	if (HAS_PCH_CNP(dev_priv))
2207*3f2dd94aSFrançois Tigeot 		dev_priv->rawclk_freq = cnp_rawclk(dev_priv);
2208*3f2dd94aSFrançois Tigeot 	else if (HAS_PCH_SPLIT(dev_priv))
2209a85cb24fSFrançois Tigeot 		dev_priv->rawclk_freq = pch_rawclk(dev_priv);
2210a85cb24fSFrançois Tigeot 	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
2211a85cb24fSFrançois Tigeot 		dev_priv->rawclk_freq = vlv_hrawclk(dev_priv);
2212a85cb24fSFrançois Tigeot 	else if (IS_G4X(dev_priv) || IS_PINEVIEW(dev_priv))
2213a85cb24fSFrançois Tigeot 		dev_priv->rawclk_freq = g4x_hrawclk(dev_priv);
2214a85cb24fSFrançois Tigeot 	else
2215a85cb24fSFrançois Tigeot 		/* no rawclk on other platforms, or no need to know it */
2216a85cb24fSFrançois Tigeot 		return;
2217a85cb24fSFrançois Tigeot 
2218a85cb24fSFrançois Tigeot 	DRM_DEBUG_DRIVER("rawclk rate: %d kHz\n", dev_priv->rawclk_freq);
2219a85cb24fSFrançois Tigeot }
2220a85cb24fSFrançois Tigeot 
2221a85cb24fSFrançois Tigeot /**
2222a85cb24fSFrançois Tigeot  * intel_init_cdclk_hooks - Initialize CDCLK related modesetting hooks
2223a85cb24fSFrançois Tigeot  * @dev_priv: i915 device
2224a85cb24fSFrançois Tigeot  */
intel_init_cdclk_hooks(struct drm_i915_private * dev_priv)2225a85cb24fSFrançois Tigeot void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
2226a85cb24fSFrançois Tigeot {
2227a85cb24fSFrançois Tigeot 	if (IS_CHERRYVIEW(dev_priv)) {
2228a85cb24fSFrançois Tigeot 		dev_priv->display.set_cdclk = chv_set_cdclk;
2229a85cb24fSFrançois Tigeot 		dev_priv->display.modeset_calc_cdclk =
2230a85cb24fSFrançois Tigeot 			vlv_modeset_calc_cdclk;
2231a85cb24fSFrançois Tigeot 	} else if (IS_VALLEYVIEW(dev_priv)) {
2232a85cb24fSFrançois Tigeot 		dev_priv->display.set_cdclk = vlv_set_cdclk;
2233a85cb24fSFrançois Tigeot 		dev_priv->display.modeset_calc_cdclk =
2234a85cb24fSFrançois Tigeot 			vlv_modeset_calc_cdclk;
2235a85cb24fSFrançois Tigeot 	} else if (IS_BROADWELL(dev_priv)) {
2236a85cb24fSFrançois Tigeot 		dev_priv->display.set_cdclk = bdw_set_cdclk;
2237a85cb24fSFrançois Tigeot 		dev_priv->display.modeset_calc_cdclk =
2238a85cb24fSFrançois Tigeot 			bdw_modeset_calc_cdclk;
2239a85cb24fSFrançois Tigeot 	} else if (IS_GEN9_LP(dev_priv)) {
2240a85cb24fSFrançois Tigeot 		dev_priv->display.set_cdclk = bxt_set_cdclk;
2241a85cb24fSFrançois Tigeot 		dev_priv->display.modeset_calc_cdclk =
2242a85cb24fSFrançois Tigeot 			bxt_modeset_calc_cdclk;
2243a85cb24fSFrançois Tigeot 	} else if (IS_GEN9_BC(dev_priv)) {
2244a85cb24fSFrançois Tigeot 		dev_priv->display.set_cdclk = skl_set_cdclk;
2245a85cb24fSFrançois Tigeot 		dev_priv->display.modeset_calc_cdclk =
2246a85cb24fSFrançois Tigeot 			skl_modeset_calc_cdclk;
2247*3f2dd94aSFrançois Tigeot 	} else if (IS_CANNONLAKE(dev_priv)) {
2248*3f2dd94aSFrançois Tigeot 		dev_priv->display.set_cdclk = cnl_set_cdclk;
2249*3f2dd94aSFrançois Tigeot 		dev_priv->display.modeset_calc_cdclk =
2250*3f2dd94aSFrançois Tigeot 			cnl_modeset_calc_cdclk;
2251a85cb24fSFrançois Tigeot 	}
2252a85cb24fSFrançois Tigeot 
2253*3f2dd94aSFrançois Tigeot 	if (IS_CANNONLAKE(dev_priv))
2254*3f2dd94aSFrançois Tigeot 		dev_priv->display.get_cdclk = cnl_get_cdclk;
2255*3f2dd94aSFrançois Tigeot 	else if (IS_GEN9_BC(dev_priv))
2256a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = skl_get_cdclk;
2257a85cb24fSFrançois Tigeot 	else if (IS_GEN9_LP(dev_priv))
2258a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = bxt_get_cdclk;
2259a85cb24fSFrançois Tigeot 	else if (IS_BROADWELL(dev_priv))
2260a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = bdw_get_cdclk;
2261a85cb24fSFrançois Tigeot 	else if (IS_HASWELL(dev_priv))
2262a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = hsw_get_cdclk;
2263a85cb24fSFrançois Tigeot 	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
2264a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = vlv_get_cdclk;
2265a85cb24fSFrançois Tigeot 	else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
2266a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
2267a85cb24fSFrançois Tigeot 	else if (IS_GEN5(dev_priv))
2268a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = fixed_450mhz_get_cdclk;
2269a85cb24fSFrançois Tigeot 	else if (IS_GM45(dev_priv))
2270a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = gm45_get_cdclk;
2271a85cb24fSFrançois Tigeot 	else if (IS_G45(dev_priv))
2272a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = g33_get_cdclk;
2273a85cb24fSFrançois Tigeot 	else if (IS_I965GM(dev_priv))
2274a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = i965gm_get_cdclk;
2275a85cb24fSFrançois Tigeot 	else if (IS_I965G(dev_priv))
2276a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
2277a85cb24fSFrançois Tigeot 	else if (IS_PINEVIEW(dev_priv))
2278a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = pnv_get_cdclk;
2279a85cb24fSFrançois Tigeot 	else if (IS_G33(dev_priv))
2280a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = g33_get_cdclk;
2281a85cb24fSFrançois Tigeot 	else if (IS_I945GM(dev_priv))
2282a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = i945gm_get_cdclk;
2283a85cb24fSFrançois Tigeot 	else if (IS_I945G(dev_priv))
2284a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = fixed_400mhz_get_cdclk;
2285a85cb24fSFrançois Tigeot 	else if (IS_I915GM(dev_priv))
2286a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = i915gm_get_cdclk;
2287a85cb24fSFrançois Tigeot 	else if (IS_I915G(dev_priv))
2288a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = fixed_333mhz_get_cdclk;
2289a85cb24fSFrançois Tigeot 	else if (IS_I865G(dev_priv))
2290a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = fixed_266mhz_get_cdclk;
2291a85cb24fSFrançois Tigeot 	else if (IS_I85X(dev_priv))
2292a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = i85x_get_cdclk;
2293a85cb24fSFrançois Tigeot 	else if (IS_I845G(dev_priv))
2294a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk;
2295a85cb24fSFrançois Tigeot 	else { /* 830 */
2296a85cb24fSFrançois Tigeot 		WARN(!IS_I830(dev_priv),
2297a85cb24fSFrançois Tigeot 		     "Unknown platform. Assuming 133 MHz CDCLK\n");
2298a85cb24fSFrançois Tigeot 		dev_priv->display.get_cdclk = fixed_133mhz_get_cdclk;
2299a85cb24fSFrançois Tigeot 	}
2300a85cb24fSFrançois Tigeot }
2301