Branch data Line data Source code
1 : : /*
2 : : * Copyright © 2013 Intel Corporation
3 : : *
4 : : * Permission is hereby granted, free of charge, to any person obtaining a
5 : : * copy of this software and associated documentation files (the "Software"),
6 : : * to deal in the Software without restriction, including without limitation
7 : : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 : : * and/or sell copies of the Software, and to permit persons to whom the
9 : : * Software is furnished to do so, subject to the following conditions:
10 : : *
11 : : * The above copyright notice and this permission notice (including the next
12 : : * paragraph) shall be included in all copies or substantial portions of the
13 : : * Software.
14 : : *
15 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 : : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 : : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 : : * DEALINGS IN THE SOFTWARE.
22 : : *
23 : : * Authors:
24 : : * Shobhit Kumar <shobhit.kumar@intel.com>
25 : : * Yogesh Mohan Marimuthu <yogesh.mohan.marimuthu@intel.com>
26 : : */
27 : :
28 : : #include <linux/kernel.h>
29 : :
30 : : #include "i915_drv.h"
31 : : #include "intel_display_types.h"
32 : : #include "intel_dsi.h"
33 : : #include "intel_sideband.h"
34 : :
35 : : static const u16 lfsr_converts[] = {
36 : : 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 62 - 70 */
37 : : 461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */
38 : : 106, 53, 282, 397, 454, 227, 113, 56, 284, 142, /* 81 - 90 */
39 : : 71, 35, 273, 136, 324, 418, 465, 488, 500, 506 /* 91 - 100 */
40 : : };
41 : :
42 : : /* Get DSI clock from pixel clock */
43 : 0 : static u32 dsi_clk_from_pclk(u32 pclk, enum mipi_dsi_pixel_format fmt,
44 : : int lane_count)
45 : : {
46 : 0 : u32 dsi_clk_khz;
47 : 0 : u32 bpp = mipi_dsi_pixel_format_to_bpp(fmt);
48 : :
49 : : /* DSI data rate = pixel clock * bits per pixel / lane count
50 : : pixel clock is converted from KHz to Hz */
51 : 0 : dsi_clk_khz = DIV_ROUND_CLOSEST(pclk * bpp, lane_count);
52 : :
53 : 0 : return dsi_clk_khz;
54 : : }
55 : :
56 : : static int dsi_calc_mnp(struct drm_i915_private *dev_priv,
57 : : struct intel_crtc_state *config,
58 : : int target_dsi_clk)
59 : : {
60 : : unsigned int m_min, m_max, p_min = 2, p_max = 6;
61 : : unsigned int m, n, p;
62 : : unsigned int calc_m, calc_p;
63 : : int delta, ref_clk;
64 : :
65 : : /* target_dsi_clk is expected in kHz */
66 : : if (target_dsi_clk < 300000 || target_dsi_clk > 1150000) {
67 : : DRM_ERROR("DSI CLK Out of Range\n");
68 : : return -ECHRNG;
69 : : }
70 : :
71 : : if (IS_CHERRYVIEW(dev_priv)) {
72 : : ref_clk = 100000;
73 : : n = 4;
74 : : m_min = 70;
75 : : m_max = 96;
76 : : } else {
77 : : ref_clk = 25000;
78 : : n = 1;
79 : : m_min = 62;
80 : : m_max = 92;
81 : : }
82 : :
83 : : calc_p = p_min;
84 : : calc_m = m_min;
85 : : delta = abs(target_dsi_clk - (m_min * ref_clk) / (p_min * n));
86 : :
87 : : for (m = m_min; m <= m_max && delta; m++) {
88 : : for (p = p_min; p <= p_max && delta; p++) {
89 : : /*
90 : : * Find the optimal m and p divisors with minimal delta
91 : : * +/- the required clock
92 : : */
93 : : int calc_dsi_clk = (m * ref_clk) / (p * n);
94 : : int d = abs(target_dsi_clk - calc_dsi_clk);
95 : : if (d < delta) {
96 : : delta = d;
97 : : calc_m = m;
98 : : calc_p = p;
99 : : }
100 : : }
101 : : }
102 : :
103 : : /* register has log2(N1), this works fine for powers of two */
104 : : config->dsi_pll.ctrl = 1 << (DSI_PLL_P1_POST_DIV_SHIFT + calc_p - 2);
105 : : config->dsi_pll.div =
106 : : (ffs(n) - 1) << DSI_PLL_N1_DIV_SHIFT |
107 : : (u32)lfsr_converts[calc_m - 62] << DSI_PLL_M1_DIV_SHIFT;
108 : :
109 : : return 0;
110 : : }
111 : :
112 : : /*
113 : : * XXX: The muxing and gating is hard coded for now. Need to add support for
114 : : * sharing PLLs with two DSI outputs.
115 : : */
116 : 0 : int vlv_dsi_pll_compute(struct intel_encoder *encoder,
117 : : struct intel_crtc_state *config)
118 : : {
119 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
120 [ # # ]: 0 : struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
121 : 0 : int ret;
122 : 0 : u32 dsi_clk;
123 : :
124 : 0 : dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format,
125 [ # # ]: 0 : intel_dsi->lane_count);
126 : :
127 : 0 : ret = dsi_calc_mnp(dev_priv, config, dsi_clk);
128 [ # # ]: 0 : if (ret) {
129 : 0 : DRM_DEBUG_KMS("dsi_calc_mnp failed\n");
130 : 0 : return ret;
131 : : }
132 : :
133 [ # # ]: 0 : if (intel_dsi->ports & (1 << PORT_A))
134 : 0 : config->dsi_pll.ctrl |= DSI_PLL_CLK_GATE_DSI0_DSIPLL;
135 : :
136 [ # # ]: 0 : if (intel_dsi->ports & (1 << PORT_C))
137 : 0 : config->dsi_pll.ctrl |= DSI_PLL_CLK_GATE_DSI1_DSIPLL;
138 : :
139 : 0 : config->dsi_pll.ctrl |= DSI_PLL_VCO_EN;
140 : :
141 : 0 : DRM_DEBUG_KMS("dsi pll div %08x, ctrl %08x\n",
142 : : config->dsi_pll.div, config->dsi_pll.ctrl);
143 : :
144 : 0 : return 0;
145 : : }
146 : :
147 : 0 : void vlv_dsi_pll_enable(struct intel_encoder *encoder,
148 : : const struct intel_crtc_state *config)
149 : : {
150 : 0 : struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
151 : :
152 : 0 : DRM_DEBUG_KMS("\n");
153 : :
154 : 0 : vlv_cck_get(dev_priv);
155 : :
156 : 0 : vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, 0);
157 : 0 : vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_DIVIDER, config->dsi_pll.div);
158 : 0 : vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL,
159 : 0 : config->dsi_pll.ctrl & ~DSI_PLL_VCO_EN);
160 : :
161 : : /* wait at least 0.5 us after ungating before enabling VCO,
162 : : * allow hrtimer subsystem optimization by relaxing timing
163 : : */
164 : 0 : usleep_range(10, 50);
165 : :
166 : 0 : vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, config->dsi_pll.ctrl);
167 : :
168 [ # # # # : 0 : if (wait_for(vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL) &
# # # # ]
169 : : DSI_PLL_LOCK, 20)) {
170 : :
171 : 0 : vlv_cck_put(dev_priv);
172 : 0 : DRM_ERROR("DSI PLL lock failed\n");
173 : 0 : return;
174 : : }
175 : 0 : vlv_cck_put(dev_priv);
176 : :
177 : 0 : DRM_DEBUG_KMS("DSI PLL locked\n");
178 : : }
179 : :
180 : 0 : void vlv_dsi_pll_disable(struct intel_encoder *encoder)
181 : : {
182 : 0 : struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
183 : 0 : u32 tmp;
184 : :
185 : 0 : DRM_DEBUG_KMS("\n");
186 : :
187 : 0 : vlv_cck_get(dev_priv);
188 : :
189 : 0 : tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
190 : 0 : tmp &= ~DSI_PLL_VCO_EN;
191 : 0 : tmp |= DSI_PLL_LDO_GATE;
192 : 0 : vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp);
193 : :
194 : 0 : vlv_cck_put(dev_priv);
195 : 0 : }
196 : :
197 : 0 : bool bxt_dsi_pll_is_enabled(struct drm_i915_private *dev_priv)
198 : : {
199 : 0 : bool enabled;
200 : 0 : u32 val;
201 : 0 : u32 mask;
202 : :
203 : 0 : mask = BXT_DSI_PLL_DO_ENABLE | BXT_DSI_PLL_LOCKED;
204 : 0 : val = I915_READ(BXT_DSI_PLL_ENABLE);
205 : 0 : enabled = (val & mask) == mask;
206 : :
207 [ # # ]: 0 : if (!enabled)
208 : : return false;
209 : :
210 : : /*
211 : : * Dividers must be programmed with valid values. As per BSEPC, for
212 : : * GEMINLAKE only PORT A divider values are checked while for BXT
213 : : * both divider values are validated. Check this here for
214 : : * paranoia, since BIOS is known to misconfigure PLLs in this way at
215 : : * times, and since accessing DSI registers with invalid dividers
216 : : * causes a system hang.
217 : : */
218 : 0 : val = I915_READ(BXT_DSI_PLL_CTL);
219 [ # # ]: 0 : if (IS_GEMINILAKE(dev_priv)) {
220 [ # # ]: 0 : if (!(val & BXT_DSIA_16X_MASK)) {
221 : 0 : DRM_DEBUG_DRIVER("Invalid PLL divider (%08x)\n", val);
222 : 0 : enabled = false;
223 : : }
224 : : } else {
225 [ # # # # ]: 0 : if (!(val & BXT_DSIA_16X_MASK) || !(val & BXT_DSIC_16X_MASK)) {
226 : 0 : DRM_DEBUG_DRIVER("Invalid PLL divider (%08x)\n", val);
227 : 0 : enabled = false;
228 : : }
229 : : }
230 : :
231 : : return enabled;
232 : : }
233 : :
234 : 0 : void bxt_dsi_pll_disable(struct intel_encoder *encoder)
235 : : {
236 : 0 : struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
237 : 0 : u32 val;
238 : :
239 : 0 : DRM_DEBUG_KMS("\n");
240 : :
241 : 0 : val = I915_READ(BXT_DSI_PLL_ENABLE);
242 : 0 : val &= ~BXT_DSI_PLL_DO_ENABLE;
243 : 0 : I915_WRITE(BXT_DSI_PLL_ENABLE, val);
244 : :
245 : : /*
246 : : * PLL lock should deassert within 200us.
247 : : * Wait up to 1ms before timing out.
248 : : */
249 [ # # ]: 0 : if (intel_de_wait_for_clear(dev_priv, BXT_DSI_PLL_ENABLE,
250 : : BXT_DSI_PLL_LOCKED, 1))
251 : 0 : DRM_ERROR("Timeout waiting for PLL lock deassertion\n");
252 : 0 : }
253 : :
254 : 0 : u32 vlv_dsi_get_pclk(struct intel_encoder *encoder,
255 : : struct intel_crtc_state *config)
256 : : {
257 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
258 [ # # ]: 0 : struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
259 [ # # ]: 0 : int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
260 : 0 : u32 dsi_clock, pclk;
261 : 0 : u32 pll_ctl, pll_div;
262 : 0 : u32 m = 0, p = 0, n;
263 [ # # ]: 0 : int refclk = IS_CHERRYVIEW(dev_priv) ? 100000 : 25000;
264 : 0 : int i;
265 : :
266 : 0 : DRM_DEBUG_KMS("\n");
267 : :
268 : 0 : vlv_cck_get(dev_priv);
269 : 0 : pll_ctl = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
270 : 0 : pll_div = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_DIVIDER);
271 : 0 : vlv_cck_put(dev_priv);
272 : :
273 : 0 : config->dsi_pll.ctrl = pll_ctl & ~DSI_PLL_LOCK;
274 : 0 : config->dsi_pll.div = pll_div;
275 : :
276 : : /* mask out other bits and extract the P1 divisor */
277 : 0 : pll_ctl &= DSI_PLL_P1_POST_DIV_MASK;
278 : 0 : pll_ctl = pll_ctl >> (DSI_PLL_P1_POST_DIV_SHIFT - 2);
279 : :
280 : : /* N1 divisor */
281 : 0 : n = (pll_div & DSI_PLL_N1_DIV_MASK) >> DSI_PLL_N1_DIV_SHIFT;
282 : 0 : n = 1 << n; /* register has log2(N1) */
283 : :
284 : : /* mask out the other bits and extract the M1 divisor */
285 : 0 : pll_div &= DSI_PLL_M1_DIV_MASK;
286 : 0 : pll_div = pll_div >> DSI_PLL_M1_DIV_SHIFT;
287 : :
288 [ # # ]: 0 : while (pll_ctl) {
289 : 0 : pll_ctl = pll_ctl >> 1;
290 : 0 : p++;
291 : : }
292 : 0 : p--;
293 : :
294 [ # # ]: 0 : if (!p) {
295 : 0 : DRM_ERROR("wrong P1 divisor\n");
296 : 0 : return 0;
297 : : }
298 : :
299 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(lfsr_converts); i++) {
300 [ # # ]: 0 : if (lfsr_converts[i] == pll_div)
301 : : break;
302 : : }
303 : :
304 [ # # ]: 0 : if (i == ARRAY_SIZE(lfsr_converts)) {
305 : 0 : DRM_ERROR("wrong m_seed programmed\n");
306 : 0 : return 0;
307 : : }
308 : :
309 : 0 : m = i + 62;
310 : :
311 : 0 : dsi_clock = (m * refclk) / (p * n);
312 : :
313 : 0 : pclk = DIV_ROUND_CLOSEST(dsi_clock * intel_dsi->lane_count, bpp);
314 : :
315 : 0 : return pclk;
316 : : }
317 : :
318 : 0 : u32 bxt_dsi_get_pclk(struct intel_encoder *encoder,
319 : : struct intel_crtc_state *config)
320 : : {
321 : 0 : u32 pclk;
322 : 0 : u32 dsi_clk;
323 : 0 : u32 dsi_ratio;
324 [ # # ]: 0 : struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
325 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
326 [ # # ]: 0 : int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
327 : :
328 : 0 : config->dsi_pll.ctrl = I915_READ(BXT_DSI_PLL_CTL);
329 : :
330 : 0 : dsi_ratio = config->dsi_pll.ctrl & BXT_DSI_PLL_RATIO_MASK;
331 : :
332 : 0 : dsi_clk = (dsi_ratio * BXT_REF_CLOCK_KHZ) / 2;
333 : :
334 : 0 : pclk = DIV_ROUND_CLOSEST(dsi_clk * intel_dsi->lane_count, bpp);
335 : :
336 : 0 : DRM_DEBUG_DRIVER("Calculated pclk=%u\n", pclk);
337 : 0 : return pclk;
338 : : }
339 : :
340 : 0 : void vlv_dsi_reset_clocks(struct intel_encoder *encoder, enum port port)
341 : : {
342 : 0 : u32 temp;
343 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
344 [ # # ]: 0 : struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
345 : :
346 [ # # ]: 0 : temp = I915_READ(MIPI_CTRL(port));
347 : 0 : temp &= ~ESCAPE_CLOCK_DIVIDER_MASK;
348 [ # # ]: 0 : I915_WRITE(MIPI_CTRL(port), temp |
349 : : intel_dsi->escape_clk_div <<
350 : : ESCAPE_CLOCK_DIVIDER_SHIFT);
351 : 0 : }
352 : :
353 : : static void glk_dsi_program_esc_clock(struct drm_device *dev,
354 : : const struct intel_crtc_state *config)
355 : : {
356 : : struct drm_i915_private *dev_priv = to_i915(dev);
357 : : u32 dsi_rate = 0;
358 : : u32 pll_ratio = 0;
359 : : u32 ddr_clk = 0;
360 : : u32 div1_value = 0;
361 : : u32 div2_value = 0;
362 : : u32 txesc1_div = 0;
363 : : u32 txesc2_div = 0;
364 : :
365 : : pll_ratio = config->dsi_pll.ctrl & BXT_DSI_PLL_RATIO_MASK;
366 : :
367 : : dsi_rate = (BXT_REF_CLOCK_KHZ * pll_ratio) / 2;
368 : :
369 : : ddr_clk = dsi_rate / 2;
370 : :
371 : : /* Variable divider value */
372 : : div1_value = DIV_ROUND_CLOSEST(ddr_clk, 20000);
373 : :
374 : : /* Calculate TXESC1 divider */
375 : : if (div1_value <= 10)
376 : : txesc1_div = div1_value;
377 : : else if ((div1_value > 10) && (div1_value <= 20))
378 : : txesc1_div = DIV_ROUND_UP(div1_value, 2);
379 : : else if ((div1_value > 20) && (div1_value <= 30))
380 : : txesc1_div = DIV_ROUND_UP(div1_value, 4);
381 : : else if ((div1_value > 30) && (div1_value <= 40))
382 : : txesc1_div = DIV_ROUND_UP(div1_value, 6);
383 : : else if ((div1_value > 40) && (div1_value <= 50))
384 : : txesc1_div = DIV_ROUND_UP(div1_value, 8);
385 : : else
386 : : txesc1_div = 10;
387 : :
388 : : /* Calculate TXESC2 divider */
389 : : div2_value = DIV_ROUND_UP(div1_value, txesc1_div);
390 : :
391 : : if (div2_value < 10)
392 : : txesc2_div = div2_value;
393 : : else
394 : : txesc2_div = 10;
395 : :
396 : : I915_WRITE(MIPIO_TXESC_CLK_DIV1, (1 << (txesc1_div - 1)) & GLK_TX_ESC_CLK_DIV1_MASK);
397 : : I915_WRITE(MIPIO_TXESC_CLK_DIV2, (1 << (txesc2_div - 1)) & GLK_TX_ESC_CLK_DIV2_MASK);
398 : : }
399 : :
400 : : /* Program BXT Mipi clocks and dividers */
401 : : static void bxt_dsi_program_clocks(struct drm_device *dev, enum port port,
402 : : const struct intel_crtc_state *config)
403 : : {
404 : : struct drm_i915_private *dev_priv = to_i915(dev);
405 : : u32 tmp;
406 : : u32 dsi_rate = 0;
407 : : u32 pll_ratio = 0;
408 : : u32 rx_div;
409 : : u32 tx_div;
410 : : u32 rx_div_upper;
411 : : u32 rx_div_lower;
412 : : u32 mipi_8by3_divider;
413 : :
414 : : /* Clear old configurations */
415 : : tmp = I915_READ(BXT_MIPI_CLOCK_CTL);
416 : : tmp &= ~(BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port));
417 : : tmp &= ~(BXT_MIPI_RX_ESCLK_UPPER_FIXDIV_MASK(port));
418 : : tmp &= ~(BXT_MIPI_8X_BY3_DIVIDER_MASK(port));
419 : : tmp &= ~(BXT_MIPI_RX_ESCLK_LOWER_FIXDIV_MASK(port));
420 : :
421 : : /* Get the current DSI rate(actual) */
422 : : pll_ratio = config->dsi_pll.ctrl & BXT_DSI_PLL_RATIO_MASK;
423 : : dsi_rate = (BXT_REF_CLOCK_KHZ * pll_ratio) / 2;
424 : :
425 : : /*
426 : : * tx clock should be <= 20MHz and the div value must be
427 : : * subtracted by 1 as per bspec
428 : : */
429 : : tx_div = DIV_ROUND_UP(dsi_rate, 20000) - 1;
430 : : /*
431 : : * rx clock should be <= 150MHz and the div value must be
432 : : * subtracted by 1 as per bspec
433 : : */
434 : : rx_div = DIV_ROUND_UP(dsi_rate, 150000) - 1;
435 : :
436 : : /*
437 : : * rx divider value needs to be updated in the
438 : : * two differnt bit fields in the register hence splitting the
439 : : * rx divider value accordingly
440 : : */
441 : : rx_div_lower = rx_div & RX_DIVIDER_BIT_1_2;
442 : : rx_div_upper = (rx_div & RX_DIVIDER_BIT_3_4) >> 2;
443 : :
444 : : mipi_8by3_divider = 0x2;
445 : :
446 : : tmp |= BXT_MIPI_8X_BY3_DIVIDER(port, mipi_8by3_divider);
447 : : tmp |= BXT_MIPI_TX_ESCLK_DIVIDER(port, tx_div);
448 : : tmp |= BXT_MIPI_RX_ESCLK_LOWER_DIVIDER(port, rx_div_lower);
449 : : tmp |= BXT_MIPI_RX_ESCLK_UPPER_DIVIDER(port, rx_div_upper);
450 : :
451 : : I915_WRITE(BXT_MIPI_CLOCK_CTL, tmp);
452 : : }
453 : :
454 : 0 : int bxt_dsi_pll_compute(struct intel_encoder *encoder,
455 : : struct intel_crtc_state *config)
456 : : {
457 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
458 [ # # ]: 0 : struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
459 : 0 : u8 dsi_ratio, dsi_ratio_min, dsi_ratio_max;
460 : 0 : u32 dsi_clk;
461 : :
462 : 0 : dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format,
463 [ # # ]: 0 : intel_dsi->lane_count);
464 : :
465 : : /*
466 : : * From clock diagram, to get PLL ratio divider, divide double of DSI
467 : : * link rate (i.e., 2*8x=16x frequency value) by ref clock. Make sure to
468 : : * round 'up' the result
469 : : */
470 : 0 : dsi_ratio = DIV_ROUND_UP(dsi_clk * 2, BXT_REF_CLOCK_KHZ);
471 : :
472 [ # # ]: 0 : if (IS_BROXTON(dev_priv)) {
473 : : dsi_ratio_min = BXT_DSI_PLL_RATIO_MIN;
474 : : dsi_ratio_max = BXT_DSI_PLL_RATIO_MAX;
475 : : } else {
476 : 0 : dsi_ratio_min = GLK_DSI_PLL_RATIO_MIN;
477 : 0 : dsi_ratio_max = GLK_DSI_PLL_RATIO_MAX;
478 : : }
479 : :
480 [ # # ]: 0 : if (dsi_ratio < dsi_ratio_min || dsi_ratio > dsi_ratio_max) {
481 : 0 : DRM_ERROR("Cant get a suitable ratio from DSI PLL ratios\n");
482 : 0 : return -ECHRNG;
483 : : } else
484 : 0 : DRM_DEBUG_KMS("DSI PLL calculation is Done!!\n");
485 : :
486 : : /*
487 : : * Program DSI ratio and Select MIPIC and MIPIA PLL output as 8x
488 : : * Spec says both have to be programmed, even if one is not getting
489 : : * used. Configure MIPI_CLOCK_CTL dividers in modeset
490 : : */
491 : 0 : config->dsi_pll.ctrl = dsi_ratio | BXT_DSIA_16X_BY2 | BXT_DSIC_16X_BY2;
492 : :
493 : : /* As per recommendation from hardware team,
494 : : * Prog PVD ratio =1 if dsi ratio <= 50
495 : : */
496 [ # # # # ]: 0 : if (IS_BROXTON(dev_priv) && dsi_ratio <= 50)
497 : 0 : config->dsi_pll.ctrl |= BXT_DSI_PLL_PVD_RATIO_1;
498 : :
499 : : return 0;
500 : : }
501 : :
502 : 0 : void bxt_dsi_pll_enable(struct intel_encoder *encoder,
503 : : const struct intel_crtc_state *config)
504 : : {
505 : 0 : struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
506 : 0 : struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
507 : 0 : enum port port;
508 : 0 : u32 val;
509 : :
510 : 0 : DRM_DEBUG_KMS("\n");
511 : :
512 : : /* Configure PLL vales */
513 : 0 : I915_WRITE(BXT_DSI_PLL_CTL, config->dsi_pll.ctrl);
514 : 0 : POSTING_READ(BXT_DSI_PLL_CTL);
515 : :
516 : : /* Program TX, RX, Dphy clocks */
517 [ # # ]: 0 : if (IS_BROXTON(dev_priv)) {
518 [ # # # # ]: 0 : for_each_dsi_port(port, intel_dsi->ports)
519 : 0 : bxt_dsi_program_clocks(encoder->base.dev, port, config);
520 : : } else {
521 : 0 : glk_dsi_program_esc_clock(encoder->base.dev, config);
522 : : }
523 : :
524 : : /* Enable DSI PLL */
525 : 0 : val = I915_READ(BXT_DSI_PLL_ENABLE);
526 : 0 : val |= BXT_DSI_PLL_DO_ENABLE;
527 : 0 : I915_WRITE(BXT_DSI_PLL_ENABLE, val);
528 : :
529 : : /* Timeout and fail if PLL not locked */
530 [ # # ]: 0 : if (intel_de_wait_for_set(dev_priv, BXT_DSI_PLL_ENABLE,
531 : : BXT_DSI_PLL_LOCKED, 1)) {
532 : 0 : DRM_ERROR("Timed out waiting for DSI PLL to lock\n");
533 : 0 : return;
534 : : }
535 : :
536 : 0 : DRM_DEBUG_KMS("DSI PLL locked\n");
537 : : }
538 : :
539 : 0 : void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port)
540 : : {
541 : 0 : u32 tmp;
542 : 0 : struct drm_device *dev = encoder->base.dev;
543 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(dev);
544 : :
545 : : /* Clear old configurations */
546 [ # # ]: 0 : if (IS_BROXTON(dev_priv)) {
547 : 0 : tmp = I915_READ(BXT_MIPI_CLOCK_CTL);
548 [ # # ]: 0 : tmp &= ~(BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port));
549 [ # # ]: 0 : tmp &= ~(BXT_MIPI_RX_ESCLK_UPPER_FIXDIV_MASK(port));
550 [ # # ]: 0 : tmp &= ~(BXT_MIPI_8X_BY3_DIVIDER_MASK(port));
551 [ # # ]: 0 : tmp &= ~(BXT_MIPI_RX_ESCLK_LOWER_FIXDIV_MASK(port));
552 : 0 : I915_WRITE(BXT_MIPI_CLOCK_CTL, tmp);
553 : : } else {
554 : 0 : tmp = I915_READ(MIPIO_TXESC_CLK_DIV1);
555 : 0 : tmp &= ~GLK_TX_ESC_CLK_DIV1_MASK;
556 : 0 : I915_WRITE(MIPIO_TXESC_CLK_DIV1, tmp);
557 : :
558 : 0 : tmp = I915_READ(MIPIO_TXESC_CLK_DIV2);
559 : 0 : tmp &= ~GLK_TX_ESC_CLK_DIV2_MASK;
560 : 0 : I915_WRITE(MIPIO_TXESC_CLK_DIV2, tmp);
561 : : }
562 [ # # ]: 0 : I915_WRITE(MIPI_EOT_DISABLE(port), CLOCKSTOP);
563 : 0 : }
|