aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_lvds.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-06-12 21:09:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-12 21:09:18 -0400
commit6b702462cbe5b6f372966a53f4465d745d86b65c (patch)
tree19a8d090b284bb804e8a2ffa38fa51b58118db6a /drivers/gpu/drm/i915/intel_lvds.c
parent947ec0b0c1e7e80eef4fe64f7763a06d0cf04d2e (diff)
parent3c24475c1e4e8d10e50df161d8c4f1d382997a7c (diff)
Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (50 commits) drm: include kernel list header file in hashtab header drm: Export hash table functionality. drm: Split out the mm declarations in a separate header. Add atomic operations. drm/radeon: add support for RV790. drm/radeon: add rv740 drm support. drm_calloc_large: check right size, check integer overflow, use GFP_ZERO drm: Eliminate magic I2C frobbing when reading EDID drm/i915: duplicate desired mode for use by fbcon. drm/via: vfree() no need checking before calling it drm: Replace DRM_DEBUG with DRM_DEBUG_DRIVER in i915 driver drm: Replace DRM_DEBUG with DRM_DEBUG_MODE in drm_mode drm/i915: Replace DRM_DEBUG with DRM_DEBUG_KMS in intel_sdvo drm/i915: replace DRM_DEBUG with DRM_DEBUG_KMS in intel_lvds drm: add separate drm debugging levels radeon: remove _DRM_DRIVER from the preadded sarea map drm: don't associate _DRM_DRIVER maps with a master drm: simplify kcalloc() call to kzalloc(). intelfb: fix spelling of "CLOCK" drm: fix LOCK_TEST_WITH_RETURN macro drm/i915: Hook connector to encoder during load detection (fixes tv/vga detect) ...
Diffstat (limited to 'drivers/gpu/drm/i915/intel_lvds.c')
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c151
1 files changed, 125 insertions, 26 deletions
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 53cccfa58b95..f073ed8432e8 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -37,6 +37,8 @@
37#include "i915_drm.h" 37#include "i915_drm.h"
38#include "i915_drv.h" 38#include "i915_drv.h"
39 39
40#define I915_LVDS "i915_lvds"
41
40/** 42/**
41 * Sets the backlight level. 43 * Sets the backlight level.
42 * 44 *
@@ -45,10 +47,15 @@
45static void intel_lvds_set_backlight(struct drm_device *dev, int level) 47static void intel_lvds_set_backlight(struct drm_device *dev, int level)
46{ 48{
47 struct drm_i915_private *dev_priv = dev->dev_private; 49 struct drm_i915_private *dev_priv = dev->dev_private;
48 u32 blc_pwm_ctl; 50 u32 blc_pwm_ctl, reg;
51
52 if (IS_IGDNG(dev))
53 reg = BLC_PWM_CPU_CTL;
54 else
55 reg = BLC_PWM_CTL;
49 56
50 blc_pwm_ctl = I915_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; 57 blc_pwm_ctl = I915_READ(reg) & ~BACKLIGHT_DUTY_CYCLE_MASK;
51 I915_WRITE(BLC_PWM_CTL, (blc_pwm_ctl | 58 I915_WRITE(reg, (blc_pwm_ctl |
52 (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); 59 (level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
53} 60}
54 61
@@ -58,8 +65,14 @@ static void intel_lvds_set_backlight(struct drm_device *dev, int level)
58static u32 intel_lvds_get_max_backlight(struct drm_device *dev) 65static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
59{ 66{
60 struct drm_i915_private *dev_priv = dev->dev_private; 67 struct drm_i915_private *dev_priv = dev->dev_private;
68 u32 reg;
69
70 if (IS_IGDNG(dev))
71 reg = BLC_PWM_PCH_CTL2;
72 else
73 reg = BLC_PWM_CTL;
61 74
62 return ((I915_READ(BLC_PWM_CTL) & BACKLIGHT_MODULATION_FREQ_MASK) >> 75 return ((I915_READ(reg) & BACKLIGHT_MODULATION_FREQ_MASK) >>
63 BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; 76 BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
64} 77}
65 78
@@ -69,23 +82,31 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
69static void intel_lvds_set_power(struct drm_device *dev, bool on) 82static void intel_lvds_set_power(struct drm_device *dev, bool on)
70{ 83{
71 struct drm_i915_private *dev_priv = dev->dev_private; 84 struct drm_i915_private *dev_priv = dev->dev_private;
72 u32 pp_status; 85 u32 pp_status, ctl_reg, status_reg;
86
87 if (IS_IGDNG(dev)) {
88 ctl_reg = PCH_PP_CONTROL;
89 status_reg = PCH_PP_STATUS;
90 } else {
91 ctl_reg = PP_CONTROL;
92 status_reg = PP_STATUS;
93 }
73 94
74 if (on) { 95 if (on) {
75 I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | 96 I915_WRITE(ctl_reg, I915_READ(ctl_reg) |
76 POWER_TARGET_ON); 97 POWER_TARGET_ON);
77 do { 98 do {
78 pp_status = I915_READ(PP_STATUS); 99 pp_status = I915_READ(status_reg);
79 } while ((pp_status & PP_ON) == 0); 100 } while ((pp_status & PP_ON) == 0);
80 101
81 intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle); 102 intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle);
82 } else { 103 } else {
83 intel_lvds_set_backlight(dev, 0); 104 intel_lvds_set_backlight(dev, 0);
84 105
85 I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 106 I915_WRITE(ctl_reg, I915_READ(ctl_reg) &
86 ~POWER_TARGET_ON); 107 ~POWER_TARGET_ON);
87 do { 108 do {
88 pp_status = I915_READ(PP_STATUS); 109 pp_status = I915_READ(status_reg);
89 } while (pp_status & PP_ON); 110 } while (pp_status & PP_ON);
90 } 111 }
91} 112}
@@ -106,12 +127,28 @@ static void intel_lvds_save(struct drm_connector *connector)
106{ 127{
107 struct drm_device *dev = connector->dev; 128 struct drm_device *dev = connector->dev;
108 struct drm_i915_private *dev_priv = dev->dev_private; 129 struct drm_i915_private *dev_priv = dev->dev_private;
130 u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
131 u32 pwm_ctl_reg;
132
133 if (IS_IGDNG(dev)) {
134 pp_on_reg = PCH_PP_ON_DELAYS;
135 pp_off_reg = PCH_PP_OFF_DELAYS;
136 pp_ctl_reg = PCH_PP_CONTROL;
137 pp_div_reg = PCH_PP_DIVISOR;
138 pwm_ctl_reg = BLC_PWM_CPU_CTL;
139 } else {
140 pp_on_reg = PP_ON_DELAYS;
141 pp_off_reg = PP_OFF_DELAYS;
142 pp_ctl_reg = PP_CONTROL;
143 pp_div_reg = PP_DIVISOR;
144 pwm_ctl_reg = BLC_PWM_CTL;
145 }
109 146
110 dev_priv->savePP_ON = I915_READ(PP_ON_DELAYS); 147 dev_priv->savePP_ON = I915_READ(pp_on_reg);
111 dev_priv->savePP_OFF = I915_READ(PP_OFF_DELAYS); 148 dev_priv->savePP_OFF = I915_READ(pp_off_reg);
112 dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL); 149 dev_priv->savePP_CONTROL = I915_READ(pp_ctl_reg);
113 dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); 150 dev_priv->savePP_DIVISOR = I915_READ(pp_div_reg);
114 dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); 151 dev_priv->saveBLC_PWM_CTL = I915_READ(pwm_ctl_reg);
115 dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & 152 dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
116 BACKLIGHT_DUTY_CYCLE_MASK); 153 BACKLIGHT_DUTY_CYCLE_MASK);
117 154
@@ -127,12 +164,28 @@ static void intel_lvds_restore(struct drm_connector *connector)
127{ 164{
128 struct drm_device *dev = connector->dev; 165 struct drm_device *dev = connector->dev;
129 struct drm_i915_private *dev_priv = dev->dev_private; 166 struct drm_i915_private *dev_priv = dev->dev_private;
167 u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
168 u32 pwm_ctl_reg;
169
170 if (IS_IGDNG(dev)) {
171 pp_on_reg = PCH_PP_ON_DELAYS;
172 pp_off_reg = PCH_PP_OFF_DELAYS;
173 pp_ctl_reg = PCH_PP_CONTROL;
174 pp_div_reg = PCH_PP_DIVISOR;
175 pwm_ctl_reg = BLC_PWM_CPU_CTL;
176 } else {
177 pp_on_reg = PP_ON_DELAYS;
178 pp_off_reg = PP_OFF_DELAYS;
179 pp_ctl_reg = PP_CONTROL;
180 pp_div_reg = PP_DIVISOR;
181 pwm_ctl_reg = BLC_PWM_CTL;
182 }
130 183
131 I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL); 184 I915_WRITE(pwm_ctl_reg, dev_priv->saveBLC_PWM_CTL);
132 I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON); 185 I915_WRITE(pp_on_reg, dev_priv->savePP_ON);
133 I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF); 186 I915_WRITE(pp_off_reg, dev_priv->savePP_OFF);
134 I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); 187 I915_WRITE(pp_div_reg, dev_priv->savePP_DIVISOR);
135 I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); 188 I915_WRITE(pp_ctl_reg, dev_priv->savePP_CONTROL);
136 if (dev_priv->savePP_CONTROL & POWER_TARGET_ON) 189 if (dev_priv->savePP_CONTROL & POWER_TARGET_ON)
137 intel_lvds_set_power(dev, true); 190 intel_lvds_set_power(dev, true);
138 else 191 else
@@ -216,8 +269,14 @@ static void intel_lvds_prepare(struct drm_encoder *encoder)
216{ 269{
217 struct drm_device *dev = encoder->dev; 270 struct drm_device *dev = encoder->dev;
218 struct drm_i915_private *dev_priv = dev->dev_private; 271 struct drm_i915_private *dev_priv = dev->dev_private;
272 u32 reg;
273
274 if (IS_IGDNG(dev))
275 reg = BLC_PWM_CPU_CTL;
276 else
277 reg = BLC_PWM_CTL;
219 278
220 dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); 279 dev_priv->saveBLC_PWM_CTL = I915_READ(reg);
221 dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & 280 dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
222 BACKLIGHT_DUTY_CYCLE_MASK); 281 BACKLIGHT_DUTY_CYCLE_MASK);
223 282
@@ -251,6 +310,10 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
251 * settings. 310 * settings.
252 */ 311 */
253 312
313 /* No panel fitting yet, fixme */
314 if (IS_IGDNG(dev))
315 return;
316
254 /* 317 /*
255 * Enable automatic panel scaling so that non-native modes fill the 318 * Enable automatic panel scaling so that non-native modes fill the
256 * screen. Should be enabled before the pipe is enabled, according to 319 * screen. Should be enabled before the pipe is enabled, according to
@@ -382,7 +445,8 @@ static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
382 445
383static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id) 446static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
384{ 447{
385 DRM_DEBUG("Skipping LVDS initialization for %s\n", id->ident); 448 DRM_DEBUG_KMS(I915_LVDS,
449 "Skipping LVDS initialization for %s\n", id->ident);
386 return 1; 450 return 1;
387} 451}
388 452
@@ -420,8 +484,21 @@ static const struct dmi_system_id intel_no_lvds[] = {
420 DMI_MATCH(DMI_PRODUCT_NAME, "Studio Hybrid 140g"), 484 DMI_MATCH(DMI_PRODUCT_NAME, "Studio Hybrid 140g"),
421 }, 485 },
422 }, 486 },
423 487 {
424 /* FIXME: add a check for the Aopen Mini PC */ 488 .callback = intel_no_lvds_dmi_callback,
489 .ident = "AOpen Mini PC",
490 .matches = {
491 DMI_MATCH(DMI_SYS_VENDOR, "AOpen"),
492 DMI_MATCH(DMI_PRODUCT_NAME, "i965GMx-IF"),
493 },
494 },
495 {
496 .callback = intel_no_lvds_dmi_callback,
497 .ident = "Aopen i945GTt-VFA",
498 .matches = {
499 DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),
500 },
501 },
425 502
426 { } /* terminating entry */ 503 { } /* terminating entry */
427}; 504};
@@ -442,12 +519,18 @@ void intel_lvds_init(struct drm_device *dev)
442 struct drm_display_mode *scan; /* *modes, *bios_mode; */ 519 struct drm_display_mode *scan; /* *modes, *bios_mode; */
443 struct drm_crtc *crtc; 520 struct drm_crtc *crtc;
444 u32 lvds; 521 u32 lvds;
445 int pipe; 522 int pipe, gpio = GPIOC;
446 523
447 /* Skip init on machines we know falsely report LVDS */ 524 /* Skip init on machines we know falsely report LVDS */
448 if (dmi_check_system(intel_no_lvds)) 525 if (dmi_check_system(intel_no_lvds))
449 return; 526 return;
450 527
528 if (IS_IGDNG(dev)) {
529 if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
530 return;
531 gpio = PCH_GPIOC;
532 }
533
451 intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); 534 intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
452 if (!intel_output) { 535 if (!intel_output) {
453 return; 536 return;
@@ -482,7 +565,7 @@ void intel_lvds_init(struct drm_device *dev)
482 */ 565 */
483 566
484 /* Set up the DDC bus. */ 567 /* Set up the DDC bus. */
485 intel_output->ddc_bus = intel_i2c_create(dev, GPIOC, "LVDSDDC_C"); 568 intel_output->ddc_bus = intel_i2c_create(dev, gpio, "LVDSDDC_C");
486 if (!intel_output->ddc_bus) { 569 if (!intel_output->ddc_bus) {
487 dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " 570 dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
488 "failed.\n"); 571 "failed.\n");
@@ -524,6 +607,11 @@ void intel_lvds_init(struct drm_device *dev)
524 * on. If so, assume that whatever is currently programmed is the 607 * on. If so, assume that whatever is currently programmed is the
525 * correct mode. 608 * correct mode.
526 */ 609 */
610
611 /* IGDNG: FIXME if still fail, not try pipe mode now */
612 if (IS_IGDNG(dev))
613 goto failed;
614
527 lvds = I915_READ(LVDS); 615 lvds = I915_READ(LVDS);
528 pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; 616 pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
529 crtc = intel_get_crtc_from_pipe(dev, pipe); 617 crtc = intel_get_crtc_from_pipe(dev, pipe);
@@ -542,11 +630,22 @@ void intel_lvds_init(struct drm_device *dev)
542 goto failed; 630 goto failed;
543 631
544out: 632out:
633 if (IS_IGDNG(dev)) {
634 u32 pwm;
635 /* make sure PWM is enabled */
636 pwm = I915_READ(BLC_PWM_CPU_CTL2);
637 pwm |= (PWM_ENABLE | PWM_PIPE_B);
638 I915_WRITE(BLC_PWM_CPU_CTL2, pwm);
639
640 pwm = I915_READ(BLC_PWM_PCH_CTL1);
641 pwm |= PWM_PCH_ENABLE;
642 I915_WRITE(BLC_PWM_PCH_CTL1, pwm);
643 }
545 drm_sysfs_connector_add(connector); 644 drm_sysfs_connector_add(connector);
546 return; 645 return;
547 646
548failed: 647failed:
549 DRM_DEBUG("No LVDS modes found, disabling.\n"); 648 DRM_DEBUG_KMS(I915_LVDS, "No LVDS modes found, disabling.\n");
550 if (intel_output->ddc_bus) 649 if (intel_output->ddc_bus)
551 intel_i2c_destroy(intel_output->ddc_bus); 650 intel_i2c_destroy(intel_output->ddc_bus);
552 drm_connector_cleanup(connector); 651 drm_connector_cleanup(connector);