2 * Copyright © 2006-2007 Intel Corporation
3 * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 * Eric Anholt <eric@anholt.net>
26 * Dave Airlie <airlied@linux.ie>
27 * Jesse Barnes <jesse.barnes@intel.com>
30 #include <linux/dmi.h>
31 #include <linux/i2c.h>
36 #include "intel_drv.h"
40 #define I915_LVDS "i915_lvds"
43 * the following four scaling options are defined.
44 * #define DRM_MODE_SCALE_NON_GPU 0
45 * #define DRM_MODE_SCALE_FULLSCREEN 1
46 * #define DRM_MODE_SCALE_NO_SCALE 2
47 * #define DRM_MODE_SCALE_ASPECT 3
50 /* Private structure for the integrated LVDS support */
51 struct intel_lvds_priv
{
58 * Sets the backlight level.
60 * \param level backlight level, from 0 to intel_lvds_get_max_backlight().
62 static void intel_lvds_set_backlight(struct drm_device
*dev
, int level
)
64 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
68 reg
= BLC_PWM_CPU_CTL
;
72 blc_pwm_ctl
= I915_READ(reg
) & ~BACKLIGHT_DUTY_CYCLE_MASK
;
73 I915_WRITE(reg
, (blc_pwm_ctl
|
74 (level
<< BACKLIGHT_DUTY_CYCLE_SHIFT
)));
78 * Returns the maximum level of the backlight duty cycle field.
80 static u32
intel_lvds_get_max_backlight(struct drm_device
*dev
)
82 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
86 reg
= BLC_PWM_PCH_CTL2
;
90 return ((I915_READ(reg
) & BACKLIGHT_MODULATION_FREQ_MASK
) >>
91 BACKLIGHT_MODULATION_FREQ_SHIFT
) * 2;
95 * Sets the power state for the panel.
97 static void intel_lvds_set_power(struct drm_device
*dev
, bool on
)
99 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
100 u32 pp_status
, ctl_reg
, status_reg
;
103 ctl_reg
= PCH_PP_CONTROL
;
104 status_reg
= PCH_PP_STATUS
;
106 ctl_reg
= PP_CONTROL
;
107 status_reg
= PP_STATUS
;
111 I915_WRITE(ctl_reg
, I915_READ(ctl_reg
) |
114 pp_status
= I915_READ(status_reg
);
115 } while ((pp_status
& PP_ON
) == 0);
117 intel_lvds_set_backlight(dev
, dev_priv
->backlight_duty_cycle
);
119 intel_lvds_set_backlight(dev
, 0);
121 I915_WRITE(ctl_reg
, I915_READ(ctl_reg
) &
124 pp_status
= I915_READ(status_reg
);
125 } while (pp_status
& PP_ON
);
129 static void intel_lvds_dpms(struct drm_encoder
*encoder
, int mode
)
131 struct drm_device
*dev
= encoder
->dev
;
133 if (mode
== DRM_MODE_DPMS_ON
)
134 intel_lvds_set_power(dev
, true);
136 intel_lvds_set_power(dev
, false);
138 /* XXX: We never power down the LVDS pairs. */
141 static void intel_lvds_save(struct drm_connector
*connector
)
143 struct drm_device
*dev
= connector
->dev
;
144 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
145 u32 pp_on_reg
, pp_off_reg
, pp_ctl_reg
, pp_div_reg
;
149 pp_on_reg
= PCH_PP_ON_DELAYS
;
150 pp_off_reg
= PCH_PP_OFF_DELAYS
;
151 pp_ctl_reg
= PCH_PP_CONTROL
;
152 pp_div_reg
= PCH_PP_DIVISOR
;
153 pwm_ctl_reg
= BLC_PWM_CPU_CTL
;
155 pp_on_reg
= PP_ON_DELAYS
;
156 pp_off_reg
= PP_OFF_DELAYS
;
157 pp_ctl_reg
= PP_CONTROL
;
158 pp_div_reg
= PP_DIVISOR
;
159 pwm_ctl_reg
= BLC_PWM_CTL
;
162 dev_priv
->savePP_ON
= I915_READ(pp_on_reg
);
163 dev_priv
->savePP_OFF
= I915_READ(pp_off_reg
);
164 dev_priv
->savePP_CONTROL
= I915_READ(pp_ctl_reg
);
165 dev_priv
->savePP_DIVISOR
= I915_READ(pp_div_reg
);
166 dev_priv
->saveBLC_PWM_CTL
= I915_READ(pwm_ctl_reg
);
167 dev_priv
->backlight_duty_cycle
= (dev_priv
->saveBLC_PWM_CTL
&
168 BACKLIGHT_DUTY_CYCLE_MASK
);
171 * If the light is off at server startup, just make it full brightness
173 if (dev_priv
->backlight_duty_cycle
== 0)
174 dev_priv
->backlight_duty_cycle
=
175 intel_lvds_get_max_backlight(dev
);
178 static void intel_lvds_restore(struct drm_connector
*connector
)
180 struct drm_device
*dev
= connector
->dev
;
181 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
182 u32 pp_on_reg
, pp_off_reg
, pp_ctl_reg
, pp_div_reg
;
186 pp_on_reg
= PCH_PP_ON_DELAYS
;
187 pp_off_reg
= PCH_PP_OFF_DELAYS
;
188 pp_ctl_reg
= PCH_PP_CONTROL
;
189 pp_div_reg
= PCH_PP_DIVISOR
;
190 pwm_ctl_reg
= BLC_PWM_CPU_CTL
;
192 pp_on_reg
= PP_ON_DELAYS
;
193 pp_off_reg
= PP_OFF_DELAYS
;
194 pp_ctl_reg
= PP_CONTROL
;
195 pp_div_reg
= PP_DIVISOR
;
196 pwm_ctl_reg
= BLC_PWM_CTL
;
199 I915_WRITE(pwm_ctl_reg
, dev_priv
->saveBLC_PWM_CTL
);
200 I915_WRITE(pp_on_reg
, dev_priv
->savePP_ON
);
201 I915_WRITE(pp_off_reg
, dev_priv
->savePP_OFF
);
202 I915_WRITE(pp_div_reg
, dev_priv
->savePP_DIVISOR
);
203 I915_WRITE(pp_ctl_reg
, dev_priv
->savePP_CONTROL
);
204 if (dev_priv
->savePP_CONTROL
& POWER_TARGET_ON
)
205 intel_lvds_set_power(dev
, true);
207 intel_lvds_set_power(dev
, false);
210 static int intel_lvds_mode_valid(struct drm_connector
*connector
,
211 struct drm_display_mode
*mode
)
213 struct drm_device
*dev
= connector
->dev
;
214 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
215 struct drm_display_mode
*fixed_mode
= dev_priv
->panel_fixed_mode
;
218 if (mode
->hdisplay
> fixed_mode
->hdisplay
)
220 if (mode
->vdisplay
> fixed_mode
->vdisplay
)
227 static bool intel_lvds_mode_fixup(struct drm_encoder
*encoder
,
228 struct drm_display_mode
*mode
,
229 struct drm_display_mode
*adjusted_mode
)
232 * float point operation is not supported . So the PANEL_RATIO_FACTOR
233 * is defined, which can avoid the float point computation when
234 * calculating the panel ratio.
236 #define PANEL_RATIO_FACTOR 8192
237 struct drm_device
*dev
= encoder
->dev
;
238 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
239 struct intel_crtc
*intel_crtc
= to_intel_crtc(encoder
->crtc
);
240 struct drm_encoder
*tmp_encoder
;
241 struct intel_output
*intel_output
= enc_to_intel_output(encoder
);
242 struct intel_lvds_priv
*lvds_priv
= intel_output
->dev_priv
;
243 u32 pfit_control
= 0, pfit_pgm_ratios
= 0;
244 int left_border
= 0, right_border
= 0, top_border
= 0;
245 int bottom_border
= 0;
247 int panel_ratio
, desired_ratio
, vert_scale
, horiz_scale
;
248 int horiz_ratio
, vert_ratio
;
249 u32 hsync_width
, vsync_width
;
250 u32 hblank_width
, vblank_width
;
251 u32 hsync_pos
, vsync_pos
;
253 /* Should never happen!! */
254 if (!IS_I965G(dev
) && intel_crtc
->pipe
== 0) {
255 printk(KERN_ERR
"Can't support LVDS on pipe A\n");
259 /* Should never happen!! */
260 list_for_each_entry(tmp_encoder
, &dev
->mode_config
.encoder_list
, head
) {
261 if (tmp_encoder
!= encoder
&& tmp_encoder
->crtc
== encoder
->crtc
) {
262 printk(KERN_ERR
"Can't enable LVDS and another "
263 "encoder on the same pipe\n");
267 /* If we don't have a panel mode, there is nothing we can do */
268 if (dev_priv
->panel_fixed_mode
== NULL
)
271 * If we have timings from the BIOS for the panel, put them in
272 * to the adjusted mode. The CRTC will be set up for this mode,
273 * with the panel scaling set up to source from the H/VDisplay
274 * of the original mode.
276 if (dev_priv
->panel_fixed_mode
!= NULL
) {
277 adjusted_mode
->hdisplay
= dev_priv
->panel_fixed_mode
->hdisplay
;
278 adjusted_mode
->hsync_start
=
279 dev_priv
->panel_fixed_mode
->hsync_start
;
280 adjusted_mode
->hsync_end
=
281 dev_priv
->panel_fixed_mode
->hsync_end
;
282 adjusted_mode
->htotal
= dev_priv
->panel_fixed_mode
->htotal
;
283 adjusted_mode
->vdisplay
= dev_priv
->panel_fixed_mode
->vdisplay
;
284 adjusted_mode
->vsync_start
=
285 dev_priv
->panel_fixed_mode
->vsync_start
;
286 adjusted_mode
->vsync_end
=
287 dev_priv
->panel_fixed_mode
->vsync_end
;
288 adjusted_mode
->vtotal
= dev_priv
->panel_fixed_mode
->vtotal
;
289 adjusted_mode
->clock
= dev_priv
->panel_fixed_mode
->clock
;
290 drm_mode_set_crtcinfo(adjusted_mode
, CRTC_INTERLACE_HALVE_V
);
293 /* Make sure pre-965s set dither correctly */
294 if (!IS_I965G(dev
)) {
295 if (dev_priv
->panel_wants_dither
|| dev_priv
->lvds_dither
)
296 pfit_control
|= PANEL_8TO6_DITHER_ENABLE
;
299 /* Native modes don't need fitting */
300 if (adjusted_mode
->hdisplay
== mode
->hdisplay
&&
301 adjusted_mode
->vdisplay
== mode
->vdisplay
) {
307 /* 965+ wants fuzzy fitting */
309 pfit_control
|= (intel_crtc
->pipe
<< PFIT_PIPE_SHIFT
) |
312 hsync_width
= adjusted_mode
->crtc_hsync_end
-
313 adjusted_mode
->crtc_hsync_start
;
314 vsync_width
= adjusted_mode
->crtc_vsync_end
-
315 adjusted_mode
->crtc_vsync_start
;
316 hblank_width
= adjusted_mode
->crtc_hblank_end
-
317 adjusted_mode
->crtc_hblank_start
;
318 vblank_width
= adjusted_mode
->crtc_vblank_end
-
319 adjusted_mode
->crtc_vblank_start
;
321 * Deal with panel fitting options. Figure out how to stretch the
322 * image based on its aspect ratio & the current panel fitting mode.
324 panel_ratio
= adjusted_mode
->hdisplay
* PANEL_RATIO_FACTOR
/
325 adjusted_mode
->vdisplay
;
326 desired_ratio
= mode
->hdisplay
* PANEL_RATIO_FACTOR
/
329 * Enable automatic panel scaling for non-native modes so that they fill
330 * the screen. Should be enabled before the pipe is enabled, according
331 * to register description and PRM.
332 * Change the value here to see the borders for debugging
334 I915_WRITE(BCLRPAT_A
, 0);
335 I915_WRITE(BCLRPAT_B
, 0);
337 switch (lvds_priv
->fitting_mode
) {
338 case DRM_MODE_SCALE_NO_SCALE
:
340 * For centered modes, we have to calculate border widths &
341 * heights and modify the values programmed into the CRTC.
343 left_border
= (adjusted_mode
->hdisplay
- mode
->hdisplay
) / 2;
344 right_border
= left_border
;
345 if (mode
->hdisplay
& 1)
347 top_border
= (adjusted_mode
->vdisplay
- mode
->vdisplay
) / 2;
348 bottom_border
= top_border
;
349 if (mode
->vdisplay
& 1)
351 /* Set active & border values */
352 adjusted_mode
->crtc_hdisplay
= mode
->hdisplay
;
353 /* Keep the boder be even */
354 if (right_border
& 1)
356 /* use the border directly instead of border minuse one */
357 adjusted_mode
->crtc_hblank_start
= mode
->hdisplay
+
359 /* keep the blank width constant */
360 adjusted_mode
->crtc_hblank_end
=
361 adjusted_mode
->crtc_hblank_start
+ hblank_width
;
362 /* get the hsync pos relative to hblank start */
363 hsync_pos
= (hblank_width
- hsync_width
) / 2;
364 /* keep the hsync pos be even */
367 adjusted_mode
->crtc_hsync_start
=
368 adjusted_mode
->crtc_hblank_start
+ hsync_pos
;
369 /* keep the hsync width constant */
370 adjusted_mode
->crtc_hsync_end
=
371 adjusted_mode
->crtc_hsync_start
+ hsync_width
;
372 adjusted_mode
->crtc_vdisplay
= mode
->vdisplay
;
373 /* use the border instead of border minus one */
374 adjusted_mode
->crtc_vblank_start
= mode
->vdisplay
+
376 /* keep the vblank width constant */
377 adjusted_mode
->crtc_vblank_end
=
378 adjusted_mode
->crtc_vblank_start
+ vblank_width
;
379 /* get the vsync start postion relative to vblank start */
380 vsync_pos
= (vblank_width
- vsync_width
) / 2;
381 adjusted_mode
->crtc_vsync_start
=
382 adjusted_mode
->crtc_vblank_start
+ vsync_pos
;
383 /* keep the vsync width constant */
384 adjusted_mode
->crtc_vsync_end
=
385 adjusted_mode
->crtc_vblank_start
+ vsync_width
;
388 case DRM_MODE_SCALE_ASPECT
:
389 /* Scale but preserve the spect ratio */
390 pfit_control
|= PFIT_ENABLE
;
392 /* 965+ is easy, it does everything in hw */
393 if (panel_ratio
> desired_ratio
)
394 pfit_control
|= PFIT_SCALING_PILLAR
;
395 else if (panel_ratio
< desired_ratio
)
396 pfit_control
|= PFIT_SCALING_LETTER
;
398 pfit_control
|= PFIT_SCALING_AUTO
;
401 * For earlier chips we have to calculate the scaling
402 * ratio by hand and program it into the
403 * PFIT_PGM_RATIO register
405 u32 horiz_bits
, vert_bits
, bits
= 12;
406 horiz_ratio
= mode
->hdisplay
* PANEL_RATIO_FACTOR
/
407 adjusted_mode
->hdisplay
;
408 vert_ratio
= mode
->vdisplay
* PANEL_RATIO_FACTOR
/
409 adjusted_mode
->vdisplay
;
410 horiz_scale
= adjusted_mode
->hdisplay
*
411 PANEL_RATIO_FACTOR
/ mode
->hdisplay
;
412 vert_scale
= adjusted_mode
->vdisplay
*
413 PANEL_RATIO_FACTOR
/ mode
->vdisplay
;
415 /* retain aspect ratio */
416 if (panel_ratio
> desired_ratio
) { /* Pillar */
418 scaled_width
= mode
->hdisplay
* vert_scale
/
420 horiz_ratio
= vert_ratio
;
421 pfit_control
|= (VERT_AUTO_SCALE
|
422 VERT_INTERP_BILINEAR
|
423 HORIZ_INTERP_BILINEAR
);
424 /* Pillar will have left/right borders */
425 left_border
= (adjusted_mode
->hdisplay
-
427 right_border
= left_border
;
428 if (mode
->hdisplay
& 1) /* odd resolutions */
430 /* keep the border be even */
431 if (right_border
& 1)
433 adjusted_mode
->crtc_hdisplay
= scaled_width
;
434 /* use border instead of border minus one */
435 adjusted_mode
->crtc_hblank_start
=
436 scaled_width
+ right_border
;
437 /* keep the hblank width constant */
438 adjusted_mode
->crtc_hblank_end
=
439 adjusted_mode
->crtc_hblank_start
+
442 * get the hsync start pos relative to
445 hsync_pos
= (hblank_width
- hsync_width
) / 2;
446 /* keep the hsync_pos be even */
449 adjusted_mode
->crtc_hsync_start
=
450 adjusted_mode
->crtc_hblank_start
+
452 /* keept hsync width constant */
453 adjusted_mode
->crtc_hsync_end
=
454 adjusted_mode
->crtc_hsync_start
+
457 } else if (panel_ratio
< desired_ratio
) { /* letter */
458 u32 scaled_height
= mode
->vdisplay
*
459 horiz_scale
/ PANEL_RATIO_FACTOR
;
460 vert_ratio
= horiz_ratio
;
461 pfit_control
|= (HORIZ_AUTO_SCALE
|
462 VERT_INTERP_BILINEAR
|
463 HORIZ_INTERP_BILINEAR
);
464 /* Letterbox will have top/bottom border */
465 top_border
= (adjusted_mode
->vdisplay
-
467 bottom_border
= top_border
;
468 if (mode
->vdisplay
& 1)
470 adjusted_mode
->crtc_vdisplay
= scaled_height
;
471 /* use border instead of border minus one */
472 adjusted_mode
->crtc_vblank_start
=
473 scaled_height
+ bottom_border
;
474 /* keep the vblank width constant */
475 adjusted_mode
->crtc_vblank_end
=
476 adjusted_mode
->crtc_vblank_start
+
479 * get the vsync start pos relative to
482 vsync_pos
= (vblank_width
- vsync_width
) / 2;
483 adjusted_mode
->crtc_vsync_start
=
484 adjusted_mode
->crtc_vblank_start
+
486 /* keep the vsync width constant */
487 adjusted_mode
->crtc_vsync_end
=
488 adjusted_mode
->crtc_vsync_start
+
492 /* Aspects match, Let hw scale both directions */
493 pfit_control
|= (VERT_AUTO_SCALE
|
495 VERT_INTERP_BILINEAR
|
496 HORIZ_INTERP_BILINEAR
);
498 horiz_bits
= (1 << bits
) * horiz_ratio
/
500 vert_bits
= (1 << bits
) * vert_ratio
/
503 ((vert_bits
<< PFIT_VERT_SCALE_SHIFT
) &
504 PFIT_VERT_SCALE_MASK
) |
505 ((horiz_bits
<< PFIT_HORIZ_SCALE_SHIFT
) &
506 PFIT_HORIZ_SCALE_MASK
);
510 case DRM_MODE_SCALE_FULLSCREEN
:
512 * Full scaling, even if it changes the aspect ratio.
513 * Fortunately this is all done for us in hw.
515 pfit_control
|= PFIT_ENABLE
;
517 pfit_control
|= PFIT_SCALING_AUTO
;
519 pfit_control
|= (VERT_AUTO_SCALE
| HORIZ_AUTO_SCALE
|
520 VERT_INTERP_BILINEAR
|
521 HORIZ_INTERP_BILINEAR
);
528 lvds_priv
->pfit_control
= pfit_control
;
529 lvds_priv
->pfit_pgm_ratios
= pfit_pgm_ratios
;
531 * XXX: It would be nice to support lower refresh rates on the
532 * panels to reduce power consumption, and perhaps match the
533 * user's requested refresh rate.
539 static void intel_lvds_prepare(struct drm_encoder
*encoder
)
541 struct drm_device
*dev
= encoder
->dev
;
542 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
546 reg
= BLC_PWM_CPU_CTL
;
550 dev_priv
->saveBLC_PWM_CTL
= I915_READ(reg
);
551 dev_priv
->backlight_duty_cycle
= (dev_priv
->saveBLC_PWM_CTL
&
552 BACKLIGHT_DUTY_CYCLE_MASK
);
554 intel_lvds_set_power(dev
, false);
557 static void intel_lvds_commit( struct drm_encoder
*encoder
)
559 struct drm_device
*dev
= encoder
->dev
;
560 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
562 if (dev_priv
->backlight_duty_cycle
== 0)
563 dev_priv
->backlight_duty_cycle
=
564 intel_lvds_get_max_backlight(dev
);
566 intel_lvds_set_power(dev
, true);
569 static void intel_lvds_mode_set(struct drm_encoder
*encoder
,
570 struct drm_display_mode
*mode
,
571 struct drm_display_mode
*adjusted_mode
)
573 struct drm_device
*dev
= encoder
->dev
;
574 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
575 struct intel_output
*intel_output
= enc_to_intel_output(encoder
);
576 struct intel_lvds_priv
*lvds_priv
= intel_output
->dev_priv
;
579 * The LVDS pin pair will already have been turned on in the
580 * intel_crtc_mode_set since it has a large impact on the DPLL
584 /* No panel fitting yet, fixme */
589 * Enable automatic panel scaling so that non-native modes fill the
590 * screen. Should be enabled before the pipe is enabled, according to
591 * register description and PRM.
593 I915_WRITE(PFIT_PGM_RATIOS
, lvds_priv
->pfit_pgm_ratios
);
594 I915_WRITE(PFIT_CONTROL
, lvds_priv
->pfit_control
);
598 * Detect the LVDS connection.
600 * This always returns CONNECTOR_STATUS_CONNECTED. This connector should only have
601 * been set up if the LVDS was actually connected anyway.
603 static enum drm_connector_status
intel_lvds_detect(struct drm_connector
*connector
)
605 return connector_status_connected
;
609 * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
611 static int intel_lvds_get_modes(struct drm_connector
*connector
)
613 struct drm_device
*dev
= connector
->dev
;
614 struct intel_output
*intel_output
= to_intel_output(connector
);
615 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
618 ret
= intel_ddc_get_modes(intel_output
);
623 /* Didn't get an EDID, so
624 * Set wide sync ranges so we get all modes
625 * handed to valid_mode for checking
627 connector
->display_info
.min_vfreq
= 0;
628 connector
->display_info
.max_vfreq
= 200;
629 connector
->display_info
.min_hfreq
= 0;
630 connector
->display_info
.max_hfreq
= 200;
632 if (dev_priv
->panel_fixed_mode
!= NULL
) {
633 struct drm_display_mode
*mode
;
635 mode
= drm_mode_duplicate(dev
, dev_priv
->panel_fixed_mode
);
636 drm_mode_probed_add(connector
, mode
);
645 * intel_lvds_destroy - unregister and free LVDS structures
646 * @connector: connector to free
648 * Unregister the DDC bus for this connector then free the driver private
651 static void intel_lvds_destroy(struct drm_connector
*connector
)
653 struct intel_output
*intel_output
= to_intel_output(connector
);
655 if (intel_output
->ddc_bus
)
656 intel_i2c_destroy(intel_output
->ddc_bus
);
657 drm_sysfs_connector_remove(connector
);
658 drm_connector_cleanup(connector
);
662 static int intel_lvds_set_property(struct drm_connector
*connector
,
663 struct drm_property
*property
,
666 struct drm_device
*dev
= connector
->dev
;
667 struct intel_output
*intel_output
=
668 to_intel_output(connector
);
670 if (property
== dev
->mode_config
.scaling_mode_property
&&
671 connector
->encoder
) {
672 struct drm_crtc
*crtc
= connector
->encoder
->crtc
;
673 struct intel_lvds_priv
*lvds_priv
= intel_output
->dev_priv
;
674 if (value
== DRM_MODE_SCALE_NON_GPU
) {
675 DRM_DEBUG_KMS(I915_LVDS
,
676 "non_GPU property is unsupported\n");
679 if (lvds_priv
->fitting_mode
== value
) {
680 /* the LVDS scaling property is not changed */
683 lvds_priv
->fitting_mode
= value
;
684 if (crtc
&& crtc
->enabled
) {
686 * If the CRTC is enabled, the display will be changed
687 * according to the new panel fitting mode.
689 drm_crtc_helper_set_mode(crtc
, &crtc
->mode
,
690 crtc
->x
, crtc
->y
, crtc
->fb
);
697 static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs
= {
698 .dpms
= intel_lvds_dpms
,
699 .mode_fixup
= intel_lvds_mode_fixup
,
700 .prepare
= intel_lvds_prepare
,
701 .mode_set
= intel_lvds_mode_set
,
702 .commit
= intel_lvds_commit
,
705 static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs
= {
706 .get_modes
= intel_lvds_get_modes
,
707 .mode_valid
= intel_lvds_mode_valid
,
708 .best_encoder
= intel_best_encoder
,
711 static const struct drm_connector_funcs intel_lvds_connector_funcs
= {
712 .dpms
= drm_helper_connector_dpms
,
713 .save
= intel_lvds_save
,
714 .restore
= intel_lvds_restore
,
715 .detect
= intel_lvds_detect
,
716 .fill_modes
= drm_helper_probe_single_connector_modes
,
717 .set_property
= intel_lvds_set_property
,
718 .destroy
= intel_lvds_destroy
,
722 static void intel_lvds_enc_destroy(struct drm_encoder
*encoder
)
724 drm_encoder_cleanup(encoder
);
727 static const struct drm_encoder_funcs intel_lvds_enc_funcs
= {
728 .destroy
= intel_lvds_enc_destroy
,
731 static int __init
intel_no_lvds_dmi_callback(const struct dmi_system_id
*id
)
733 DRM_DEBUG_KMS(I915_LVDS
,
734 "Skipping LVDS initialization for %s\n", id
->ident
);
738 /* These systems claim to have LVDS, but really don't */
739 static const struct dmi_system_id intel_no_lvds
[] = {
741 .callback
= intel_no_lvds_dmi_callback
,
742 .ident
= "Apple Mac Mini (Core series)",
744 DMI_MATCH(DMI_SYS_VENDOR
, "Apple"),
745 DMI_MATCH(DMI_PRODUCT_NAME
, "Macmini1,1"),
749 .callback
= intel_no_lvds_dmi_callback
,
750 .ident
= "Apple Mac Mini (Core 2 series)",
752 DMI_MATCH(DMI_SYS_VENDOR
, "Apple"),
753 DMI_MATCH(DMI_PRODUCT_NAME
, "Macmini2,1"),
757 .callback
= intel_no_lvds_dmi_callback
,
758 .ident
= "MSI IM-945GSE-A",
760 DMI_MATCH(DMI_SYS_VENDOR
, "MSI"),
761 DMI_MATCH(DMI_PRODUCT_NAME
, "A9830IMS"),
765 .callback
= intel_no_lvds_dmi_callback
,
766 .ident
= "Dell Studio Hybrid",
768 DMI_MATCH(DMI_SYS_VENDOR
, "Dell Inc."),
769 DMI_MATCH(DMI_PRODUCT_NAME
, "Studio Hybrid 140g"),
773 .callback
= intel_no_lvds_dmi_callback
,
774 .ident
= "AOpen Mini PC",
776 DMI_MATCH(DMI_SYS_VENDOR
, "AOpen"),
777 DMI_MATCH(DMI_PRODUCT_NAME
, "i965GMx-IF"),
781 .callback
= intel_no_lvds_dmi_callback
,
782 .ident
= "Aopen i945GTt-VFA",
784 DMI_MATCH(DMI_PRODUCT_VERSION
, "AO00001JW"),
788 { } /* terminating entry */
792 * intel_lvds_init - setup LVDS connectors on this device
795 * Create the connector, register the LVDS DDC bus, and try to figure out what
796 * modes we can display on the LVDS panel (if present).
798 void intel_lvds_init(struct drm_device
*dev
)
800 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
801 struct intel_output
*intel_output
;
802 struct drm_connector
*connector
;
803 struct drm_encoder
*encoder
;
804 struct drm_display_mode
*scan
; /* *modes, *bios_mode; */
805 struct drm_crtc
*crtc
;
806 struct intel_lvds_priv
*lvds_priv
;
808 int pipe
, gpio
= GPIOC
;
810 /* Skip init on machines we know falsely report LVDS */
811 if (dmi_check_system(intel_no_lvds
))
815 if ((I915_READ(PCH_LVDS
) & LVDS_DETECTED
) == 0)
820 intel_output
= kzalloc(sizeof(struct intel_output
) +
821 sizeof(struct intel_lvds_priv
), GFP_KERNEL
);
826 connector
= &intel_output
->base
;
827 encoder
= &intel_output
->enc
;
828 drm_connector_init(dev
, &intel_output
->base
, &intel_lvds_connector_funcs
,
829 DRM_MODE_CONNECTOR_LVDS
);
831 drm_encoder_init(dev
, &intel_output
->enc
, &intel_lvds_enc_funcs
,
832 DRM_MODE_ENCODER_LVDS
);
834 drm_mode_connector_attach_encoder(&intel_output
->base
, &intel_output
->enc
);
835 intel_output
->type
= INTEL_OUTPUT_LVDS
;
837 drm_encoder_helper_add(encoder
, &intel_lvds_helper_funcs
);
838 drm_connector_helper_add(connector
, &intel_lvds_connector_helper_funcs
);
839 connector
->display_info
.subpixel_order
= SubPixelHorizontalRGB
;
840 connector
->interlace_allowed
= false;
841 connector
->doublescan_allowed
= false;
843 lvds_priv
= (struct intel_lvds_priv
*)(intel_output
+ 1);
844 intel_output
->dev_priv
= lvds_priv
;
845 /* create the scaling mode property */
846 drm_mode_create_scaling_mode_property(dev
);
848 * the initial panel fitting mode will be FULL_SCREEN.
851 drm_connector_attach_property(&intel_output
->base
,
852 dev
->mode_config
.scaling_mode_property
,
853 DRM_MODE_SCALE_FULLSCREEN
);
854 lvds_priv
->fitting_mode
= DRM_MODE_SCALE_FULLSCREEN
;
857 * 1) check for EDID on DDC
858 * 2) check for VBT data
859 * 3) check to see if LVDS is already on
860 * if none of the above, no panel
861 * 4) make sure lid is open
862 * if closed, act like it's not there for now
865 /* Set up the DDC bus. */
866 intel_output
->ddc_bus
= intel_i2c_create(dev
, gpio
, "LVDSDDC_C");
867 if (!intel_output
->ddc_bus
) {
868 dev_printk(KERN_ERR
, &dev
->pdev
->dev
, "DDC bus registration "
874 * Attempt to get the fixed panel mode from DDC. Assume that the
875 * preferred mode is the right one.
877 intel_ddc_get_modes(intel_output
);
879 list_for_each_entry(scan
, &connector
->probed_modes
, head
) {
880 mutex_lock(&dev
->mode_config
.mutex
);
881 if (scan
->type
& DRM_MODE_TYPE_PREFERRED
) {
882 dev_priv
->panel_fixed_mode
=
883 drm_mode_duplicate(dev
, scan
);
884 mutex_unlock(&dev
->mode_config
.mutex
);
887 mutex_unlock(&dev
->mode_config
.mutex
);
890 /* Failed to get EDID, what about VBT? */
891 if (dev_priv
->lfp_lvds_vbt_mode
) {
892 mutex_lock(&dev
->mode_config
.mutex
);
893 dev_priv
->panel_fixed_mode
=
894 drm_mode_duplicate(dev
, dev_priv
->lfp_lvds_vbt_mode
);
895 mutex_unlock(&dev
->mode_config
.mutex
);
896 if (dev_priv
->panel_fixed_mode
) {
897 dev_priv
->panel_fixed_mode
->type
|=
898 DRM_MODE_TYPE_PREFERRED
;
904 * If we didn't get EDID, try checking if the panel is already turned
905 * on. If so, assume that whatever is currently programmed is the
909 /* IGDNG: FIXME if still fail, not try pipe mode now */
913 lvds
= I915_READ(LVDS
);
914 pipe
= (lvds
& LVDS_PIPEB_SELECT
) ? 1 : 0;
915 crtc
= intel_get_crtc_from_pipe(dev
, pipe
);
917 if (crtc
&& (lvds
& LVDS_PORT_EN
)) {
918 dev_priv
->panel_fixed_mode
= intel_crtc_mode_get(dev
, crtc
);
919 if (dev_priv
->panel_fixed_mode
) {
920 dev_priv
->panel_fixed_mode
->type
|=
921 DRM_MODE_TYPE_PREFERRED
;
926 /* If we still don't have a mode after all that, give up. */
927 if (!dev_priv
->panel_fixed_mode
)
933 /* make sure PWM is enabled */
934 pwm
= I915_READ(BLC_PWM_CPU_CTL2
);
935 pwm
|= (PWM_ENABLE
| PWM_PIPE_B
);
936 I915_WRITE(BLC_PWM_CPU_CTL2
, pwm
);
938 pwm
= I915_READ(BLC_PWM_PCH_CTL1
);
939 pwm
|= PWM_PCH_ENABLE
;
940 I915_WRITE(BLC_PWM_PCH_CTL1
, pwm
);
942 drm_sysfs_connector_add(connector
);
946 DRM_DEBUG_KMS(I915_LVDS
, "No LVDS modes found, disabling.\n");
947 if (intel_output
->ddc_bus
)
948 intel_i2c_destroy(intel_output
->ddc_bus
);
949 drm_connector_cleanup(connector
);