Rev 5354 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5354 | Rev 6084 | ||
---|---|---|---|
Line 36... | Line 36... | ||
36 | #define DSI_HBP_PACKET_EXTRA_SIZE 6 |
36 | #define DSI_HBP_PACKET_EXTRA_SIZE 6 |
37 | #define DSI_HACTIVE_PACKET_EXTRA_SIZE 6 |
37 | #define DSI_HACTIVE_PACKET_EXTRA_SIZE 6 |
38 | #define DSI_HFP_PACKET_EXTRA_SIZE 6 |
38 | #define DSI_HFP_PACKET_EXTRA_SIZE 6 |
39 | #define DSI_EOTP_PACKET_SIZE 4 |
39 | #define DSI_EOTP_PACKET_SIZE 4 |
Line -... | Line 40... | ||
- | 40 | ||
- | 41 | static int dsi_pixel_format_bpp(int pixel_format) |
|
- | 42 | { |
|
- | 43 | int bpp; |
|
- | 44 | ||
- | 45 | switch (pixel_format) { |
|
- | 46 | default: |
|
- | 47 | case VID_MODE_FORMAT_RGB888: |
|
- | 48 | case VID_MODE_FORMAT_RGB666_LOOSE: |
|
- | 49 | bpp = 24; |
|
- | 50 | break; |
|
- | 51 | case VID_MODE_FORMAT_RGB666: |
|
- | 52 | bpp = 18; |
|
- | 53 | break; |
|
- | 54 | case VID_MODE_FORMAT_RGB565: |
|
- | 55 | bpp = 16; |
|
- | 56 | break; |
|
- | 57 | } |
|
- | 58 | ||
- | 59 | return bpp; |
|
- | 60 | } |
|
40 | 61 | ||
41 | struct dsi_mnp { |
62 | struct dsi_mnp { |
42 | u32 dsi_pll_ctrl; |
63 | u32 dsi_pll_ctrl; |
43 | u32 dsi_pll_div; |
64 | u32 dsi_pll_div; |
Line 44... | Line 65... | ||
44 | }; |
65 | }; |
45 | 66 | ||
46 | static const u32 lfsr_converts[] = { |
67 | static const u32 lfsr_converts[] = { |
47 | 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 62 - 70 */ |
68 | 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 62 - 70 */ |
48 | 461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */ |
69 | 461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */ |
49 | 106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */ |
70 | 106, 53, 282, 397, 454, 227, 113, 56, 284, 142, /* 81 - 90 */ |
Line 50... | Line 71... | ||
50 | 71, 35 /* 91 - 92 */ |
71 | 71, 35, 273, 136, 324, 418, 465, 488, 500, 506 /* 91 - 100 */ |
Line 51... | Line 72... | ||
51 | }; |
72 | }; |
Line 63... | Line 84... | ||
63 | u32 num_frames; |
84 | u32 num_frames; |
64 | u32 bytes_per_x_frames, bytes_per_x_frames_x_lanes; |
85 | u32 bytes_per_x_frames, bytes_per_x_frames_x_lanes; |
65 | u32 dsi_bit_clock_hz; |
86 | u32 dsi_bit_clock_hz; |
66 | u32 dsi_clk; |
87 | u32 dsi_clk; |
Line 67... | Line 88... | ||
67 | 88 | ||
68 | switch (pixel_format) { |
- | |
69 | default: |
- | |
70 | case VID_MODE_FORMAT_RGB888: |
- | |
71 | case VID_MODE_FORMAT_RGB666_LOOSE: |
- | |
72 | bpp = 24; |
- | |
73 | break; |
- | |
74 | case VID_MODE_FORMAT_RGB666: |
- | |
75 | bpp = 18; |
- | |
76 | break; |
- | |
77 | case VID_MODE_FORMAT_RGB565: |
- | |
78 | bpp = 16; |
- | |
79 | break; |
- | |
Line 80... | Line 89... | ||
80 | } |
89 | bpp = dsi_pixel_format_bpp(pixel_format); |
81 | 90 | ||
82 | hactive = mode->hdisplay; |
91 | hactive = mode->hdisplay; |
83 | vactive = mode->vdisplay; |
92 | vactive = mode->vdisplay; |
Line 135... | Line 144... | ||
135 | 144 | ||
136 | /* Get DSI clock from pixel clock */ |
145 | /* Get DSI clock from pixel clock */ |
137 | static u32 dsi_clk_from_pclk(u32 pclk, int pixel_format, int lane_count) |
146 | static u32 dsi_clk_from_pclk(u32 pclk, int pixel_format, int lane_count) |
138 | { |
147 | { |
139 | u32 dsi_clk_khz; |
- | |
140 | u32 bpp; |
- | |
141 | 148 | u32 dsi_clk_khz; |
|
142 | switch (pixel_format) { |
- | |
143 | default: |
- | |
144 | case VID_MODE_FORMAT_RGB888: |
- | |
145 | case VID_MODE_FORMAT_RGB666_LOOSE: |
- | |
146 | bpp = 24; |
- | |
147 | break; |
- | |
148 | case VID_MODE_FORMAT_RGB666: |
- | |
149 | bpp = 18; |
- | |
150 | break; |
- | |
151 | case VID_MODE_FORMAT_RGB565: |
- | |
152 | bpp = 16; |
- | |
153 | break; |
- | |
Line 154... | Line 149... | ||
154 | } |
149 | u32 bpp = dsi_pixel_format_bpp(pixel_format); |
155 | 150 | ||
156 | /* DSI data rate = pixel clock * bits per pixel / lane count |
151 | /* DSI data rate = pixel clock * bits per pixel / lane count |
Line 157... | Line 152... | ||
157 | pixel clock is converted from KHz to Hz */ |
152 | pixel clock is converted from KHz to Hz */ |
158 | dsi_clk_khz = DIV_ROUND_CLOSEST(pclk * bpp, lane_count); |
153 | dsi_clk_khz = DIV_ROUND_CLOSEST(pclk * bpp, lane_count); |
Line 159... | Line 154... | ||
159 | 154 | ||
Line 160... | Line 155... | ||
160 | return dsi_clk_khz; |
155 | return dsi_clk_khz; |
- | 156 | } |
|
161 | } |
157 | |
162 | 158 | #endif |
|
163 | #endif |
159 | |
164 | - | ||
165 | static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp) |
160 | static int dsi_calc_mnp(struct drm_i915_private *dev_priv, |
166 | { |
161 | struct dsi_mnp *dsi_mnp, int target_dsi_clk) |
167 | u32 m, n, p; |
162 | { |
168 | u32 ref_clk; |
- | |
169 | u32 error; |
- | |
170 | u32 tmp_error; |
163 | unsigned int calc_m = 0, calc_p = 0; |
Line 171... | Line 164... | ||
171 | int target_dsi_clk; |
164 | unsigned int m_min, m_max, p_min = 2, p_max = 6; |
172 | int calc_dsi_clk; |
165 | unsigned int m, n, p; |
173 | u32 calc_m; |
166 | int ref_clk; |
174 | u32 calc_p; |
167 | int delta = target_dsi_clk; |
175 | u32 m_seed; |
168 | u32 m_seed; |
Line -... | Line 169... | ||
- | 169 | ||
- | 170 | /* target_dsi_clk is expected in kHz */ |
|
- | 171 | if (target_dsi_clk < 300000 || target_dsi_clk > 1150000) { |
|
- | 172 | DRM_ERROR("DSI CLK Out of Range\n"); |
|
- | 173 | return -ECHRNG; |
|
- | 174 | } |
|
176 | 175 | ||
177 | /* dsi_clk is expected in KHZ */ |
- | |
178 | if (dsi_clk < 300000 || dsi_clk > 1150000) { |
- | |
179 | DRM_ERROR("DSI CLK Out of Range\n"); |
- | |
180 | return -ECHRNG; |
176 | if (IS_CHERRYVIEW(dev_priv)) { |
181 | } |
177 | ref_clk = 100000; |
182 | - | ||
183 | ref_clk = 25000; |
- | |
184 | target_dsi_clk = dsi_clk; |
- | |
185 | error = 0xFFFFFFFF; |
- | |
186 | tmp_error = 0xFFFFFFFF; |
- | |
187 | calc_m = 0; |
- | |
188 | calc_p = 0; |
- | |
189 | - | ||
190 | for (m = 62; m <= 92; m++) { |
178 | n = 4; |
191 | for (p = 2; p <= 6; p++) { |
- | |
192 | /* Find the optimal m and p divisors |
- | |
193 | with minimal error +/- the required clock */ |
179 | m_min = 70; |
194 | calc_dsi_clk = (m * ref_clk) / p; |
- | |
Line -... | Line 180... | ||
- | 180 | m_max = 96; |
|
- | 181 | } else { |
|
- | 182 | ref_clk = 25000; |
|
- | 183 | n = 1; |
|
- | 184 | m_min = 62; |
|
- | 185 | m_max = 92; |
|
- | 186 | } |
|
- | 187 | ||
195 | if (calc_dsi_clk == target_dsi_clk) { |
188 | for (m = m_min; m <= m_max && delta; m++) { |
196 | calc_m = m; |
189 | for (p = p_min; p <= p_max && delta; p++) { |
197 | calc_p = p; |
190 | /* |
198 | error = 0; |
191 | * Find the optimal m and p divisors with minimal delta |
199 | break; |
192 | * +/- the required clock |
200 | } else |
193 | */ |
201 | tmp_error = abs(target_dsi_clk - calc_dsi_clk); |
- | |
202 | - | ||
203 | if (tmp_error < error) { |
- | |
204 | error = tmp_error; |
194 | int calc_dsi_clk = (m * ref_clk) / (p * n); |
Line -... | Line 195... | ||
- | 195 | int d = abs(target_dsi_clk - calc_dsi_clk); |
|
- | 196 | if (d < delta) { |
|
205 | calc_m = m; |
197 | delta = d; |
206 | calc_p = p; |
- | |
207 | } |
198 | calc_m = m; |
208 | } |
199 | calc_p = p; |
209 | 200 | } |
|
Line 210... | Line 201... | ||
210 | if (error == 0) |
201 | } |
211 | break; |
202 | } |
Line 233... | Line 224... | ||
233 | u32 dsi_clk; |
224 | u32 dsi_clk; |
Line 234... | Line 225... | ||
234 | 225 | ||
235 | dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format, |
226 | dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format, |
Line 236... | Line 227... | ||
236 | intel_dsi->lane_count); |
227 | intel_dsi->lane_count); |
237 | 228 | ||
238 | ret = dsi_calc_mnp(dsi_clk, &dsi_mnp); |
229 | ret = dsi_calc_mnp(dev_priv, &dsi_mnp, dsi_clk); |
239 | if (ret) { |
230 | if (ret) { |
240 | DRM_DEBUG_KMS("dsi_calc_mnp failed\n"); |
231 | DRM_DEBUG_KMS("dsi_calc_mnp failed\n"); |
Line -... | Line 232... | ||
- | 232 | return; |
|
241 | return; |
233 | } |
Line -... | Line 234... | ||
- | 234 | ||
- | 235 | if (intel_dsi->ports & (1 << PORT_A)) |
|
- | 236 | dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI0_DSIPLL; |
|
242 | } |
237 | |
243 | 238 | if (intel_dsi->ports & (1 << PORT_C)) |
|
Line 244... | Line 239... | ||
244 | dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI0_DSIPLL; |
239 | dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI1_DSIPLL; |
245 | 240 | ||
246 | DRM_DEBUG_KMS("dsi pll div %08x, ctrl %08x\n", |
241 | DRM_DEBUG_KMS("dsi pll div %08x, ctrl %08x\n", |
247 | dsi_mnp.dsi_pll_div, dsi_mnp.dsi_pll_ctrl); |
242 | dsi_mnp.dsi_pll_div, dsi_mnp.dsi_pll_ctrl); |
Line 248... | Line 243... | ||
248 | 243 | ||
249 | vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, 0); |
244 | vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, 0); |
250 | vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_DIVIDER, dsi_mnp.dsi_pll_div); |
245 | vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_DIVIDER, dsi_mnp.dsi_pll_div); |
251 | vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_mnp.dsi_pll_ctrl); |
246 | vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_mnp.dsi_pll_ctrl); |
Line 252... | Line 247... | ||
252 | } |
247 | } |
Line 253... | Line 248... | ||
253 | 248 | ||
Line 254... | Line 249... | ||
254 | void vlv_enable_dsi_pll(struct intel_encoder *encoder) |
249 | static void vlv_enable_dsi_pll(struct intel_encoder *encoder) |
Line 255... | Line 250... | ||
255 | { |
250 | { |
256 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
251 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
Line 257... | Line 252... | ||
257 | u32 tmp; |
252 | u32 tmp; |
258 | 253 | ||
259 | DRM_DEBUG_KMS("\n"); |
254 | DRM_DEBUG_KMS("\n"); |
Line 260... | Line 255... | ||
260 | 255 | ||
- | 256 | mutex_lock(&dev_priv->sb_lock); |
|
Line 261... | Line 257... | ||
261 | mutex_lock(&dev_priv->dpio_lock); |
257 | |
262 | 258 | vlv_configure_dsi_pll(encoder); |
|
263 | vlv_configure_dsi_pll(encoder); |
259 | |
264 | 260 | /* wait at least 0.5 us after ungating before enabling VCO */ |
|
- | 261 | usleep_range(1, 10); |
|
Line 265... | Line 262... | ||
265 | /* wait at least 0.5 us after ungating before enabling VCO */ |
262 | |
266 | usleep_range(1, 10); |
263 | tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); |
Line 267... | Line 264... | ||
267 | 264 | tmp |= DSI_PLL_VCO_EN; |
|
268 | tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); |
265 | vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp); |
269 | tmp |= DSI_PLL_VCO_EN; |
266 | |
270 | vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp); |
267 | if (wait_for(vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL) & |
Line 271... | Line 268... | ||
271 | 268 | DSI_PLL_LOCK, 20)) { |
|
Line 272... | Line 269... | ||
272 | mutex_unlock(&dev_priv->dpio_lock); |
269 | |
Line 273... | Line 270... | ||
273 | 270 | mutex_unlock(&dev_priv->sb_lock); |
|
274 | if (wait_for(I915_READ(PIPECONF(PIPE_A)) & PIPECONF_DSI_PLL_LOCKED, 20)) { |
271 | DRM_ERROR("DSI PLL lock failed\n"); |
275 | DRM_ERROR("DSI PLL lock failed\n"); |
272 | return; |
276 | return; |
273 | } |
Line 277... | Line 274... | ||
277 | } |
274 | mutex_unlock(&dev_priv->sb_lock); |
278 | 275 | ||
Line 279... | Line 276... | ||
279 | DRM_DEBUG_KMS("DSI PLL locked\n"); |
276 | DRM_DEBUG_KMS("DSI PLL locked\n"); |
280 | } |
277 | } |
- | 278 | ||
281 | 279 | static void vlv_disable_dsi_pll(struct intel_encoder *encoder) |
|
Line 282... | Line 280... | ||
282 | void vlv_disable_dsi_pll(struct intel_encoder *encoder) |
280 | { |
283 | { |
281 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
284 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
282 | u32 tmp; |
285 | u32 tmp; |
283 | |
286 | 284 | DRM_DEBUG_KMS("\n"); |
|
- | 285 | ||
287 | DRM_DEBUG_KMS("\n"); |
286 | mutex_lock(&dev_priv->sb_lock); |
288 | 287 | ||
289 | mutex_lock(&dev_priv->dpio_lock); |
288 | tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); |
290 | 289 | tmp &= ~DSI_PLL_VCO_EN; |
|
291 | tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); |
290 | tmp |= DSI_PLL_LDO_GATE; |
292 | tmp &= ~DSI_PLL_VCO_EN; |
291 | vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp); |
293 | tmp |= DSI_PLL_LDO_GATE; |
292 | |
294 | vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp); |
293 | mutex_unlock(&dev_priv->sb_lock); |
Line -... | Line 294... | ||
- | 294 | } |
|
- | 295 | ||
- | 296 | static void bxt_disable_dsi_pll(struct intel_encoder *encoder) |
|
- | 297 | { |
|
295 | 298 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
|
296 | mutex_unlock(&dev_priv->dpio_lock); |
299 | u32 val; |
297 | } |
300 | |
298 | 301 | DRM_DEBUG_KMS("\n"); |
|
Line 323... | Line 326... | ||
323 | { |
326 | { |
324 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
327 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
325 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); |
328 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); |
326 | u32 dsi_clock, pclk; |
329 | u32 dsi_clock, pclk; |
327 | u32 pll_ctl, pll_div; |
330 | u32 pll_ctl, pll_div; |
328 | u32 m = 0, p = 0; |
331 | u32 m = 0, p = 0, n; |
329 | int refclk = 25000; |
332 | int refclk = 25000; |
330 | int i; |
333 | int i; |
Line 331... | Line 334... | ||
331 | 334 | ||
Line 332... | Line 335... | ||
332 | DRM_DEBUG_KMS("\n"); |
335 | DRM_DEBUG_KMS("\n"); |
333 | 336 | ||
334 | mutex_lock(&dev_priv->dpio_lock); |
337 | mutex_lock(&dev_priv->sb_lock); |
335 | pll_ctl = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); |
338 | pll_ctl = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); |
Line 336... | Line 339... | ||
336 | pll_div = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_DIVIDER); |
339 | pll_div = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_DIVIDER); |
337 | mutex_unlock(&dev_priv->dpio_lock); |
340 | mutex_unlock(&dev_priv->sb_lock); |
338 | 341 | ||
Line -... | Line 342... | ||
- | 342 | /* mask out other bits and extract the P1 divisor */ |
|
- | 343 | pll_ctl &= DSI_PLL_P1_POST_DIV_MASK; |
|
- | 344 | pll_ctl = pll_ctl >> (DSI_PLL_P1_POST_DIV_SHIFT - 2); |
|
- | 345 | ||
339 | /* mask out other bits and extract the P1 divisor */ |
346 | /* N1 divisor */ |
340 | pll_ctl &= DSI_PLL_P1_POST_DIV_MASK; |
347 | n = (pll_div & DSI_PLL_N1_DIV_MASK) >> DSI_PLL_N1_DIV_SHIFT; |
341 | pll_ctl = pll_ctl >> (DSI_PLL_P1_POST_DIV_SHIFT - 2); |
348 | n = 1 << n; /* register has log2(N1) */ |
Line 342... | Line 349... | ||
342 | 349 | ||
Line 365... | Line 372... | ||
365 | return 0; |
372 | return 0; |
366 | } |
373 | } |
Line 367... | Line 374... | ||
367 | 374 | ||
Line 368... | Line 375... | ||
368 | m = i + 62; |
375 | m = i + 62; |
Line 369... | Line 376... | ||
369 | 376 | ||
370 | dsi_clock = (m * refclk) / p; |
377 | dsi_clock = (m * refclk) / (p * n); |
Line 371... | Line 378... | ||
371 | 378 | ||
Line 372... | Line 379... | ||
372 | /* pixel_format and pipe_bpp should agree */ |
379 | /* pixel_format and pipe_bpp should agree */ |
373 | assert_bpp_mismatch(intel_dsi->pixel_format, pipe_bpp); |
380 | assert_bpp_mismatch(intel_dsi->pixel_format, pipe_bpp); |
- | 381 | ||
- | 382 | pclk = DIV_ROUND_CLOSEST(dsi_clock * intel_dsi->lane_count, pipe_bpp); |
|
- | 383 | ||
- | 384 | return pclk; |
|
- | 385 | } |
|
- | 386 | ||
- | 387 | u32 bxt_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp) |
|
- | 388 | { |
|
- | 389 | u32 pclk; |
|
- | 390 | u32 dsi_clk; |
|
- | 391 | u32 dsi_ratio; |
|
- | 392 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); |
|
- | 393 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
|
- | 394 | ||
- | 395 | /* Divide by zero */ |
|
- | 396 | if (!pipe_bpp) { |
|
- | 397 | DRM_ERROR("Invalid BPP(0)\n"); |
|
- | 398 | return 0; |
|
- | 399 | } |
|
- | 400 | ||
- | 401 | dsi_ratio = I915_READ(BXT_DSI_PLL_CTL) & |
|
- | 402 | BXT_DSI_PLL_RATIO_MASK; |
|
- | 403 | ||
- | 404 | /* Invalid DSI ratio ? */ |
|
- | 405 | if (dsi_ratio < BXT_DSI_PLL_RATIO_MIN || |
|
- | 406 | dsi_ratio > BXT_DSI_PLL_RATIO_MAX) { |
|
- | 407 | DRM_ERROR("Invalid DSI pll ratio(%u) programmed\n", dsi_ratio); |
|
- | 408 | return 0; |
|
- | 409 | } |
|
- | 410 | ||
- | 411 | dsi_clk = (dsi_ratio * BXT_REF_CLOCK_KHZ) / 2; |
|
- | 412 | ||
- | 413 | /* pixel_format and pipe_bpp should agree */ |
|
- | 414 | assert_bpp_mismatch(intel_dsi->pixel_format, pipe_bpp); |
|
- | 415 | ||
- | 416 | pclk = DIV_ROUND_CLOSEST(dsi_clk * intel_dsi->lane_count, pipe_bpp); |
|
- | 417 | ||
- | 418 | DRM_DEBUG_DRIVER("Calculated pclk=%u\n", pclk); |
|
- | 419 | return pclk; |
|
- | 420 | } |
|
- | 421 | ||
- | 422 | static void vlv_dsi_reset_clocks(struct intel_encoder *encoder, enum port port) |
|
- | 423 | { |
|
- | 424 | u32 temp; |
|
- | 425 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
|
- | 426 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); |
|
- | 427 | ||
- | 428 | temp = I915_READ(MIPI_CTRL(port)); |
|
- | 429 | temp &= ~ESCAPE_CLOCK_DIVIDER_MASK; |
|
- | 430 | I915_WRITE(MIPI_CTRL(port), temp | |
|
- | 431 | intel_dsi->escape_clk_div << |
|
- | 432 | ESCAPE_CLOCK_DIVIDER_SHIFT); |
|
- | 433 | } |
|
- | 434 | ||
- | 435 | /* Program BXT Mipi clocks and dividers */ |
|
- | 436 | static void bxt_dsi_program_clocks(struct drm_device *dev, enum port port) |
|
- | 437 | { |
|
- | 438 | u32 tmp; |
|
- | 439 | u32 divider; |
|
- | 440 | u32 dsi_rate; |
|
- | 441 | u32 pll_ratio; |
|
- | 442 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 443 | ||
- | 444 | /* Clear old configurations */ |
|
- | 445 | tmp = I915_READ(BXT_MIPI_CLOCK_CTL); |
|
- | 446 | tmp &= ~(BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port)); |
|
- | 447 | tmp &= ~(BXT_MIPI_RX_ESCLK_FIXDIV_MASK(port)); |
|
- | 448 | tmp &= ~(BXT_MIPI_ESCLK_VAR_DIV_MASK(port)); |
|
- | 449 | tmp &= ~(BXT_MIPI_DPHY_DIVIDER_MASK(port)); |
|
- | 450 | ||
- | 451 | /* Get the current DSI rate(actual) */ |
|
- | 452 | pll_ratio = I915_READ(BXT_DSI_PLL_CTL) & |
|
- | 453 | BXT_DSI_PLL_RATIO_MASK; |
|
- | 454 | dsi_rate = (BXT_REF_CLOCK_KHZ * pll_ratio) / 2; |
|
- | 455 | ||
- | 456 | /* Max possible output of clock is 39.5 MHz, program value -1 */ |
|
- | 457 | divider = (dsi_rate / BXT_MAX_VAR_OUTPUT_KHZ) - 1; |
|
- | 458 | tmp |= BXT_MIPI_ESCLK_VAR_DIV(port, divider); |
|
- | 459 | ||
- | 460 | /* |
|
- | 461 | * Tx escape clock must be as close to 20MHz possible, but should |
|
- | 462 | * not exceed it. Hence select divide by 2 |
|
- | 463 | */ |
|
- | 464 | tmp |= BXT_MIPI_TX_ESCLK_8XDIV_BY2(port); |
|
- | 465 | ||
- | 466 | tmp |= BXT_MIPI_RX_ESCLK_8X_BY3(port); |
|
- | 467 | ||
- | 468 | I915_WRITE(BXT_MIPI_CLOCK_CTL, tmp); |
|
- | 469 | } |
|
- | 470 | ||
- | 471 | static bool bxt_configure_dsi_pll(struct intel_encoder *encoder) |
|
- | 472 | { |
|
- | 473 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
|
- | 474 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); |
|
- | 475 | u8 dsi_ratio; |
|
- | 476 | u32 dsi_clk; |
|
- | 477 | u32 val; |
|
- | 478 | ||
- | 479 | dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format, |
|
- | 480 | intel_dsi->lane_count); |
|
- | 481 | ||
- | 482 | /* |
|
- | 483 | * From clock diagram, to get PLL ratio divider, divide double of DSI |
|
- | 484 | * link rate (i.e., 2*8x=16x frequency value) by ref clock. Make sure to |
|
- | 485 | * round 'up' the result |
|
- | 486 | */ |
|
- | 487 | dsi_ratio = DIV_ROUND_UP(dsi_clk * 2, BXT_REF_CLOCK_KHZ); |
|
- | 488 | if (dsi_ratio < BXT_DSI_PLL_RATIO_MIN || |
|
- | 489 | dsi_ratio > BXT_DSI_PLL_RATIO_MAX) { |
|
- | 490 | DRM_ERROR("Cant get a suitable ratio from DSI PLL ratios\n"); |
|
- | 491 | return false; |
|
- | 492 | } |
|
- | 493 | ||
- | 494 | /* |
|
- | 495 | * Program DSI ratio and Select MIPIC and MIPIA PLL output as 8x |
|
- | 496 | * Spec says both have to be programmed, even if one is not getting |
|
- | 497 | * used. Configure MIPI_CLOCK_CTL dividers in modeset |
|
- | 498 | */ |
|
- | 499 | val = I915_READ(BXT_DSI_PLL_CTL); |
|
- | 500 | val &= ~BXT_DSI_PLL_PVD_RATIO_MASK; |
|
- | 501 | val &= ~BXT_DSI_FREQ_SEL_MASK; |
|
- | 502 | val &= ~BXT_DSI_PLL_RATIO_MASK; |
|
- | 503 | val |= (dsi_ratio | BXT_DSIA_16X_BY2 | BXT_DSIC_16X_BY2); |
|
- | 504 | ||
- | 505 | /* As per recommendation from hardware team, |
|
- | 506 | * Prog PVD ratio =1 if dsi ratio <= 50 |
|
- | 507 | */ |
|
- | 508 | if (dsi_ratio <= 50) { |
|
- | 509 | val &= ~BXT_DSI_PLL_PVD_RATIO_MASK; |
|
- | 510 | val |= BXT_DSI_PLL_PVD_RATIO_1; |
|
- | 511 | } |
|
- | 512 | ||
- | 513 | I915_WRITE(BXT_DSI_PLL_CTL, val); |
|
- | 514 | POSTING_READ(BXT_DSI_PLL_CTL); |
|
- | 515 | ||
- | 516 | return true; |
|
- | 517 | } |
|
- | 518 | ||
- | 519 | static void bxt_enable_dsi_pll(struct intel_encoder *encoder) |
|
- | 520 | { |
|
- | 521 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
|
- | 522 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); |
|
- | 523 | enum port port; |
|
- | 524 | u32 val; |
|
- | 525 | ||
- | 526 | DRM_DEBUG_KMS("\n"); |
|
- | 527 | ||
- | 528 | val = I915_READ(BXT_DSI_PLL_ENABLE); |
|
- | 529 | ||
- | 530 | if (val & BXT_DSI_PLL_DO_ENABLE) { |
|
- | 531 | WARN(1, "DSI PLL already enabled. Disabling it.\n"); |
|
- | 532 | val &= ~BXT_DSI_PLL_DO_ENABLE; |
|
- | 533 | I915_WRITE(BXT_DSI_PLL_ENABLE, val); |
|
- | 534 | } |
|
- | 535 | ||
- | 536 | /* Configure PLL vales */ |
|
- | 537 | if (!bxt_configure_dsi_pll(encoder)) { |
|
- | 538 | DRM_ERROR("Configure DSI PLL failed, abort PLL enable\n"); |
|
- | 539 | return; |
|
- | 540 | } |
|
- | 541 | ||
- | 542 | /* Program TX, RX, Dphy clocks */ |
|
- | 543 | for_each_dsi_port(port, intel_dsi->ports) |
|
- | 544 | bxt_dsi_program_clocks(encoder->base.dev, port); |
|
- | 545 | ||
- | 546 | /* Enable DSI PLL */ |
|
- | 547 | val = I915_READ(BXT_DSI_PLL_ENABLE); |
|
- | 548 | val |= BXT_DSI_PLL_DO_ENABLE; |
|
- | 549 | I915_WRITE(BXT_DSI_PLL_ENABLE, val); |
|
- | 550 | ||
- | 551 | /* Timeout and fail if PLL not locked */ |
|
- | 552 | if (wait_for(I915_READ(BXT_DSI_PLL_ENABLE) & BXT_DSI_PLL_LOCKED, 1)) { |
|
- | 553 | DRM_ERROR("Timed out waiting for DSI PLL to lock\n"); |
|
- | 554 | return; |
|
- | 555 | } |
|
- | 556 | ||
- | 557 | DRM_DEBUG_KMS("DSI PLL locked\n"); |
|
- | 558 | } |
|
- | 559 | ||
- | 560 | void intel_enable_dsi_pll(struct intel_encoder *encoder) |
|
- | 561 | { |
|
- | 562 | struct drm_device *dev = encoder->base.dev; |
|
- | 563 | ||
- | 564 | if (IS_VALLEYVIEW(dev)) |
|
- | 565 | vlv_enable_dsi_pll(encoder); |
|
- | 566 | else if (IS_BROXTON(dev)) |
|
- | 567 | bxt_enable_dsi_pll(encoder); |
|
- | 568 | } |
|
- | 569 | ||
- | 570 | void intel_disable_dsi_pll(struct intel_encoder *encoder) |
|
- | 571 | { |
|
- | 572 | struct drm_device *dev = encoder->base.dev; |
|
- | 573 | ||
- | 574 | if (IS_VALLEYVIEW(dev)) |
|
- | 575 | vlv_disable_dsi_pll(encoder); |
|
- | 576 | else if (IS_BROXTON(dev)) |
|
- | 577 | bxt_disable_dsi_pll(encoder); |
|
- | 578 | } |
|
- | 579 | ||
- | 580 | static void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port) |
|
- | 581 | { |
|
- | 582 | u32 tmp; |
|
- | 583 | struct drm_device *dev = encoder->base.dev; |
|
- | 584 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 585 | ||
- | 586 | /* Clear old configurations */ |
|
- | 587 | tmp = I915_READ(BXT_MIPI_CLOCK_CTL); |
|
- | 588 | tmp &= ~(BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port)); |
|
- | 589 | tmp &= ~(BXT_MIPI_RX_ESCLK_FIXDIV_MASK(port)); |
|
- | 590 | tmp &= ~(BXT_MIPI_ESCLK_VAR_DIV_MASK(port)); |
|
- | 591 | tmp &= ~(BXT_MIPI_DPHY_DIVIDER_MASK(port)); |
|
- | 592 | I915_WRITE(BXT_MIPI_CLOCK_CTL, tmp); |
|
- | 593 | I915_WRITE(MIPI_EOT_DISABLE(port), CLOCKSTOP); |
|
- | 594 | } |
|
- | 595 | ||
- | 596 | void intel_dsi_reset_clocks(struct intel_encoder *encoder, enum port port) |
|
- | 597 | { |
|
- | 598 | struct drm_device *dev = encoder->base.dev; |
|
- | 599 |