diff options
author | Zhenyu Wang <zhenyuw@linux.intel.com> | 2009-06-05 03:38:44 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-06-05 07:35:49 -0400 |
commit | 541998a18b72d2cac48b3369fa4540116ff3f0a8 (patch) | |
tree | 0173c46d2a51118583aa46f2854509076ef90ada /drivers/gpu | |
parent | 30ad48b7334a2eb2edf22f6c91f7b3f22a22a837 (diff) |
drm/i915: Add LVDS support for IGDNG
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 127 |
2 files changed, 114 insertions, 26 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 53cf6efa67b6..05bd97e3e3e0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -1542,6 +1542,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1542 | int pch_fp_reg = (pipe == 0) ? PCH_FPA0 : PCH_FPB0; | 1542 | int pch_fp_reg = (pipe == 0) ? PCH_FPA0 : PCH_FPB0; |
1543 | int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; | 1543 | int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; |
1544 | int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL; | 1544 | int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL; |
1545 | int lvds_reg = LVDS; | ||
1545 | u32 temp; | 1546 | u32 temp; |
1546 | int sdvo_pixel_multiply; | 1547 | int sdvo_pixel_multiply; |
1547 | 1548 | ||
@@ -1772,8 +1773,12 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1772 | * things on. | 1773 | * things on. |
1773 | */ | 1774 | */ |
1774 | if (is_lvds) { | 1775 | if (is_lvds) { |
1775 | u32 lvds = I915_READ(LVDS); | 1776 | u32 lvds; |
1776 | 1777 | ||
1778 | if (IS_IGDNG(dev)) | ||
1779 | lvds_reg = PCH_LVDS; | ||
1780 | |||
1781 | lvds = I915_READ(lvds_reg); | ||
1777 | lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT; | 1782 | lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT; |
1778 | /* Set the B0-B3 data pairs corresponding to whether we're going to | 1783 | /* Set the B0-B3 data pairs corresponding to whether we're going to |
1779 | * set the DPLLs for dual-channel mode or not. | 1784 | * set the DPLLs for dual-channel mode or not. |
@@ -1788,8 +1793,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1788 | * panels behave in the two modes. | 1793 | * panels behave in the two modes. |
1789 | */ | 1794 | */ |
1790 | 1795 | ||
1791 | I915_WRITE(LVDS, lvds); | 1796 | I915_WRITE(lvds_reg, lvds); |
1792 | I915_READ(LVDS); | 1797 | I915_READ(lvds_reg); |
1793 | } | 1798 | } |
1794 | 1799 | ||
1795 | I915_WRITE(fp_reg, fp); | 1800 | I915_WRITE(fp_reg, fp); |
@@ -2428,7 +2433,7 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
2428 | intel_crt_init(dev); | 2433 | intel_crt_init(dev); |
2429 | 2434 | ||
2430 | /* Set up integrated LVDS */ | 2435 | /* Set up integrated LVDS */ |
2431 | if (IS_MOBILE(dev) && !IS_I830(dev) && !IS_IGDNG(dev)) | 2436 | if (IS_MOBILE(dev) && !IS_I830(dev)) |
2432 | intel_lvds_init(dev); | 2437 | intel_lvds_init(dev); |
2433 | 2438 | ||
2434 | if (IS_IGDNG(dev)) { | 2439 | if (IS_IGDNG(dev)) { |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 53731f0ffcb5..eea3a548b82a 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
@@ -45,10 +45,15 @@ | |||
45 | static void intel_lvds_set_backlight(struct drm_device *dev, int level) | 45 | static void intel_lvds_set_backlight(struct drm_device *dev, int level) |
46 | { | 46 | { |
47 | struct drm_i915_private *dev_priv = dev->dev_private; | 47 | struct drm_i915_private *dev_priv = dev->dev_private; |
48 | u32 blc_pwm_ctl; | 48 | u32 blc_pwm_ctl, reg; |
49 | 49 | ||
50 | blc_pwm_ctl = I915_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; | 50 | if (IS_IGDNG(dev)) |
51 | I915_WRITE(BLC_PWM_CTL, (blc_pwm_ctl | | 51 | reg = BLC_PWM_CPU_CTL; |
52 | else | ||
53 | reg = BLC_PWM_CTL; | ||
54 | |||
55 | blc_pwm_ctl = I915_READ(reg) & ~BACKLIGHT_DUTY_CYCLE_MASK; | ||
56 | I915_WRITE(reg, (blc_pwm_ctl | | ||
52 | (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); | 57 | (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); |
53 | } | 58 | } |
54 | 59 | ||
@@ -58,8 +63,14 @@ static void intel_lvds_set_backlight(struct drm_device *dev, int level) | |||
58 | static u32 intel_lvds_get_max_backlight(struct drm_device *dev) | 63 | static u32 intel_lvds_get_max_backlight(struct drm_device *dev) |
59 | { | 64 | { |
60 | struct drm_i915_private *dev_priv = dev->dev_private; | 65 | struct drm_i915_private *dev_priv = dev->dev_private; |
66 | u32 reg; | ||
67 | |||
68 | if (IS_IGDNG(dev)) | ||
69 | reg = BLC_PWM_PCH_CTL2; | ||
70 | else | ||
71 | reg = BLC_PWM_CTL; | ||
61 | 72 | ||
62 | return ((I915_READ(BLC_PWM_CTL) & BACKLIGHT_MODULATION_FREQ_MASK) >> | 73 | return ((I915_READ(reg) & BACKLIGHT_MODULATION_FREQ_MASK) >> |
63 | BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; | 74 | BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; |
64 | } | 75 | } |
65 | 76 | ||
@@ -69,23 +80,31 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev) | |||
69 | static void intel_lvds_set_power(struct drm_device *dev, bool on) | 80 | static void intel_lvds_set_power(struct drm_device *dev, bool on) |
70 | { | 81 | { |
71 | struct drm_i915_private *dev_priv = dev->dev_private; | 82 | struct drm_i915_private *dev_priv = dev->dev_private; |
72 | u32 pp_status; | 83 | u32 pp_status, ctl_reg, status_reg; |
84 | |||
85 | if (IS_IGDNG(dev)) { | ||
86 | ctl_reg = PCH_PP_CONTROL; | ||
87 | status_reg = PCH_PP_STATUS; | ||
88 | } else { | ||
89 | ctl_reg = PP_CONTROL; | ||
90 | status_reg = PP_STATUS; | ||
91 | } | ||
73 | 92 | ||
74 | if (on) { | 93 | if (on) { |
75 | I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | | 94 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) | |
76 | POWER_TARGET_ON); | 95 | POWER_TARGET_ON); |
77 | do { | 96 | do { |
78 | pp_status = I915_READ(PP_STATUS); | 97 | pp_status = I915_READ(status_reg); |
79 | } while ((pp_status & PP_ON) == 0); | 98 | } while ((pp_status & PP_ON) == 0); |
80 | 99 | ||
81 | intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle); | 100 | intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle); |
82 | } else { | 101 | } else { |
83 | intel_lvds_set_backlight(dev, 0); | 102 | intel_lvds_set_backlight(dev, 0); |
84 | 103 | ||
85 | I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & | 104 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) & |
86 | ~POWER_TARGET_ON); | 105 | ~POWER_TARGET_ON); |
87 | do { | 106 | do { |
88 | pp_status = I915_READ(PP_STATUS); | 107 | pp_status = I915_READ(status_reg); |
89 | } while (pp_status & PP_ON); | 108 | } while (pp_status & PP_ON); |
90 | } | 109 | } |
91 | } | 110 | } |
@@ -106,12 +125,28 @@ static void intel_lvds_save(struct drm_connector *connector) | |||
106 | { | 125 | { |
107 | struct drm_device *dev = connector->dev; | 126 | struct drm_device *dev = connector->dev; |
108 | struct drm_i915_private *dev_priv = dev->dev_private; | 127 | struct drm_i915_private *dev_priv = dev->dev_private; |
128 | u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg; | ||
129 | u32 pwm_ctl_reg; | ||
130 | |||
131 | if (IS_IGDNG(dev)) { | ||
132 | pp_on_reg = PCH_PP_ON_DELAYS; | ||
133 | pp_off_reg = PCH_PP_OFF_DELAYS; | ||
134 | pp_ctl_reg = PCH_PP_CONTROL; | ||
135 | pp_div_reg = PCH_PP_DIVISOR; | ||
136 | pwm_ctl_reg = BLC_PWM_CPU_CTL; | ||
137 | } else { | ||
138 | pp_on_reg = PP_ON_DELAYS; | ||
139 | pp_off_reg = PP_OFF_DELAYS; | ||
140 | pp_ctl_reg = PP_CONTROL; | ||
141 | pp_div_reg = PP_DIVISOR; | ||
142 | pwm_ctl_reg = BLC_PWM_CTL; | ||
143 | } | ||
109 | 144 | ||
110 | dev_priv->savePP_ON = I915_READ(PP_ON_DELAYS); | 145 | dev_priv->savePP_ON = I915_READ(pp_on_reg); |
111 | dev_priv->savePP_OFF = I915_READ(PP_OFF_DELAYS); | 146 | dev_priv->savePP_OFF = I915_READ(pp_off_reg); |
112 | dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL); | 147 | dev_priv->savePP_CONTROL = I915_READ(pp_ctl_reg); |
113 | dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); | 148 | dev_priv->savePP_DIVISOR = I915_READ(pp_div_reg); |
114 | dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); | 149 | dev_priv->saveBLC_PWM_CTL = I915_READ(pwm_ctl_reg); |
115 | dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & | 150 | dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & |
116 | BACKLIGHT_DUTY_CYCLE_MASK); | 151 | BACKLIGHT_DUTY_CYCLE_MASK); |
117 | 152 | ||
@@ -127,12 +162,28 @@ static void intel_lvds_restore(struct drm_connector *connector) | |||
127 | { | 162 | { |
128 | struct drm_device *dev = connector->dev; | 163 | struct drm_device *dev = connector->dev; |
129 | struct drm_i915_private *dev_priv = dev->dev_private; | 164 | struct drm_i915_private *dev_priv = dev->dev_private; |
165 | u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg; | ||
166 | u32 pwm_ctl_reg; | ||
167 | |||
168 | if (IS_IGDNG(dev)) { | ||
169 | pp_on_reg = PCH_PP_ON_DELAYS; | ||
170 | pp_off_reg = PCH_PP_OFF_DELAYS; | ||
171 | pp_ctl_reg = PCH_PP_CONTROL; | ||
172 | pp_div_reg = PCH_PP_DIVISOR; | ||
173 | pwm_ctl_reg = BLC_PWM_CPU_CTL; | ||
174 | } else { | ||
175 | pp_on_reg = PP_ON_DELAYS; | ||
176 | pp_off_reg = PP_OFF_DELAYS; | ||
177 | pp_ctl_reg = PP_CONTROL; | ||
178 | pp_div_reg = PP_DIVISOR; | ||
179 | pwm_ctl_reg = BLC_PWM_CTL; | ||
180 | } | ||
130 | 181 | ||
131 | I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL); | 182 | I915_WRITE(pwm_ctl_reg, dev_priv->saveBLC_PWM_CTL); |
132 | I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON); | 183 | I915_WRITE(pp_on_reg, dev_priv->savePP_ON); |
133 | I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF); | 184 | I915_WRITE(pp_off_reg, dev_priv->savePP_OFF); |
134 | I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); | 185 | I915_WRITE(pp_div_reg, dev_priv->savePP_DIVISOR); |
135 | I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); | 186 | I915_WRITE(pp_ctl_reg, dev_priv->savePP_CONTROL); |
136 | if (dev_priv->savePP_CONTROL & POWER_TARGET_ON) | 187 | if (dev_priv->savePP_CONTROL & POWER_TARGET_ON) |
137 | intel_lvds_set_power(dev, true); | 188 | intel_lvds_set_power(dev, true); |
138 | else | 189 | else |
@@ -216,8 +267,14 @@ static void intel_lvds_prepare(struct drm_encoder *encoder) | |||
216 | { | 267 | { |
217 | struct drm_device *dev = encoder->dev; | 268 | struct drm_device *dev = encoder->dev; |
218 | struct drm_i915_private *dev_priv = dev->dev_private; | 269 | struct drm_i915_private *dev_priv = dev->dev_private; |
270 | u32 reg; | ||
219 | 271 | ||
220 | dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); | 272 | if (IS_IGDNG(dev)) |
273 | reg = BLC_PWM_CPU_CTL; | ||
274 | else | ||
275 | reg = BLC_PWM_CTL; | ||
276 | |||
277 | dev_priv->saveBLC_PWM_CTL = I915_READ(reg); | ||
221 | dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & | 278 | dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & |
222 | BACKLIGHT_DUTY_CYCLE_MASK); | 279 | BACKLIGHT_DUTY_CYCLE_MASK); |
223 | 280 | ||
@@ -251,6 +308,10 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
251 | * settings. | 308 | * settings. |
252 | */ | 309 | */ |
253 | 310 | ||
311 | /* No panel fitting yet, fixme */ | ||
312 | if (IS_IGDNG(dev)) | ||
313 | return; | ||
314 | |||
254 | /* | 315 | /* |
255 | * Enable automatic panel scaling so that non-native modes fill the | 316 | * Enable automatic panel scaling so that non-native modes fill the |
256 | * screen. Should be enabled before the pipe is enabled, according to | 317 | * screen. Should be enabled before the pipe is enabled, according to |
@@ -446,12 +507,18 @@ void intel_lvds_init(struct drm_device *dev) | |||
446 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ | 507 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ |
447 | struct drm_crtc *crtc; | 508 | struct drm_crtc *crtc; |
448 | u32 lvds; | 509 | u32 lvds; |
449 | int pipe; | 510 | int pipe, gpio = GPIOC; |
450 | 511 | ||
451 | /* Skip init on machines we know falsely report LVDS */ | 512 | /* Skip init on machines we know falsely report LVDS */ |
452 | if (dmi_check_system(intel_no_lvds)) | 513 | if (dmi_check_system(intel_no_lvds)) |
453 | return; | 514 | return; |
454 | 515 | ||
516 | if (IS_IGDNG(dev)) { | ||
517 | if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) | ||
518 | return; | ||
519 | gpio = PCH_GPIOC; | ||
520 | } | ||
521 | |||
455 | intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); | 522 | intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); |
456 | if (!intel_output) { | 523 | if (!intel_output) { |
457 | return; | 524 | return; |
@@ -486,7 +553,7 @@ void intel_lvds_init(struct drm_device *dev) | |||
486 | */ | 553 | */ |
487 | 554 | ||
488 | /* Set up the DDC bus. */ | 555 | /* Set up the DDC bus. */ |
489 | intel_output->ddc_bus = intel_i2c_create(dev, GPIOC, "LVDSDDC_C"); | 556 | intel_output->ddc_bus = intel_i2c_create(dev, gpio, "LVDSDDC_C"); |
490 | if (!intel_output->ddc_bus) { | 557 | if (!intel_output->ddc_bus) { |
491 | dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " | 558 | dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " |
492 | "failed.\n"); | 559 | "failed.\n"); |
@@ -528,6 +595,11 @@ void intel_lvds_init(struct drm_device *dev) | |||
528 | * on. If so, assume that whatever is currently programmed is the | 595 | * on. If so, assume that whatever is currently programmed is the |
529 | * correct mode. | 596 | * correct mode. |
530 | */ | 597 | */ |
598 | |||
599 | /* IGDNG: FIXME if still fail, not try pipe mode now */ | ||
600 | if (IS_IGDNG(dev)) | ||
601 | goto failed; | ||
602 | |||
531 | lvds = I915_READ(LVDS); | 603 | lvds = I915_READ(LVDS); |
532 | pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; | 604 | pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; |
533 | crtc = intel_get_crtc_from_pipe(dev, pipe); | 605 | crtc = intel_get_crtc_from_pipe(dev, pipe); |
@@ -546,6 +618,17 @@ void intel_lvds_init(struct drm_device *dev) | |||
546 | goto failed; | 618 | goto failed; |
547 | 619 | ||
548 | out: | 620 | out: |
621 | if (IS_IGDNG(dev)) { | ||
622 | u32 pwm; | ||
623 | /* make sure PWM is enabled */ | ||
624 | pwm = I915_READ(BLC_PWM_CPU_CTL2); | ||
625 | pwm |= (PWM_ENABLE | PWM_PIPE_B); | ||
626 | I915_WRITE(BLC_PWM_CPU_CTL2, pwm); | ||
627 | |||
628 | pwm = I915_READ(BLC_PWM_PCH_CTL1); | ||
629 | pwm |= PWM_PCH_ENABLE; | ||
630 | I915_WRITE(BLC_PWM_PCH_CTL1, pwm); | ||
631 | } | ||
549 | drm_sysfs_connector_add(connector); | 632 | drm_sysfs_connector_add(connector); |
550 | return; | 633 | return; |
551 | 634 | ||