diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 102 |
1 files changed, 99 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index eee2bbec2958..f9151f6641d9 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -367,6 +367,9 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, | |||
367 | union hdmi_infoframe frame; | 367 | union hdmi_infoframe frame; |
368 | int ret; | 368 | int ret; |
369 | 369 | ||
370 | /* Set user selected PAR to incoming mode's member */ | ||
371 | adjusted_mode->picture_aspect_ratio = intel_hdmi->aspect_ratio; | ||
372 | |||
370 | ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, | 373 | ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, |
371 | adjusted_mode); | 374 | adjusted_mode); |
372 | if (ret < 0) { | 375 | if (ret < 0) { |
@@ -879,7 +882,7 @@ static bool hdmi_12bpc_possible(struct intel_crtc *crtc) | |||
879 | struct intel_encoder *encoder; | 882 | struct intel_encoder *encoder; |
880 | int count = 0, count_hdmi = 0; | 883 | int count = 0, count_hdmi = 0; |
881 | 884 | ||
882 | if (!HAS_PCH_SPLIT(dev)) | 885 | if (HAS_GMCH_DISPLAY(dev)) |
883 | return false; | 886 | return false; |
884 | 887 | ||
885 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { | 888 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { |
@@ -1124,6 +1127,23 @@ intel_hdmi_set_property(struct drm_connector *connector, | |||
1124 | goto done; | 1127 | goto done; |
1125 | } | 1128 | } |
1126 | 1129 | ||
1130 | if (property == connector->dev->mode_config.aspect_ratio_property) { | ||
1131 | switch (val) { | ||
1132 | case DRM_MODE_PICTURE_ASPECT_NONE: | ||
1133 | intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_NONE; | ||
1134 | break; | ||
1135 | case DRM_MODE_PICTURE_ASPECT_4_3: | ||
1136 | intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_4_3; | ||
1137 | break; | ||
1138 | case DRM_MODE_PICTURE_ASPECT_16_9: | ||
1139 | intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_16_9; | ||
1140 | break; | ||
1141 | default: | ||
1142 | return -EINVAL; | ||
1143 | } | ||
1144 | goto done; | ||
1145 | } | ||
1146 | |||
1127 | return -EINVAL; | 1147 | return -EINVAL; |
1128 | 1148 | ||
1129 | done: | 1149 | done: |
@@ -1229,6 +1249,70 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder) | |||
1229 | mutex_unlock(&dev_priv->dpio_lock); | 1249 | mutex_unlock(&dev_priv->dpio_lock); |
1230 | } | 1250 | } |
1231 | 1251 | ||
1252 | static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder) | ||
1253 | { | ||
1254 | struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); | ||
1255 | struct drm_device *dev = encoder->base.dev; | ||
1256 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1257 | struct intel_crtc *intel_crtc = | ||
1258 | to_intel_crtc(encoder->base.crtc); | ||
1259 | enum dpio_channel ch = vlv_dport_to_channel(dport); | ||
1260 | enum pipe pipe = intel_crtc->pipe; | ||
1261 | u32 val; | ||
1262 | |||
1263 | mutex_lock(&dev_priv->dpio_lock); | ||
1264 | |||
1265 | /* program left/right clock distribution */ | ||
1266 | if (pipe != PIPE_B) { | ||
1267 | val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0); | ||
1268 | val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK); | ||
1269 | if (ch == DPIO_CH0) | ||
1270 | val |= CHV_BUFLEFTENA1_FORCE; | ||
1271 | if (ch == DPIO_CH1) | ||
1272 | val |= CHV_BUFRIGHTENA1_FORCE; | ||
1273 | vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val); | ||
1274 | } else { | ||
1275 | val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1); | ||
1276 | val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK); | ||
1277 | if (ch == DPIO_CH0) | ||
1278 | val |= CHV_BUFLEFTENA2_FORCE; | ||
1279 | if (ch == DPIO_CH1) | ||
1280 | val |= CHV_BUFRIGHTENA2_FORCE; | ||
1281 | vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val); | ||
1282 | } | ||
1283 | |||
1284 | /* program clock channel usage */ | ||
1285 | val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(ch)); | ||
1286 | val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE; | ||
1287 | if (pipe != PIPE_B) | ||
1288 | val &= ~CHV_PCS_USEDCLKCHANNEL; | ||
1289 | else | ||
1290 | val |= CHV_PCS_USEDCLKCHANNEL; | ||
1291 | vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW8(ch), val); | ||
1292 | |||
1293 | val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW8(ch)); | ||
1294 | val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE; | ||
1295 | if (pipe != PIPE_B) | ||
1296 | val &= ~CHV_PCS_USEDCLKCHANNEL; | ||
1297 | else | ||
1298 | val |= CHV_PCS_USEDCLKCHANNEL; | ||
1299 | vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW8(ch), val); | ||
1300 | |||
1301 | /* | ||
1302 | * This a a bit weird since generally CL | ||
1303 | * matches the pipe, but here we need to | ||
1304 | * pick the CL based on the port. | ||
1305 | */ | ||
1306 | val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW19(ch)); | ||
1307 | if (pipe != PIPE_B) | ||
1308 | val &= ~CHV_CMN_USEDCLKCHANNEL; | ||
1309 | else | ||
1310 | val |= CHV_CMN_USEDCLKCHANNEL; | ||
1311 | vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW19(ch), val); | ||
1312 | |||
1313 | mutex_unlock(&dev_priv->dpio_lock); | ||
1314 | } | ||
1315 | |||
1232 | static void vlv_hdmi_post_disable(struct intel_encoder *encoder) | 1316 | static void vlv_hdmi_post_disable(struct intel_encoder *encoder) |
1233 | { | 1317 | { |
1234 | struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); | 1318 | struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); |
@@ -1416,11 +1500,22 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { | |||
1416 | }; | 1500 | }; |
1417 | 1501 | ||
1418 | static void | 1502 | static void |
1503 | intel_attach_aspect_ratio_property(struct drm_connector *connector) | ||
1504 | { | ||
1505 | if (!drm_mode_create_aspect_ratio_property(connector->dev)) | ||
1506 | drm_object_attach_property(&connector->base, | ||
1507 | connector->dev->mode_config.aspect_ratio_property, | ||
1508 | DRM_MODE_PICTURE_ASPECT_NONE); | ||
1509 | } | ||
1510 | |||
1511 | static void | ||
1419 | intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector) | 1512 | intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector) |
1420 | { | 1513 | { |
1421 | intel_attach_force_audio_property(connector); | 1514 | intel_attach_force_audio_property(connector); |
1422 | intel_attach_broadcast_rgb_property(connector); | 1515 | intel_attach_broadcast_rgb_property(connector); |
1423 | intel_hdmi->color_range_auto = true; | 1516 | intel_hdmi->color_range_auto = true; |
1517 | intel_attach_aspect_ratio_property(connector); | ||
1518 | intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_NONE; | ||
1424 | } | 1519 | } |
1425 | 1520 | ||
1426 | void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, | 1521 | void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, |
@@ -1467,7 +1562,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, | |||
1467 | if (IS_VALLEYVIEW(dev)) { | 1562 | if (IS_VALLEYVIEW(dev)) { |
1468 | intel_hdmi->write_infoframe = vlv_write_infoframe; | 1563 | intel_hdmi->write_infoframe = vlv_write_infoframe; |
1469 | intel_hdmi->set_infoframes = vlv_set_infoframes; | 1564 | intel_hdmi->set_infoframes = vlv_set_infoframes; |
1470 | } else if (!HAS_PCH_SPLIT(dev)) { | 1565 | } else if (IS_G4X(dev)) { |
1471 | intel_hdmi->write_infoframe = g4x_write_infoframe; | 1566 | intel_hdmi->write_infoframe = g4x_write_infoframe; |
1472 | intel_hdmi->set_infoframes = g4x_set_infoframes; | 1567 | intel_hdmi->set_infoframes = g4x_set_infoframes; |
1473 | } else if (HAS_DDI(dev)) { | 1568 | } else if (HAS_DDI(dev)) { |
@@ -1490,7 +1585,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, | |||
1490 | intel_hdmi_add_properties(intel_hdmi, connector); | 1585 | intel_hdmi_add_properties(intel_hdmi, connector); |
1491 | 1586 | ||
1492 | intel_connector_attach_encoder(intel_connector, intel_encoder); | 1587 | intel_connector_attach_encoder(intel_connector, intel_encoder); |
1493 | drm_sysfs_connector_add(connector); | 1588 | drm_connector_register(connector); |
1494 | 1589 | ||
1495 | /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written | 1590 | /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written |
1496 | * 0xd. Failure to do so will result in spurious interrupts being | 1591 | * 0xd. Failure to do so will result in spurious interrupts being |
@@ -1528,6 +1623,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) | |||
1528 | intel_encoder->get_hw_state = intel_hdmi_get_hw_state; | 1623 | intel_encoder->get_hw_state = intel_hdmi_get_hw_state; |
1529 | intel_encoder->get_config = intel_hdmi_get_config; | 1624 | intel_encoder->get_config = intel_hdmi_get_config; |
1530 | if (IS_CHERRYVIEW(dev)) { | 1625 | if (IS_CHERRYVIEW(dev)) { |
1626 | intel_encoder->pre_pll_enable = chv_hdmi_pre_pll_enable; | ||
1531 | intel_encoder->pre_enable = chv_hdmi_pre_enable; | 1627 | intel_encoder->pre_enable = chv_hdmi_pre_enable; |
1532 | intel_encoder->enable = vlv_enable_hdmi; | 1628 | intel_encoder->enable = vlv_enable_hdmi; |
1533 | intel_encoder->post_disable = chv_hdmi_post_disable; | 1629 | intel_encoder->post_disable = chv_hdmi_post_disable; |