aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/intel_ddi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ddi.c')
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c115
1 files changed, 75 insertions, 40 deletions
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index b63d4fa204a3..68703cecdefc 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -95,8 +95,8 @@ static const struct ddi_buf_trans bdw_ddi_translations_dp[] = {
{ 0x00BEFFFF, 0x00140006 },
{ 0x80B2CFFF, 0x001B0002 },
{ 0x00FFFFFF, 0x000E000A },
- { 0x00D75FFF, 0x00180004 },
- { 0x80CB2FFF, 0x001B0002 },
+ { 0x00DB6FFF, 0x00160005 },
+ { 0x80C71FFF, 0x001A0002 },
{ 0x00F7DFFF, 0x00180004 },
{ 0x80D75FFF, 0x001B0002 },
};
@@ -127,6 +127,32 @@ static const struct ddi_buf_trans bdw_ddi_translations_hdmi[] = {
{ 0x80FFFFFF, 0x001B0002 }, /* 9: 1000 1000 0 */
};
+static const struct ddi_buf_trans skl_ddi_translations_dp[] = {
+ { 0x00000018, 0x000000a0 },
+ { 0x00004014, 0x00000098 },
+ { 0x00006012, 0x00000088 },
+ { 0x00008010, 0x00000080 },
+ { 0x00000018, 0x00000098 },
+ { 0x00004014, 0x00000088 },
+ { 0x00006012, 0x00000080 },
+ { 0x00000018, 0x00000088 },
+ { 0x00004014, 0x00000080 },
+};
+
+static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = {
+ /* Idx NT mV T mV db */
+ { 0x00000018, 0x000000a0 }, /* 0: 400 400 0 */
+ { 0x00004014, 0x00000098 }, /* 1: 400 600 3.5 */
+ { 0x00006012, 0x00000088 }, /* 2: 400 800 6 */
+ { 0x00000018, 0x0000003c }, /* 3: 450 450 0 */
+ { 0x00000018, 0x00000098 }, /* 4: 600 600 0 */
+ { 0x00003015, 0x00000088 }, /* 5: 600 800 2.5 */
+ { 0x00005013, 0x00000080 }, /* 6: 600 1000 4.5 */
+ { 0x00000018, 0x00000088 }, /* 7: 800 800 0 */
+ { 0x00000096, 0x00000080 }, /* 8: 800 1000 2 */
+ { 0x00000018, 0x00000080 }, /* 9: 1200 1200 0 */
+};
+
enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
{
struct drm_encoder *encoder = &intel_encoder->base;
@@ -169,7 +195,14 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
const struct ddi_buf_trans *ddi_translations_hdmi;
const struct ddi_buf_trans *ddi_translations;
- if (IS_BROADWELL(dev)) {
+ if (IS_SKYLAKE(dev)) {
+ ddi_translations_fdi = NULL;
+ ddi_translations_dp = skl_ddi_translations_dp;
+ ddi_translations_edp = skl_ddi_translations_dp;
+ ddi_translations_hdmi = skl_ddi_translations_hdmi;
+ n_hdmi_entries = ARRAY_SIZE(skl_ddi_translations_hdmi);
+ hdmi_800mV_0dB = 7;
+ } else 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;
@@ -208,7 +241,10 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
ddi_translations = ddi_translations_dp;
break;
case PORT_E:
- ddi_translations = ddi_translations_fdi;
+ if (ddi_translations_fdi)
+ ddi_translations = ddi_translations_fdi;
+ else
+ ddi_translations = ddi_translations_dp;
break;
default:
BUG();
@@ -423,6 +459,27 @@ intel_ddi_get_crtc_encoder(struct drm_crtc *crtc)
return ret;
}
+static struct intel_encoder *
+intel_ddi_get_crtc_new_encoder(struct intel_crtc *crtc)
+{
+ struct drm_device *dev = crtc->base.dev;
+ struct intel_encoder *intel_encoder, *ret = NULL;
+ int num_encoders = 0;
+
+ for_each_intel_encoder(dev, intel_encoder) {
+ if (intel_encoder->new_crtc == crtc) {
+ ret = intel_encoder;
+ num_encoders++;
+ }
+ }
+
+ WARN(num_encoders != 1, "%d encoders on crtc for pipe %c\n", num_encoders,
+ pipe_name(crtc->pipe));
+
+ BUG_ON(ret == NULL);
+ return ret;
+}
+
#define LC_FREQ 2700
#define LC_FREQ_2K U64_C(LC_FREQ * 2000)
@@ -756,7 +813,7 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
WRPLL_DIVIDER_POST(p);
- intel_crtc->config.dpll_hw_state.wrpll = val;
+ intel_crtc->new_config->dpll_hw_state.wrpll = val;
pll = intel_get_shared_dpll(intel_crtc);
if (pll == NULL) {
@@ -765,7 +822,7 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
return false;
}
- intel_crtc->config.ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id);
+ intel_crtc->new_config->ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id);
}
return true;
@@ -781,11 +838,9 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
*/
bool intel_ddi_pll_select(struct intel_crtc *intel_crtc)
{
- struct drm_crtc *crtc = &intel_crtc->base;
- struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
- int clock = intel_crtc->config.port_clock;
-
- intel_put_shared_dpll(intel_crtc);
+ struct intel_encoder *intel_encoder =
+ intel_ddi_get_crtc_new_encoder(intel_crtc);
+ int clock = intel_crtc->new_config->port_clock;
return hsw_ddi_pll_select(intel_crtc, intel_encoder, clock);
}
@@ -962,7 +1017,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
uint32_t tmp;
power_domain = intel_display_port_power_domain(intel_encoder);
- if (!intel_display_power_enabled(dev_priv, power_domain))
+ if (!intel_display_power_is_enabled(dev_priv, power_domain))
return false;
if (!intel_encoder->get_hw_state(intel_encoder, &pipe))
@@ -1008,7 +1063,7 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
int i;
power_domain = intel_display_port_power_domain(encoder);
- if (!intel_display_power_enabled(dev_priv, power_domain))
+ if (!intel_display_power_is_enabled(dev_priv, power_domain))
return false;
tmp = I915_READ(DDI_BUF_CTL(port));
@@ -1084,15 +1139,6 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
enum port port = intel_ddi_get_encoder_port(intel_encoder);
int type = intel_encoder->type;
- if (crtc->config.has_audio) {
- DRM_DEBUG_DRIVER("Audio on pipe %c on DDI\n",
- pipe_name(crtc->pipe));
-
- /* write eld */
- DRM_DEBUG_DRIVER("DDI audio: write eld information\n");
- intel_write_eld(encoder, &crtc->config.adjusted_mode);
- }
-
if (type == INTEL_OUTPUT_EDP) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
intel_edp_panel_on(intel_dp);
@@ -1159,12 +1205,10 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
struct drm_encoder *encoder = &intel_encoder->base;
struct drm_crtc *crtc = encoder->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- int pipe = intel_crtc->pipe;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
enum port port = intel_ddi_get_encoder_port(intel_encoder);
int type = intel_encoder->type;
- uint32_t tmp;
if (type == INTEL_OUTPUT_HDMI) {
struct intel_digital_port *intel_dig_port =
@@ -1189,9 +1233,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
if (intel_crtc->config.has_audio) {
intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
- tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
- tmp |= ((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << (pipe * 4));
- I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
+ intel_audio_codec_enable(intel_encoder);
}
}
@@ -1200,19 +1242,12 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
struct drm_encoder *encoder = &intel_encoder->base;
struct drm_crtc *crtc = encoder->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- int pipe = intel_crtc->pipe;
int type = intel_encoder->type;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- uint32_t tmp;
- /* We can't touch HSW_AUD_PIN_ELD_CP_VLD uncionditionally because this
- * register is part of the power well on Haswell. */
if (intel_crtc->config.has_audio) {
- tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
- tmp &= ~((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) <<
- (pipe * 4));
- I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
+ intel_audio_codec_disable(intel_encoder);
intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
}
@@ -1255,7 +1290,7 @@ static int hsw_get_cdclk_freq(struct drm_i915_private *dev_priv)
return 450000;
else if (freq == LCPLL_CLK_FREQ_450)
return 450000;
- else if (IS_ULT(dev))
+ else if (IS_HSW_ULT(dev))
return 337500;
else
return 540000;
@@ -1275,7 +1310,7 @@ int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv)
static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll)
{
- I915_WRITE(WRPLL_CTL(pll->id), pll->hw_state.wrpll);
+ I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll);
POSTING_READ(WRPLL_CTL(pll->id));
udelay(20);
}
@@ -1296,7 +1331,7 @@ static bool hsw_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
{
uint32_t val;
- if (!intel_display_power_enabled(dev_priv, POWER_DOMAIN_PLLS))
+ if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
return false;
val = I915_READ(WRPLL_CTL(pll->id));
@@ -1486,9 +1521,9 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
break;
}
- if (intel_display_power_enabled(dev_priv, POWER_DOMAIN_AUDIO)) {
+ if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) {
temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
- if (temp & (AUDIO_OUTPUT_ENABLE_A << (intel_crtc->pipe * 4)))
+ if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe))
pipe_config->has_audio = true;
}