Rev 3746 | Rev 4560 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3746 | Rev 4104 | ||
---|---|---|---|
Line 47... | Line 47... | ||
47 | }; |
47 | }; |
Line 48... | Line 48... | ||
48 | 48 | ||
49 | struct intel_lvds_encoder { |
49 | struct intel_lvds_encoder { |
Line 50... | Line -... | ||
50 | struct intel_encoder base; |
- | |
51 | - | ||
52 | u32 pfit_control; |
50 | struct intel_encoder base; |
53 | u32 pfit_pgm_ratios; |
51 | |
Line 54... | Line 52... | ||
54 | bool is_dual_link; |
52 | bool is_dual_link; |
55 | u32 reg; |
53 | u32 reg; |
Line 86... | Line 84... | ||
86 | *pipe = PORT_TO_PIPE(tmp); |
84 | *pipe = PORT_TO_PIPE(tmp); |
Line 87... | Line 85... | ||
87 | 85 | ||
88 | return true; |
86 | return true; |
Line -... | Line 87... | ||
- | 87 | } |
|
- | 88 | ||
- | 89 | static void intel_lvds_get_config(struct intel_encoder *encoder, |
|
- | 90 | struct intel_crtc_config *pipe_config) |
|
- | 91 | { |
|
- | 92 | struct drm_device *dev = encoder->base.dev; |
|
- | 93 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 94 | u32 lvds_reg, tmp, flags = 0; |
|
- | 95 | ||
- | 96 | if (HAS_PCH_SPLIT(dev)) |
|
- | 97 | lvds_reg = PCH_LVDS; |
|
- | 98 | else |
|
- | 99 | lvds_reg = LVDS; |
|
- | 100 | ||
- | 101 | tmp = I915_READ(lvds_reg); |
|
- | 102 | if (tmp & LVDS_HSYNC_POLARITY) |
|
- | 103 | flags |= DRM_MODE_FLAG_NHSYNC; |
|
- | 104 | else |
|
- | 105 | flags |= DRM_MODE_FLAG_PHSYNC; |
|
- | 106 | if (tmp & LVDS_VSYNC_POLARITY) |
|
- | 107 | flags |= DRM_MODE_FLAG_NVSYNC; |
|
- | 108 | else |
|
- | 109 | flags |= DRM_MODE_FLAG_PVSYNC; |
|
- | 110 | ||
- | 111 | pipe_config->adjusted_mode.flags |= flags; |
|
- | 112 | ||
- | 113 | /* gen2/3 store dither state in pfit control, needs to match */ |
|
- | 114 | if (INTEL_INFO(dev)->gen < 4) { |
|
- | 115 | tmp = I915_READ(PFIT_CONTROL); |
|
- | 116 | ||
- | 117 | pipe_config->gmch_pfit.control |= tmp & PANEL_8TO6_DITHER_ENABLE; |
|
- | 118 | } |
|
89 | } |
119 | } |
90 | 120 | ||
91 | /* The LVDS pin pair needs to be on before the DPLLs are enabled. |
121 | /* The LVDS pin pair needs to be on before the DPLLs are enabled. |
92 | * This is an exception to the general rule that mode_set doesn't turn |
122 | * This is an exception to the general rule that mode_set doesn't turn |
93 | * things on. |
123 | * things on. |
94 | */ |
124 | */ |
95 | static void intel_pre_pll_enable_lvds(struct intel_encoder *encoder) |
125 | static void intel_pre_enable_lvds(struct intel_encoder *encoder) |
96 | { |
126 | { |
97 | struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); |
127 | struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); |
98 | struct drm_device *dev = encoder->base.dev; |
128 | struct drm_device *dev = encoder->base.dev; |
99 | struct drm_i915_private *dev_priv = dev->dev_private; |
129 | struct drm_i915_private *dev_priv = dev->dev_private; |
100 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); |
130 | struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
101 | struct drm_display_mode *fixed_mode = |
131 | const struct drm_display_mode *adjusted_mode = |
102 | lvds_encoder->attached_connector->base.panel.fixed_mode; |
132 | &crtc->config.adjusted_mode; |
Line -... | Line 133... | ||
- | 133 | int pipe = crtc->pipe; |
|
- | 134 | u32 temp; |
|
- | 135 | ||
- | 136 | if (HAS_PCH_SPLIT(dev)) { |
|
- | 137 | assert_fdi_rx_pll_disabled(dev_priv, pipe); |
|
- | 138 | assert_shared_dpll_disabled(dev_priv, |
|
- | 139 | intel_crtc_to_shared_dpll(crtc)); |
|
- | 140 | } else { |
|
103 | int pipe = intel_crtc->pipe; |
141 | assert_pll_disabled(dev_priv, pipe); |
104 | u32 temp; |
142 | } |
Line 105... | Line 143... | ||
105 | 143 | ||
106 | temp = I915_READ(lvds_encoder->reg); |
144 | temp = I915_READ(lvds_encoder->reg); |
Line 116... | Line 154... | ||
116 | temp &= ~LVDS_PIPEB_SELECT; |
154 | temp &= ~LVDS_PIPEB_SELECT; |
117 | } |
155 | } |
118 | } |
156 | } |
Line 119... | Line 157... | ||
119 | 157 | ||
- | 158 | /* set the corresponsding LVDS_BORDER bit */ |
|
120 | /* set the corresponsding LVDS_BORDER bit */ |
159 | temp &= ~LVDS_BORDER_ENABLE; |
121 | temp |= dev_priv->lvds_border_bits; |
160 | temp |= crtc->config.gmch_pfit.lvds_border_bits; |
122 | /* Set the B0-B3 data pairs corresponding to whether we're going to |
161 | /* Set the B0-B3 data pairs corresponding to whether we're going to |
123 | * set the DPLLs for dual-channel mode or not. |
162 | * set the DPLLs for dual-channel mode or not. |
124 | */ |
163 | */ |
125 | if (lvds_encoder->is_dual_link) |
164 | if (lvds_encoder->is_dual_link) |
Line 134... | Line 173... | ||
134 | 173 | ||
135 | /* Set the dithering flag on LVDS as needed, note that there is no |
174 | /* Set the dithering flag on LVDS as needed, note that there is no |
136 | * special lvds dither control bit on pch-split platforms, dithering is |
175 | * special lvds dither control bit on pch-split platforms, dithering is |
137 | * only controlled through the PIPECONF reg. */ |
176 | * only controlled through the PIPECONF reg. */ |
- | 177 | if (INTEL_INFO(dev)->gen == 4) { |
|
138 | if (INTEL_INFO(dev)->gen == 4) { |
178 | /* Bspec wording suggests that LVDS port dithering only exists |
- | 179 | * for 18bpp panels. */ |
|
139 | if (dev_priv->lvds_dither) |
180 | if (crtc->config.dither && crtc->config.pipe_bpp == 18) |
140 | temp |= LVDS_ENABLE_DITHER; |
181 | temp |= LVDS_ENABLE_DITHER; |
141 | else |
182 | else |
142 | temp &= ~LVDS_ENABLE_DITHER; |
183 | temp &= ~LVDS_ENABLE_DITHER; |
143 | } |
184 | } |
144 | temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); |
185 | temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); |
145 | if (fixed_mode->flags & DRM_MODE_FLAG_NHSYNC) |
186 | if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) |
146 | temp |= LVDS_HSYNC_POLARITY; |
187 | temp |= LVDS_HSYNC_POLARITY; |
147 | if (fixed_mode->flags & DRM_MODE_FLAG_NVSYNC) |
188 | if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) |
Line 148... | Line 189... | ||
148 | temp |= LVDS_VSYNC_POLARITY; |
189 | temp |= LVDS_VSYNC_POLARITY; |
149 | 190 | ||
Line 150... | Line -... | ||
150 | I915_WRITE(lvds_encoder->reg, temp); |
- | |
151 | } |
- | |
152 | - | ||
153 | static void intel_pre_enable_lvds(struct intel_encoder *encoder) |
- | |
154 | { |
- | |
155 | struct drm_device *dev = encoder->base.dev; |
- | |
156 | struct intel_lvds_encoder *enc = to_lvds_encoder(&encoder->base); |
- | |
157 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | |
158 | - | ||
159 | if (HAS_PCH_SPLIT(dev) || !enc->pfit_control) |
- | |
160 | return; |
- | |
161 | - | ||
162 | /* |
- | |
163 | * Enable automatic panel scaling so that non-native modes |
- | |
164 | * fill the screen. The panel fitter should only be |
- | |
165 | * adjusted whilst the pipe is disabled, according to |
- | |
166 | * register description and PRM. |
- | |
167 | */ |
- | |
168 | DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n", |
- | |
169 | enc->pfit_control, |
- | |
170 | enc->pfit_pgm_ratios); |
- | |
171 | - | ||
172 | I915_WRITE(PFIT_PGM_RATIOS, enc->pfit_pgm_ratios); |
- | |
173 | I915_WRITE(PFIT_CONTROL, enc->pfit_control); |
191 | I915_WRITE(lvds_encoder->reg, temp); |
174 | } |
192 | } |
175 | 193 | ||
176 | /** |
194 | /** |
177 | * Sets the power state for the panel. |
195 | * Sets the power state for the panel. |
Line 239... | Line 257... | ||
239 | return MODE_PANEL; |
257 | return MODE_PANEL; |
Line 240... | Line 258... | ||
240 | 258 | ||
241 | return MODE_OK; |
259 | return MODE_OK; |
Line 242... | Line -... | ||
242 | } |
- | |
243 | - | ||
244 | static void |
- | |
245 | centre_horizontally(struct drm_display_mode *mode, |
- | |
246 | int width) |
- | |
247 | { |
- | |
248 | u32 border, sync_pos, blank_width, sync_width; |
- | |
249 | - | ||
250 | /* keep the hsync and hblank widths constant */ |
- | |
251 | sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start; |
- | |
252 | blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start; |
- | |
253 | sync_pos = (blank_width - sync_width + 1) / 2; |
- | |
254 | - | ||
255 | border = (mode->hdisplay - width + 1) / 2; |
- | |
256 | border += border & 1; /* make the border even */ |
- | |
257 | - | ||
258 | mode->crtc_hdisplay = width; |
- | |
259 | mode->crtc_hblank_start = width + border; |
- | |
260 | mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width; |
- | |
261 | - | ||
262 | mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos; |
- | |
263 | mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width; |
- | |
264 | } |
- | |
265 | - | ||
266 | static void |
- | |
267 | centre_vertically(struct drm_display_mode *mode, |
- | |
268 | int height) |
- | |
269 | { |
- | |
270 | u32 border, sync_pos, blank_width, sync_width; |
- | |
271 | - | ||
272 | /* keep the vsync and vblank widths constant */ |
- | |
273 | sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start; |
- | |
274 | blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start; |
- | |
275 | sync_pos = (blank_width - sync_width + 1) / 2; |
- | |
276 | - | ||
277 | border = (mode->vdisplay - height + 1) / 2; |
- | |
278 | - | ||
279 | mode->crtc_vdisplay = height; |
- | |
280 | mode->crtc_vblank_start = height + border; |
- | |
281 | mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width; |
- | |
282 | - | ||
283 | mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos; |
- | |
284 | mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width; |
- | |
285 | } |
- | |
286 | - | ||
287 | static inline u32 panel_fitter_scaling(u32 source, u32 target) |
- | |
288 | { |
- | |
289 | /* |
- | |
290 | * Floating point operation is not supported. So the FACTOR |
- | |
291 | * is defined, which can avoid the floating point computation |
- | |
292 | * when calculating the panel ratio. |
- | |
293 | */ |
- | |
294 | #define ACCURACY 12 |
- | |
295 | #define FACTOR (1 << ACCURACY) |
- | |
296 | u32 ratio = source * FACTOR / target; |
- | |
297 | return (FACTOR * ratio + FACTOR/2) / FACTOR; |
- | |
298 | } |
260 | } |
299 | 261 | ||
300 | static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder, |
262 | static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder, |
301 | struct intel_crtc_config *pipe_config) |
263 | struct intel_crtc_config *pipe_config) |
302 | { |
264 | { |
303 | struct drm_device *dev = intel_encoder->base.dev; |
265 | struct drm_device *dev = intel_encoder->base.dev; |
304 | struct drm_i915_private *dev_priv = dev->dev_private; |
266 | struct drm_i915_private *dev_priv = dev->dev_private; |
305 | struct intel_lvds_encoder *lvds_encoder = |
267 | struct intel_lvds_encoder *lvds_encoder = |
306 | to_lvds_encoder(&intel_encoder->base); |
268 | to_lvds_encoder(&intel_encoder->base); |
307 | struct intel_connector *intel_connector = |
269 | struct intel_connector *intel_connector = |
308 | &lvds_encoder->attached_connector->base; |
- | |
309 | struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; |
270 | &lvds_encoder->attached_connector->base; |
310 | struct drm_display_mode *mode = &pipe_config->requested_mode; |
- | |
311 | struct intel_crtc *intel_crtc = lvds_encoder->base.new_crtc; |
271 | struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; |
312 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; |
- | |
Line 313... | Line 272... | ||
313 | unsigned int lvds_bpp; |
272 | struct intel_crtc *intel_crtc = lvds_encoder->base.new_crtc; |
314 | int pipe; |
273 | unsigned int lvds_bpp; |
315 | 274 | ||
316 | /* Should never happen!! */ |
275 | /* Should never happen!! */ |
317 | if (INTEL_INFO(dev)->gen < 4 && intel_crtc->pipe == 0) { |
276 | if (INTEL_INFO(dev)->gen < 4 && intel_crtc->pipe == 0) { |
Line 318... | Line -... | ||
318 | DRM_ERROR("Can't support LVDS on pipe A\n"); |
- | |
319 | return false; |
- | |
320 | } |
- | |
321 | 277 | DRM_ERROR("Can't support LVDS on pipe A\n"); |
|
322 | if (intel_encoder_check_is_cloned(&lvds_encoder->base)) |
278 | return false; |
323 | return false; |
279 | } |
324 | 280 | ||
325 | if ((I915_READ(lvds_encoder->reg) & LVDS_A3_POWER_MASK) == |
281 | if ((I915_READ(lvds_encoder->reg) & LVDS_A3_POWER_MASK) == |
Line 326... | Line 282... | ||
326 | LVDS_A3_POWER_UP) |
282 | LVDS_A3_POWER_UP) |
327 | lvds_bpp = 8*3; |
283 | lvds_bpp = 8*3; |
328 | else |
284 | else |
329 | lvds_bpp = 6*3; |
285 | lvds_bpp = 6*3; |
330 | 286 | ||
- | 287 | if (lvds_bpp != pipe_config->pipe_bpp && !pipe_config->bw_constrained) { |
|
331 | if (lvds_bpp != pipe_config->pipe_bpp) { |
288 | DRM_DEBUG_KMS("forcing display bpp (was %d) to LVDS (%d)\n", |
332 | DRM_DEBUG_KMS("forcing display bpp (was %d) to LVDS (%d)\n", |
289 | pipe_config->pipe_bpp, lvds_bpp); |
333 | pipe_config->pipe_bpp, lvds_bpp); |
290 | pipe_config->pipe_bpp = lvds_bpp; |
334 | pipe_config->pipe_bpp = lvds_bpp; |
291 | } |
335 | } |
292 | |
Line 343... | Line 300... | ||
343 | adjusted_mode); |
300 | adjusted_mode); |
Line 344... | Line 301... | ||
344 | 301 | ||
345 | if (HAS_PCH_SPLIT(dev)) { |
302 | if (HAS_PCH_SPLIT(dev)) { |
Line 346... | Line 303... | ||
346 | pipe_config->has_pch_encoder = true; |
303 | pipe_config->has_pch_encoder = true; |
347 | 304 | ||
348 | intel_pch_panel_fitting(dev, |
- | |
349 | intel_connector->panel.fitting_mode, |
- | |
350 | mode, adjusted_mode); |
- | |
351 | return true; |
- | |
352 | } |
- | |
353 | - | ||
354 | /* Native modes don't need fitting */ |
- | |
355 | if (adjusted_mode->hdisplay == mode->hdisplay && |
- | |
356 | adjusted_mode->vdisplay == mode->vdisplay) |
- | |
357 | goto out; |
- | |
358 | - | ||
359 | /* 965+ wants fuzzy fitting */ |
- | |
360 | if (INTEL_INFO(dev)->gen >= 4) |
- | |
361 | pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) | |
- | |
362 | PFIT_FILTER_FUZZY); |
- | |
363 | - | ||
364 | /* |
- | |
365 | * Enable automatic panel scaling for non-native modes so that they fill |
- | |
366 | * the screen. Should be enabled before the pipe is enabled, according |
- | |
367 | * to register description and PRM. |
- | |
368 | * Change the value here to see the borders for debugging |
- | |
369 | */ |
- | |
370 | for_each_pipe(pipe) |
- | |
371 | I915_WRITE(BCLRPAT(pipe), 0); |
- | |
372 | - | ||
373 | drm_mode_set_crtcinfo(adjusted_mode, 0); |
- | |
374 | pipe_config->timings_set = true; |
- | |
375 | - | ||
376 | switch (intel_connector->panel.fitting_mode) { |
- | |
377 | case DRM_MODE_SCALE_CENTER: |
- | |
378 | /* |
- | |
379 | * For centered modes, we have to calculate border widths & |
- | |
380 | * heights and modify the values programmed into the CRTC. |
- | |
381 | */ |
- | |
382 | centre_horizontally(adjusted_mode, mode->hdisplay); |
- | |
383 | centre_vertically(adjusted_mode, mode->vdisplay); |
- | |
384 | border = LVDS_BORDER_ENABLE; |
- | |
385 | break; |
- | |
386 | - | ||
387 | case DRM_MODE_SCALE_ASPECT: |
- | |
388 | /* Scale but preserve the aspect ratio */ |
- | |
389 | if (INTEL_INFO(dev)->gen >= 4) { |
- | |
390 | u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay; |
- | |
391 | u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay; |
- | |
392 | - | ||
393 | /* 965+ is easy, it does everything in hw */ |
- | |
394 | if (scaled_width > scaled_height) |
- | |
395 | pfit_control |= PFIT_ENABLE | PFIT_SCALING_PILLAR; |
- | |
396 | else if (scaled_width < scaled_height) |
- | |
397 | pfit_control |= PFIT_ENABLE | PFIT_SCALING_LETTER; |
- | |
398 | else if (adjusted_mode->hdisplay != mode->hdisplay) |
305 | intel_pch_panel_fitting(intel_crtc, pipe_config, |
399 | pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; |
- | |
400 | } else { |
- | |
401 | u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay; |
- | |
402 | u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay; |
- | |
403 | /* |
- | |
404 | * For earlier chips we have to calculate the scaling |
- | |
405 | * ratio by hand and program it into the |
- | |
406 | * PFIT_PGM_RATIO register |
- | |
407 | */ |
- | |
408 | if (scaled_width > scaled_height) { /* pillar */ |
- | |
409 | centre_horizontally(adjusted_mode, scaled_height / mode->vdisplay); |
- | |
410 | - | ||
411 | border = LVDS_BORDER_ENABLE; |
- | |
412 | if (mode->vdisplay != adjusted_mode->vdisplay) { |
- | |
413 | u32 bits = panel_fitter_scaling(mode->vdisplay, adjusted_mode->vdisplay); |
- | |
414 | pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | |
- | |
415 | bits << PFIT_VERT_SCALE_SHIFT); |
- | |
416 | pfit_control |= (PFIT_ENABLE | |
- | |
417 | VERT_INTERP_BILINEAR | |
- | |
418 | HORIZ_INTERP_BILINEAR); |
306 | intel_connector->panel.fitting_mode); |
419 | } |
- | |
420 | } else if (scaled_width < scaled_height) { /* letter */ |
- | |
421 | centre_vertically(adjusted_mode, scaled_width / mode->hdisplay); |
- | |
422 | - | ||
423 | border = LVDS_BORDER_ENABLE; |
- | |
424 | if (mode->hdisplay != adjusted_mode->hdisplay) { |
- | |
425 | u32 bits = panel_fitter_scaling(mode->hdisplay, adjusted_mode->hdisplay); |
- | |
426 | pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | |
307 | } else { |
427 | bits << PFIT_VERT_SCALE_SHIFT); |
- | |
428 | pfit_control |= (PFIT_ENABLE | |
- | |
429 | VERT_INTERP_BILINEAR | |
- | |
430 | HORIZ_INTERP_BILINEAR); |
- | |
431 | } |
- | |
432 | } else |
- | |
433 | /* Aspects match, Let hw scale both directions */ |
- | |
434 | pfit_control |= (PFIT_ENABLE | |
- | |
435 | VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | |
- | |
436 | VERT_INTERP_BILINEAR | |
- | |
437 | HORIZ_INTERP_BILINEAR); |
- | |
Line 438... | Line -... | ||
438 | } |
- | |
439 | break; |
- | |
440 | - | ||
441 | case DRM_MODE_SCALE_FULLSCREEN: |
- | |
442 | /* |
- | |
443 | * Full scaling, even if it changes the aspect ratio. |
- | |
444 | * Fortunately this is all done for us in hw. |
- | |
445 | */ |
- | |
446 | if (mode->vdisplay != adjusted_mode->vdisplay || |
- | |
447 | mode->hdisplay != adjusted_mode->hdisplay) { |
- | |
448 | pfit_control |= PFIT_ENABLE; |
- | |
449 | if (INTEL_INFO(dev)->gen >= 4) |
- | |
450 | pfit_control |= PFIT_SCALING_AUTO; |
- | |
451 | else |
- | |
452 | pfit_control |= (VERT_AUTO_SCALE | |
- | |
453 | VERT_INTERP_BILINEAR | |
308 | intel_gmch_panel_fitting(intel_crtc, pipe_config, |
454 | HORIZ_AUTO_SCALE | |
- | |
455 | HORIZ_INTERP_BILINEAR); |
- | |
456 | } |
- | |
457 | break; |
- | |
458 | - | ||
459 | default: |
- | |
460 | break; |
- | |
461 | } |
- | |
462 | - | ||
463 | out: |
- | |
464 | /* If not enabling scaling, be consistent and always use 0. */ |
- | |
465 | if ((pfit_control & PFIT_ENABLE) == 0) { |
- | |
466 | pfit_control = 0; |
- | |
467 | pfit_pgm_ratios = 0; |
- | |
468 | } |
- | |
469 | - | ||
470 | /* Make sure pre-965 set dither correctly */ |
- | |
471 | if (INTEL_INFO(dev)->gen < 4 && dev_priv->lvds_dither) |
- | |
472 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; |
- | |
473 | - | ||
474 | if (pfit_control != lvds_encoder->pfit_control || |
- | |
475 | pfit_pgm_ratios != lvds_encoder->pfit_pgm_ratios) { |
- | |
476 | lvds_encoder->pfit_control = pfit_control; |
- | |
Line 477... | Line 309... | ||
477 | lvds_encoder->pfit_pgm_ratios = pfit_pgm_ratios; |
309 | intel_connector->panel.fitting_mode); |
478 | } |
310 | |
479 | dev_priv->lvds_border_bits = border; |
311 | } |
480 | 312 | ||
481 | /* |
313 | /* |
Line 482... | Line 314... | ||
482 | * XXX: It would be nice to support lower refresh rates on the |
314 | * XXX: It would be nice to support lower refresh rates on the |
483 | * panels to reduce power consumption, and perhaps match the |
315 | * panels to reduce power consumption, and perhaps match the |
Line 484... | Line 316... | ||
484 | * user's requested refresh rate. |
316 | * user's requested refresh rate. |
485 | */ |
- | |
486 | - | ||
487 | return true; |
317 | */ |
488 | } |
318 | |
489 | 319 | return true; |
|
490 | static void intel_lvds_mode_set(struct drm_encoder *encoder, |
320 | } |
491 | struct drm_display_mode *mode, |
321 | |
492 | struct drm_display_mode *adjusted_mode) |
322 | static void intel_lvds_mode_set(struct intel_encoder *encoder) |
493 | { |
323 | { |
Line 494... | Line 324... | ||
494 | /* |
324 | /* |
495 | * The LVDS pin pair will already have been turned on in the |
325 | * We don't do anything here, the LVDS port is fully set up in the pre |
Line 509... | Line 339... | ||
509 | intel_lvds_detect(struct drm_connector *connector, bool force) |
339 | intel_lvds_detect(struct drm_connector *connector, bool force) |
510 | { |
340 | { |
511 | struct drm_device *dev = connector->dev; |
341 | struct drm_device *dev = connector->dev; |
512 | enum drm_connector_status status; |
342 | enum drm_connector_status status; |
Line -... | Line 343... | ||
- | 343 | ||
- | 344 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", |
|
- | 345 | connector->base.id, drm_get_connector_name(connector)); |
|
513 | 346 | ||
514 | status = intel_panel_detect(dev); |
347 | status = intel_panel_detect(dev); |
515 | if (status != connector_status_unknown) |
348 | if (status != connector_status_unknown) |
Line 516... | Line 349... | ||
516 | return status; |
349 | return status; |
Line 670... | Line 503... | ||
670 | } |
503 | } |
Line 671... | Line 504... | ||
671 | 504 | ||
672 | return 0; |
505 | return 0; |
Line 673... | Line -... | ||
673 | } |
- | |
674 | - | ||
675 | static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = { |
- | |
676 | .mode_set = intel_lvds_mode_set, |
- | |
677 | }; |
506 | } |
678 | 507 | ||
679 | static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = { |
508 | static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = { |
680 | .get_modes = intel_lvds_get_modes, |
509 | .get_modes = intel_lvds_get_modes, |
681 | .mode_valid = intel_lvds_mode_valid, |
510 | .mode_valid = intel_lvds_mode_valid, |
Line 867... | Line 696... | ||
867 | .matches = { |
696 | .matches = { |
868 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
697 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
869 | DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Q900"), |
698 | DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Q900"), |
870 | }, |
699 | }, |
871 | }, |
700 | }, |
- | 701 | { |
|
- | 702 | .callback = intel_no_lvds_dmi_callback, |
|
- | 703 | .ident = "Intel D510MO", |
|
- | 704 | .matches = { |
|
- | 705 | DMI_MATCH(DMI_BOARD_VENDOR, "Intel"), |
|
- | 706 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "D510MO"), |
|
- | 707 | }, |
|
- | 708 | }, |
|
- | 709 | { |
|
- | 710 | .callback = intel_no_lvds_dmi_callback, |
|
- | 711 | .ident = "Intel D525MW", |
|
- | 712 | .matches = { |
|
- | 713 | DMI_MATCH(DMI_BOARD_VENDOR, "Intel"), |
|
- | 714 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "D525MW"), |
|
- | 715 | }, |
|
- | 716 | }, |
|
Line 872... | Line 717... | ||
872 | 717 | ||
873 | { } /* terminating entry */ |
718 | { } /* terminating entry */ |
Line 874... | Line 719... | ||
874 | }; |
719 | }; |
Line 935... | Line 780... | ||
935 | u8 *i2c_pin) |
780 | u8 *i2c_pin) |
936 | { |
781 | { |
937 | struct drm_i915_private *dev_priv = dev->dev_private; |
782 | struct drm_i915_private *dev_priv = dev->dev_private; |
938 | int i; |
783 | int i; |
Line 939... | Line 784... | ||
939 | 784 | ||
940 | if (!dev_priv->child_dev_num) |
785 | if (!dev_priv->vbt.child_dev_num) |
Line 941... | Line 786... | ||
941 | return true; |
786 | return true; |
942 | 787 | ||
Line 943... | Line 788... | ||
943 | for (i = 0; i < dev_priv->child_dev_num; i++) { |
788 | for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { |
944 | struct child_device_config *child = dev_priv->child_dev + i; |
789 | struct child_device_config *child = dev_priv->vbt.child_dev + i; |
945 | 790 | ||
946 | /* If the device type is not LFP, continue. |
791 | /* If the device type is not LFP, continue. |
Line 977... | Line 822... | ||
977 | static int intel_dual_link_lvds_callback(const struct dmi_system_id *id) |
822 | static int intel_dual_link_lvds_callback(const struct dmi_system_id *id) |
978 | { |
823 | { |
979 | DRM_INFO("Forcing lvds to dual link mode on %s\n", id->ident); |
824 | DRM_INFO("Forcing lvds to dual link mode on %s\n", id->ident); |
980 | return 1; |
825 | return 1; |
981 | } |
826 | } |
- | 827 | ||
- | 828 | static const struct dmi_system_id intel_dual_link_lvds[] = { |
|
- | 829 | { |
|
- | 830 | .callback = intel_dual_link_lvds_callback, |
|
- | 831 | .ident = "Apple MacBook Pro (Core i5/i7 Series)", |
|
- | 832 | .matches = { |
|
- | 833 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), |
|
- | 834 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"), |
|
- | 835 | }, |
|
- | 836 | }, |
|
- | 837 | { } /* terminating entry */ |
|
- | 838 | }; |
|
- | 839 | ||
982 | bool intel_is_dual_link_lvds(struct drm_device *dev) |
840 | bool intel_is_dual_link_lvds(struct drm_device *dev) |
983 | { |
841 | { |
984 | struct intel_encoder *encoder; |
842 | struct intel_encoder *encoder; |
985 | struct intel_lvds_encoder *lvds_encoder; |
843 | struct intel_lvds_encoder *lvds_encoder; |
Line 1014... | Line 872... | ||
1014 | * we need to check "the value to be set" in VBT when LVDS |
872 | * we need to check "the value to be set" in VBT when LVDS |
1015 | * register is uninitialized. |
873 | * register is uninitialized. |
1016 | */ |
874 | */ |
1017 | val = I915_READ(lvds_encoder->reg); |
875 | val = I915_READ(lvds_encoder->reg); |
1018 | if (!(val & ~(LVDS_PIPE_MASK | LVDS_DETECTED))) |
876 | if (!(val & ~(LVDS_PIPE_MASK | LVDS_DETECTED))) |
1019 | val = dev_priv->bios_lvds_val; |
877 | val = dev_priv->vbt.bios_lvds_val; |
Line 1020... | Line 878... | ||
1020 | 878 | ||
1021 | return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP; |
879 | return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP; |
Line 1022... | Line 880... | ||
1022 | } |
880 | } |
Line 1041... | Line 899... | ||
1041 | * @dev: drm device |
899 | * @dev: drm device |
1042 | * |
900 | * |
1043 | * Create the connector, register the LVDS DDC bus, and try to figure out what |
901 | * Create the connector, register the LVDS DDC bus, and try to figure out what |
1044 | * modes we can display on the LVDS panel (if present). |
902 | * modes we can display on the LVDS panel (if present). |
1045 | */ |
903 | */ |
1046 | bool intel_lvds_init(struct drm_device *dev) |
904 | void intel_lvds_init(struct drm_device *dev) |
1047 | { |
905 | { |
1048 | struct drm_i915_private *dev_priv = dev->dev_private; |
906 | struct drm_i915_private *dev_priv = dev->dev_private; |
1049 | struct intel_lvds_encoder *lvds_encoder; |
907 | struct intel_lvds_encoder *lvds_encoder; |
1050 | struct intel_encoder *intel_encoder; |
908 | struct intel_encoder *intel_encoder; |
1051 | struct intel_lvds_connector *lvds_connector; |
909 | struct intel_lvds_connector *lvds_connector; |
Line 1059... | Line 917... | ||
1059 | u32 lvds; |
917 | u32 lvds; |
1060 | int pipe; |
918 | int pipe; |
1061 | u8 pin; |
919 | u8 pin; |
Line 1062... | Line 920... | ||
1062 | 920 | ||
1063 | if (!intel_lvds_supported(dev)) |
921 | if (!intel_lvds_supported(dev)) |
Line 1064... | Line 922... | ||
1064 | return false; |
922 | return; |
1065 | 923 | ||
1066 | /* Skip init on machines we know falsely report LVDS */ |
924 | /* Skip init on machines we know falsely report LVDS */ |
Line 1067... | Line 925... | ||
1067 | // if (dmi_check_system(intel_no_lvds)) |
925 | // if (dmi_check_system(intel_no_lvds)) |
1068 | // return false; |
926 | // return false; |
1069 | 927 | ||
1070 | pin = GMBUS_PORT_PANEL; |
928 | pin = GMBUS_PORT_PANEL; |
1071 | if (!lvds_is_present_in_vbt(dev, &pin)) { |
929 | if (!lvds_is_present_in_vbt(dev, &pin)) { |
Line 1072... | Line 930... | ||
1072 | DRM_DEBUG_KMS("LVDS is not present in VBT\n"); |
930 | DRM_DEBUG_KMS("LVDS is not present in VBT\n"); |
1073 | return false; |
931 | return; |
1074 | } |
932 | } |
1075 | 933 | ||
1076 | if (HAS_PCH_SPLIT(dev)) { |
934 | if (HAS_PCH_SPLIT(dev)) { |
1077 | if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) |
935 | if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) |
1078 | return false; |
936 | return; |
1079 | if (dev_priv->edp.support) { |
937 | if (dev_priv->vbt.edp_support) { |
Line 1080... | Line 938... | ||
1080 | DRM_DEBUG_KMS("disable LVDS for eDP support\n"); |
938 | DRM_DEBUG_KMS("disable LVDS for eDP support\n"); |
1081 | return false; |
939 | return; |
1082 | } |
940 | } |
Line 1083... | Line 941... | ||
1083 | } |
941 | } |
1084 | 942 | ||
1085 | lvds_encoder = kzalloc(sizeof(struct intel_lvds_encoder), GFP_KERNEL); |
943 | lvds_encoder = kzalloc(sizeof(struct intel_lvds_encoder), GFP_KERNEL); |
1086 | if (!lvds_encoder) |
944 | if (!lvds_encoder) |
1087 | return false; |
945 | return; |
Line 1088... | Line 946... | ||
1088 | 946 | ||
Line 1089... | Line -... | ||
1089 | lvds_connector = kzalloc(sizeof(struct intel_lvds_connector), GFP_KERNEL); |
- | |
1090 | if (!lvds_connector) { |
- | |
1091 | kfree(lvds_encoder); |
- | |
1092 | return false; |
- | |
1093 | } |
947 | lvds_connector = kzalloc(sizeof(struct intel_lvds_connector), GFP_KERNEL); |
1094 | 948 | if (!lvds_connector) { |
|
1095 | lvds_encoder->attached_connector = lvds_connector; |
949 | kfree(lvds_encoder); |
1096 | 950 | return; |
|
1097 | if (!HAS_PCH_SPLIT(dev)) { |
951 | } |
Line 1108... | Line 962... | ||
1108 | drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs, |
962 | drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs, |
1109 | DRM_MODE_ENCODER_LVDS); |
963 | DRM_MODE_ENCODER_LVDS); |
Line 1110... | Line 964... | ||
1110 | 964 | ||
1111 | intel_encoder->enable = intel_enable_lvds; |
965 | intel_encoder->enable = intel_enable_lvds; |
1112 | intel_encoder->pre_enable = intel_pre_enable_lvds; |
- | |
1113 | intel_encoder->pre_pll_enable = intel_pre_pll_enable_lvds; |
966 | intel_encoder->pre_enable = intel_pre_enable_lvds; |
- | 967 | intel_encoder->compute_config = intel_lvds_compute_config; |
|
1114 | intel_encoder->compute_config = intel_lvds_compute_config; |
968 | intel_encoder->mode_set = intel_lvds_mode_set; |
1115 | intel_encoder->disable = intel_disable_lvds; |
969 | intel_encoder->disable = intel_disable_lvds; |
- | 970 | intel_encoder->get_hw_state = intel_lvds_get_hw_state; |
|
1116 | intel_encoder->get_hw_state = intel_lvds_get_hw_state; |
971 | intel_encoder->get_config = intel_lvds_get_config; |
Line 1117... | Line 972... | ||
1117 | intel_connector->get_hw_state = intel_connector_get_hw_state; |
972 | intel_connector->get_hw_state = intel_connector_get_hw_state; |
1118 | 973 | ||
Line 1125... | Line 980... | ||
1125 | else if (IS_GEN4(dev)) |
980 | else if (IS_GEN4(dev)) |
1126 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); |
981 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); |
1127 | else |
982 | else |
1128 | intel_encoder->crtc_mask = (1 << 1); |
983 | intel_encoder->crtc_mask = (1 << 1); |
Line 1129... | Line -... | ||
1129 | - | ||
1130 | drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); |
984 | |
1131 | drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); |
985 | drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); |
1132 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; |
986 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; |
1133 | connector->interlace_allowed = false; |
987 | connector->interlace_allowed = false; |
Line 1197... | Line 1051... | ||
1197 | } |
1051 | } |
1198 | } |
1052 | } |
1199 | } |
1053 | } |
Line 1200... | Line 1054... | ||
1200 | 1054 | ||
1201 | /* Failed to get EDID, what about VBT? */ |
1055 | /* Failed to get EDID, what about VBT? */ |
1202 | if (dev_priv->lfp_lvds_vbt_mode) { |
1056 | if (dev_priv->vbt.lfp_lvds_vbt_mode) { |
1203 | DRM_DEBUG_KMS("using mode from VBT: "); |
1057 | DRM_DEBUG_KMS("using mode from VBT: "); |
Line 1204... | Line 1058... | ||
1204 | drm_mode_debug_printmodeline(dev_priv->lfp_lvds_vbt_mode); |
1058 | drm_mode_debug_printmodeline(dev_priv->vbt.lfp_lvds_vbt_mode); |
1205 | 1059 | ||
1206 | fixed_mode = drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); |
1060 | fixed_mode = drm_mode_duplicate(dev, dev_priv->vbt.lfp_lvds_vbt_mode); |
1207 | if (fixed_mode) { |
1061 | if (fixed_mode) { |
1208 | fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; |
1062 | fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; |
1209 | goto out; |
1063 | goto out; |
Line 1262... | Line 1116... | ||
1262 | drm_sysfs_connector_add(connector); |
1116 | drm_sysfs_connector_add(connector); |
Line 1263... | Line 1117... | ||
1263 | 1117 | ||
1264 | intel_panel_init(&intel_connector->panel, fixed_mode); |
1118 | intel_panel_init(&intel_connector->panel, fixed_mode); |
Line 1265... | Line 1119... | ||
1265 | intel_panel_setup_backlight(connector); |
1119 | intel_panel_setup_backlight(connector); |
Line 1266... | Line 1120... | ||
1266 | 1120 | ||
1267 | return true; |
1121 | return; |
1268 | 1122 | ||
1269 | failed: |
1123 | failed: |
1270 | DRM_DEBUG_KMS("No LVDS modes found, disabling.\n"); |
1124 | DRM_DEBUG_KMS("No LVDS modes found, disabling.\n"); |
1271 | drm_connector_cleanup(connector); |
1125 | drm_connector_cleanup(connector); |
1272 | drm_encoder_cleanup(encoder); |
1126 | drm_encoder_cleanup(encoder); |
1273 | if (fixed_mode) |
1127 | if (fixed_mode) |
1274 | drm_mode_destroy(dev, fixed_mode); |
1128 | drm_mode_destroy(dev, fixed_mode); |
1275 | kfree(lvds_encoder); |
1129 | kfree(lvds_encoder); |