From f71ab1589efbf238311e8006638b8f2f208408bf Mon Sep 17 00:00:00 2001 From: Zhao Yakui <yakui.zhao@intel.com> Date: Tue, 25 May 2010 21:20:20 +0800 Subject: [PATCH] drm/i915: Add the support of eDP on DP-D Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> --- drivers/gpu/drm/i915/intel_display.c | 4 +- drivers/gpu/drm/i915/intel_dp.c | 82 ++++++++++++++++++++++++++++++--- drivers/gpu/drm/i915/intel_drv.h | 1 + 3 files changed, 78 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c7502b6..6239f55 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3088,7 +3088,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, temp |= PIPE_12BPC; break; } - } else + } else if (is_dp) + temp |= intel_dp_bpc(crtc); + else temp |= PIPE_8BPC; I915_WRITE(pipeconf_reg, temp); I915_READ(pipeconf_reg); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 77e40cf..6d14d47 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -58,6 +58,8 @@ struct intel_dp_priv { struct intel_encoder *intel_encoder; struct i2c_adapter adapter; struct i2c_algo_dp_aux_data algo; + uint8_t dp_bpp; + bool is_edp; }; static void @@ -130,11 +132,12 @@ intel_dp_link_required(struct drm_device *dev, struct intel_encoder *intel_encoder, int pixel_clock) { struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_dp_priv *dp_priv = intel_encoder->dev_priv; if (IS_eDP(intel_encoder)) return (pixel_clock * dev_priv->edp_bpp) / 8; else - return pixel_clock * 3; + return (pixel_clock * dp_priv->dp_bpp) / 8; } static int @@ -534,14 +537,14 @@ intel_reduce_ratio(uint32_t *num, uint32_t *den) } static void -intel_dp_compute_m_n(int bytes_per_pixel, +intel_dp_compute_m_n(int bpp, int nlanes, int pixel_clock, int link_clock, struct intel_dp_m_n *m_n) { m_n->tu = 64; - m_n->gmch_m = pixel_clock * bytes_per_pixel; + m_n->gmch_m = (pixel_clock * bpp) >> 3; m_n->gmch_n = link_clock * nlanes; intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); m_n->link_m = pixel_clock; @@ -549,6 +552,33 @@ intel_dp_compute_m_n(int bytes_per_pixel, intel_reduce_ratio(&m_n->link_m, &m_n->link_n); } +int intel_dp_bpc(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_connector *connector; + struct drm_i915_private *dev_priv = dev->dev_private; + int ret = PIPE_8BPC; + + /* + * Find the lane count in the intel_encoder private + */ + list_for_each_entry(connector, &mode_config->connector_list, head) { + struct intel_encoder *intel_encoder = to_intel_encoder(connector); + struct intel_dp_priv *dp_priv = intel_encoder->dev_priv; + + if (!connector->encoder || connector->encoder->crtc != crtc) + continue; + + if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) { + if (dp_priv->dp_bpp == 18) + ret = PIPE_6BPC; + break; + } + } + return ret; +} + void intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -558,7 +588,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_connector *connector; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int lane_count = 4; + int lane_count = 4, bpp = 24; struct intel_dp_m_n m_n; /* @@ -573,6 +603,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) { lane_count = dp_priv->lane_count; + bpp = dp_priv->dp_bpp; break; } } @@ -582,7 +613,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, * the number of bytes_per_pixel post-LUT, which we always * set up for 8-bits of R/G/B, or 3 bytes total. */ - intel_dp_compute_m_n(3, lane_count, + intel_dp_compute_m_n(bpp, lane_count, mode->clock, adjusted_mode->clock, &m_n); if (HAS_PCH_SPLIT(dev)) { @@ -1299,6 +1330,28 @@ intel_dp_hot_plug(struct intel_encoder *intel_encoder) intel_dp_check_link_status(intel_encoder); } +static bool intel_dpd_is_edp(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct child_device_config *p_child; + int i, ret = false; + + if (!dev_priv->child_dev_num) + return false; + + for (i = 0; i < dev_priv->child_dev_num; i++) { + p_child = dev_priv->child_dev + i; + if (p_child->device_type != DEVICE_TYPE_eDP) + continue; + + if (p_child->dvo_port == PORT_IDPD) { + ret = true; + break; + } + } + return ret; +} + void intel_dp_init(struct drm_device *dev, int output_reg) { @@ -1320,11 +1373,16 @@ intel_dp_init(struct drm_device *dev, int output_reg) DRM_MODE_CONNECTOR_DisplayPort); drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs); - if (output_reg == DP_A) + if (output_reg == DP_A) { intel_encoder->type = INTEL_OUTPUT_EDP; - else + dp_priv->is_edp = true; + dp_priv->dp_bpp = dev_priv->edp_bpp; + } else { intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; - + dp_priv->is_edp = false; + dp_priv->dp_bpp = 24; + /* default color depth is 24 */ + } if (output_reg == DP_B || output_reg == PCH_DP_B) intel_encoder->clone_mask = (1 << INTEL_DP_B_CLONE_BIT); else if (output_reg == DP_C || output_reg == PCH_DP_C) @@ -1335,6 +1393,14 @@ intel_dp_init(struct drm_device *dev, int output_reg) if (IS_eDP(intel_encoder)) intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT); + if (HAS_PCH_SPLIT(dev) && (output_reg == PCH_DP_D)) { + /* judge whether the DP-D is eDP */ + if (intel_dpd_is_edp(dev)) { + dp_priv->is_edp = true; + dp_priv->dp_bpp = dev_priv->edp_bpp; + } + } + intel_encoder->crtc_mask = (1 << 0) | (1 << 1); connector->interlace_allowed = true; connector->doublescan_allowed = 0; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index e302537..8769f4e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -175,6 +175,7 @@ extern void intel_dp_init(struct drm_device *dev, int dp_reg); void intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); +extern int intel_dp_bpc(struct drm_crtc *crtc); extern void intel_edp_link_config (struct intel_encoder *, int *, int *); -- 1.5.4.5