diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_hdmi.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 120 | 
1 files changed, 111 insertions, 9 deletions
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 29ec1535992d..3abc2000fce9 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c  | |||
| @@ -166,6 +166,19 @@ static void g4x_write_infoframe(struct drm_encoder *encoder, | |||
| 166 | POSTING_READ(VIDEO_DIP_CTL); | 166 | POSTING_READ(VIDEO_DIP_CTL); | 
| 167 | } | 167 | } | 
| 168 | 168 | ||
| 169 | static bool g4x_infoframe_enabled(struct drm_encoder *encoder) | ||
| 170 | { | ||
| 171 | struct drm_device *dev = encoder->dev; | ||
| 172 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 173 | struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); | ||
| 174 | u32 val = I915_READ(VIDEO_DIP_CTL); | ||
| 175 | |||
| 176 | if (VIDEO_DIP_PORT(intel_dig_port->port) == (val & VIDEO_DIP_PORT_MASK)) | ||
| 177 | return val & VIDEO_DIP_ENABLE; | ||
| 178 | |||
| 179 | return false; | ||
| 180 | } | ||
| 181 | |||
| 169 | static void ibx_write_infoframe(struct drm_encoder *encoder, | 182 | static void ibx_write_infoframe(struct drm_encoder *encoder, | 
| 170 | enum hdmi_infoframe_type type, | 183 | enum hdmi_infoframe_type type, | 
| 171 | const void *frame, ssize_t len) | 184 | const void *frame, ssize_t len) | 
| @@ -204,6 +217,17 @@ static void ibx_write_infoframe(struct drm_encoder *encoder, | |||
| 204 | POSTING_READ(reg); | 217 | POSTING_READ(reg); | 
| 205 | } | 218 | } | 
| 206 | 219 | ||
| 220 | static bool ibx_infoframe_enabled(struct drm_encoder *encoder) | ||
| 221 | { | ||
| 222 | struct drm_device *dev = encoder->dev; | ||
| 223 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 224 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | ||
| 225 | int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); | ||
| 226 | u32 val = I915_READ(reg); | ||
| 227 | |||
| 228 | return val & VIDEO_DIP_ENABLE; | ||
| 229 | } | ||
| 230 | |||
| 207 | static void cpt_write_infoframe(struct drm_encoder *encoder, | 231 | static void cpt_write_infoframe(struct drm_encoder *encoder, | 
| 208 | enum hdmi_infoframe_type type, | 232 | enum hdmi_infoframe_type type, | 
| 209 | const void *frame, ssize_t len) | 233 | const void *frame, ssize_t len) | 
| @@ -245,6 +269,17 @@ static void cpt_write_infoframe(struct drm_encoder *encoder, | |||
| 245 | POSTING_READ(reg); | 269 | POSTING_READ(reg); | 
| 246 | } | 270 | } | 
| 247 | 271 | ||
| 272 | static bool cpt_infoframe_enabled(struct drm_encoder *encoder) | ||
| 273 | { | ||
| 274 | struct drm_device *dev = encoder->dev; | ||
| 275 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 276 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | ||
| 277 | int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); | ||
| 278 | u32 val = I915_READ(reg); | ||
| 279 | |||
| 280 | return val & VIDEO_DIP_ENABLE; | ||
| 281 | } | ||
| 282 | |||
| 248 | static void vlv_write_infoframe(struct drm_encoder *encoder, | 283 | static void vlv_write_infoframe(struct drm_encoder *encoder, | 
| 249 | enum hdmi_infoframe_type type, | 284 | enum hdmi_infoframe_type type, | 
| 250 | const void *frame, ssize_t len) | 285 | const void *frame, ssize_t len) | 
| @@ -283,6 +318,17 @@ static void vlv_write_infoframe(struct drm_encoder *encoder, | |||
| 283 | POSTING_READ(reg); | 318 | POSTING_READ(reg); | 
| 284 | } | 319 | } | 
| 285 | 320 | ||
| 321 | static bool vlv_infoframe_enabled(struct drm_encoder *encoder) | ||
| 322 | { | ||
| 323 | struct drm_device *dev = encoder->dev; | ||
| 324 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 325 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | ||
| 326 | int reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); | ||
| 327 | u32 val = I915_READ(reg); | ||
| 328 | |||
| 329 | return val & VIDEO_DIP_ENABLE; | ||
| 330 | } | ||
| 331 | |||
| 286 | static void hsw_write_infoframe(struct drm_encoder *encoder, | 332 | static void hsw_write_infoframe(struct drm_encoder *encoder, | 
| 287 | enum hdmi_infoframe_type type, | 333 | enum hdmi_infoframe_type type, | 
| 288 | const void *frame, ssize_t len) | 334 | const void *frame, ssize_t len) | 
| @@ -320,6 +366,18 @@ static void hsw_write_infoframe(struct drm_encoder *encoder, | |||
| 320 | POSTING_READ(ctl_reg); | 366 | POSTING_READ(ctl_reg); | 
| 321 | } | 367 | } | 
| 322 | 368 | ||
| 369 | static bool hsw_infoframe_enabled(struct drm_encoder *encoder) | ||
| 370 | { | ||
| 371 | struct drm_device *dev = encoder->dev; | ||
| 372 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 373 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | ||
| 374 | u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder); | ||
| 375 | u32 val = I915_READ(ctl_reg); | ||
| 376 | |||
| 377 | return val & (VIDEO_DIP_ENABLE_AVI_HSW | VIDEO_DIP_ENABLE_SPD_HSW | | ||
| 378 | VIDEO_DIP_ENABLE_VS_HSW); | ||
| 379 | } | ||
| 380 | |||
| 323 | /* | 381 | /* | 
| 324 | * The data we write to the DIP data buffer registers is 1 byte bigger than the | 382 | * The data we write to the DIP data buffer registers is 1 byte bigger than the | 
| 325 | * HDMI infoframe size because of an ECC/reserved byte at position 3 (starting | 383 | * HDMI infoframe size because of an ECC/reserved byte at position 3 (starting | 
| @@ -661,14 +719,6 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder) | |||
| 661 | if (crtc->config.has_hdmi_sink) | 719 | if (crtc->config.has_hdmi_sink) | 
| 662 | hdmi_val |= HDMI_MODE_SELECT_HDMI; | 720 | hdmi_val |= HDMI_MODE_SELECT_HDMI; | 
| 663 | 721 | ||
| 664 | if (crtc->config.has_audio) { | ||
| 665 | WARN_ON(!crtc->config.has_hdmi_sink); | ||
| 666 | DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n", | ||
| 667 | pipe_name(crtc->pipe)); | ||
| 668 | hdmi_val |= SDVO_AUDIO_ENABLE; | ||
| 669 | intel_write_eld(&encoder->base, adjusted_mode); | ||
| 670 | } | ||
| 671 | |||
| 672 | if (HAS_PCH_CPT(dev)) | 722 | if (HAS_PCH_CPT(dev)) | 
| 673 | hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe); | 723 | hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe); | 
| 674 | else if (IS_CHERRYVIEW(dev)) | 724 | else if (IS_CHERRYVIEW(dev)) | 
| @@ -690,7 +740,7 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder, | |||
| 690 | u32 tmp; | 740 | u32 tmp; | 
| 691 | 741 | ||
| 692 | power_domain = intel_display_port_power_domain(encoder); | 742 | power_domain = intel_display_port_power_domain(encoder); | 
| 693 | if (!intel_display_power_enabled(dev_priv, power_domain)) | 743 | if (!intel_display_power_is_enabled(dev_priv, power_domain)) | 
| 694 | return false; | 744 | return false; | 
| 695 | 745 | ||
| 696 | tmp = I915_READ(intel_hdmi->hdmi_reg); | 746 | tmp = I915_READ(intel_hdmi->hdmi_reg); | 
| @@ -732,6 +782,9 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, | |||
| 732 | if (tmp & HDMI_MODE_SELECT_HDMI) | 782 | if (tmp & HDMI_MODE_SELECT_HDMI) | 
| 733 | pipe_config->has_hdmi_sink = true; | 783 | pipe_config->has_hdmi_sink = true; | 
| 734 | 784 | ||
| 785 | if (intel_hdmi->infoframe_enabled(&encoder->base)) | ||
| 786 | pipe_config->has_infoframe = true; | ||
| 787 | |||
| 735 | if (tmp & SDVO_AUDIO_ENABLE) | 788 | if (tmp & SDVO_AUDIO_ENABLE) | 
| 736 | pipe_config->has_audio = true; | 789 | pipe_config->has_audio = true; | 
| 737 | 790 | ||
| @@ -791,6 +844,13 @@ static void intel_enable_hdmi(struct intel_encoder *encoder) | |||
| 791 | I915_WRITE(intel_hdmi->hdmi_reg, temp); | 844 | I915_WRITE(intel_hdmi->hdmi_reg, temp); | 
| 792 | POSTING_READ(intel_hdmi->hdmi_reg); | 845 | POSTING_READ(intel_hdmi->hdmi_reg); | 
| 793 | } | 846 | } | 
| 847 | |||
| 848 | if (intel_crtc->config.has_audio) { | ||
| 849 | WARN_ON(!intel_crtc->config.has_hdmi_sink); | ||
| 850 | DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n", | ||
| 851 | pipe_name(intel_crtc->pipe)); | ||
| 852 | intel_audio_codec_enable(encoder); | ||
| 853 | } | ||
| 794 | } | 854 | } | 
| 795 | 855 | ||
| 796 | static void vlv_enable_hdmi(struct intel_encoder *encoder) | 856 | static void vlv_enable_hdmi(struct intel_encoder *encoder) | 
| @@ -802,9 +862,13 @@ static void intel_disable_hdmi(struct intel_encoder *encoder) | |||
| 802 | struct drm_device *dev = encoder->base.dev; | 862 | struct drm_device *dev = encoder->base.dev; | 
| 803 | struct drm_i915_private *dev_priv = dev->dev_private; | 863 | struct drm_i915_private *dev_priv = dev->dev_private; | 
| 804 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); | 864 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); | 
| 865 | struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); | ||
| 805 | u32 temp; | 866 | u32 temp; | 
| 806 | u32 enable_bits = SDVO_ENABLE | SDVO_AUDIO_ENABLE; | 867 | u32 enable_bits = SDVO_ENABLE | SDVO_AUDIO_ENABLE; | 
| 807 | 868 | ||
| 869 | if (crtc->config.has_audio) | ||
| 870 | intel_audio_codec_disable(encoder); | ||
| 871 | |||
| 808 | temp = I915_READ(intel_hdmi->hdmi_reg); | 872 | temp = I915_READ(intel_hdmi->hdmi_reg); | 
| 809 | 873 | ||
| 810 | /* HW workaround for IBX, we need to move the port to transcoder A | 874 | /* HW workaround for IBX, we need to move the port to transcoder A | 
| @@ -922,6 +986,9 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, | |||
| 922 | 986 | ||
| 923 | pipe_config->has_hdmi_sink = intel_hdmi->has_hdmi_sink; | 987 | pipe_config->has_hdmi_sink = intel_hdmi->has_hdmi_sink; | 
| 924 | 988 | ||
| 989 | if (pipe_config->has_hdmi_sink) | ||
| 990 | pipe_config->has_infoframe = true; | ||
| 991 | |||
| 925 | if (intel_hdmi->color_range_auto) { | 992 | if (intel_hdmi->color_range_auto) { | 
| 926 | /* See CEA-861-E - 5.1 Default Encoding Parameters */ | 993 | /* See CEA-861-E - 5.1 Default Encoding Parameters */ | 
| 927 | if (pipe_config->has_hdmi_sink && | 994 | if (pipe_config->has_hdmi_sink && | 
| @@ -1394,10 +1461,13 @@ static void chv_hdmi_post_disable(struct intel_encoder *encoder) | |||
| 1394 | static void chv_hdmi_pre_enable(struct intel_encoder *encoder) | 1461 | static void chv_hdmi_pre_enable(struct intel_encoder *encoder) | 
| 1395 | { | 1462 | { | 
| 1396 | struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); | 1463 | struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); | 
| 1464 | struct intel_hdmi *intel_hdmi = &dport->hdmi; | ||
| 1397 | struct drm_device *dev = encoder->base.dev; | 1465 | struct drm_device *dev = encoder->base.dev; | 
| 1398 | struct drm_i915_private *dev_priv = dev->dev_private; | 1466 | struct drm_i915_private *dev_priv = dev->dev_private; | 
| 1399 | struct intel_crtc *intel_crtc = | 1467 | struct intel_crtc *intel_crtc = | 
| 1400 | to_intel_crtc(encoder->base.crtc); | 1468 | to_intel_crtc(encoder->base.crtc); | 
| 1469 | struct drm_display_mode *adjusted_mode = | ||
| 1470 | &intel_crtc->config.adjusted_mode; | ||
| 1401 | enum dpio_channel ch = vlv_dport_to_channel(dport); | 1471 | enum dpio_channel ch = vlv_dport_to_channel(dport); | 
| 1402 | int pipe = intel_crtc->pipe; | 1472 | int pipe = intel_crtc->pipe; | 
| 1403 | int data, i; | 1473 | int data, i; | 
| @@ -1405,6 +1475,15 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) | |||
| 1405 | 1475 | ||
| 1406 | mutex_lock(&dev_priv->dpio_lock); | 1476 | mutex_lock(&dev_priv->dpio_lock); | 
| 1407 | 1477 | ||
| 1478 | /* allow hardware to manage TX FIFO reset source */ | ||
| 1479 | val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW11(ch)); | ||
| 1480 | val &= ~DPIO_LANEDESKEW_STRAP_OVRD; | ||
| 1481 | vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val); | ||
| 1482 | |||
| 1483 | val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch)); | ||
| 1484 | val &= ~DPIO_LANEDESKEW_STRAP_OVRD; | ||
| 1485 | vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val); | ||
| 1486 | |||
| 1408 | /* Deassert soft data lane reset*/ | 1487 | /* Deassert soft data lane reset*/ | 
| 1409 | val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); | 1488 | val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); | 
| 1410 | val |= CHV_PCS_REQ_SOFTRESET_EN; | 1489 | val |= CHV_PCS_REQ_SOFTRESET_EN; | 
| @@ -1441,12 +1520,26 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) | |||
| 1441 | /* Clear calc init */ | 1520 | /* Clear calc init */ | 
| 1442 | val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch)); | 1521 | val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch)); | 
| 1443 | val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); | 1522 | val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); | 
| 1523 | val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK); | ||
| 1524 | val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; | ||
| 1444 | vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW10(ch), val); | 1525 | vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW10(ch), val); | 
| 1445 | 1526 | ||
| 1446 | val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch)); | 1527 | val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch)); | 
| 1447 | val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); | 1528 | val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); | 
| 1529 | val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK); | ||
| 1530 | val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; | ||
| 1448 | vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val); | 1531 | vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val); | 
| 1449 | 1532 | ||
| 1533 | val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW9(ch)); | ||
| 1534 | val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); | ||
| 1535 | val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; | ||
| 1536 | vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW9(ch), val); | ||
| 1537 | |||
| 1538 | val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW9(ch)); | ||
| 1539 | val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); | ||
| 1540 | val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; | ||
| 1541 | vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW9(ch), val); | ||
| 1542 | |||
| 1450 | /* FIXME: Program the support xxx V-dB */ | 1543 | /* FIXME: Program the support xxx V-dB */ | 
| 1451 | /* Use 800mV-0dB */ | 1544 | /* Use 800mV-0dB */ | 
| 1452 | for (i = 0; i < 4; i++) { | 1545 | for (i = 0; i < 4; i++) { | 
| @@ -1499,6 +1592,10 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) | |||
| 1499 | 1592 | ||
| 1500 | mutex_unlock(&dev_priv->dpio_lock); | 1593 | mutex_unlock(&dev_priv->dpio_lock); | 
| 1501 | 1594 | ||
| 1595 | intel_hdmi->set_infoframes(&encoder->base, | ||
| 1596 | intel_crtc->config.has_hdmi_sink, | ||
| 1597 | adjusted_mode); | ||
| 1598 | |||
| 1502 | intel_enable_hdmi(encoder); | 1599 | intel_enable_hdmi(encoder); | 
| 1503 | 1600 | ||
| 1504 | vlv_wait_port_ready(dev_priv, dport); | 1601 | vlv_wait_port_ready(dev_priv, dport); | 
| @@ -1593,18 +1690,23 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 1593 | if (IS_VALLEYVIEW(dev)) { | 1690 | if (IS_VALLEYVIEW(dev)) { | 
| 1594 | intel_hdmi->write_infoframe = vlv_write_infoframe; | 1691 | intel_hdmi->write_infoframe = vlv_write_infoframe; | 
| 1595 | intel_hdmi->set_infoframes = vlv_set_infoframes; | 1692 | intel_hdmi->set_infoframes = vlv_set_infoframes; | 
| 1693 | intel_hdmi->infoframe_enabled = vlv_infoframe_enabled; | ||
| 1596 | } else if (IS_G4X(dev)) { | 1694 | } else if (IS_G4X(dev)) { | 
| 1597 | intel_hdmi->write_infoframe = g4x_write_infoframe; | 1695 | intel_hdmi->write_infoframe = g4x_write_infoframe; | 
| 1598 | intel_hdmi->set_infoframes = g4x_set_infoframes; | 1696 | intel_hdmi->set_infoframes = g4x_set_infoframes; | 
| 1697 | intel_hdmi->infoframe_enabled = g4x_infoframe_enabled; | ||
| 1599 | } else if (HAS_DDI(dev)) { | 1698 | } else if (HAS_DDI(dev)) { | 
| 1600 | intel_hdmi->write_infoframe = hsw_write_infoframe; | 1699 | intel_hdmi->write_infoframe = hsw_write_infoframe; | 
| 1601 | intel_hdmi->set_infoframes = hsw_set_infoframes; | 1700 | intel_hdmi->set_infoframes = hsw_set_infoframes; | 
| 1701 | intel_hdmi->infoframe_enabled = hsw_infoframe_enabled; | ||
| 1602 | } else if (HAS_PCH_IBX(dev)) { | 1702 | } else if (HAS_PCH_IBX(dev)) { | 
| 1603 | intel_hdmi->write_infoframe = ibx_write_infoframe; | 1703 | intel_hdmi->write_infoframe = ibx_write_infoframe; | 
| 1604 | intel_hdmi->set_infoframes = ibx_set_infoframes; | 1704 | intel_hdmi->set_infoframes = ibx_set_infoframes; | 
| 1705 | intel_hdmi->infoframe_enabled = ibx_infoframe_enabled; | ||
| 1605 | } else { | 1706 | } else { | 
| 1606 | intel_hdmi->write_infoframe = cpt_write_infoframe; | 1707 | intel_hdmi->write_infoframe = cpt_write_infoframe; | 
| 1607 | intel_hdmi->set_infoframes = cpt_set_infoframes; | 1708 | intel_hdmi->set_infoframes = cpt_set_infoframes; | 
| 1709 | intel_hdmi->infoframe_enabled = cpt_infoframe_enabled; | ||
| 1608 | } | 1710 | } | 
| 1609 | 1711 | ||
| 1610 | if (HAS_DDI(dev)) | 1712 | if (HAS_DDI(dev)) | 
