diff options
author | Zhao Yakui <yakui.zhao@intel.com> | 2012-08-08 09:55:55 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-08-23 19:29:25 -0400 |
commit | d112a8163f83752361dd639a9a579ae5cc05c6cf (patch) | |
tree | 53a97ff373718223d0b46cb6d74dc81906058439 /drivers/gpu/drm/gma500/cdv_intel_dp.c | |
parent | 35659715c42b5cd148935e8ebd4e5e8e4e256b96 (diff) |
gma500/cdv: Add eDP support
Introduce the eDP support into the driver.
This has been reworked a bit because kernel driver proper uses encoder/connectors
while the legacy Intel driver uses the old output stuff.
It also diverges on the backlight handling. The legacy Intel driver adds a panel
abstraction based upon the i915 one. It's only really used for backlight bits
and we have a perfectly good backlight abstraction which can extend instead.
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
[ported to upstream driver, redid backlight abstraction]
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/gma500/cdv_intel_dp.c')
-rw-r--r-- | drivers/gpu/drm/gma500/cdv_intel_dp.c | 468 |
1 files changed, 448 insertions, 20 deletions
diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index b29b6026b6ef..0571ef9b889b 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c | |||
@@ -36,6 +36,20 @@ | |||
36 | #include "psb_intel_reg.h" | 36 | #include "psb_intel_reg.h" |
37 | #include "drm_dp_helper.h" | 37 | #include "drm_dp_helper.h" |
38 | 38 | ||
39 | #define _wait_for(COND, MS, W) ({ \ | ||
40 | unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \ | ||
41 | int ret__ = 0; \ | ||
42 | while (! (COND)) { \ | ||
43 | if (time_after(jiffies, timeout__)) { \ | ||
44 | ret__ = -ETIMEDOUT; \ | ||
45 | break; \ | ||
46 | } \ | ||
47 | if (W && !in_dbg_master()) msleep(W); \ | ||
48 | } \ | ||
49 | ret__; \ | ||
50 | }) | ||
51 | |||
52 | #define wait_for(COND, MS) _wait_for(COND, MS, 1) | ||
39 | 53 | ||
40 | #define DP_LINK_STATUS_SIZE 6 | 54 | #define DP_LINK_STATUS_SIZE 6 |
41 | #define DP_LINK_CHECK_TIMEOUT (10 * 1000) | 55 | #define DP_LINK_CHECK_TIMEOUT (10 * 1000) |
@@ -59,6 +73,13 @@ struct cdv_intel_dp { | |||
59 | struct i2c_algo_dp_aux_data algo; | 73 | struct i2c_algo_dp_aux_data algo; |
60 | uint8_t train_set[4]; | 74 | uint8_t train_set[4]; |
61 | uint8_t link_status[DP_LINK_STATUS_SIZE]; | 75 | uint8_t link_status[DP_LINK_STATUS_SIZE]; |
76 | int panel_power_up_delay; | ||
77 | int panel_power_down_delay; | ||
78 | int panel_power_cycle_delay; | ||
79 | int backlight_on_delay; | ||
80 | int backlight_off_delay; | ||
81 | struct drm_display_mode *panel_fixed_mode; /* for eDP */ | ||
82 | bool panel_on; | ||
62 | }; | 83 | }; |
63 | 84 | ||
64 | struct ddi_regoff { | 85 | struct ddi_regoff { |
@@ -159,31 +180,166 @@ cdv_intel_dp_max_data_rate(int max_link_clock, int max_lanes) | |||
159 | return (max_link_clock * max_lanes * 19) / 20; | 180 | return (max_link_clock * max_lanes * 19) / 20; |
160 | } | 181 | } |
161 | 182 | ||
183 | static void cdv_intel_edp_panel_vdd_on(struct psb_intel_encoder *intel_encoder) | ||
184 | { | ||
185 | struct drm_device *dev = intel_encoder->base.dev; | ||
186 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; | ||
187 | u32 pp; | ||
188 | |||
189 | if (intel_dp->panel_on) { | ||
190 | DRM_DEBUG_KMS("Skip VDD on because of panel on\n"); | ||
191 | return; | ||
192 | } | ||
193 | DRM_DEBUG_KMS("\n"); | ||
194 | |||
195 | pp = REG_READ(PP_CONTROL); | ||
196 | |||
197 | pp |= EDP_FORCE_VDD; | ||
198 | REG_WRITE(PP_CONTROL, pp); | ||
199 | REG_READ(PP_CONTROL); | ||
200 | msleep(intel_dp->panel_power_up_delay); | ||
201 | } | ||
202 | |||
203 | static void cdv_intel_edp_panel_vdd_off(struct psb_intel_encoder *intel_encoder) | ||
204 | { | ||
205 | struct drm_device *dev = intel_encoder->base.dev; | ||
206 | u32 pp; | ||
207 | |||
208 | DRM_DEBUG_KMS("\n"); | ||
209 | pp = REG_READ(PP_CONTROL); | ||
210 | |||
211 | pp &= ~EDP_FORCE_VDD; | ||
212 | REG_WRITE(PP_CONTROL, pp); | ||
213 | REG_READ(PP_CONTROL); | ||
214 | |||
215 | } | ||
216 | |||
217 | /* Returns true if the panel was already on when called */ | ||
218 | static bool cdv_intel_edp_panel_on(struct psb_intel_encoder *intel_encoder) | ||
219 | { | ||
220 | struct drm_device *dev = intel_encoder->base.dev; | ||
221 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; | ||
222 | u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_NONE; | ||
223 | |||
224 | if (intel_dp->panel_on) | ||
225 | return true; | ||
226 | |||
227 | DRM_DEBUG_KMS("\n"); | ||
228 | pp = REG_READ(PP_CONTROL); | ||
229 | pp &= ~PANEL_UNLOCK_MASK; | ||
230 | |||
231 | pp |= (PANEL_UNLOCK_REGS | POWER_TARGET_ON); | ||
232 | REG_WRITE(PP_CONTROL, pp); | ||
233 | REG_READ(PP_CONTROL); | ||
234 | |||
235 | if (wait_for(((REG_READ(PP_STATUS) & idle_on_mask) == idle_on_mask), 1000)) { | ||
236 | DRM_DEBUG_KMS("Error in Powering up eDP panel, status %x\n", REG_READ(PP_STATUS)); | ||
237 | intel_dp->panel_on = false; | ||
238 | } else | ||
239 | intel_dp->panel_on = true; | ||
240 | msleep(intel_dp->panel_power_up_delay); | ||
241 | |||
242 | return false; | ||
243 | } | ||
244 | |||
245 | static void cdv_intel_edp_panel_off (struct psb_intel_encoder *intel_encoder) | ||
246 | { | ||
247 | struct drm_device *dev = intel_encoder->base.dev; | ||
248 | u32 pp, idle_off_mask = PP_ON ; | ||
249 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; | ||
250 | |||
251 | DRM_DEBUG_KMS("\n"); | ||
252 | |||
253 | pp = REG_READ(PP_CONTROL); | ||
254 | |||
255 | if ((pp & POWER_TARGET_ON) == 0) | ||
256 | return; | ||
257 | |||
258 | intel_dp->panel_on = false; | ||
259 | pp &= ~PANEL_UNLOCK_MASK; | ||
260 | /* ILK workaround: disable reset around power sequence */ | ||
261 | |||
262 | pp &= ~POWER_TARGET_ON; | ||
263 | pp &= ~EDP_FORCE_VDD; | ||
264 | pp &= ~EDP_BLC_ENABLE; | ||
265 | REG_WRITE(PP_CONTROL, pp); | ||
266 | REG_READ(PP_CONTROL); | ||
267 | DRM_DEBUG_KMS("PP_STATUS %x\n", REG_READ(PP_STATUS)); | ||
268 | |||
269 | if (wait_for((REG_READ(PP_STATUS) & idle_off_mask) == 0, 1000)) { | ||
270 | DRM_DEBUG_KMS("Error in turning off Panel\n"); | ||
271 | } | ||
272 | |||
273 | msleep(intel_dp->panel_power_cycle_delay); | ||
274 | DRM_DEBUG_KMS("Over\n"); | ||
275 | } | ||
276 | |||
277 | static void cdv_intel_edp_backlight_on (struct psb_intel_encoder *intel_encoder) | ||
278 | { | ||
279 | struct drm_device *dev = intel_encoder->base.dev; | ||
280 | u32 pp; | ||
281 | |||
282 | DRM_DEBUG_KMS("\n"); | ||
283 | /* | ||
284 | * If we enable the backlight right away following a panel power | ||
285 | * on, we may see slight flicker as the panel syncs with the eDP | ||
286 | * link. So delay a bit to make sure the image is solid before | ||
287 | * allowing it to appear. | ||
288 | */ | ||
289 | msleep(300); | ||
290 | pp = REG_READ(PP_CONTROL); | ||
291 | |||
292 | pp |= EDP_BLC_ENABLE; | ||
293 | REG_WRITE(PP_CONTROL, pp); | ||
294 | gma_backlight_enable(dev); | ||
295 | } | ||
296 | |||
297 | static void cdv_intel_edp_backlight_off (struct psb_intel_encoder *intel_encoder) | ||
298 | { | ||
299 | struct drm_device *dev = intel_encoder->base.dev; | ||
300 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; | ||
301 | u32 pp; | ||
302 | |||
303 | DRM_DEBUG_KMS("\n"); | ||
304 | gma_backlight_disable(dev); | ||
305 | msleep(10); | ||
306 | pp = REG_READ(PP_CONTROL); | ||
307 | |||
308 | pp &= ~EDP_BLC_ENABLE; | ||
309 | REG_WRITE(PP_CONTROL, pp); | ||
310 | msleep(intel_dp->backlight_off_delay); | ||
311 | } | ||
312 | |||
162 | static int | 313 | static int |
163 | cdv_intel_dp_mode_valid(struct drm_connector *connector, | 314 | cdv_intel_dp_mode_valid(struct drm_connector *connector, |
164 | struct drm_display_mode *mode) | 315 | struct drm_display_mode *mode) |
165 | { | 316 | { |
166 | struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector); | 317 | struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector); |
167 | struct drm_device *dev = connector->dev; | 318 | struct cdv_intel_dp *intel_dp = encoder->dev_priv; |
168 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
169 | int max_link_clock = cdv_intel_dp_link_clock(cdv_intel_dp_max_link_bw(encoder)); | 319 | int max_link_clock = cdv_intel_dp_link_clock(cdv_intel_dp_max_link_bw(encoder)); |
170 | int max_lanes = cdv_intel_dp_max_lane_count(encoder); | 320 | int max_lanes = cdv_intel_dp_max_lane_count(encoder); |
321 | struct drm_psb_private *dev_priv = connector->dev->dev_private; | ||
171 | 322 | ||
172 | if (is_edp(encoder) && dev_priv->panel_fixed_mode) { | 323 | if (is_edp(encoder) && intel_dp->panel_fixed_mode) { |
173 | if (mode->hdisplay > dev_priv->panel_fixed_mode->hdisplay) | 324 | if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay) |
174 | return MODE_PANEL; | 325 | return MODE_PANEL; |
175 | 326 | if (mode->vdisplay > intel_dp->panel_fixed_mode->vdisplay) | |
176 | if (mode->vdisplay > dev_priv->panel_fixed_mode->vdisplay) | ||
177 | return MODE_PANEL; | 327 | return MODE_PANEL; |
178 | } | 328 | } |
179 | 329 | ||
180 | /* only refuse the mode on non eDP since we have seen some weird eDP panels | 330 | /* only refuse the mode on non eDP since we have seen some weird eDP panels |
181 | which are outside spec tolerances but somehow work by magic */ | 331 | which are outside spec tolerances but somehow work by magic */ |
182 | if (!is_edp(encoder) && | 332 | if (!is_edp(encoder) && |
183 | (cdv_intel_dp_link_required(mode->clock, 24) | 333 | (cdv_intel_dp_link_required(mode->clock, dev_priv->edp.bpp) |
184 | > cdv_intel_dp_max_data_rate(max_link_clock, max_lanes))) | 334 | > cdv_intel_dp_max_data_rate(max_link_clock, max_lanes))) |
185 | return MODE_CLOCK_HIGH; | 335 | return MODE_CLOCK_HIGH; |
186 | 336 | ||
337 | if (is_edp(encoder)) { | ||
338 | if (cdv_intel_dp_link_required(mode->clock, 24) | ||
339 | > cdv_intel_dp_max_data_rate(max_link_clock, max_lanes)) | ||
340 | return MODE_CLOCK_HIGH; | ||
341 | |||
342 | } | ||
187 | if (mode->clock < 10000) | 343 | if (mode->clock < 10000) |
188 | return MODE_CLOCK_LOW; | 344 | return MODE_CLOCK_LOW; |
189 | 345 | ||
@@ -238,6 +394,8 @@ cdv_intel_dp_aux_ch(struct psb_intel_encoder *encoder, | |||
238 | aux_clock_divider = 200 / 2; | 394 | aux_clock_divider = 200 / 2; |
239 | 395 | ||
240 | precharge = 4; | 396 | precharge = 4; |
397 | if (is_edp(encoder)) | ||
398 | precharge = 10; | ||
241 | 399 | ||
242 | if (REG_READ(ch_ctl) & DP_AUX_CH_CTL_SEND_BUSY) { | 400 | if (REG_READ(ch_ctl) & DP_AUX_CH_CTL_SEND_BUSY) { |
243 | DRM_ERROR("dp_aux_ch not started status 0x%08x\n", | 401 | DRM_ERROR("dp_aux_ch not started status 0x%08x\n", |
@@ -492,7 +650,10 @@ static int | |||
492 | cdv_intel_dp_i2c_init(struct psb_intel_connector *connector, struct psb_intel_encoder *encoder, const char *name) | 650 | cdv_intel_dp_i2c_init(struct psb_intel_connector *connector, struct psb_intel_encoder *encoder, const char *name) |
493 | { | 651 | { |
494 | struct cdv_intel_dp *intel_dp = encoder->dev_priv; | 652 | struct cdv_intel_dp *intel_dp = encoder->dev_priv; |
653 | int ret; | ||
654 | |||
495 | DRM_DEBUG_KMS("i2c_init %s\n", name); | 655 | DRM_DEBUG_KMS("i2c_init %s\n", name); |
656 | |||
496 | intel_dp->algo.running = false; | 657 | intel_dp->algo.running = false; |
497 | intel_dp->algo.address = 0; | 658 | intel_dp->algo.address = 0; |
498 | intel_dp->algo.aux_ch = cdv_intel_dp_i2c_aux_ch; | 659 | intel_dp->algo.aux_ch = cdv_intel_dp_i2c_aux_ch; |
@@ -505,27 +666,58 @@ cdv_intel_dp_i2c_init(struct psb_intel_connector *connector, struct psb_intel_en | |||
505 | intel_dp->adapter.algo_data = &intel_dp->algo; | 666 | intel_dp->adapter.algo_data = &intel_dp->algo; |
506 | intel_dp->adapter.dev.parent = &connector->base.kdev; | 667 | intel_dp->adapter.dev.parent = &connector->base.kdev; |
507 | 668 | ||
508 | return i2c_dp_aux_add_bus(&intel_dp->adapter); | 669 | if (is_edp(encoder)) |
670 | cdv_intel_edp_panel_vdd_on(encoder); | ||
671 | ret = i2c_dp_aux_add_bus(&intel_dp->adapter); | ||
672 | if (is_edp(encoder)) | ||
673 | cdv_intel_edp_panel_vdd_off(encoder); | ||
674 | |||
675 | return ret; | ||
676 | } | ||
677 | |||
678 | void cdv_intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, | ||
679 | struct drm_display_mode *adjusted_mode) | ||
680 | { | ||
681 | adjusted_mode->hdisplay = fixed_mode->hdisplay; | ||
682 | adjusted_mode->hsync_start = fixed_mode->hsync_start; | ||
683 | adjusted_mode->hsync_end = fixed_mode->hsync_end; | ||
684 | adjusted_mode->htotal = fixed_mode->htotal; | ||
685 | |||
686 | adjusted_mode->vdisplay = fixed_mode->vdisplay; | ||
687 | adjusted_mode->vsync_start = fixed_mode->vsync_start; | ||
688 | adjusted_mode->vsync_end = fixed_mode->vsync_end; | ||
689 | adjusted_mode->vtotal = fixed_mode->vtotal; | ||
690 | |||
691 | adjusted_mode->clock = fixed_mode->clock; | ||
692 | |||
693 | drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); | ||
509 | } | 694 | } |
510 | 695 | ||
511 | static bool | 696 | static bool |
512 | cdv_intel_dp_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, | 697 | cdv_intel_dp_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, |
513 | struct drm_display_mode *adjusted_mode) | 698 | struct drm_display_mode *adjusted_mode) |
514 | { | 699 | { |
700 | struct drm_psb_private *dev_priv = encoder->dev->dev_private; | ||
515 | struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); | 701 | struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); |
516 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; | 702 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; |
517 | int lane_count, clock; | 703 | int lane_count, clock; |
518 | int max_lane_count = cdv_intel_dp_max_lane_count(intel_encoder); | 704 | int max_lane_count = cdv_intel_dp_max_lane_count(intel_encoder); |
519 | int max_clock = cdv_intel_dp_max_link_bw(intel_encoder) == DP_LINK_BW_2_7 ? 1 : 0; | 705 | int max_clock = cdv_intel_dp_max_link_bw(intel_encoder) == DP_LINK_BW_2_7 ? 1 : 0; |
520 | static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; | 706 | static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; |
707 | int refclock = mode->clock; | ||
708 | int bpp = 24; | ||
521 | 709 | ||
710 | if (is_edp(intel_encoder) && intel_dp->panel_fixed_mode) { | ||
711 | cdv_intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode); | ||
712 | refclock = intel_dp->panel_fixed_mode->clock; | ||
713 | bpp = dev_priv->edp.bpp; | ||
714 | } | ||
522 | 715 | ||
523 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { | 716 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { |
524 | for (clock = max_clock; clock >= 0; clock--) { | 717 | for (clock = max_clock; clock >= 0; clock--) { |
525 | int link_avail = cdv_intel_dp_max_data_rate(cdv_intel_dp_link_clock(bws[clock]), lane_count); | 718 | int link_avail = cdv_intel_dp_max_data_rate(cdv_intel_dp_link_clock(bws[clock]), lane_count); |
526 | 719 | ||
527 | if (cdv_intel_dp_link_required(mode->clock, 24) | 720 | if (cdv_intel_dp_link_required(refclock, bpp) <= link_avail) { |
528 | <= link_avail) { | ||
529 | intel_dp->link_bw = bws[clock]; | 721 | intel_dp->link_bw = bws[clock]; |
530 | intel_dp->lane_count = lane_count; | 722 | intel_dp->lane_count = lane_count; |
531 | adjusted_mode->clock = cdv_intel_dp_link_clock(intel_dp->link_bw); | 723 | adjusted_mode->clock = cdv_intel_dp_link_clock(intel_dp->link_bw); |
@@ -537,7 +729,18 @@ cdv_intel_dp_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mo | |||
537 | } | 729 | } |
538 | } | 730 | } |
539 | } | 731 | } |
540 | 732 | if (is_edp(intel_encoder)) { | |
733 | /* okay we failed just pick the highest */ | ||
734 | intel_dp->lane_count = max_lane_count; | ||
735 | intel_dp->link_bw = bws[max_clock]; | ||
736 | adjusted_mode->clock = cdv_intel_dp_link_clock(intel_dp->link_bw); | ||
737 | DRM_DEBUG_KMS("Force picking display port link bw %02x lane " | ||
738 | "count %d clock %d\n", | ||
739 | intel_dp->link_bw, intel_dp->lane_count, | ||
740 | adjusted_mode->clock); | ||
741 | |||
742 | return true; | ||
743 | } | ||
541 | return false; | 744 | return false; |
542 | } | 745 | } |
543 | 746 | ||
@@ -550,7 +753,7 @@ struct cdv_intel_dp_m_n { | |||
550 | }; | 753 | }; |
551 | 754 | ||
552 | static void | 755 | static void |
553 | psb_intel_reduce_ratio(uint32_t *num, uint32_t *den) | 756 | cdv_intel_reduce_ratio(uint32_t *num, uint32_t *den) |
554 | { | 757 | { |
555 | /* | 758 | /* |
556 | while (*num > 0xffffff || *den > 0xffffff) { | 759 | while (*num > 0xffffff || *den > 0xffffff) { |
@@ -575,10 +778,10 @@ cdv_intel_dp_compute_m_n(int bpp, | |||
575 | m_n->tu = 64; | 778 | m_n->tu = 64; |
576 | m_n->gmch_m = (pixel_clock * bpp + 7) >> 3; | 779 | m_n->gmch_m = (pixel_clock * bpp + 7) >> 3; |
577 | m_n->gmch_n = link_clock * nlanes; | 780 | m_n->gmch_n = link_clock * nlanes; |
578 | psb_intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); | 781 | cdv_intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); |
579 | m_n->link_m = pixel_clock; | 782 | m_n->link_m = pixel_clock; |
580 | m_n->link_n = link_clock; | 783 | m_n->link_n = link_clock; |
581 | psb_intel_reduce_ratio(&m_n->link_m, &m_n->link_n); | 784 | cdv_intel_reduce_ratio(&m_n->link_m, &m_n->link_n); |
582 | } | 785 | } |
583 | 786 | ||
584 | void | 787 | void |
@@ -586,6 +789,7 @@ cdv_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
586 | struct drm_display_mode *adjusted_mode) | 789 | struct drm_display_mode *adjusted_mode) |
587 | { | 790 | { |
588 | struct drm_device *dev = crtc->dev; | 791 | struct drm_device *dev = crtc->dev; |
792 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
589 | struct drm_mode_config *mode_config = &dev->mode_config; | 793 | struct drm_mode_config *mode_config = &dev->mode_config; |
590 | struct drm_encoder *encoder; | 794 | struct drm_encoder *encoder; |
591 | struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); | 795 | struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); |
@@ -610,6 +814,7 @@ cdv_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
610 | break; | 814 | break; |
611 | } else if (is_edp(intel_encoder)) { | 815 | } else if (is_edp(intel_encoder)) { |
612 | lane_count = intel_dp->lane_count; | 816 | lane_count = intel_dp->lane_count; |
817 | bpp = dev_priv->edp.bpp; | ||
613 | break; | 818 | break; |
614 | } | 819 | } |
615 | } | 820 | } |
@@ -640,7 +845,7 @@ cdv_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode | |||
640 | struct drm_crtc *crtc = encoder->crtc; | 845 | struct drm_crtc *crtc = encoder->crtc; |
641 | struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); | 846 | struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); |
642 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; | 847 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; |
643 | 848 | struct drm_device *dev = encoder->dev; | |
644 | 849 | ||
645 | intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; | 850 | intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; |
646 | intel_dp->DP |= intel_dp->color_range; | 851 | intel_dp->DP |= intel_dp->color_range; |
@@ -683,7 +888,22 @@ cdv_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode | |||
683 | if (intel_crtc->pipe == 1) | 888 | if (intel_crtc->pipe == 1) |
684 | intel_dp->DP |= DP_PIPEB_SELECT; | 889 | intel_dp->DP |= DP_PIPEB_SELECT; |
685 | 890 | ||
891 | REG_WRITE(intel_dp->output_reg, (intel_dp->DP | DP_PORT_EN)); | ||
686 | DRM_DEBUG_KMS("DP expected reg is %x\n", intel_dp->DP); | 892 | DRM_DEBUG_KMS("DP expected reg is %x\n", intel_dp->DP); |
893 | if (is_edp(intel_encoder)) { | ||
894 | uint32_t pfit_control; | ||
895 | cdv_intel_edp_panel_on(intel_encoder); | ||
896 | |||
897 | if (mode->hdisplay != adjusted_mode->hdisplay || | ||
898 | mode->vdisplay != adjusted_mode->vdisplay) | ||
899 | pfit_control = PFIT_ENABLE; | ||
900 | else | ||
901 | pfit_control = 0; | ||
902 | |||
903 | pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT; | ||
904 | |||
905 | REG_WRITE(PFIT_CONTROL, pfit_control); | ||
906 | } | ||
687 | } | 907 | } |
688 | 908 | ||
689 | 909 | ||
@@ -721,18 +941,31 @@ static void cdv_intel_dp_sink_dpms(struct psb_intel_encoder *encoder, int mode) | |||
721 | static void cdv_intel_dp_prepare(struct drm_encoder *encoder) | 941 | static void cdv_intel_dp_prepare(struct drm_encoder *encoder) |
722 | { | 942 | { |
723 | struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); | 943 | struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); |
944 | int edp = is_edp(intel_encoder); | ||
724 | 945 | ||
946 | if (edp) { | ||
947 | cdv_intel_edp_backlight_off(intel_encoder); | ||
948 | cdv_intel_edp_panel_off(intel_encoder); | ||
949 | cdv_intel_edp_panel_vdd_on(intel_encoder); | ||
950 | } | ||
725 | /* Wake up the sink first */ | 951 | /* Wake up the sink first */ |
726 | cdv_intel_dp_sink_dpms(intel_encoder, DRM_MODE_DPMS_ON); | 952 | cdv_intel_dp_sink_dpms(intel_encoder, DRM_MODE_DPMS_ON); |
727 | cdv_intel_dp_link_down(intel_encoder); | 953 | cdv_intel_dp_link_down(intel_encoder); |
954 | if (edp) | ||
955 | cdv_intel_edp_panel_vdd_off(intel_encoder); | ||
728 | } | 956 | } |
729 | 957 | ||
730 | static void cdv_intel_dp_commit(struct drm_encoder *encoder) | 958 | static void cdv_intel_dp_commit(struct drm_encoder *encoder) |
731 | { | 959 | { |
732 | struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); | 960 | struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); |
961 | int edp = is_edp(intel_encoder); | ||
733 | 962 | ||
963 | if (edp) | ||
964 | cdv_intel_edp_panel_on(intel_encoder); | ||
734 | cdv_intel_dp_start_link_train(intel_encoder); | 965 | cdv_intel_dp_start_link_train(intel_encoder); |
735 | cdv_intel_dp_complete_link_train(intel_encoder); | 966 | cdv_intel_dp_complete_link_train(intel_encoder); |
967 | if (edp) | ||
968 | cdv_intel_edp_backlight_on(intel_encoder); | ||
736 | } | 969 | } |
737 | 970 | ||
738 | static void | 971 | static void |
@@ -742,16 +975,29 @@ cdv_intel_dp_dpms(struct drm_encoder *encoder, int mode) | |||
742 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; | 975 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; |
743 | struct drm_device *dev = encoder->dev; | 976 | struct drm_device *dev = encoder->dev; |
744 | uint32_t dp_reg = REG_READ(intel_dp->output_reg); | 977 | uint32_t dp_reg = REG_READ(intel_dp->output_reg); |
978 | int edp = is_edp(intel_encoder); | ||
745 | 979 | ||
746 | if (mode != DRM_MODE_DPMS_ON) { | 980 | if (mode != DRM_MODE_DPMS_ON) { |
981 | if (edp) { | ||
982 | cdv_intel_edp_backlight_off(intel_encoder); | ||
983 | cdv_intel_edp_panel_vdd_on(intel_encoder); | ||
984 | } | ||
747 | cdv_intel_dp_sink_dpms(intel_encoder, mode); | 985 | cdv_intel_dp_sink_dpms(intel_encoder, mode); |
748 | cdv_intel_dp_link_down(intel_encoder); | 986 | cdv_intel_dp_link_down(intel_encoder); |
987 | if (edp) { | ||
988 | cdv_intel_edp_panel_vdd_off(intel_encoder); | ||
989 | cdv_intel_edp_panel_off(intel_encoder); | ||
990 | } | ||
749 | } else { | 991 | } else { |
992 | if (edp) | ||
993 | cdv_intel_edp_panel_on(intel_encoder); | ||
750 | cdv_intel_dp_sink_dpms(intel_encoder, mode); | 994 | cdv_intel_dp_sink_dpms(intel_encoder, mode); |
751 | if (!(dp_reg & DP_PORT_EN)) { | 995 | if (!(dp_reg & DP_PORT_EN)) { |
752 | cdv_intel_dp_start_link_train(intel_encoder); | 996 | cdv_intel_dp_start_link_train(intel_encoder); |
753 | cdv_intel_dp_complete_link_train(intel_encoder); | 997 | cdv_intel_dp_complete_link_train(intel_encoder); |
754 | } | 998 | } |
999 | if (edp) | ||
1000 | cdv_intel_edp_backlight_on(intel_encoder); | ||
755 | } | 1001 | } |
756 | } | 1002 | } |
757 | 1003 | ||
@@ -1090,6 +1336,10 @@ cdv_intel_dp_start_link_train(struct psb_intel_encoder *encoder) | |||
1090 | 1336 | ||
1091 | for (;;) { | 1337 | for (;;) { |
1092 | /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ | 1338 | /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ |
1339 | DRM_DEBUG_KMS("DP Link Train Set %x, Link_config %x, %x\n", | ||
1340 | intel_dp->train_set[0], | ||
1341 | intel_dp->link_configuration[0], | ||
1342 | intel_dp->link_configuration[1]); | ||
1093 | 1343 | ||
1094 | if (!cdv_intel_dp_set_link_train(encoder, reg, DP_TRAINING_PATTERN_1)) { | 1344 | if (!cdv_intel_dp_set_link_train(encoder, reg, DP_TRAINING_PATTERN_1)) { |
1095 | DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 1\n"); | 1345 | DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 1\n"); |
@@ -1103,6 +1353,10 @@ cdv_intel_dp_start_link_train(struct psb_intel_encoder *encoder) | |||
1103 | if (!cdv_intel_dp_get_link_status(encoder)) | 1353 | if (!cdv_intel_dp_get_link_status(encoder)) |
1104 | break; | 1354 | break; |
1105 | 1355 | ||
1356 | DRM_DEBUG_KMS("DP Link status %x, %x, %x, %x, %x, %x\n", | ||
1357 | intel_dp->link_status[0], intel_dp->link_status[1], intel_dp->link_status[2], | ||
1358 | intel_dp->link_status[3], intel_dp->link_status[4], intel_dp->link_status[5]); | ||
1359 | |||
1106 | if (cdv_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { | 1360 | if (cdv_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { |
1107 | DRM_DEBUG_KMS("PT1 train is done\n"); | 1361 | DRM_DEBUG_KMS("PT1 train is done\n"); |
1108 | clock_recovery = true; | 1362 | clock_recovery = true; |
@@ -1156,7 +1410,13 @@ cdv_intel_dp_complete_link_train(struct psb_intel_encoder *encoder) | |||
1156 | reg = DP | DP_LINK_TRAIN_PAT_2; | 1410 | reg = DP | DP_LINK_TRAIN_PAT_2; |
1157 | 1411 | ||
1158 | for (;;) { | 1412 | for (;;) { |
1159 | /* channel eq pattern */ | 1413 | |
1414 | DRM_DEBUG_KMS("DP Link Train Set %x, Link_config %x, %x\n", | ||
1415 | intel_dp->train_set[0], | ||
1416 | intel_dp->link_configuration[0], | ||
1417 | intel_dp->link_configuration[1]); | ||
1418 | /* channel eq pattern */ | ||
1419 | |||
1160 | if (!cdv_intel_dp_set_link_train(encoder, reg, | 1420 | if (!cdv_intel_dp_set_link_train(encoder, reg, |
1161 | DP_TRAINING_PATTERN_2)) { | 1421 | DP_TRAINING_PATTERN_2)) { |
1162 | DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 2\n"); | 1422 | DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 2\n"); |
@@ -1177,6 +1437,10 @@ cdv_intel_dp_complete_link_train(struct psb_intel_encoder *encoder) | |||
1177 | if (!cdv_intel_dp_get_link_status(encoder)) | 1437 | if (!cdv_intel_dp_get_link_status(encoder)) |
1178 | break; | 1438 | break; |
1179 | 1439 | ||
1440 | DRM_DEBUG_KMS("DP Link status %x, %x, %x, %x, %x, %x\n", | ||
1441 | intel_dp->link_status[0], intel_dp->link_status[1], intel_dp->link_status[2], | ||
1442 | intel_dp->link_status[3], intel_dp->link_status[4], intel_dp->link_status[5]); | ||
1443 | |||
1180 | /* Make sure clock is still ok */ | 1444 | /* Make sure clock is still ok */ |
1181 | if (!cdv_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { | 1445 | if (!cdv_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { |
1182 | cdv_intel_dp_start_link_train(encoder); | 1446 | cdv_intel_dp_start_link_train(encoder); |
@@ -1271,12 +1535,18 @@ cdv_intel_dp_detect(struct drm_connector *connector, bool force) | |||
1271 | struct cdv_intel_dp *intel_dp = encoder->dev_priv; | 1535 | struct cdv_intel_dp *intel_dp = encoder->dev_priv; |
1272 | enum drm_connector_status status; | 1536 | enum drm_connector_status status; |
1273 | struct edid *edid = NULL; | 1537 | struct edid *edid = NULL; |
1538 | int edp = is_edp(encoder); | ||
1274 | 1539 | ||
1275 | intel_dp->has_audio = false; | 1540 | intel_dp->has_audio = false; |
1276 | 1541 | ||
1542 | if (edp) | ||
1543 | cdv_intel_edp_panel_vdd_on(encoder); | ||
1277 | status = cdv_dp_detect(encoder); | 1544 | status = cdv_dp_detect(encoder); |
1278 | if (status != connector_status_connected) | 1545 | if (status != connector_status_connected) { |
1546 | if (edp) | ||
1547 | cdv_intel_edp_panel_vdd_off(encoder); | ||
1279 | return status; | 1548 | return status; |
1549 | } | ||
1280 | 1550 | ||
1281 | if (intel_dp->force_audio) { | 1551 | if (intel_dp->force_audio) { |
1282 | intel_dp->has_audio = intel_dp->force_audio > 0; | 1552 | intel_dp->has_audio = intel_dp->force_audio > 0; |
@@ -1288,6 +1558,8 @@ cdv_intel_dp_detect(struct drm_connector *connector, bool force) | |||
1288 | kfree(edid); | 1558 | kfree(edid); |
1289 | } | 1559 | } |
1290 | } | 1560 | } |
1561 | if (edp) | ||
1562 | cdv_intel_edp_panel_vdd_off(encoder); | ||
1291 | 1563 | ||
1292 | return connector_status_connected; | 1564 | return connector_status_connected; |
1293 | } | 1565 | } |
@@ -1298,6 +1570,7 @@ static int cdv_intel_dp_get_modes(struct drm_connector *connector) | |||
1298 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; | 1570 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; |
1299 | struct edid *edid = NULL; | 1571 | struct edid *edid = NULL; |
1300 | int ret = 0; | 1572 | int ret = 0; |
1573 | int edp = is_edp(intel_encoder); | ||
1301 | 1574 | ||
1302 | 1575 | ||
1303 | edid = drm_get_edid(connector, &intel_dp->adapter); | 1576 | edid = drm_get_edid(connector, &intel_dp->adapter); |
@@ -1307,6 +1580,42 @@ static int cdv_intel_dp_get_modes(struct drm_connector *connector) | |||
1307 | kfree(edid); | 1580 | kfree(edid); |
1308 | } | 1581 | } |
1309 | 1582 | ||
1583 | if (is_edp(intel_encoder)) { | ||
1584 | struct drm_device *dev = connector->dev; | ||
1585 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
1586 | |||
1587 | cdv_intel_edp_panel_vdd_off(intel_encoder); | ||
1588 | if (ret) { | ||
1589 | if (edp && !intel_dp->panel_fixed_mode) { | ||
1590 | struct drm_display_mode *newmode; | ||
1591 | list_for_each_entry(newmode, &connector->probed_modes, | ||
1592 | head) { | ||
1593 | if (newmode->type & DRM_MODE_TYPE_PREFERRED) { | ||
1594 | intel_dp->panel_fixed_mode = | ||
1595 | drm_mode_duplicate(dev, newmode); | ||
1596 | break; | ||
1597 | } | ||
1598 | } | ||
1599 | } | ||
1600 | |||
1601 | return ret; | ||
1602 | } | ||
1603 | if (!intel_dp->panel_fixed_mode && dev_priv->lfp_lvds_vbt_mode) { | ||
1604 | intel_dp->panel_fixed_mode = | ||
1605 | drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); | ||
1606 | if (intel_dp->panel_fixed_mode) { | ||
1607 | intel_dp->panel_fixed_mode->type |= | ||
1608 | DRM_MODE_TYPE_PREFERRED; | ||
1609 | } | ||
1610 | } | ||
1611 | if (intel_dp->panel_fixed_mode != NULL) { | ||
1612 | struct drm_display_mode *mode; | ||
1613 | mode = drm_mode_duplicate(dev, intel_dp->panel_fixed_mode); | ||
1614 | drm_mode_probed_add(connector, mode); | ||
1615 | return 1; | ||
1616 | } | ||
1617 | } | ||
1618 | |||
1310 | return ret; | 1619 | return ret; |
1311 | } | 1620 | } |
1312 | 1621 | ||
@@ -1317,6 +1626,10 @@ cdv_intel_dp_detect_audio(struct drm_connector *connector) | |||
1317 | struct cdv_intel_dp *intel_dp = encoder->dev_priv; | 1626 | struct cdv_intel_dp *intel_dp = encoder->dev_priv; |
1318 | struct edid *edid; | 1627 | struct edid *edid; |
1319 | bool has_audio = false; | 1628 | bool has_audio = false; |
1629 | int edp = is_edp(encoder); | ||
1630 | |||
1631 | if (edp) | ||
1632 | cdv_intel_edp_panel_vdd_on(encoder); | ||
1320 | 1633 | ||
1321 | edid = drm_get_edid(connector, &intel_dp->adapter); | 1634 | edid = drm_get_edid(connector, &intel_dp->adapter); |
1322 | if (edid) { | 1635 | if (edid) { |
@@ -1325,6 +1638,8 @@ cdv_intel_dp_detect_audio(struct drm_connector *connector) | |||
1325 | connector->display_info.raw_edid = NULL; | 1638 | connector->display_info.raw_edid = NULL; |
1326 | kfree(edid); | 1639 | kfree(edid); |
1327 | } | 1640 | } |
1641 | if (edp) | ||
1642 | cdv_intel_edp_panel_vdd_off(encoder); | ||
1328 | 1643 | ||
1329 | return has_audio; | 1644 | return has_audio; |
1330 | } | 1645 | } |
@@ -1386,12 +1701,19 @@ done: | |||
1386 | } | 1701 | } |
1387 | 1702 | ||
1388 | static void | 1703 | static void |
1389 | cdv_intel_dp_destroy (struct drm_connector *connector) | 1704 | cdv_intel_dp_destroy(struct drm_connector *connector) |
1390 | { | 1705 | { |
1391 | struct psb_intel_encoder *psb_intel_encoder = | 1706 | struct psb_intel_encoder *psb_intel_encoder = |
1392 | psb_intel_attached_encoder(connector); | 1707 | psb_intel_attached_encoder(connector); |
1393 | struct cdv_intel_dp *intel_dp = psb_intel_encoder->dev_priv; | 1708 | struct cdv_intel_dp *intel_dp = psb_intel_encoder->dev_priv; |
1394 | 1709 | ||
1710 | if (is_edp(psb_intel_encoder)) { | ||
1711 | /* cdv_intel_panel_destroy_backlight(connector->dev); */ | ||
1712 | if (intel_dp->panel_fixed_mode) { | ||
1713 | kfree(intel_dp->panel_fixed_mode); | ||
1714 | intel_dp->panel_fixed_mode = NULL; | ||
1715 | } | ||
1716 | } | ||
1395 | i2c_del_adapter(&intel_dp->adapter); | 1717 | i2c_del_adapter(&intel_dp->adapter); |
1396 | drm_sysfs_connector_remove(connector); | 1718 | drm_sysfs_connector_remove(connector); |
1397 | drm_connector_cleanup(connector); | 1719 | drm_connector_cleanup(connector); |
@@ -1436,6 +1758,26 @@ static void cdv_intel_dp_add_properties(struct drm_connector *connector) | |||
1436 | cdv_intel_attach_broadcast_rgb_property(connector); | 1758 | cdv_intel_attach_broadcast_rgb_property(connector); |
1437 | } | 1759 | } |
1438 | 1760 | ||
1761 | /* check the VBT to see whether the eDP is on DP-D port */ | ||
1762 | static bool cdv_intel_dpc_is_edp(struct drm_device *dev) | ||
1763 | { | ||
1764 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
1765 | struct child_device_config *p_child; | ||
1766 | int i; | ||
1767 | |||
1768 | if (!dev_priv->child_dev_num) | ||
1769 | return false; | ||
1770 | |||
1771 | for (i = 0; i < dev_priv->child_dev_num; i++) { | ||
1772 | p_child = dev_priv->child_dev + i; | ||
1773 | |||
1774 | if (p_child->dvo_port == PORT_IDPC && | ||
1775 | p_child->device_type == DEVICE_TYPE_eDP) | ||
1776 | return true; | ||
1777 | } | ||
1778 | return false; | ||
1779 | } | ||
1780 | |||
1439 | void | 1781 | void |
1440 | cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, int output_reg) | 1782 | cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, int output_reg) |
1441 | { | 1783 | { |
@@ -1445,6 +1787,7 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev | |||
1445 | struct drm_encoder *encoder; | 1787 | struct drm_encoder *encoder; |
1446 | struct cdv_intel_dp *intel_dp; | 1788 | struct cdv_intel_dp *intel_dp; |
1447 | const char *name = NULL; | 1789 | const char *name = NULL; |
1790 | int type = DRM_MODE_CONNECTOR_DisplayPort; | ||
1448 | 1791 | ||
1449 | psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL); | 1792 | psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL); |
1450 | if (!psb_intel_encoder) | 1793 | if (!psb_intel_encoder) |
@@ -1456,14 +1799,22 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev | |||
1456 | if (!intel_dp) | 1799 | if (!intel_dp) |
1457 | goto err_priv; | 1800 | goto err_priv; |
1458 | 1801 | ||
1802 | if ((output_reg == DP_C) && cdv_intel_dpc_is_edp(dev)) | ||
1803 | type = DRM_MODE_CONNECTOR_eDP; | ||
1804 | |||
1459 | connector = &psb_intel_connector->base; | 1805 | connector = &psb_intel_connector->base; |
1460 | encoder = &psb_intel_encoder->base; | 1806 | encoder = &psb_intel_encoder->base; |
1461 | 1807 | ||
1462 | drm_connector_init(dev, connector, &cdv_intel_dp_connector_funcs, DRM_MODE_CONNECTOR_DisplayPort); | 1808 | drm_connector_init(dev, connector, &cdv_intel_dp_connector_funcs, type); |
1463 | drm_encoder_init(dev, encoder, &cdv_intel_dp_enc_funcs, DRM_MODE_ENCODER_TMDS); | 1809 | drm_encoder_init(dev, encoder, &cdv_intel_dp_enc_funcs, DRM_MODE_ENCODER_TMDS); |
1464 | 1810 | ||
1465 | psb_intel_connector_attach_encoder(psb_intel_connector, psb_intel_encoder); | 1811 | psb_intel_connector_attach_encoder(psb_intel_connector, psb_intel_encoder); |
1466 | psb_intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; | 1812 | |
1813 | if (type == DRM_MODE_CONNECTOR_DisplayPort) | ||
1814 | psb_intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; | ||
1815 | else | ||
1816 | psb_intel_encoder->type = INTEL_OUTPUT_EDP; | ||
1817 | |||
1467 | 1818 | ||
1468 | psb_intel_encoder->dev_priv=intel_dp; | 1819 | psb_intel_encoder->dev_priv=intel_dp; |
1469 | intel_dp->encoder = psb_intel_encoder; | 1820 | intel_dp->encoder = psb_intel_encoder; |
@@ -1493,6 +1844,83 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev | |||
1493 | cdv_intel_dp_i2c_init(psb_intel_connector, psb_intel_encoder, name); | 1844 | cdv_intel_dp_i2c_init(psb_intel_connector, psb_intel_encoder, name); |
1494 | /* FIXME:fail check */ | 1845 | /* FIXME:fail check */ |
1495 | cdv_intel_dp_add_properties(connector); | 1846 | cdv_intel_dp_add_properties(connector); |
1847 | |||
1848 | if (is_edp(psb_intel_encoder)) { | ||
1849 | int ret; | ||
1850 | struct edp_power_seq cur; | ||
1851 | u32 pp_on, pp_off, pp_div; | ||
1852 | u32 pwm_ctrl; | ||
1853 | |||
1854 | pp_on = REG_READ(PP_CONTROL); | ||
1855 | pp_on &= ~PANEL_UNLOCK_MASK; | ||
1856 | pp_on |= PANEL_UNLOCK_REGS; | ||
1857 | |||
1858 | REG_WRITE(PP_CONTROL, pp_on); | ||
1859 | |||
1860 | pwm_ctrl = REG_READ(BLC_PWM_CTL2); | ||
1861 | pwm_ctrl |= PWM_PIPE_B; | ||
1862 | REG_WRITE(BLC_PWM_CTL2, pwm_ctrl); | ||
1863 | |||
1864 | pp_on = REG_READ(PP_ON_DELAYS); | ||
1865 | pp_off = REG_READ(PP_OFF_DELAYS); | ||
1866 | pp_div = REG_READ(PP_DIVISOR); | ||
1867 | |||
1868 | /* Pull timing values out of registers */ | ||
1869 | cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >> | ||
1870 | PANEL_POWER_UP_DELAY_SHIFT; | ||
1871 | |||
1872 | cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >> | ||
1873 | PANEL_LIGHT_ON_DELAY_SHIFT; | ||
1874 | |||
1875 | cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >> | ||
1876 | PANEL_LIGHT_OFF_DELAY_SHIFT; | ||
1877 | |||
1878 | cur.t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >> | ||
1879 | PANEL_POWER_DOWN_DELAY_SHIFT; | ||
1880 | |||
1881 | cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >> | ||
1882 | PANEL_POWER_CYCLE_DELAY_SHIFT); | ||
1883 | |||
1884 | DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n", | ||
1885 | cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12); | ||
1886 | |||
1887 | |||
1888 | intel_dp->panel_power_up_delay = cur.t1_t3 / 10; | ||
1889 | intel_dp->backlight_on_delay = cur.t8 / 10; | ||
1890 | intel_dp->backlight_off_delay = cur.t9 / 10; | ||
1891 | intel_dp->panel_power_down_delay = cur.t10 / 10; | ||
1892 | intel_dp->panel_power_cycle_delay = (cur.t11_t12 - 1) * 100; | ||
1893 | |||
1894 | DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n", | ||
1895 | intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay, | ||
1896 | intel_dp->panel_power_cycle_delay); | ||
1897 | |||
1898 | DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", | ||
1899 | intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); | ||
1900 | |||
1901 | |||
1902 | cdv_intel_edp_panel_vdd_on(psb_intel_encoder); | ||
1903 | ret = cdv_intel_dp_aux_native_read(psb_intel_encoder, DP_DPCD_REV, | ||
1904 | intel_dp->dpcd, | ||
1905 | sizeof(intel_dp->dpcd)); | ||
1906 | cdv_intel_edp_panel_vdd_off(psb_intel_encoder); | ||
1907 | if (ret == 0) { | ||
1908 | /* if this fails, presume the device is a ghost */ | ||
1909 | DRM_INFO("failed to retrieve link info, disabling eDP\n"); | ||
1910 | cdv_intel_dp_encoder_destroy(encoder); | ||
1911 | cdv_intel_dp_destroy(connector); | ||
1912 | goto err_priv; | ||
1913 | } else { | ||
1914 | DRM_DEBUG_KMS("DPCD: Rev=%x LN_Rate=%x LN_CNT=%x LN_DOWNSP=%x\n", | ||
1915 | intel_dp->dpcd[0], intel_dp->dpcd[1], | ||
1916 | intel_dp->dpcd[2], intel_dp->dpcd[3]); | ||
1917 | |||
1918 | } | ||
1919 | /* The CDV reference driver moves pnale backlight setup into the displays that | ||
1920 | have a backlight: this is a good idea and one we should probably adopt, however | ||
1921 | we need to migrate all the drivers before we can do that */ | ||
1922 | /*cdv_intel_panel_setup_backlight(dev); */ | ||
1923 | } | ||
1496 | return; | 1924 | return; |
1497 | 1925 | ||
1498 | err_priv: | 1926 | err_priv: |