Loading...
Note: File does not exist in v3.1.
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2021 Intel Corporation
4 */
5
6#include "i915_reg.h"
7#include "intel_de.h"
8#include "intel_display_types.h"
9#include "intel_panel.h"
10#include "intel_pch_refclk.h"
11#include "intel_sbi.h"
12
13static void lpt_fdi_reset_mphy(struct drm_i915_private *dev_priv)
14{
15 u32 tmp;
16
17 tmp = intel_de_read(dev_priv, SOUTH_CHICKEN2);
18 tmp |= FDI_MPHY_IOSFSB_RESET_CTL;
19 intel_de_write(dev_priv, SOUTH_CHICKEN2, tmp);
20
21 if (wait_for_us(intel_de_read(dev_priv, SOUTH_CHICKEN2) &
22 FDI_MPHY_IOSFSB_RESET_STATUS, 100))
23 drm_err(&dev_priv->drm, "FDI mPHY reset assert timeout\n");
24
25 tmp = intel_de_read(dev_priv, SOUTH_CHICKEN2);
26 tmp &= ~FDI_MPHY_IOSFSB_RESET_CTL;
27 intel_de_write(dev_priv, SOUTH_CHICKEN2, tmp);
28
29 if (wait_for_us((intel_de_read(dev_priv, SOUTH_CHICKEN2) &
30 FDI_MPHY_IOSFSB_RESET_STATUS) == 0, 100))
31 drm_err(&dev_priv->drm, "FDI mPHY reset de-assert timeout\n");
32}
33
34/* WaMPhyProgramming:hsw */
35static void lpt_fdi_program_mphy(struct drm_i915_private *dev_priv)
36{
37 u32 tmp;
38
39 lpt_fdi_reset_mphy(dev_priv);
40
41 tmp = intel_sbi_read(dev_priv, 0x8008, SBI_MPHY);
42 tmp &= ~(0xFF << 24);
43 tmp |= (0x12 << 24);
44 intel_sbi_write(dev_priv, 0x8008, tmp, SBI_MPHY);
45
46 tmp = intel_sbi_read(dev_priv, 0x2008, SBI_MPHY);
47 tmp |= (1 << 11);
48 intel_sbi_write(dev_priv, 0x2008, tmp, SBI_MPHY);
49
50 tmp = intel_sbi_read(dev_priv, 0x2108, SBI_MPHY);
51 tmp |= (1 << 11);
52 intel_sbi_write(dev_priv, 0x2108, tmp, SBI_MPHY);
53
54 tmp = intel_sbi_read(dev_priv, 0x206C, SBI_MPHY);
55 tmp |= (1 << 24) | (1 << 21) | (1 << 18);
56 intel_sbi_write(dev_priv, 0x206C, tmp, SBI_MPHY);
57
58 tmp = intel_sbi_read(dev_priv, 0x216C, SBI_MPHY);
59 tmp |= (1 << 24) | (1 << 21) | (1 << 18);
60 intel_sbi_write(dev_priv, 0x216C, tmp, SBI_MPHY);
61
62 tmp = intel_sbi_read(dev_priv, 0x2080, SBI_MPHY);
63 tmp &= ~(7 << 13);
64 tmp |= (5 << 13);
65 intel_sbi_write(dev_priv, 0x2080, tmp, SBI_MPHY);
66
67 tmp = intel_sbi_read(dev_priv, 0x2180, SBI_MPHY);
68 tmp &= ~(7 << 13);
69 tmp |= (5 << 13);
70 intel_sbi_write(dev_priv, 0x2180, tmp, SBI_MPHY);
71
72 tmp = intel_sbi_read(dev_priv, 0x208C, SBI_MPHY);
73 tmp &= ~0xFF;
74 tmp |= 0x1C;
75 intel_sbi_write(dev_priv, 0x208C, tmp, SBI_MPHY);
76
77 tmp = intel_sbi_read(dev_priv, 0x218C, SBI_MPHY);
78 tmp &= ~0xFF;
79 tmp |= 0x1C;
80 intel_sbi_write(dev_priv, 0x218C, tmp, SBI_MPHY);
81
82 tmp = intel_sbi_read(dev_priv, 0x2098, SBI_MPHY);
83 tmp &= ~(0xFF << 16);
84 tmp |= (0x1C << 16);
85 intel_sbi_write(dev_priv, 0x2098, tmp, SBI_MPHY);
86
87 tmp = intel_sbi_read(dev_priv, 0x2198, SBI_MPHY);
88 tmp &= ~(0xFF << 16);
89 tmp |= (0x1C << 16);
90 intel_sbi_write(dev_priv, 0x2198, tmp, SBI_MPHY);
91
92 tmp = intel_sbi_read(dev_priv, 0x20C4, SBI_MPHY);
93 tmp |= (1 << 27);
94 intel_sbi_write(dev_priv, 0x20C4, tmp, SBI_MPHY);
95
96 tmp = intel_sbi_read(dev_priv, 0x21C4, SBI_MPHY);
97 tmp |= (1 << 27);
98 intel_sbi_write(dev_priv, 0x21C4, tmp, SBI_MPHY);
99
100 tmp = intel_sbi_read(dev_priv, 0x20EC, SBI_MPHY);
101 tmp &= ~(0xF << 28);
102 tmp |= (4 << 28);
103 intel_sbi_write(dev_priv, 0x20EC, tmp, SBI_MPHY);
104
105 tmp = intel_sbi_read(dev_priv, 0x21EC, SBI_MPHY);
106 tmp &= ~(0xF << 28);
107 tmp |= (4 << 28);
108 intel_sbi_write(dev_priv, 0x21EC, tmp, SBI_MPHY);
109}
110
111void lpt_disable_iclkip(struct drm_i915_private *dev_priv)
112{
113 u32 temp;
114
115 intel_de_write(dev_priv, PIXCLK_GATE, PIXCLK_GATE_GATE);
116
117 mutex_lock(&dev_priv->sb_lock);
118
119 temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
120 temp |= SBI_SSCCTL_DISABLE;
121 intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
122
123 mutex_unlock(&dev_priv->sb_lock);
124}
125
126struct iclkip_params {
127 u32 iclk_virtual_root_freq;
128 u32 iclk_pi_range;
129 u32 divsel, phaseinc, auxdiv, phasedir, desired_divisor;
130};
131
132static void iclkip_params_init(struct iclkip_params *p)
133{
134 memset(p, 0, sizeof(*p));
135
136 p->iclk_virtual_root_freq = 172800 * 1000;
137 p->iclk_pi_range = 64;
138}
139
140static int lpt_iclkip_freq(struct iclkip_params *p)
141{
142 return DIV_ROUND_CLOSEST(p->iclk_virtual_root_freq,
143 p->desired_divisor << p->auxdiv);
144}
145
146static void lpt_compute_iclkip(struct iclkip_params *p, int clock)
147{
148 iclkip_params_init(p);
149
150 /* The iCLK virtual clock root frequency is in MHz,
151 * but the adjusted_mode->crtc_clock in KHz. To get the
152 * divisors, it is necessary to divide one by another, so we
153 * convert the virtual clock precision to KHz here for higher
154 * precision.
155 */
156 for (p->auxdiv = 0; p->auxdiv < 2; p->auxdiv++) {
157 p->desired_divisor = DIV_ROUND_CLOSEST(p->iclk_virtual_root_freq,
158 clock << p->auxdiv);
159 p->divsel = (p->desired_divisor / p->iclk_pi_range) - 2;
160 p->phaseinc = p->desired_divisor % p->iclk_pi_range;
161
162 /*
163 * Near 20MHz is a corner case which is
164 * out of range for the 7-bit divisor
165 */
166 if (p->divsel <= 0x7f)
167 break;
168 }
169}
170
171int lpt_iclkip(const struct intel_crtc_state *crtc_state)
172{
173 struct iclkip_params p;
174
175 lpt_compute_iclkip(&p, crtc_state->hw.adjusted_mode.crtc_clock);
176
177 return lpt_iclkip_freq(&p);
178}
179
180/* Program iCLKIP clock to the desired frequency */
181void lpt_program_iclkip(const struct intel_crtc_state *crtc_state)
182{
183 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
184 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
185 int clock = crtc_state->hw.adjusted_mode.crtc_clock;
186 struct iclkip_params p;
187 u32 temp;
188
189 lpt_disable_iclkip(dev_priv);
190
191 lpt_compute_iclkip(&p, clock);
192 drm_WARN_ON(&dev_priv->drm, lpt_iclkip_freq(&p) != clock);
193
194 /* This should not happen with any sane values */
195 drm_WARN_ON(&dev_priv->drm, SBI_SSCDIVINTPHASE_DIVSEL(p.divsel) &
196 ~SBI_SSCDIVINTPHASE_DIVSEL_MASK);
197 drm_WARN_ON(&dev_priv->drm, SBI_SSCDIVINTPHASE_DIR(p.phasedir) &
198 ~SBI_SSCDIVINTPHASE_INCVAL_MASK);
199
200 drm_dbg_kms(&dev_priv->drm,
201 "iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n",
202 clock, p.auxdiv, p.divsel, p.phasedir, p.phaseinc);
203
204 mutex_lock(&dev_priv->sb_lock);
205
206 /* Program SSCDIVINTPHASE6 */
207 temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK);
208 temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK;
209 temp |= SBI_SSCDIVINTPHASE_DIVSEL(p.divsel);
210 temp &= ~SBI_SSCDIVINTPHASE_INCVAL_MASK;
211 temp |= SBI_SSCDIVINTPHASE_INCVAL(p.phaseinc);
212 temp |= SBI_SSCDIVINTPHASE_DIR(p.phasedir);
213 temp |= SBI_SSCDIVINTPHASE_PROPAGATE;
214 intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE6, temp, SBI_ICLK);
215
216 /* Program SSCAUXDIV */
217 temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK);
218 temp &= ~SBI_SSCAUXDIV_FINALDIV2SEL(1);
219 temp |= SBI_SSCAUXDIV_FINALDIV2SEL(p.auxdiv);
220 intel_sbi_write(dev_priv, SBI_SSCAUXDIV6, temp, SBI_ICLK);
221
222 /* Enable modulator and associated divider */
223 temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
224 temp &= ~SBI_SSCCTL_DISABLE;
225 intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
226
227 mutex_unlock(&dev_priv->sb_lock);
228
229 /* Wait for initialization time */
230 udelay(24);
231
232 intel_de_write(dev_priv, PIXCLK_GATE, PIXCLK_GATE_UNGATE);
233}
234
235int lpt_get_iclkip(struct drm_i915_private *dev_priv)
236{
237 struct iclkip_params p;
238 u32 temp;
239
240 if ((intel_de_read(dev_priv, PIXCLK_GATE) & PIXCLK_GATE_UNGATE) == 0)
241 return 0;
242
243 iclkip_params_init(&p);
244
245 mutex_lock(&dev_priv->sb_lock);
246
247 temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
248 if (temp & SBI_SSCCTL_DISABLE) {
249 mutex_unlock(&dev_priv->sb_lock);
250 return 0;
251 }
252
253 temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK);
254 p.divsel = (temp & SBI_SSCDIVINTPHASE_DIVSEL_MASK) >>
255 SBI_SSCDIVINTPHASE_DIVSEL_SHIFT;
256 p.phaseinc = (temp & SBI_SSCDIVINTPHASE_INCVAL_MASK) >>
257 SBI_SSCDIVINTPHASE_INCVAL_SHIFT;
258
259 temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK);
260 p.auxdiv = (temp & SBI_SSCAUXDIV_FINALDIV2SEL_MASK) >>
261 SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT;
262
263 mutex_unlock(&dev_priv->sb_lock);
264
265 p.desired_divisor = (p.divsel + 2) * p.iclk_pi_range + p.phaseinc;
266
267 return lpt_iclkip_freq(&p);
268}
269
270/* Implements 3 different sequences from BSpec chapter "Display iCLK
271 * Programming" based on the parameters passed:
272 * - Sequence to enable CLKOUT_DP
273 * - Sequence to enable CLKOUT_DP without spread
274 * - Sequence to enable CLKOUT_DP for FDI usage and configure PCH FDI I/O
275 */
276static void lpt_enable_clkout_dp(struct drm_i915_private *dev_priv,
277 bool with_spread, bool with_fdi)
278{
279 u32 reg, tmp;
280
281 if (drm_WARN(&dev_priv->drm, with_fdi && !with_spread,
282 "FDI requires downspread\n"))
283 with_spread = true;
284 if (drm_WARN(&dev_priv->drm, HAS_PCH_LPT_LP(dev_priv) &&
285 with_fdi, "LP PCH doesn't have FDI\n"))
286 with_fdi = false;
287
288 mutex_lock(&dev_priv->sb_lock);
289
290 tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
291 tmp &= ~SBI_SSCCTL_DISABLE;
292 tmp |= SBI_SSCCTL_PATHALT;
293 intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
294
295 udelay(24);
296
297 if (with_spread) {
298 tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
299 tmp &= ~SBI_SSCCTL_PATHALT;
300 intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
301
302 if (with_fdi)
303 lpt_fdi_program_mphy(dev_priv);
304 }
305
306 reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0;
307 tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK);
308 tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE;
309 intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK);
310
311 mutex_unlock(&dev_priv->sb_lock);
312}
313
314/* Sequence to disable CLKOUT_DP */
315void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv)
316{
317 u32 reg, tmp;
318
319 mutex_lock(&dev_priv->sb_lock);
320
321 reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0;
322 tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK);
323 tmp &= ~SBI_GEN0_CFG_BUFFENABLE_DISABLE;
324 intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK);
325
326 tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
327 if (!(tmp & SBI_SSCCTL_DISABLE)) {
328 if (!(tmp & SBI_SSCCTL_PATHALT)) {
329 tmp |= SBI_SSCCTL_PATHALT;
330 intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
331 udelay(32);
332 }
333 tmp |= SBI_SSCCTL_DISABLE;
334 intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
335 }
336
337 mutex_unlock(&dev_priv->sb_lock);
338}
339
340#define BEND_IDX(steps) ((50 + (steps)) / 5)
341
342static const u16 sscdivintphase[] = {
343 [BEND_IDX( 50)] = 0x3B23,
344 [BEND_IDX( 45)] = 0x3B23,
345 [BEND_IDX( 40)] = 0x3C23,
346 [BEND_IDX( 35)] = 0x3C23,
347 [BEND_IDX( 30)] = 0x3D23,
348 [BEND_IDX( 25)] = 0x3D23,
349 [BEND_IDX( 20)] = 0x3E23,
350 [BEND_IDX( 15)] = 0x3E23,
351 [BEND_IDX( 10)] = 0x3F23,
352 [BEND_IDX( 5)] = 0x3F23,
353 [BEND_IDX( 0)] = 0x0025,
354 [BEND_IDX( -5)] = 0x0025,
355 [BEND_IDX(-10)] = 0x0125,
356 [BEND_IDX(-15)] = 0x0125,
357 [BEND_IDX(-20)] = 0x0225,
358 [BEND_IDX(-25)] = 0x0225,
359 [BEND_IDX(-30)] = 0x0325,
360 [BEND_IDX(-35)] = 0x0325,
361 [BEND_IDX(-40)] = 0x0425,
362 [BEND_IDX(-45)] = 0x0425,
363 [BEND_IDX(-50)] = 0x0525,
364};
365
366/*
367 * Bend CLKOUT_DP
368 * steps -50 to 50 inclusive, in steps of 5
369 * < 0 slow down the clock, > 0 speed up the clock, 0 == no bend (135MHz)
370 * change in clock period = -(steps / 10) * 5.787 ps
371 */
372static void lpt_bend_clkout_dp(struct drm_i915_private *dev_priv, int steps)
373{
374 u32 tmp;
375 int idx = BEND_IDX(steps);
376
377 if (drm_WARN_ON(&dev_priv->drm, steps % 5 != 0))
378 return;
379
380 if (drm_WARN_ON(&dev_priv->drm, idx >= ARRAY_SIZE(sscdivintphase)))
381 return;
382
383 mutex_lock(&dev_priv->sb_lock);
384
385 if (steps % 10 != 0)
386 tmp = 0xAAAAAAAB;
387 else
388 tmp = 0x00000000;
389 intel_sbi_write(dev_priv, SBI_SSCDITHPHASE, tmp, SBI_ICLK);
390
391 tmp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE, SBI_ICLK);
392 tmp &= 0xffff0000;
393 tmp |= sscdivintphase[idx];
394 intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE, tmp, SBI_ICLK);
395
396 mutex_unlock(&dev_priv->sb_lock);
397}
398
399#undef BEND_IDX
400
401static bool spll_uses_pch_ssc(struct drm_i915_private *dev_priv)
402{
403 u32 fuse_strap = intel_de_read(dev_priv, FUSE_STRAP);
404 u32 ctl = intel_de_read(dev_priv, SPLL_CTL);
405
406 if ((ctl & SPLL_PLL_ENABLE) == 0)
407 return false;
408
409 if ((ctl & SPLL_REF_MASK) == SPLL_REF_MUXED_SSC &&
410 (fuse_strap & HSW_CPU_SSC_ENABLE) == 0)
411 return true;
412
413 if (IS_BROADWELL(dev_priv) &&
414 (ctl & SPLL_REF_MASK) == SPLL_REF_PCH_SSC_BDW)
415 return true;
416
417 return false;
418}
419
420static bool wrpll_uses_pch_ssc(struct drm_i915_private *dev_priv,
421 enum intel_dpll_id id)
422{
423 u32 fuse_strap = intel_de_read(dev_priv, FUSE_STRAP);
424 u32 ctl = intel_de_read(dev_priv, WRPLL_CTL(id));
425
426 if ((ctl & WRPLL_PLL_ENABLE) == 0)
427 return false;
428
429 if ((ctl & WRPLL_REF_MASK) == WRPLL_REF_PCH_SSC)
430 return true;
431
432 if ((IS_BROADWELL(dev_priv) || IS_HSW_ULT(dev_priv)) &&
433 (ctl & WRPLL_REF_MASK) == WRPLL_REF_MUXED_SSC_BDW &&
434 (fuse_strap & HSW_CPU_SSC_ENABLE) == 0)
435 return true;
436
437 return false;
438}
439
440static void lpt_init_pch_refclk(struct drm_i915_private *dev_priv)
441{
442 struct intel_encoder *encoder;
443 bool has_fdi = false;
444
445 for_each_intel_encoder(&dev_priv->drm, encoder) {
446 switch (encoder->type) {
447 case INTEL_OUTPUT_ANALOG:
448 has_fdi = true;
449 break;
450 default:
451 break;
452 }
453 }
454
455 /*
456 * The BIOS may have decided to use the PCH SSC
457 * reference so we must not disable it until the
458 * relevant PLLs have stopped relying on it. We'll
459 * just leave the PCH SSC reference enabled in case
460 * any active PLL is using it. It will get disabled
461 * after runtime suspend if we don't have FDI.
462 *
463 * TODO: Move the whole reference clock handling
464 * to the modeset sequence proper so that we can
465 * actually enable/disable/reconfigure these things
466 * safely. To do that we need to introduce a real
467 * clock hierarchy. That would also allow us to do
468 * clock bending finally.
469 */
470 dev_priv->pch_ssc_use = 0;
471
472 if (spll_uses_pch_ssc(dev_priv)) {
473 drm_dbg_kms(&dev_priv->drm, "SPLL using PCH SSC\n");
474 dev_priv->pch_ssc_use |= BIT(DPLL_ID_SPLL);
475 }
476
477 if (wrpll_uses_pch_ssc(dev_priv, DPLL_ID_WRPLL1)) {
478 drm_dbg_kms(&dev_priv->drm, "WRPLL1 using PCH SSC\n");
479 dev_priv->pch_ssc_use |= BIT(DPLL_ID_WRPLL1);
480 }
481
482 if (wrpll_uses_pch_ssc(dev_priv, DPLL_ID_WRPLL2)) {
483 drm_dbg_kms(&dev_priv->drm, "WRPLL2 using PCH SSC\n");
484 dev_priv->pch_ssc_use |= BIT(DPLL_ID_WRPLL2);
485 }
486
487 if (dev_priv->pch_ssc_use)
488 return;
489
490 if (has_fdi) {
491 lpt_bend_clkout_dp(dev_priv, 0);
492 lpt_enable_clkout_dp(dev_priv, true, true);
493 } else {
494 lpt_disable_clkout_dp(dev_priv);
495 }
496}
497
498static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv)
499{
500 struct intel_encoder *encoder;
501 int i;
502 u32 val, final;
503 bool has_lvds = false;
504 bool has_cpu_edp = false;
505 bool has_panel = false;
506 bool has_ck505 = false;
507 bool can_ssc = false;
508 bool using_ssc_source = false;
509
510 /* We need to take the global config into account */
511 for_each_intel_encoder(&dev_priv->drm, encoder) {
512 switch (encoder->type) {
513 case INTEL_OUTPUT_LVDS:
514 has_panel = true;
515 has_lvds = true;
516 break;
517 case INTEL_OUTPUT_EDP:
518 has_panel = true;
519 if (encoder->port == PORT_A)
520 has_cpu_edp = true;
521 break;
522 default:
523 break;
524 }
525 }
526
527 if (HAS_PCH_IBX(dev_priv)) {
528 has_ck505 = dev_priv->display.vbt.display_clock_mode;
529 can_ssc = has_ck505;
530 } else {
531 has_ck505 = false;
532 can_ssc = true;
533 }
534
535 /* Check if any DPLLs are using the SSC source */
536 for (i = 0; i < dev_priv->display.dpll.num_shared_dpll; i++) {
537 u32 temp = intel_de_read(dev_priv, PCH_DPLL(i));
538
539 if (!(temp & DPLL_VCO_ENABLE))
540 continue;
541
542 if ((temp & PLL_REF_INPUT_MASK) ==
543 PLLB_REF_INPUT_SPREADSPECTRUMIN) {
544 using_ssc_source = true;
545 break;
546 }
547 }
548
549 drm_dbg_kms(&dev_priv->drm,
550 "has_panel %d has_lvds %d has_ck505 %d using_ssc_source %d\n",
551 has_panel, has_lvds, has_ck505, using_ssc_source);
552
553 /* Ironlake: try to setup display ref clock before DPLL
554 * enabling. This is only under driver's control after
555 * PCH B stepping, previous chipset stepping should be
556 * ignoring this setting.
557 */
558 val = intel_de_read(dev_priv, PCH_DREF_CONTROL);
559
560 /* As we must carefully and slowly disable/enable each source in turn,
561 * compute the final state we want first and check if we need to
562 * make any changes at all.
563 */
564 final = val;
565 final &= ~DREF_NONSPREAD_SOURCE_MASK;
566 if (has_ck505)
567 final |= DREF_NONSPREAD_CK505_ENABLE;
568 else
569 final |= DREF_NONSPREAD_SOURCE_ENABLE;
570
571 final &= ~DREF_SSC_SOURCE_MASK;
572 final &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
573 final &= ~DREF_SSC1_ENABLE;
574
575 if (has_panel) {
576 final |= DREF_SSC_SOURCE_ENABLE;
577
578 if (intel_panel_use_ssc(dev_priv) && can_ssc)
579 final |= DREF_SSC1_ENABLE;
580
581 if (has_cpu_edp) {
582 if (intel_panel_use_ssc(dev_priv) && can_ssc)
583 final |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
584 else
585 final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
586 } else {
587 final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
588 }
589 } else if (using_ssc_source) {
590 final |= DREF_SSC_SOURCE_ENABLE;
591 final |= DREF_SSC1_ENABLE;
592 }
593
594 if (final == val)
595 return;
596
597 /* Always enable nonspread source */
598 val &= ~DREF_NONSPREAD_SOURCE_MASK;
599
600 if (has_ck505)
601 val |= DREF_NONSPREAD_CK505_ENABLE;
602 else
603 val |= DREF_NONSPREAD_SOURCE_ENABLE;
604
605 if (has_panel) {
606 val &= ~DREF_SSC_SOURCE_MASK;
607 val |= DREF_SSC_SOURCE_ENABLE;
608
609 /* SSC must be turned on before enabling the CPU output */
610 if (intel_panel_use_ssc(dev_priv) && can_ssc) {
611 drm_dbg_kms(&dev_priv->drm, "Using SSC on panel\n");
612 val |= DREF_SSC1_ENABLE;
613 } else {
614 val &= ~DREF_SSC1_ENABLE;
615 }
616
617 /* Get SSC going before enabling the outputs */
618 intel_de_write(dev_priv, PCH_DREF_CONTROL, val);
619 intel_de_posting_read(dev_priv, PCH_DREF_CONTROL);
620 udelay(200);
621
622 val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
623
624 /* Enable CPU source on CPU attached eDP */
625 if (has_cpu_edp) {
626 if (intel_panel_use_ssc(dev_priv) && can_ssc) {
627 drm_dbg_kms(&dev_priv->drm,
628 "Using SSC on eDP\n");
629 val |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
630 } else {
631 val |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
632 }
633 } else {
634 val |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
635 }
636
637 intel_de_write(dev_priv, PCH_DREF_CONTROL, val);
638 intel_de_posting_read(dev_priv, PCH_DREF_CONTROL);
639 udelay(200);
640 } else {
641 drm_dbg_kms(&dev_priv->drm, "Disabling CPU source output\n");
642
643 val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
644
645 /* Turn off CPU output */
646 val |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
647
648 intel_de_write(dev_priv, PCH_DREF_CONTROL, val);
649 intel_de_posting_read(dev_priv, PCH_DREF_CONTROL);
650 udelay(200);
651
652 if (!using_ssc_source) {
653 drm_dbg_kms(&dev_priv->drm, "Disabling SSC source\n");
654
655 /* Turn off the SSC source */
656 val &= ~DREF_SSC_SOURCE_MASK;
657 val |= DREF_SSC_SOURCE_DISABLE;
658
659 /* Turn off SSC1 */
660 val &= ~DREF_SSC1_ENABLE;
661
662 intel_de_write(dev_priv, PCH_DREF_CONTROL, val);
663 intel_de_posting_read(dev_priv, PCH_DREF_CONTROL);
664 udelay(200);
665 }
666 }
667
668 drm_WARN_ON(&dev_priv->drm, val != final);
669}
670
671/*
672 * Initialize reference clocks when the driver loads
673 */
674void intel_init_pch_refclk(struct drm_i915_private *dev_priv)
675{
676 if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
677 ilk_init_pch_refclk(dev_priv);
678 else if (HAS_PCH_LPT(dev_priv))
679 lpt_init_pch_refclk(dev_priv);
680}