From 20f4dbe45950e462aa7c3243f95c0d8bcc369ca0 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 30 Aug 2013 19:40:28 +0300 Subject: drm/i915: expose intel_ddi_get_encoder_port() In preparation for followup work. Signed-off-by: Jani Nikula Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 63aca49d11a..060ea5096e5 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -58,7 +58,7 @@ static const u32 hsw_ddi_translations_fdi[] = { 0x00FFFFFF, 0x00040006 /* HDMI parameters */ }; -static enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) +enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) { struct drm_encoder *encoder = &intel_encoder->base; int type = intel_encoder->type; -- cgit v1.2.3-70-g09d2 From a666283e9061c58fc888ddf1d9fc552123f1f014 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Sep 2013 17:03:41 +0300 Subject: drm/i915: Fix HSW sync flags to use pipe config adjusted_mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_ddi_enable_transcoder_func() picked the sync flags from crtc->mode instead of the pipe config adjusted_mode. Fix the problem and hopefully rid my HSW machine of the remaining pipe config warnings. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 060ea5096e5..67880f264c6 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -767,9 +767,9 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) BUG(); } - if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC) + if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_PVSYNC) temp |= TRANS_DDI_PVSYNC; - if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC) + if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_PHSYNC) temp |= TRANS_DDI_PHSYNC; if (cpu_transcoder == TRANSCODER_EDP) { -- cgit v1.2.3-70-g09d2 From 42571aefafb1d330ef84eb29418832f72e7dfb4c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 6 Sep 2013 23:29:00 +0300 Subject: drm/i915: Add support for pipe_bpp readout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On CTG+ read out the pipe bpp setting from hardware and fill it into pipe config. Also check it appropriately. v2: Don't do the pipe_bpp extraction inside the PCH only code block on ILK+. Avoid the PIPECONF read as we already have read it for the PIPECONF_EANBLE check. Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 17 +++++++++++++++++ drivers/gpu/drm/i915/intel_display.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 67880f264c6..d5215e2db42 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1268,6 +1268,23 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, flags |= DRM_MODE_FLAG_NVSYNC; pipe_config->adjusted_mode.flags |= flags; + + switch (temp & TRANS_DDI_BPC_MASK) { + case TRANS_DDI_BPC_6: + pipe_config->pipe_bpp = 18; + break; + case TRANS_DDI_BPC_8: + pipe_config->pipe_bpp = 24; + break; + case TRANS_DDI_BPC_10: + pipe_config->pipe_bpp = 30; + break; + case TRANS_DDI_BPC_12: + pipe_config->pipe_bpp = 36; + break; + default: + break; + } } static void intel_ddi_destroy(struct drm_encoder *encoder) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f1b3d33320d..1f280cc7b1e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4997,6 +4997,22 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, if (!(tmp & PIPECONF_ENABLE)) return false; + if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) { + switch (tmp & PIPECONF_BPC_MASK) { + case PIPECONF_6BPC: + pipe_config->pipe_bpp = 18; + break; + case PIPECONF_8BPC: + pipe_config->pipe_bpp = 24; + break; + case PIPECONF_10BPC: + pipe_config->pipe_bpp = 30; + break; + default: + break; + } + } + intel_get_pipe_timings(crtc, pipe_config); i9xx_get_pfit_config(crtc, pipe_config); @@ -5895,6 +5911,23 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, if (!(tmp & PIPECONF_ENABLE)) return false; + switch (tmp & PIPECONF_BPC_MASK) { + case PIPECONF_6BPC: + pipe_config->pipe_bpp = 18; + break; + case PIPECONF_8BPC: + pipe_config->pipe_bpp = 24; + break; + case PIPECONF_10BPC: + pipe_config->pipe_bpp = 30; + break; + case PIPECONF_12BPC: + pipe_config->pipe_bpp = 36; + break; + default: + break; + } + if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) { struct intel_shared_dpll *pll; @@ -8624,6 +8657,9 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_X(dpll_hw_state.fp0); PIPE_CONF_CHECK_X(dpll_hw_state.fp1); + if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) + PIPE_CONF_CHECK_I(pipe_bpp); + #undef PIPE_CONF_CHECK_X #undef PIPE_CONF_CHECK_I #undef PIPE_CONF_CHECK_FLAGS -- cgit v1.2.3-70-g09d2 From eb14cb747bc53465cbc93e54d9f19f49eed2c0c7 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Sep 2013 17:02:54 +0300 Subject: drm/i915: Add state readout and checking for has_dp_encoder and dp_m_n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add functions to read out the CPU and PCH transcoder M/N values, and use them to fill out the pipe config dp_m_n information. And while at it populate has_dp_encoder too. Also refactor ironlake_get_fdi_m_n_config() to simply call the new intel_cpu_transcoder_get_m_n() function. v2: Remember the DDI Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 14 +++++++ drivers/gpu/drm/i915/intel_display.c | 76 +++++++++++++++++++++++++++++++----- drivers/gpu/drm/i915/intel_dp.c | 4 ++ drivers/gpu/drm/i915/intel_drv.h | 2 + 4 files changed, 86 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index d5215e2db42..491899539aa 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1285,6 +1285,20 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, default: break; } + + switch (temp & TRANS_DDI_MODE_SELECT_MASK) { + case TRANS_DDI_MODE_SELECT_HDMI: + case TRANS_DDI_MODE_SELECT_DVI: + case TRANS_DDI_MODE_SELECT_FDI: + break; + case TRANS_DDI_MODE_SELECT_DP_SST: + case TRANS_DDI_MODE_SELECT_DP_MST: + pipe_config->has_dp_encoder = true; + intel_dp_get_m_n(intel_crtc, pipe_config); + break; + default: + break; + } } static void intel_ddi_destroy(struct drm_encoder *encoder) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1f280cc7b1e..a4f24346d0b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5858,20 +5858,64 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, return ret; } -static void ironlake_get_fdi_m_n_config(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) +static void intel_pch_transcoder_get_m_n(struct intel_crtc *crtc, + struct intel_link_m_n *m_n) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe = crtc->pipe; + + m_n->link_m = I915_READ(PCH_TRANS_LINK_M1(pipe)); + m_n->link_n = I915_READ(PCH_TRANS_LINK_N1(pipe)); + m_n->gmch_m = I915_READ(PCH_TRANS_DATA_M1(pipe)) + & ~TU_SIZE_MASK; + m_n->gmch_n = I915_READ(PCH_TRANS_DATA_N1(pipe)); + m_n->tu = ((I915_READ(PCH_TRANS_DATA_M1(pipe)) + & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1; +} + +static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc, + enum transcoder transcoder, + struct intel_link_m_n *m_n) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - enum transcoder transcoder = pipe_config->cpu_transcoder; + enum pipe pipe = crtc->pipe; + + if (INTEL_INFO(dev)->gen >= 5) { + m_n->link_m = I915_READ(PIPE_LINK_M1(transcoder)); + m_n->link_n = I915_READ(PIPE_LINK_N1(transcoder)); + m_n->gmch_m = I915_READ(PIPE_DATA_M1(transcoder)) + & ~TU_SIZE_MASK; + m_n->gmch_n = I915_READ(PIPE_DATA_N1(transcoder)); + m_n->tu = ((I915_READ(PIPE_DATA_M1(transcoder)) + & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1; + } else { + m_n->link_m = I915_READ(PIPE_LINK_M_G4X(pipe)); + m_n->link_n = I915_READ(PIPE_LINK_N_G4X(pipe)); + m_n->gmch_m = I915_READ(PIPE_DATA_M_G4X(pipe)) + & ~TU_SIZE_MASK; + m_n->gmch_n = I915_READ(PIPE_DATA_N_G4X(pipe)); + m_n->tu = ((I915_READ(PIPE_DATA_M_G4X(pipe)) + & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1; + } +} + +void intel_dp_get_m_n(struct intel_crtc *crtc, + struct intel_crtc_config *pipe_config) +{ + if (crtc->config.has_pch_encoder) + intel_pch_transcoder_get_m_n(crtc, &pipe_config->dp_m_n); + else + intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder, + &pipe_config->dp_m_n); +} - pipe_config->fdi_m_n.link_m = I915_READ(PIPE_LINK_M1(transcoder)); - pipe_config->fdi_m_n.link_n = I915_READ(PIPE_LINK_N1(transcoder)); - pipe_config->fdi_m_n.gmch_m = I915_READ(PIPE_DATA_M1(transcoder)) - & ~TU_SIZE_MASK; - pipe_config->fdi_m_n.gmch_n = I915_READ(PIPE_DATA_N1(transcoder)); - pipe_config->fdi_m_n.tu = ((I915_READ(PIPE_DATA_M1(transcoder)) - & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1; +static void ironlake_get_fdi_m_n_config(struct intel_crtc *crtc, + struct intel_crtc_config *pipe_config) +{ + intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder, + &pipe_config->fdi_m_n); } static void ironlake_get_pfit_config(struct intel_crtc *crtc, @@ -8239,6 +8283,11 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, pipe_config->fdi_m_n.gmch_m, pipe_config->fdi_m_n.gmch_n, pipe_config->fdi_m_n.link_m, pipe_config->fdi_m_n.link_n, pipe_config->fdi_m_n.tu); + DRM_DEBUG_KMS("dp: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n", + pipe_config->has_dp_encoder, + pipe_config->dp_m_n.gmch_m, pipe_config->dp_m_n.gmch_n, + pipe_config->dp_m_n.link_m, pipe_config->dp_m_n.link_n, + pipe_config->dp_m_n.tu); DRM_DEBUG_KMS("requested mode:\n"); drm_mode_debug_printmodeline(&pipe_config->requested_mode); DRM_DEBUG_KMS("adjusted mode:\n"); @@ -8608,6 +8657,13 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_I(fdi_m_n.link_n); PIPE_CONF_CHECK_I(fdi_m_n.tu); + PIPE_CONF_CHECK_I(has_dp_encoder); + PIPE_CONF_CHECK_I(dp_m_n.gmch_m); + PIPE_CONF_CHECK_I(dp_m_n.gmch_n); + PIPE_CONF_CHECK_I(dp_m_n.link_m); + PIPE_CONF_CHECK_I(dp_m_n.link_n); + PIPE_CONF_CHECK_I(dp_m_n.tu); + PIPE_CONF_CHECK_I(adjusted_mode.crtc_hdisplay); PIPE_CONF_CHECK_I(adjusted_mode.crtc_htotal); PIPE_CONF_CHECK_I(adjusted_mode.crtc_hblank_start); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8c70a833950..9ba697cc149 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1444,6 +1444,10 @@ static void intel_dp_get_config(struct intel_encoder *encoder, pipe_config->adjusted_mode.flags |= flags; + pipe_config->has_dp_encoder = true; + + intel_dp_get_m_n(crtc, pipe_config); + if (dp_to_dig_port(intel_dp)->port == PORT_A) { if ((I915_READ(DP_A) & DP_PLL_FREQ_MASK) == DP_PLL_FREQ_160MHZ) pipe_config->port_clock = 162000; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index b6393e2a2a5..f6d5c920f89 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -801,5 +801,7 @@ extern void hsw_pc8_disable_interrupts(struct drm_device *dev); extern void hsw_pc8_restore_interrupts(struct drm_device *dev); extern void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv); extern void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv); +extern void intel_dp_get_m_n(struct intel_crtc *crtc, + struct intel_crtc_config *pipe_config); #endif /* __INTEL_DRV_H__ */ -- cgit v1.2.3-70-g09d2 From b14c5679dd2c87b5bd14c49c5bdd1962be2ab209 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 19 Sep 2013 12:18:32 +0200 Subject: drm/i915: use pointer = k[cmz...]alloc(sizeof(*pointer), ...) pattern Done while reviewing all our allocations for fubar. Also a few errant cases of lacking () for the sizeof operator - just a bit of OCD. I've left out all the conversions that also should use kcalloc from this patch (it's only 2). Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_dma.c | 6 +++--- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/intel_crt.c | 2 +- drivers/gpu/drm/i915/intel_ddi.c | 6 +++--- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_dp.c | 4 ++-- drivers/gpu/drm/i915/intel_dvo.c | 4 ++-- drivers/gpu/drm/i915/intel_fb.c | 2 +- drivers/gpu/drm/i915/intel_hdmi.c | 4 ++-- drivers/gpu/drm/i915/intel_lvds.c | 4 ++-- drivers/gpu/drm/i915/intel_overlay.c | 4 ++-- drivers/gpu/drm/i915/intel_pm.c | 2 +- drivers/gpu/drm/i915/intel_sdvo.c | 10 +++++----- drivers/gpu/drm/i915/intel_sprite.c | 2 +- drivers/gpu/drm/i915/intel_tv.c | 4 ++-- 16 files changed, 30 insertions(+), 30 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 80bed69fe5b..09c93d7989f 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2156,7 +2156,7 @@ drm_add_fake_info_node(struct drm_minor *minor, { struct drm_info_node *node; - node = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL); + node = kmalloc(sizeof(*node), GFP_KERNEL); if (node == NULL) { debugfs_remove(ent); return -ENOMEM; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 512645fdaff..aa69c735298 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -641,7 +641,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, if (batch->num_cliprects) { cliprects = kcalloc(batch->num_cliprects, - sizeof(struct drm_clip_rect), + sizeof(*cliprects), GFP_KERNEL); if (cliprects == NULL) return -ENOMEM; @@ -703,7 +703,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, if (cmdbuf->num_cliprects) { cliprects = kcalloc(cmdbuf->num_cliprects, - sizeof(struct drm_clip_rect), GFP_KERNEL); + sizeof(*cliprects), GFP_KERNEL); if (cliprects == NULL) { ret = -ENOMEM; goto fail_batch_free; @@ -1480,7 +1480,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev->types[8] = _DRM_STAT_SECONDARY; dev->types[9] = _DRM_STAT_DMA; - dev_priv = kzalloc(sizeof(drm_i915_private_t), GFP_KERNEL); + dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); if (dev_priv == NULL) return -ENOMEM; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 36c4ad9c752..96f65a15ffc 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4638,7 +4638,7 @@ static int i915_gem_init_phys_object(struct drm_device *dev, if (dev_priv->mm.phys_objs[id - 1] || !size) return 0; - phys_obj = kzalloc(sizeof(struct drm_i915_gem_phys_object), GFP_KERNEL); + phys_obj = kzalloc(sizeof(*phys_obj), GFP_KERNEL); if (!phys_obj) return -ENOMEM; diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 6f101d5620e..f9a5f3d1f0c 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -764,7 +764,7 @@ void intel_crt_init(struct drm_device *dev) if (!crt) return; - intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); + intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); if (!intel_connector) { kfree(crt); return; diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 04f68804834..351e21a0be0 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1337,11 +1337,11 @@ void intel_ddi_init(struct drm_device *dev, enum port port) struct intel_connector *hdmi_connector = NULL; struct intel_connector *dp_connector = NULL; - intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL); + intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); if (!intel_dig_port) return; - dp_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); + dp_connector = kzalloc(sizeof(*dp_connector), GFP_KERNEL); if (!dp_connector) { kfree(intel_dig_port); return; @@ -1381,7 +1381,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) } if (intel_encoder->type != INTEL_OUTPUT_EDP) { - hdmi_connector = kzalloc(sizeof(struct intel_connector), + hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL); if (!hdmi_connector) { return; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bef786461a3..96a0924ed75 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8097,7 +8097,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, fb->pitches[0] != crtc->fb->pitches[0])) return -EINVAL; - work = kzalloc(sizeof *work, GFP_KERNEL); + work = kzalloc(sizeof(*work), GFP_KERNEL); if (work == NULL) return -ENOMEM; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 60d2006fe15..7e4052ea99c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3625,11 +3625,11 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) struct drm_encoder *encoder; struct intel_connector *intel_connector; - intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL); + intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); if (!intel_dig_port) return; - intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); + intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); if (!intel_connector) { kfree(intel_dig_port); return; diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index ff86c366218..6305433797a 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -448,11 +448,11 @@ void intel_dvo_init(struct drm_device *dev) int i; int encoder_type = DRM_MODE_ENCODER_NONE; - intel_dvo = kzalloc(sizeof(struct intel_dvo), GFP_KERNEL); + intel_dvo = kzalloc(sizeof(*intel_dvo), GFP_KERNEL); if (!intel_dvo) return; - intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); + intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); if (!intel_connector) { kfree(intel_dvo); return; diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index bc2100007b2..6aa66aaceae 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -216,7 +216,7 @@ int intel_fbdev_init(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int ret; - ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL); + ifbdev = kzalloc(sizeof(*ifbdev), GFP_KERNEL); if (!ifbdev) return -ENOMEM; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 79582f91241..a6310ca444c 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1292,11 +1292,11 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) struct intel_encoder *intel_encoder; struct intel_connector *intel_connector; - intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL); + intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); if (!intel_dig_port) return; - intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); + intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); if (!intel_connector) { kfree(intel_dig_port); return; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 05e5485a630..639650c66e5 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -948,11 +948,11 @@ void intel_lvds_init(struct drm_device *dev) } } - lvds_encoder = kzalloc(sizeof(struct intel_lvds_encoder), GFP_KERNEL); + lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL); if (!lvds_encoder) return; - lvds_connector = kzalloc(sizeof(struct intel_lvds_connector), GFP_KERNEL); + lvds_connector = kzalloc(sizeof(*lvds_connector), GFP_KERNEL); if (!lvds_connector) { kfree(lvds_encoder); return; diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 8d6d0a1bf5b..a98a990fbab 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -1053,7 +1053,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, return ret; } - params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL); + params = kmalloc(sizeof(*params), GFP_KERNEL); if (!params) return -ENOMEM; @@ -1320,7 +1320,7 @@ void intel_setup_overlay(struct drm_device *dev) if (!HAS_OVERLAY(dev)) return; - overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL); + overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); if (!overlay) return; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4692f8cb772..d27eda66154 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -370,7 +370,7 @@ static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval) intel_cancel_fbc_work(dev_priv); - work = kzalloc(sizeof *work, GFP_KERNEL); + work = kzalloc(sizeof(*work), GFP_KERNEL); if (work == NULL) { DRM_ERROR("Failed to allocate FBC work structure\n"); dev_priv->display.enable_fbc(crtc, interval); diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 91aea9e1ab6..d8040e8a68b 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2397,7 +2397,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); + intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); if (!intel_sdvo_connector) return false; @@ -2445,7 +2445,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); + intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); if (!intel_sdvo_connector) return false; @@ -2482,7 +2482,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device) struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); + intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); if (!intel_sdvo_connector) return false; @@ -2513,7 +2513,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); + intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); if (!intel_sdvo_connector) return false; @@ -2879,7 +2879,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) struct intel_encoder *intel_encoder; struct intel_sdvo *intel_sdvo; int i; - intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL); + intel_sdvo = kzalloc(sizeof(*intel_sdvo), GFP_KERNEL); if (!intel_sdvo) return false; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 231b289e8e5..cae10bc746d 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1034,7 +1034,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) if (INTEL_INFO(dev)->gen < 5) return -ENODEV; - intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL); + intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); if (!intel_plane) return -ENOMEM; diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index dd6f84bf6c2..e6e93ce34f7 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1590,12 +1590,12 @@ intel_tv_init(struct drm_device *dev) (tv_dac_off & TVDAC_STATE_CHG_EN) != 0) return; - intel_tv = kzalloc(sizeof(struct intel_tv), GFP_KERNEL); + intel_tv = kzalloc(sizeof(*intel_tv), GFP_KERNEL); if (!intel_tv) { return; } - intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); + intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); if (!intel_connector) { kfree(intel_tv); return; -- cgit v1.2.3-70-g09d2 From 6acab15a7b0d2722924c5d671cb29974791beece Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 12 Sep 2013 17:06:24 -0300 Subject: drm/i915: use the HDMI DDI buffer translations from VBT We currently use the recommended values from BSpec, but the VBT specifies the correct value to use for the hardware we have, so use it. We also fall back to the recommended value in case we can't find the VBT. In addition, this code also provides some infrastructure to parse more information about the DDI ports. There's a lot more information we could extract and use in the future. v2: - Move some code to init_vbt_defaults. v3: - Rebase - Clarify the "DVO Port" matching code v4: - Use I915_MAX_PORTS - Change the HAS_DDI checks - Replace DRM_ERROR with DRM_DEBUG_KMS Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 6 +++ drivers/gpu/drm/i915/intel_bios.c | 77 +++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_bios.h | 13 +++++++ drivers/gpu/drm/i915/intel_ddi.c | 24 +++++++++++- 4 files changed, 118 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9868a66ef59..2eca286b57f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1057,6 +1057,10 @@ enum modeset_restore { MODESET_SUSPENDED, }; +struct ddi_vbt_port_info { + uint8_t hdmi_level_shift; +}; + struct intel_vbt_data { struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ @@ -1091,6 +1095,8 @@ struct intel_vbt_data { int child_dev_num; union child_device_config *child_dev; + + struct ddi_vbt_port_info ddi_port_info[I915_MAX_PORTS]; }; enum intel_ddb_partitioning { diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 33003b97f1f..2f434297246 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -583,6 +583,76 @@ parse_mipi(struct drm_i915_private *dev_priv, struct bdb_header *bdb) dev_priv->vbt.dsi.panel_id = mipi->panel_id; } +static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, + struct bdb_header *bdb) +{ + union child_device_config *it, *child = NULL; + struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port]; + uint8_t hdmi_level_shift; + int i, j; + /* Each DDI port can have more than one value on the "DVO Port" field, + * so look for all the possible values for each port and abort if more + * than one is found. */ + int dvo_ports[][2] = { + {DVO_PORT_HDMIA, DVO_PORT_DPA}, + {DVO_PORT_HDMIB, DVO_PORT_DPB}, + {DVO_PORT_HDMIC, DVO_PORT_DPC}, + {DVO_PORT_HDMID, DVO_PORT_DPD}, + {DVO_PORT_CRT, -1 /* Port E can only be DVO_PORT_CRT */ }, + }; + + /* Find the child device to use, abort if more than one found. */ + for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { + it = dev_priv->vbt.child_dev + i; + + for (j = 0; j < 2; j++) { + if (dvo_ports[port][j] == -1) + break; + + if (it->common.dvo_port == dvo_ports[port][j]) { + if (child) { + DRM_DEBUG_KMS("More than one child device for port %c in VBT.\n", + port_name(port)); + return; + } + child = it; + } + } + } + if (!child) + return; + + if (bdb->version >= 158) { + /* The VBT HDMI level shift values match the table we have. */ + hdmi_level_shift = child->raw[7] & 0xF; + if (hdmi_level_shift < 0xC) { + DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n", + port_name(port), + hdmi_level_shift); + info->hdmi_level_shift = hdmi_level_shift; + } + } +} + +static void parse_ddi_ports(struct drm_i915_private *dev_priv, + struct bdb_header *bdb) +{ + struct drm_device *dev = dev_priv->dev; + enum port port; + + if (!HAS_DDI(dev)) + return; + + if (!dev_priv->vbt.child_dev_num) + return; + + if (bdb->version < 155) + return; + + for (port = PORT_A; port < I915_MAX_PORTS; port++) + parse_ddi_port(dev_priv, port, bdb); +} + static void parse_device_mapping(struct drm_i915_private *dev_priv, struct bdb_header *bdb) @@ -652,6 +722,7 @@ static void init_vbt_defaults(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; + enum port port; dev_priv->vbt.crt_ddc_pin = GMBUS_PORT_VGADDC; @@ -670,6 +741,11 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) dev_priv->vbt.lvds_use_ssc = 1; dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1); DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq); + + for (port = PORT_A; port < I915_MAX_PORTS; port++) { + /* Recommended BSpec default: 800mV 0dB. */ + dev_priv->vbt.ddi_port_info[port].hdmi_level_shift = 6; + } } static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id) @@ -761,6 +837,7 @@ intel_parse_bios(struct drm_device *dev) parse_driver_features(dev_priv, bdb); parse_edp(dev_priv, bdb); parse_mipi(dev_priv, bdb); + parse_ddi_ports(dev_priv, bdb); if (bios) pci_unmap_rom(pdev, bios); diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 1da2bf20829..287cc5a21c2 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -648,6 +648,19 @@ int intel_parse_bios(struct drm_device *dev); #define PORT_IDPC 8 #define PORT_IDPD 9 +/* Possible values for the "DVO Port" field for versions >= 155: */ +#define DVO_PORT_HDMIA 0 +#define DVO_PORT_HDMIB 1 +#define DVO_PORT_HDMIC 2 +#define DVO_PORT_HDMID 3 +#define DVO_PORT_LVDS 4 +#define DVO_PORT_TV 5 +#define DVO_PORT_CRT 6 +#define DVO_PORT_DPB 7 +#define DVO_PORT_DPC 8 +#define DVO_PORT_DPD 9 +#define DVO_PORT_DPA 10 + /* MIPI DSI panel info */ struct bdb_mipi { u16 panel_id; diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 351e21a0be0..963245a104e 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -42,7 +42,6 @@ static const u32 hsw_ddi_translations_dp[] = { 0x80C30FFF, 0x000B0000, 0x00FFFFFF, 0x00040006, 0x80D75FFF, 0x000B0000, - 0x00FFFFFF, 0x00040006 /* HDMI parameters */ }; static const u32 hsw_ddi_translations_fdi[] = { @@ -55,7 +54,22 @@ static const u32 hsw_ddi_translations_fdi[] = { 0x00C30FFF, 0x001E0000, 0x00FFFFFF, 0x00060006, 0x00D75FFF, 0x001E0000, - 0x00FFFFFF, 0x00040006 /* HDMI parameters */ +}; + +static const u32 hsw_ddi_translations_hdmi[] = { + /* Idx NT mV diff T mV diff db */ + 0x00FFFFFF, 0x0006000E, /* 0: 400 400 0 */ + 0x00E79FFF, 0x000E000C, /* 1: 400 500 2 */ + 0x00D75FFF, 0x0005000A, /* 2: 400 600 3.5 */ + 0x00FFFFFF, 0x0005000A, /* 3: 600 600 0 */ + 0x00E79FFF, 0x001D0007, /* 4: 600 750 2 */ + 0x00D75FFF, 0x000C0004, /* 5: 600 900 3.5 */ + 0x00FFFFFF, 0x00040006, /* 6: 800 800 0 */ + 0x80E79FFF, 0x00030002, /* 7: 800 1000 2 */ + 0x00FFFFFF, 0x00140005, /* 8: 850 850 0 */ + 0x00FFFFFF, 0x000C0004, /* 9: 900 900 0 */ + 0x00FFFFFF, 0x001C0003, /* 10: 950 950 0 */ + 0x80FFFFFF, 0x00030002, /* 11: 1000 1000 0 */ }; enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) @@ -92,12 +106,18 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) const u32 *ddi_translations = (port == PORT_E) ? hsw_ddi_translations_fdi : hsw_ddi_translations_dp; + int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; for (i = 0, reg = DDI_BUF_TRANS(port); i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) { I915_WRITE(reg, ddi_translations[i]); reg += 4; } + /* Entry 9 is for HDMI: */ + for (i = 0; i < 2; i++) { + I915_WRITE(reg, hsw_ddi_translations_hdmi[hdmi_level * 2 + i]); + reg += 4; + } } /* Program DDI buffers translations for DP. By default, program ports A-D in DP -- cgit v1.2.3-70-g09d2 From 311a20949f047a70935d6591010f42336f5402e7 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 12 Sep 2013 17:12:18 -0300 Subject: drm/i915: don't init DP or HDMI when not supported by DDI port There's no reason to init a DP connector if the encoder just supports HDMI: we'll just waste hundreds and hundreds of cycles trying to do DP AUX transactions to detect if there's something there. Same goes for a DP connector that doesn't support HDMI, but I'm not sure these actually exist. v2: - Use bit fields - Remove useless identation level - Replace DRM_ERROR with DRM_DEBUG_KMS Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi (v1) Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 4 ++++ drivers/gpu/drm/i915/intel_bios.c | 13 ++++++++++++- drivers/gpu/drm/i915/intel_ddi.c | 20 ++++++++++++++++---- 3 files changed, 32 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2eca286b57f..b1485a008b0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1059,6 +1059,10 @@ enum modeset_restore { struct ddi_vbt_port_info { uint8_t hdmi_level_shift; + + uint8_t supports_dvi:1; + uint8_t supports_hdmi:1; + uint8_t supports_dp:1; }; struct intel_vbt_data { diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 7ce1c3c2f0f..0492b6fff10 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -632,6 +632,10 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, is_hdmi = is_dvi && (child->common.device_type & (1 << 11)) == 0; is_edp = is_dp && (child->common.device_type & (1 << 12)); + info->supports_dvi = is_dvi; + info->supports_hdmi = is_hdmi; + info->supports_dp = is_dp; + DRM_DEBUG_KMS("Port %c VBT info: DP:%d HDMI:%d DVI:%d EDP:%d CRT:%d\n", port_name(port), is_dp, is_hdmi, is_dvi, is_edp, is_crt); @@ -792,8 +796,15 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq); for (port = PORT_A; port < I915_MAX_PORTS; port++) { + struct ddi_vbt_port_info *info = + &dev_priv->vbt.ddi_port_info[port]; + /* Recommended BSpec default: 800mV 0dB. */ - dev_priv->vbt.ddi_port_info[port].hdmi_level_shift = 6; + info->hdmi_level_shift = 6; + + info->supports_dvi = (port != PORT_A && port != PORT_E); + info->supports_hdmi = info->supports_dvi; + info->supports_dp = (port != PORT_E); } } diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 963245a104e..7e9fa53a147 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1356,6 +1356,17 @@ void intel_ddi_init(struct drm_device *dev, enum port port) struct drm_encoder *encoder; struct intel_connector *hdmi_connector = NULL; struct intel_connector *dp_connector = NULL; + bool init_hdmi, init_dp; + + init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi || + dev_priv->vbt.ddi_port_info[port].supports_hdmi); + init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp; + if (!init_dp && !init_hdmi) { + DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible\n", + port_name(port)); + init_hdmi = true; + init_dp = true; + } intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); if (!intel_dig_port) @@ -1393,19 +1404,20 @@ void intel_ddi_init(struct drm_device *dev, enum port port) intel_encoder->cloneable = false; intel_encoder->hot_plug = intel_ddi_hot_plug; - if (!intel_dp_init_connector(intel_dig_port, dp_connector)) { + if (init_dp && !intel_dp_init_connector(intel_dig_port, dp_connector)) { drm_encoder_cleanup(encoder); kfree(intel_dig_port); kfree(dp_connector); return; } - if (intel_encoder->type != INTEL_OUTPUT_EDP) { + /* In theory we don't need the encoder->type check, but leave it just in + * case we have some really bad VBTs... */ + if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi) { hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL); - if (!hdmi_connector) { + if (!hdmi_connector) return; - } intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port); intel_hdmi_init_connector(intel_dig_port, hdmi_connector); -- cgit v1.2.3-70-g09d2 From 6801c18c0a43386bb44712cbc028a7e05adb9f0d Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 24 Sep 2013 14:24:05 +0300 Subject: drm/i915: Add HSW CRT output readout support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Call intel_ddi_get_config() to get the pipe_bpp settings from DDI. The sync polarity settings from DDI are irrelevant for CRT output, so override them with data from the ADPA register. v2: Extract intel_crt_get_flags() Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=69691 Tested-by: Qingshuai Tian Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_crt.c | 34 ++++++++++++++++++++++++++++------ drivers/gpu/drm/i915/intel_ddi.c | 4 ++-- drivers/gpu/drm/i915/intel_drv.h | 2 ++ 3 files changed, 32 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index f9a5f3d1f0c..019c4cea7bb 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -83,13 +83,11 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder, return true; } -static void intel_crt_get_config(struct intel_encoder *encoder, - struct intel_crtc_config *pipe_config) +static unsigned int intel_crt_get_flags(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_crt *crt = intel_encoder_to_crt(encoder); u32 tmp, flags = 0; - int dotclock; tmp = I915_READ(crt->adpa_reg); @@ -103,16 +101,37 @@ static void intel_crt_get_config(struct intel_encoder *encoder, else flags |= DRM_MODE_FLAG_NVSYNC; - pipe_config->adjusted_mode.flags |= flags; + return flags; +} + +static void intel_crt_get_config(struct intel_encoder *encoder, + struct intel_crtc_config *pipe_config) +{ + struct drm_device *dev = encoder->base.dev; + int dotclock; + + pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder); dotclock = pipe_config->port_clock; - if (HAS_PCH_SPLIT(dev_priv->dev)) + if (HAS_PCH_SPLIT(dev)) ironlake_check_encoder_dotclock(pipe_config, dotclock); pipe_config->adjusted_mode.clock = dotclock; } +static void hsw_crt_get_config(struct intel_encoder *encoder, + struct intel_crtc_config *pipe_config) +{ + intel_ddi_get_config(encoder, pipe_config); + + pipe_config->adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC | + DRM_MODE_FLAG_NHSYNC | + DRM_MODE_FLAG_PVSYNC | + DRM_MODE_FLAG_NVSYNC); + pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder); +} + /* Note: The caller is required to filter out dpms modes not supported by the * platform. */ static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode) @@ -804,7 +823,10 @@ void intel_crt_init(struct drm_device *dev) crt->base.mode_set = intel_crt_mode_set; crt->base.disable = intel_disable_crt; crt->base.enable = intel_enable_crt; - crt->base.get_config = intel_crt_get_config; + if (IS_HASWELL(dev)) + crt->base.get_config = hsw_crt_get_config; + else + crt->base.get_config = intel_crt_get_config; if (I915_HAS_HOTPLUG(dev)) crt->base.hpd_pin = HPD_CRT; if (HAS_DDI(dev)) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 7e9fa53a147..a43ac3a17bd 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1269,8 +1269,8 @@ static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder) intel_dp_check_link_status(intel_dp); } -static void intel_ddi_get_config(struct intel_encoder *encoder, - struct intel_crtc_config *pipe_config) +void intel_ddi_get_config(struct intel_encoder *encoder, + struct intel_crtc_config *pipe_config) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index fb38ef10ac5..e7fe5f1f72d 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -828,5 +828,7 @@ extern void ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe extern bool intel_crtc_active(struct drm_crtc *crtc); extern void i915_disable_vga_mem(struct drm_device *dev); +extern void intel_ddi_get_config(struct intel_encoder *encoder, + struct intel_crtc_config *pipe_config); #endif /* __INTEL_DRV_H__ */ -- cgit v1.2.3-70-g09d2 From 6aba5b6cf098ba305fc31b23cc14114a16768d22 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 4 Oct 2013 15:08:10 +0300 Subject: drm/i915/dp: get rid of intel_dp->link_configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's not really needed, rather just adds another place to hold intermediate values that could go wrong, and it's not clear that the training pattern set or training lane set should be written at this point at all. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/intel_ddi.c | 5 +---- drivers/gpu/drm/i915/intel_dp.c | 34 ++++++++++++---------------------- drivers/gpu/drm/i915/intel_drv.h | 3 --- 3 files changed, 13 insertions(+), 29 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 04f68804834..9792ea8df13 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -296,9 +296,6 @@ static void intel_ddi_mode_set(struct intel_encoder *encoder) DRM_DEBUG_DRIVER("DP audio: write eld information\n"); intel_write_eld(&encoder->base, adjusted_mode); } - - intel_dp_init_link_config(intel_dp); - } else if (type == INTEL_OUTPUT_HDMI) { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); @@ -1202,7 +1199,7 @@ void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder) val = DP_TP_CTL_ENABLE | DP_TP_CTL_MODE_SST | DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE; - if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN) + if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE; I915_WRITE(DP_TP_CTL(port), val); POSTING_READ(DP_TP_CTL(port)); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3575b86ca79..5f0c783027c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -876,21 +876,6 @@ found: return true; } -void intel_dp_init_link_config(struct intel_dp *intel_dp) -{ - memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); - intel_dp->link_configuration[0] = intel_dp->link_bw; - intel_dp->link_configuration[1] = intel_dp->lane_count; - intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B; - /* - * Check for DPCD version > 1.1 and enhanced framing support - */ - if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 && - (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) { - intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; - } -} - static void ironlake_set_pll_cpu_edp(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -963,8 +948,6 @@ static void intel_dp_mode_set(struct intel_encoder *encoder) intel_write_eld(&encoder->base, adjusted_mode); } - intel_dp_init_link_config(intel_dp); - /* Split out the IBX/CPU vs CPT settings */ if (port == PORT_A && IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) { @@ -974,7 +957,7 @@ static void intel_dp_mode_set(struct intel_encoder *encoder) intel_dp->DP |= DP_SYNC_VS_HIGH; intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; - if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN) + if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) intel_dp->DP |= DP_ENHANCED_FRAMING; intel_dp->DP |= crtc->pipe << 29; @@ -988,7 +971,7 @@ static void intel_dp_mode_set(struct intel_encoder *encoder) intel_dp->DP |= DP_SYNC_VS_HIGH; intel_dp->DP |= DP_LINK_TRAIN_OFF; - if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN) + if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) intel_dp->DP |= DP_ENHANCED_FRAMING; if (crtc->pipe == 1) @@ -2444,14 +2427,21 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) uint8_t voltage; int voltage_tries, loop_tries; uint32_t DP = intel_dp->DP; + uint8_t link_config[2]; if (HAS_DDI(dev)) intel_ddi_prepare_link_retrain(encoder); /* Write the link configuration data */ - intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, - intel_dp->link_configuration, - DP_LINK_CONFIGURATION_SIZE); + link_config[0] = intel_dp->link_bw; + link_config[1] = intel_dp->lane_count; + if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) + link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, link_config, 2); + + link_config[0] = 0; + link_config[1] = DP_SET_ANSI_8B10B; + intel_dp_aux_native_write(intel_dp, DP_DOWNSPREAD_CTRL, link_config, 2); DP |= DP_PORT_EN; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 4b75328462e..287bbef72da 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -437,13 +437,11 @@ struct intel_hdmi { }; #define DP_MAX_DOWNSTREAM_PORTS 0x10 -#define DP_LINK_CONFIGURATION_SIZE 9 struct intel_dp { uint32_t output_reg; uint32_t aux_ch_ctl_reg; uint32_t DP; - uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; bool has_audio; enum hdmi_force_audio force_audio; uint32_t color_range; @@ -548,7 +546,6 @@ extern void intel_dp_init(struct drm_device *dev, int output_reg, enum port port); extern bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port, struct intel_connector *intel_connector); -extern void intel_dp_init_link_config(struct intel_dp *intel_dp); extern void intel_dp_start_link_train(struct intel_dp *intel_dp); extern void intel_dp_complete_link_train(struct intel_dp *intel_dp); extern void intel_dp_stop_link_train(struct intel_dp *intel_dp); -- cgit v1.2.3-70-g09d2 From 4a28ae58c0abad2d45a45db21e86c7166b2b4462 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Wed, 9 Oct 2013 13:52:36 -0300 Subject: drm/i915: don't leak dp_connector at intel_ddi_init Regression introduced by: commit 311a20949f047a70935d6591010f42336f5402e7 Author: Paulo Zanoni drm/i915: don't init DP or HDMI when not supported by DDI port Since the commit above it is possible to have a DDI encoder that has the HDMI connector but not the DP connector (in case the port doesn't support DP). In this case, we must properly free the DP connector. We just leak this once, so it's not a big deal. Reported by kmemleak. Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 62 +++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 20 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 6d335f8ca34..31f4fe27138 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1345,6 +1345,41 @@ static const struct drm_encoder_funcs intel_ddi_funcs = { .destroy = intel_ddi_destroy, }; +static struct intel_connector * +intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port) +{ + struct intel_connector *connector; + enum port port = intel_dig_port->port; + + connector = kzalloc(sizeof(*connector), GFP_KERNEL); + if (!connector) + return NULL; + + intel_dig_port->dp.output_reg = DDI_BUF_CTL(port); + if (!intel_dp_init_connector(intel_dig_port, connector)) { + kfree(connector); + return NULL; + } + + return connector; +} + +static struct intel_connector * +intel_ddi_init_hdmi_connector(struct intel_digital_port *intel_dig_port) +{ + struct intel_connector *connector; + enum port port = intel_dig_port->port; + + connector = kzalloc(sizeof(*connector), GFP_KERNEL); + if (!connector) + return NULL; + + intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port); + intel_hdmi_init_connector(intel_dig_port, connector); + + return connector; +} + void intel_ddi_init(struct drm_device *dev, enum port port) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -1369,12 +1404,6 @@ void intel_ddi_init(struct drm_device *dev, enum port port) if (!intel_dig_port) return; - dp_connector = kzalloc(sizeof(*dp_connector), GFP_KERNEL); - if (!dp_connector) { - kfree(intel_dig_port); - return; - } - intel_encoder = &intel_dig_port->base; encoder = &intel_encoder->base; @@ -1394,29 +1423,22 @@ void intel_ddi_init(struct drm_device *dev, enum port port) intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) & (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES); - intel_dig_port->dp.output_reg = DDI_BUF_CTL(port); intel_encoder->type = INTEL_OUTPUT_UNKNOWN; intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->cloneable = false; intel_encoder->hot_plug = intel_ddi_hot_plug; - if (init_dp && !intel_dp_init_connector(intel_dig_port, dp_connector)) { - drm_encoder_cleanup(encoder); - kfree(intel_dig_port); - kfree(dp_connector); - return; - } + if (init_dp) + dp_connector = intel_ddi_init_dp_connector(intel_dig_port); /* In theory we don't need the encoder->type check, but leave it just in * case we have some really bad VBTs... */ - if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi) { - hdmi_connector = kzalloc(sizeof(*hdmi_connector), - GFP_KERNEL); - if (!hdmi_connector) - return; + if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi) + hdmi_connector = intel_ddi_init_hdmi_connector(intel_dig_port); - intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port); - intel_hdmi_init_connector(intel_dig_port, hdmi_connector); + if (!dp_connector && !hdmi_connector) { + drm_encoder_cleanup(encoder); + kfree(intel_dig_port); } } -- cgit v1.2.3-70-g09d2 From c7670b1098b1a05c5266a7d3d2f07165621e7de9 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Sat, 2 Nov 2013 21:07:37 -0700 Subject: drm/i915/bdw: on Broadwell, the panel fitter is on the pipe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So you can use the panel fitter while the power well is disabled and you also don't need to set the "pipe" bit. v2: Rebased on top of Jesse's pfit refactor, which moved pfit state into the pipe_config. v3: Rebase on top of the latest Haswell/panel fitter rework, which neatly resolves a FIXME we have in this patch here: v4: Rebase on top of the new power domain framework. Signed-off-by: Paulo Zanoni (v1) Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 31f4fe27138..0598669f84e 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -756,7 +756,8 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); struct drm_encoder *encoder = &intel_encoder->base; - struct drm_i915_private *dev_priv = crtc->dev->dev_private; + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; enum pipe pipe = intel_crtc->pipe; enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; enum port port = intel_ddi_get_encoder_port(intel_encoder); @@ -792,10 +793,11 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) if (cpu_transcoder == TRANSCODER_EDP) { switch (pipe) { case PIPE_A: - /* Can only use the always-on power well for eDP when - * not using the panel fitter, and when not using motion - * blur mitigation (which we don't support). */ - if (intel_crtc->config.pch_pfit.enabled) + /* On Haswell, can only use the always-on power well for + * eDP when not using the panel fitter, and when not + * using motion blur mitigation (which we don't + * support). */ + if (IS_HASWELL(dev) && intel_crtc->config.pch_pfit.enabled) temp |= TRANS_DDI_EDP_INPUT_A_ONOFF; else temp |= TRANS_DDI_EDP_INPUT_A_ON; -- cgit v1.2.3-70-g09d2 From e39bf98a91abd5c8fb290f139521dddc3db3c37d Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Sat, 2 Nov 2013 21:07:36 -0700 Subject: drm/i915/bdw: get the correct LCPLL frequency on Broadwell MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2: Rebased onto Paulo's MHz->kHz change. v3: Rebased on top of the Haswell pc8+ adjustements. v4: Use the exact 337.5MHz clock, should have been done as part of v2. Reviewed-by: Jani Nikula Signed-off-by: Paulo Zanoni (v1) Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_ddi.c | 25 ++++++++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a4a41f5df46..0b7983b87ce 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5315,6 +5315,9 @@ #define LCPLL_PLL_LOCK (1<<30) #define LCPLL_CLK_FREQ_MASK (3<<26) #define LCPLL_CLK_FREQ_450 (0<<26) +#define LCPLL_CLK_FREQ_54O_BDW (1<<26) +#define LCPLL_CLK_FREQ_337_5_BDW (2<<26) +#define LCPLL_CLK_FREQ_675_BDW (3<<26) #define LCPLL_CD_CLOCK_DISABLE (1<<25) #define LCPLL_CD2X_CLOCK_DISABLE (1<<23) #define LCPLL_POWER_DOWN_ALLOW (1<<22) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 0598669f84e..060add6468e 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1158,18 +1158,29 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder) int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv) { + struct drm_device *dev = dev_priv->dev; uint32_t lcpll = I915_READ(LCPLL_CTL); + uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; - if (lcpll & LCPLL_CD_SOURCE_FCLK) + if (lcpll & LCPLL_CD_SOURCE_FCLK) { return 800000; - else if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT) + } else if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT) { return 450000; - else if ((lcpll & LCPLL_CLK_FREQ_MASK) == LCPLL_CLK_FREQ_450) + } else if (freq == LCPLL_CLK_FREQ_450) { return 450000; - else if (IS_ULT(dev_priv->dev)) - return 337500; - else - return 540000; + } else if (IS_HASWELL(dev)) { + if (IS_ULT(dev)) + return 337500; + else + return 540000; + } else { + if (freq == LCPLL_CLK_FREQ_54O_BDW) + return 540000; + else if (freq == LCPLL_CLK_FREQ_337_5_BDW) + return 337500; + else + return 675000; + } } void intel_ddi_pll_init(struct drm_device *dev) -- cgit v1.2.3-70-g09d2 From e58623cb65dfa40f0ed9f6f9ddbca91aee3c9bd2 Mon Sep 17 00:00:00 2001 From: Art Runyan Date: Sat, 2 Nov 2013 21:07:41 -0700 Subject: drm/i915/bdw: Add BDW DDI buffer translation values Many of the DDI buffer translation values have changed for BDW. Add new translation tables and selection between HSW and BDW. v2: s/BUG/WARN/ to avoid breaking future GENs. v3: Rebase on top of the hdmi translation table changes. v4: Fix up the multiline comment while at it. Signed-off-by: Art Runyan (v2) Reviewed-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 53 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 060add6468e..bebc17730a4 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -72,6 +72,32 @@ static const u32 hsw_ddi_translations_hdmi[] = { 0x80FFFFFF, 0x00030002, /* 11: 1000 1000 0 */ }; +static const u32 bdw_ddi_translations_dp[] = { + 0x00FFFFFF, 0x0007000E, /* DP parameters */ + 0x00D75FFF, 0x000E000A, + 0x00BEFFFF, 0x00140006, + 0x00FFFFFF, 0x000E000A, + 0x00D75FFF, 0x00180004, + 0x80CB2FFF, 0x001B0002, + 0x00F7DFFF, 0x00180004, + 0x80D75FFF, 0x001B0002, + 0x80FFFFFF, 0x001B0002, + 0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/ +}; + +static const u32 bdw_ddi_translations_fdi[] = { + 0x00FFFFFF, 0x0001000E, /* FDI parameters */ + 0x00D75FFF, 0x0004000A, + 0x00C30FFF, 0x00070006, + 0x00AAAFFF, 0x000C0000, + 0x00FFFFFF, 0x0004000A, + 0x00D75FFF, 0x00090004, + 0x00C30FFF, 0x000C0000, + 0x00FFFFFF, 0x00070006, + 0x00D75FFF, 0x000C0000, + 0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/ +}; + enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) { struct drm_encoder *encoder = &intel_encoder->base; @@ -92,8 +118,9 @@ enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) } } -/* On Haswell, DDI port buffers must be programmed with correct values - * in advance. The buffer values are different for FDI and DP modes, +/* + * Starting with Haswell, DDI port buffers must be programmed with correct + * values in advance. The buffer values are different for FDI and DP modes, * but the HDMI/DVI fields are shared among those. So we program the DDI * in either FDI or DP modes only, as HDMI connections will work with both * of those @@ -103,10 +130,26 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) struct drm_i915_private *dev_priv = dev->dev_private; u32 reg; int i; - const u32 *ddi_translations = (port == PORT_E) ? - hsw_ddi_translations_fdi : - hsw_ddi_translations_dp; int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; + const u32 *ddi_translations_fdi; + const u32 *ddi_translations_dp; + const u32 *ddi_translations; + + if (IS_BROADWELL(dev)) { + ddi_translations_fdi = bdw_ddi_translations_fdi; + ddi_translations_dp = bdw_ddi_translations_dp; + } else if (IS_HASWELL(dev)) { + ddi_translations_fdi = hsw_ddi_translations_fdi; + ddi_translations_dp = hsw_ddi_translations_dp; + } else { + WARN(1, "ddi translation table missing\n"); + ddi_translations_fdi = bdw_ddi_translations_fdi; + ddi_translations_dp = bdw_ddi_translations_dp; + } + + ddi_translations = ((port == PORT_E) ? + ddi_translations_fdi : + ddi_translations_dp); for (i = 0, reg = DDI_BUF_TRANS(port); i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) { -- cgit v1.2.3-70-g09d2 From 300644c7dc4699fe9afb61b280aa5ed7109a4d93 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Sat, 2 Nov 2013 21:07:42 -0700 Subject: drm/i915/bdw: add BDW DDI buf translations for eDP Broadwell has different DDI buffer translations for eDP and DP, so add support for the missing eDP and keep Haswell the same. A future patch addresses the suggestion from Art to check for eDP on port D and use the eDP values there, too. v2: Make checkpatch happy. Reviewed-by: Art Runyan Signed-off-by: Paulo Zanoni (v1) Reviewed-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index bebc17730a4..87c55c7cb09 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -72,6 +72,19 @@ static const u32 hsw_ddi_translations_hdmi[] = { 0x80FFFFFF, 0x00030002, /* 11: 1000 1000 0 */ }; +static const u32 bdw_ddi_translations_edp[] = { + 0x00FFFFFF, 0x00000012, /* DP parameters */ + 0x00EBAFFF, 0x00020011, + 0x00C71FFF, 0x0006000F, + 0x00FFFFFF, 0x00020011, + 0x00DB6FFF, 0x0005000F, + 0x00BEEFFF, 0x000A000C, + 0x00FFFFFF, 0x0005000F, + 0x00DB6FFF, 0x000A000C, + 0x00FFFFFF, 0x000A000C, + 0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/ +}; + static const u32 bdw_ddi_translations_dp[] = { 0x00FFFFFF, 0x0007000E, /* DP parameters */ 0x00D75FFF, 0x000E000A, @@ -133,23 +146,39 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; const u32 *ddi_translations_fdi; const u32 *ddi_translations_dp; + const u32 *ddi_translations_edp; const u32 *ddi_translations; if (IS_BROADWELL(dev)) { ddi_translations_fdi = bdw_ddi_translations_fdi; ddi_translations_dp = bdw_ddi_translations_dp; + ddi_translations_edp = bdw_ddi_translations_edp; } else if (IS_HASWELL(dev)) { ddi_translations_fdi = hsw_ddi_translations_fdi; ddi_translations_dp = hsw_ddi_translations_dp; + ddi_translations_edp = hsw_ddi_translations_dp; } else { WARN(1, "ddi translation table missing\n"); + ddi_translations_edp = bdw_ddi_translations_dp; ddi_translations_fdi = bdw_ddi_translations_fdi; ddi_translations_dp = bdw_ddi_translations_dp; } - ddi_translations = ((port == PORT_E) ? - ddi_translations_fdi : - ddi_translations_dp); + switch (port) { + case PORT_A: + ddi_translations = ddi_translations_edp; + break; + case PORT_B: + case PORT_C: + case PORT_D: + ddi_translations = ddi_translations_dp; + break; + case PORT_E: + ddi_translations = ddi_translations_fdi; + break; + default: + BUG(); + } for (i = 0, reg = DDI_BUF_TRANS(port); i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) { -- cgit v1.2.3-70-g09d2 From 77d8d00944dd5a0a2f4f67809819df927ee23030 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Sat, 2 Nov 2013 21:07:45 -0700 Subject: drm/i915/bdw: check DPD on port D when setting the DDI buffers Use the eDP values on platforms where port D is eDP. This doesn't affect Haswell since it uses the same DDI buffer values for eDP and DP. Reviewed-by: Art Runyan Signed-off-by: Paulo Zanoni Reviewed-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 87c55c7cb09..1591576a610 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -170,9 +170,14 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) break; case PORT_B: case PORT_C: - case PORT_D: ddi_translations = ddi_translations_dp; break; + case PORT_D: + if (intel_dpd_is_edp(dev)) + ddi_translations = ddi_translations_edp; + else + ddi_translations = ddi_translations_dp; + break; case PORT_E: ddi_translations = ddi_translations_fdi; break; -- cgit v1.2.3-70-g09d2