diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ddi.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_ddi.c | 91 |
1 files changed, 65 insertions, 26 deletions
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index dd1d6fe12297..1a7efac65fd5 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
@@ -145,7 +145,7 @@ static const struct ddi_buf_trans skl_ddi_translations_dp[] = { | |||
145 | static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = { | 145 | static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = { |
146 | { 0x0000201B, 0x000000A2, 0x0 }, | 146 | { 0x0000201B, 0x000000A2, 0x0 }, |
147 | { 0x00005012, 0x00000088, 0x0 }, | 147 | { 0x00005012, 0x00000088, 0x0 }, |
148 | { 0x80007011, 0x000000CD, 0x0 }, | 148 | { 0x80007011, 0x000000CD, 0x1 }, |
149 | { 0x80009010, 0x000000C0, 0x1 }, | 149 | { 0x80009010, 0x000000C0, 0x1 }, |
150 | { 0x0000201B, 0x0000009D, 0x0 }, | 150 | { 0x0000201B, 0x0000009D, 0x0 }, |
151 | { 0x80005012, 0x000000C0, 0x1 }, | 151 | { 0x80005012, 0x000000C0, 0x1 }, |
@@ -158,7 +158,7 @@ static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = { | |||
158 | static const struct ddi_buf_trans skl_y_ddi_translations_dp[] = { | 158 | static const struct ddi_buf_trans skl_y_ddi_translations_dp[] = { |
159 | { 0x00000018, 0x000000A2, 0x0 }, | 159 | { 0x00000018, 0x000000A2, 0x0 }, |
160 | { 0x00005012, 0x00000088, 0x0 }, | 160 | { 0x00005012, 0x00000088, 0x0 }, |
161 | { 0x80007011, 0x000000CD, 0x0 }, | 161 | { 0x80007011, 0x000000CD, 0x3 }, |
162 | { 0x80009010, 0x000000C0, 0x3 }, | 162 | { 0x80009010, 0x000000C0, 0x3 }, |
163 | { 0x00000018, 0x0000009D, 0x0 }, | 163 | { 0x00000018, 0x0000009D, 0x0 }, |
164 | { 0x80005012, 0x000000C0, 0x3 }, | 164 | { 0x80005012, 0x000000C0, 0x3 }, |
@@ -388,6 +388,40 @@ skl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries) | |||
388 | } | 388 | } |
389 | } | 389 | } |
390 | 390 | ||
391 | static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port) | ||
392 | { | ||
393 | int n_hdmi_entries; | ||
394 | int hdmi_level; | ||
395 | int hdmi_default_entry; | ||
396 | |||
397 | hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; | ||
398 | |||
399 | if (IS_BROXTON(dev_priv)) | ||
400 | return hdmi_level; | ||
401 | |||
402 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { | ||
403 | skl_get_buf_trans_hdmi(dev_priv, &n_hdmi_entries); | ||
404 | hdmi_default_entry = 8; | ||
405 | } else if (IS_BROADWELL(dev_priv)) { | ||
406 | n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); | ||
407 | hdmi_default_entry = 7; | ||
408 | } else if (IS_HASWELL(dev_priv)) { | ||
409 | n_hdmi_entries = ARRAY_SIZE(hsw_ddi_translations_hdmi); | ||
410 | hdmi_default_entry = 6; | ||
411 | } else { | ||
412 | WARN(1, "ddi translation table missing\n"); | ||
413 | n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); | ||
414 | hdmi_default_entry = 7; | ||
415 | } | ||
416 | |||
417 | /* Choose a good default if VBT is badly populated */ | ||
418 | if (hdmi_level == HDMI_LEVEL_SHIFT_UNKNOWN || | ||
419 | hdmi_level >= n_hdmi_entries) | ||
420 | hdmi_level = hdmi_default_entry; | ||
421 | |||
422 | return hdmi_level; | ||
423 | } | ||
424 | |||
391 | /* | 425 | /* |
392 | * Starting with Haswell, DDI port buffers must be programmed with correct | 426 | * Starting with Haswell, DDI port buffers must be programmed with correct |
393 | * values in advance. The buffer values are different for FDI and DP modes, | 427 | * values in advance. The buffer values are different for FDI and DP modes, |
@@ -399,7 +433,7 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder) | |||
399 | { | 433 | { |
400 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | 434 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
401 | u32 iboost_bit = 0; | 435 | u32 iboost_bit = 0; |
402 | int i, n_hdmi_entries, n_dp_entries, n_edp_entries, hdmi_default_entry, | 436 | int i, n_hdmi_entries, n_dp_entries, n_edp_entries, |
403 | size; | 437 | size; |
404 | int hdmi_level; | 438 | int hdmi_level; |
405 | enum port port; | 439 | enum port port; |
@@ -410,7 +444,7 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder) | |||
410 | const struct ddi_buf_trans *ddi_translations; | 444 | const struct ddi_buf_trans *ddi_translations; |
411 | 445 | ||
412 | port = intel_ddi_get_encoder_port(encoder); | 446 | port = intel_ddi_get_encoder_port(encoder); |
413 | hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; | 447 | hdmi_level = intel_ddi_hdmi_level(dev_priv, port); |
414 | 448 | ||
415 | if (IS_BROXTON(dev_priv)) { | 449 | if (IS_BROXTON(dev_priv)) { |
416 | if (encoder->type != INTEL_OUTPUT_HDMI) | 450 | if (encoder->type != INTEL_OUTPUT_HDMI) |
@@ -430,7 +464,6 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder) | |||
430 | skl_get_buf_trans_edp(dev_priv, &n_edp_entries); | 464 | skl_get_buf_trans_edp(dev_priv, &n_edp_entries); |
431 | ddi_translations_hdmi = | 465 | ddi_translations_hdmi = |
432 | skl_get_buf_trans_hdmi(dev_priv, &n_hdmi_entries); | 466 | skl_get_buf_trans_hdmi(dev_priv, &n_hdmi_entries); |
433 | hdmi_default_entry = 8; | ||
434 | /* If we're boosting the current, set bit 31 of trans1 */ | 467 | /* If we're boosting the current, set bit 31 of trans1 */ |
435 | if (dev_priv->vbt.ddi_port_info[port].hdmi_boost_level || | 468 | if (dev_priv->vbt.ddi_port_info[port].hdmi_boost_level || |
436 | dev_priv->vbt.ddi_port_info[port].dp_boost_level) | 469 | dev_priv->vbt.ddi_port_info[port].dp_boost_level) |
@@ -456,7 +489,6 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder) | |||
456 | 489 | ||
457 | n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp); | 490 | n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp); |
458 | n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); | 491 | n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); |
459 | hdmi_default_entry = 7; | ||
460 | } else if (IS_HASWELL(dev_priv)) { | 492 | } else if (IS_HASWELL(dev_priv)) { |
461 | ddi_translations_fdi = hsw_ddi_translations_fdi; | 493 | ddi_translations_fdi = hsw_ddi_translations_fdi; |
462 | ddi_translations_dp = hsw_ddi_translations_dp; | 494 | ddi_translations_dp = hsw_ddi_translations_dp; |
@@ -464,7 +496,6 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder) | |||
464 | ddi_translations_hdmi = hsw_ddi_translations_hdmi; | 496 | ddi_translations_hdmi = hsw_ddi_translations_hdmi; |
465 | n_dp_entries = n_edp_entries = ARRAY_SIZE(hsw_ddi_translations_dp); | 497 | n_dp_entries = n_edp_entries = ARRAY_SIZE(hsw_ddi_translations_dp); |
466 | n_hdmi_entries = ARRAY_SIZE(hsw_ddi_translations_hdmi); | 498 | n_hdmi_entries = ARRAY_SIZE(hsw_ddi_translations_hdmi); |
467 | hdmi_default_entry = 6; | ||
468 | } else { | 499 | } else { |
469 | WARN(1, "ddi translation table missing\n"); | 500 | WARN(1, "ddi translation table missing\n"); |
470 | ddi_translations_edp = bdw_ddi_translations_dp; | 501 | ddi_translations_edp = bdw_ddi_translations_dp; |
@@ -474,7 +505,6 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder) | |||
474 | n_edp_entries = ARRAY_SIZE(bdw_ddi_translations_edp); | 505 | n_edp_entries = ARRAY_SIZE(bdw_ddi_translations_edp); |
475 | n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp); | 506 | n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp); |
476 | n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); | 507 | n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); |
477 | hdmi_default_entry = 7; | ||
478 | } | 508 | } |
479 | 509 | ||
480 | switch (encoder->type) { | 510 | switch (encoder->type) { |
@@ -505,11 +535,6 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder) | |||
505 | if (encoder->type != INTEL_OUTPUT_HDMI) | 535 | if (encoder->type != INTEL_OUTPUT_HDMI) |
506 | return; | 536 | return; |
507 | 537 | ||
508 | /* Choose a good default if VBT is badly populated */ | ||
509 | if (hdmi_level == HDMI_LEVEL_SHIFT_UNKNOWN || | ||
510 | hdmi_level >= n_hdmi_entries) | ||
511 | hdmi_level = hdmi_default_entry; | ||
512 | |||
513 | /* Entry 9 is for HDMI: */ | 538 | /* Entry 9 is for HDMI: */ |
514 | I915_WRITE(DDI_BUF_TRANS_LO(port, i), | 539 | I915_WRITE(DDI_BUF_TRANS_LO(port, i), |
515 | ddi_translations_hdmi[hdmi_level].trans1 | iboost_bit); | 540 | ddi_translations_hdmi[hdmi_level].trans1 | iboost_bit); |
@@ -1379,14 +1404,30 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc) | |||
1379 | TRANS_CLK_SEL_DISABLED); | 1404 | TRANS_CLK_SEL_DISABLED); |
1380 | } | 1405 | } |
1381 | 1406 | ||
1382 | static void skl_ddi_set_iboost(struct drm_i915_private *dev_priv, | 1407 | static void _skl_ddi_set_iboost(struct drm_i915_private *dev_priv, |
1383 | u32 level, enum port port, int type) | 1408 | enum port port, uint8_t iboost) |
1384 | { | 1409 | { |
1410 | u32 tmp; | ||
1411 | |||
1412 | tmp = I915_READ(DISPIO_CR_TX_BMU_CR0); | ||
1413 | tmp &= ~(BALANCE_LEG_MASK(port) | BALANCE_LEG_DISABLE(port)); | ||
1414 | if (iboost) | ||
1415 | tmp |= iboost << BALANCE_LEG_SHIFT(port); | ||
1416 | else | ||
1417 | tmp |= BALANCE_LEG_DISABLE(port); | ||
1418 | I915_WRITE(DISPIO_CR_TX_BMU_CR0, tmp); | ||
1419 | } | ||
1420 | |||
1421 | static void skl_ddi_set_iboost(struct intel_encoder *encoder, u32 level) | ||
1422 | { | ||
1423 | struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base); | ||
1424 | struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); | ||
1425 | enum port port = intel_dig_port->port; | ||
1426 | int type = encoder->type; | ||
1385 | const struct ddi_buf_trans *ddi_translations; | 1427 | const struct ddi_buf_trans *ddi_translations; |
1386 | uint8_t iboost; | 1428 | uint8_t iboost; |
1387 | uint8_t dp_iboost, hdmi_iboost; | 1429 | uint8_t dp_iboost, hdmi_iboost; |
1388 | int n_entries; | 1430 | int n_entries; |
1389 | u32 reg; | ||
1390 | 1431 | ||
1391 | /* VBT may override standard boost values */ | 1432 | /* VBT may override standard boost values */ |
1392 | dp_iboost = dev_priv->vbt.ddi_port_info[port].dp_boost_level; | 1433 | dp_iboost = dev_priv->vbt.ddi_port_info[port].dp_boost_level; |
@@ -1428,16 +1469,10 @@ static void skl_ddi_set_iboost(struct drm_i915_private *dev_priv, | |||
1428 | return; | 1469 | return; |
1429 | } | 1470 | } |
1430 | 1471 | ||
1431 | reg = I915_READ(DISPIO_CR_TX_BMU_CR0); | 1472 | _skl_ddi_set_iboost(dev_priv, port, iboost); |
1432 | reg &= ~BALANCE_LEG_MASK(port); | ||
1433 | reg &= ~(1 << (BALANCE_LEG_DISABLE_SHIFT + port)); | ||
1434 | |||
1435 | if (iboost) | ||
1436 | reg |= iboost << BALANCE_LEG_SHIFT(port); | ||
1437 | else | ||
1438 | reg |= 1 << (BALANCE_LEG_DISABLE_SHIFT + port); | ||
1439 | 1473 | ||
1440 | I915_WRITE(DISPIO_CR_TX_BMU_CR0, reg); | 1474 | if (port == PORT_A && intel_dig_port->max_lanes == 4) |
1475 | _skl_ddi_set_iboost(dev_priv, PORT_E, iboost); | ||
1441 | } | 1476 | } |
1442 | 1477 | ||
1443 | static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv, | 1478 | static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv, |
@@ -1568,7 +1603,7 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp) | |||
1568 | level = translate_signal_level(signal_levels); | 1603 | level = translate_signal_level(signal_levels); |
1569 | 1604 | ||
1570 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) | 1605 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) |
1571 | skl_ddi_set_iboost(dev_priv, level, port, encoder->type); | 1606 | skl_ddi_set_iboost(encoder, level); |
1572 | else if (IS_BROXTON(dev_priv)) | 1607 | else if (IS_BROXTON(dev_priv)) |
1573 | bxt_ddi_vswing_sequence(dev_priv, level, port, encoder->type); | 1608 | bxt_ddi_vswing_sequence(dev_priv, level, port, encoder->type); |
1574 | 1609 | ||
@@ -1637,6 +1672,10 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) | |||
1637 | intel_dp_stop_link_train(intel_dp); | 1672 | intel_dp_stop_link_train(intel_dp); |
1638 | } else if (type == INTEL_OUTPUT_HDMI) { | 1673 | } else if (type == INTEL_OUTPUT_HDMI) { |
1639 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | 1674 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
1675 | int level = intel_ddi_hdmi_level(dev_priv, port); | ||
1676 | |||
1677 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) | ||
1678 | skl_ddi_set_iboost(intel_encoder, level); | ||
1640 | 1679 | ||
1641 | intel_hdmi->set_infoframes(encoder, | 1680 | intel_hdmi->set_infoframes(encoder, |
1642 | crtc->config->has_hdmi_sink, | 1681 | crtc->config->has_hdmi_sink, |