diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sdvo.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 368 |
1 files changed, 274 insertions, 94 deletions
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index f03473779feb..5371d9332554 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include "drm.h" | 31 | #include "drm.h" |
| 32 | #include "drm_crtc.h" | 32 | #include "drm_crtc.h" |
| 33 | #include "intel_drv.h" | 33 | #include "intel_drv.h" |
| 34 | #include "drm_edid.h" | ||
| 34 | #include "i915_drm.h" | 35 | #include "i915_drm.h" |
| 35 | #include "i915_drv.h" | 36 | #include "i915_drv.h" |
| 36 | #include "intel_sdvo_regs.h" | 37 | #include "intel_sdvo_regs.h" |
| @@ -55,6 +56,12 @@ struct intel_sdvo_priv { | |||
| 55 | /* Pixel clock limitations reported by the SDVO device, in kHz */ | 56 | /* Pixel clock limitations reported by the SDVO device, in kHz */ |
| 56 | int pixel_clock_min, pixel_clock_max; | 57 | int pixel_clock_min, pixel_clock_max; |
| 57 | 58 | ||
| 59 | /* | ||
| 60 | * For multiple function SDVO device, | ||
| 61 | * this is for current attached outputs. | ||
| 62 | */ | ||
| 63 | uint16_t attached_output; | ||
| 64 | |||
| 58 | /** | 65 | /** |
| 59 | * This is set if we're going to treat the device as TV-out. | 66 | * This is set if we're going to treat the device as TV-out. |
| 60 | * | 67 | * |
| @@ -68,12 +75,23 @@ struct intel_sdvo_priv { | |||
| 68 | * This is set if we treat the device as HDMI, instead of DVI. | 75 | * This is set if we treat the device as HDMI, instead of DVI. |
| 69 | */ | 76 | */ |
| 70 | bool is_hdmi; | 77 | bool is_hdmi; |
| 78 | |||
| 71 | /** | 79 | /** |
| 72 | * This is set if we detect output of sdvo device as LVDS. | 80 | * This is set if we detect output of sdvo device as LVDS. |
| 73 | */ | 81 | */ |
| 74 | bool is_lvds; | 82 | bool is_lvds; |
| 75 | 83 | ||
| 76 | /** | 84 | /** |
| 85 | * This is sdvo flags for input timing. | ||
| 86 | */ | ||
| 87 | uint8_t sdvo_flags; | ||
| 88 | |||
| 89 | /** | ||
| 90 | * This is sdvo fixed pannel mode pointer | ||
| 91 | */ | ||
| 92 | struct drm_display_mode *sdvo_lvds_fixed_mode; | ||
| 93 | |||
| 94 | /** | ||
| 77 | * Returned SDTV resolutions allowed for the current format, if the | 95 | * Returned SDTV resolutions allowed for the current format, if the |
| 78 | * device reported it. | 96 | * device reported it. |
| 79 | */ | 97 | */ |
| @@ -103,6 +121,9 @@ struct intel_sdvo_priv { | |||
| 103 | u32 save_SDVOX; | 121 | u32 save_SDVOX; |
| 104 | }; | 122 | }; |
| 105 | 123 | ||
| 124 | static bool | ||
| 125 | intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags); | ||
| 126 | |||
| 106 | /** | 127 | /** |
| 107 | * Writes the SDVOB or SDVOC with the given value, but always writes both | 128 | * Writes the SDVOB or SDVOC with the given value, but always writes both |
| 108 | * SDVOB and SDVOC to work around apparent hardware issues (according to | 129 | * SDVOB and SDVOC to work around apparent hardware issues (according to |
| @@ -592,6 +613,7 @@ intel_sdvo_create_preferred_input_timing(struct intel_output *output, | |||
| 592 | uint16_t height) | 613 | uint16_t height) |
| 593 | { | 614 | { |
| 594 | struct intel_sdvo_preferred_input_timing_args args; | 615 | struct intel_sdvo_preferred_input_timing_args args; |
| 616 | struct intel_sdvo_priv *sdvo_priv = output->dev_priv; | ||
| 595 | uint8_t status; | 617 | uint8_t status; |
| 596 | 618 | ||
| 597 | memset(&args, 0, sizeof(args)); | 619 | memset(&args, 0, sizeof(args)); |
| @@ -599,7 +621,12 @@ intel_sdvo_create_preferred_input_timing(struct intel_output *output, | |||
| 599 | args.width = width; | 621 | args.width = width; |
| 600 | args.height = height; | 622 | args.height = height; |
| 601 | args.interlace = 0; | 623 | args.interlace = 0; |
| 602 | args.scaled = 0; | 624 | |
| 625 | if (sdvo_priv->is_lvds && | ||
| 626 | (sdvo_priv->sdvo_lvds_fixed_mode->hdisplay != width || | ||
| 627 | sdvo_priv->sdvo_lvds_fixed_mode->vdisplay != height)) | ||
| 628 | args.scaled = 1; | ||
| 629 | |||
| 603 | intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING, | 630 | intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING, |
| 604 | &args, sizeof(args)); | 631 | &args, sizeof(args)); |
| 605 | status = intel_sdvo_read_response(output, NULL, 0); | 632 | status = intel_sdvo_read_response(output, NULL, 0); |
| @@ -944,12 +971,7 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | |||
| 944 | struct intel_output *output = enc_to_intel_output(encoder); | 971 | struct intel_output *output = enc_to_intel_output(encoder); |
| 945 | struct intel_sdvo_priv *dev_priv = output->dev_priv; | 972 | struct intel_sdvo_priv *dev_priv = output->dev_priv; |
| 946 | 973 | ||
| 947 | if (!dev_priv->is_tv) { | 974 | if (dev_priv->is_tv) { |
| 948 | /* Make the CRTC code factor in the SDVO pixel multiplier. The | ||
| 949 | * SDVO device will be told of the multiplier during mode_set. | ||
| 950 | */ | ||
| 951 | adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode); | ||
| 952 | } else { | ||
| 953 | struct intel_sdvo_dtd output_dtd; | 975 | struct intel_sdvo_dtd output_dtd; |
| 954 | bool success; | 976 | bool success; |
| 955 | 977 | ||
| @@ -980,6 +1002,47 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | |||
| 980 | intel_sdvo_get_preferred_input_timing(output, | 1002 | intel_sdvo_get_preferred_input_timing(output, |
| 981 | &input_dtd); | 1003 | &input_dtd); |
| 982 | intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); | 1004 | intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); |
| 1005 | dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags; | ||
| 1006 | |||
| 1007 | drm_mode_set_crtcinfo(adjusted_mode, 0); | ||
| 1008 | |||
| 1009 | mode->clock = adjusted_mode->clock; | ||
| 1010 | |||
| 1011 | adjusted_mode->clock *= | ||
| 1012 | intel_sdvo_get_pixel_multiplier(mode); | ||
| 1013 | } else { | ||
| 1014 | return false; | ||
| 1015 | } | ||
| 1016 | } else if (dev_priv->is_lvds) { | ||
| 1017 | struct intel_sdvo_dtd output_dtd; | ||
| 1018 | bool success; | ||
| 1019 | |||
| 1020 | drm_mode_set_crtcinfo(dev_priv->sdvo_lvds_fixed_mode, 0); | ||
| 1021 | /* Set output timings */ | ||
| 1022 | intel_sdvo_get_dtd_from_mode(&output_dtd, | ||
| 1023 | dev_priv->sdvo_lvds_fixed_mode); | ||
| 1024 | |||
| 1025 | intel_sdvo_set_target_output(output, | ||
| 1026 | dev_priv->controlled_output); | ||
| 1027 | intel_sdvo_set_output_timing(output, &output_dtd); | ||
| 1028 | |||
| 1029 | /* Set the input timing to the screen. Assume always input 0. */ | ||
| 1030 | intel_sdvo_set_target_input(output, true, false); | ||
| 1031 | |||
| 1032 | |||
| 1033 | success = intel_sdvo_create_preferred_input_timing( | ||
| 1034 | output, | ||
| 1035 | mode->clock / 10, | ||
| 1036 | mode->hdisplay, | ||
| 1037 | mode->vdisplay); | ||
| 1038 | |||
| 1039 | if (success) { | ||
| 1040 | struct intel_sdvo_dtd input_dtd; | ||
| 1041 | |||
| 1042 | intel_sdvo_get_preferred_input_timing(output, | ||
| 1043 | &input_dtd); | ||
| 1044 | intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); | ||
| 1045 | dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags; | ||
| 983 | 1046 | ||
| 984 | drm_mode_set_crtcinfo(adjusted_mode, 0); | 1047 | drm_mode_set_crtcinfo(adjusted_mode, 0); |
| 985 | 1048 | ||
| @@ -990,6 +1053,12 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | |||
| 990 | } else { | 1053 | } else { |
| 991 | return false; | 1054 | return false; |
| 992 | } | 1055 | } |
| 1056 | |||
| 1057 | } else { | ||
| 1058 | /* Make the CRTC code factor in the SDVO pixel multiplier. The | ||
| 1059 | * SDVO device will be told of the multiplier during mode_set. | ||
| 1060 | */ | ||
| 1061 | adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode); | ||
| 993 | } | 1062 | } |
| 994 | return true; | 1063 | return true; |
| 995 | } | 1064 | } |
| @@ -1033,15 +1102,16 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
| 1033 | 1102 | ||
| 1034 | /* We have tried to get input timing in mode_fixup, and filled into | 1103 | /* We have tried to get input timing in mode_fixup, and filled into |
| 1035 | adjusted_mode */ | 1104 | adjusted_mode */ |
| 1036 | if (sdvo_priv->is_tv) | 1105 | if (sdvo_priv->is_tv || sdvo_priv->is_lvds) { |
| 1037 | intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); | 1106 | intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); |
| 1038 | else | 1107 | input_dtd.part2.sdvo_flags = sdvo_priv->sdvo_flags; |
| 1108 | } else | ||
| 1039 | intel_sdvo_get_dtd_from_mode(&input_dtd, mode); | 1109 | intel_sdvo_get_dtd_from_mode(&input_dtd, mode); |
| 1040 | 1110 | ||
| 1041 | /* If it's a TV, we already set the output timing in mode_fixup. | 1111 | /* If it's a TV, we already set the output timing in mode_fixup. |
| 1042 | * Otherwise, the output timing is equal to the input timing. | 1112 | * Otherwise, the output timing is equal to the input timing. |
| 1043 | */ | 1113 | */ |
| 1044 | if (!sdvo_priv->is_tv) { | 1114 | if (!sdvo_priv->is_tv && !sdvo_priv->is_lvds) { |
| 1045 | /* Set the output timing to the screen */ | 1115 | /* Set the output timing to the screen */ |
| 1046 | intel_sdvo_set_target_output(output, | 1116 | intel_sdvo_set_target_output(output, |
| 1047 | sdvo_priv->controlled_output); | 1117 | sdvo_priv->controlled_output); |
| @@ -1116,6 +1186,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
| 1116 | sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; | 1186 | sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; |
| 1117 | } | 1187 | } |
| 1118 | 1188 | ||
| 1189 | if (sdvo_priv->sdvo_flags & SDVO_NEED_TO_STALL) | ||
| 1190 | sdvox |= SDVO_STALL_SELECT; | ||
| 1119 | intel_sdvo_write_sdvox(output, sdvox); | 1191 | intel_sdvo_write_sdvox(output, sdvox); |
| 1120 | } | 1192 | } |
| 1121 | 1193 | ||
| @@ -1276,6 +1348,17 @@ static int intel_sdvo_mode_valid(struct drm_connector *connector, | |||
| 1276 | if (sdvo_priv->pixel_clock_max < mode->clock) | 1348 | if (sdvo_priv->pixel_clock_max < mode->clock) |
| 1277 | return MODE_CLOCK_HIGH; | 1349 | return MODE_CLOCK_HIGH; |
| 1278 | 1350 | ||
| 1351 | if (sdvo_priv->is_lvds == true) { | ||
| 1352 | if (sdvo_priv->sdvo_lvds_fixed_mode == NULL) | ||
| 1353 | return MODE_PANEL; | ||
| 1354 | |||
| 1355 | if (mode->hdisplay > sdvo_priv->sdvo_lvds_fixed_mode->hdisplay) | ||
| 1356 | return MODE_PANEL; | ||
| 1357 | |||
| 1358 | if (mode->vdisplay > sdvo_priv->sdvo_lvds_fixed_mode->vdisplay) | ||
| 1359 | return MODE_PANEL; | ||
| 1360 | } | ||
| 1361 | |||
| 1279 | return MODE_OK; | 1362 | return MODE_OK; |
| 1280 | } | 1363 | } |
| 1281 | 1364 | ||
| @@ -1362,41 +1445,96 @@ void intel_sdvo_set_hotplug(struct drm_connector *connector, int on) | |||
| 1362 | intel_sdvo_read_response(intel_output, &response, 2); | 1445 | intel_sdvo_read_response(intel_output, &response, 2); |
| 1363 | } | 1446 | } |
| 1364 | 1447 | ||
| 1365 | static void | 1448 | static bool |
| 1366 | intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) | 1449 | intel_sdvo_multifunc_encoder(struct intel_output *intel_output) |
| 1450 | { | ||
| 1451 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
| 1452 | int caps = 0; | ||
| 1453 | |||
| 1454 | if (sdvo_priv->caps.output_flags & | ||
| 1455 | (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) | ||
| 1456 | caps++; | ||
| 1457 | if (sdvo_priv->caps.output_flags & | ||
| 1458 | (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1)) | ||
| 1459 | caps++; | ||
| 1460 | if (sdvo_priv->caps.output_flags & | ||
| 1461 | (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_SVID0)) | ||
| 1462 | caps++; | ||
| 1463 | if (sdvo_priv->caps.output_flags & | ||
| 1464 | (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_CVBS1)) | ||
| 1465 | caps++; | ||
| 1466 | if (sdvo_priv->caps.output_flags & | ||
| 1467 | (SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_YPRPB1)) | ||
| 1468 | caps++; | ||
| 1469 | |||
| 1470 | if (sdvo_priv->caps.output_flags & | ||
| 1471 | (SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1)) | ||
| 1472 | caps++; | ||
| 1473 | |||
| 1474 | if (sdvo_priv->caps.output_flags & | ||
| 1475 | (SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1)) | ||
| 1476 | caps++; | ||
| 1477 | |||
| 1478 | return (caps > 1); | ||
| 1479 | } | ||
| 1480 | |||
| 1481 | enum drm_connector_status | ||
| 1482 | intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response) | ||
| 1367 | { | 1483 | { |
| 1368 | struct intel_output *intel_output = to_intel_output(connector); | 1484 | struct intel_output *intel_output = to_intel_output(connector); |
| 1369 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | 1485 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; |
| 1486 | enum drm_connector_status status = connector_status_connected; | ||
| 1370 | struct edid *edid = NULL; | 1487 | struct edid *edid = NULL; |
| 1371 | 1488 | ||
| 1372 | edid = drm_get_edid(&intel_output->base, | 1489 | edid = drm_get_edid(&intel_output->base, |
| 1373 | intel_output->ddc_bus); | 1490 | intel_output->ddc_bus); |
| 1374 | if (edid != NULL) { | 1491 | if (edid != NULL) { |
| 1375 | sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid); | 1492 | /* Don't report the output as connected if it's a DVI-I |
| 1493 | * connector with a non-digital EDID coming out. | ||
| 1494 | */ | ||
| 1495 | if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) { | ||
| 1496 | if (edid->input & DRM_EDID_INPUT_DIGITAL) | ||
| 1497 | sdvo_priv->is_hdmi = | ||
| 1498 | drm_detect_hdmi_monitor(edid); | ||
| 1499 | else | ||
| 1500 | status = connector_status_disconnected; | ||
| 1501 | } | ||
| 1502 | |||
| 1376 | kfree(edid); | 1503 | kfree(edid); |
| 1377 | intel_output->base.display_info.raw_edid = NULL; | 1504 | intel_output->base.display_info.raw_edid = NULL; |
| 1378 | } | 1505 | |
| 1506 | } else if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) | ||
| 1507 | status = connector_status_disconnected; | ||
| 1508 | |||
| 1509 | return status; | ||
| 1379 | } | 1510 | } |
| 1380 | 1511 | ||
| 1381 | static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector) | 1512 | static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector) |
| 1382 | { | 1513 | { |
| 1383 | u8 response[2]; | 1514 | uint16_t response; |
| 1384 | u8 status; | 1515 | u8 status; |
| 1385 | struct intel_output *intel_output = to_intel_output(connector); | 1516 | struct intel_output *intel_output = to_intel_output(connector); |
| 1517 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
| 1386 | 1518 | ||
| 1387 | intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0); | 1519 | intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0); |
| 1388 | status = intel_sdvo_read_response(intel_output, &response, 2); | 1520 | status = intel_sdvo_read_response(intel_output, &response, 2); |
| 1389 | 1521 | ||
| 1390 | DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]); | 1522 | DRM_DEBUG("SDVO response %d %d\n", response & 0xff, response >> 8); |
| 1391 | 1523 | ||
| 1392 | if (status != SDVO_CMD_STATUS_SUCCESS) | 1524 | if (status != SDVO_CMD_STATUS_SUCCESS) |
| 1393 | return connector_status_unknown; | 1525 | return connector_status_unknown; |
| 1394 | 1526 | ||
| 1395 | if ((response[0] != 0) || (response[1] != 0)) { | 1527 | if (response == 0) |
| 1396 | intel_sdvo_hdmi_sink_detect(connector); | ||
| 1397 | return connector_status_connected; | ||
| 1398 | } else | ||
| 1399 | return connector_status_disconnected; | 1528 | return connector_status_disconnected; |
| 1529 | |||
| 1530 | if (intel_sdvo_multifunc_encoder(intel_output) && | ||
| 1531 | sdvo_priv->attached_output != response) { | ||
| 1532 | if (sdvo_priv->controlled_output != response && | ||
| 1533 | intel_sdvo_output_setup(intel_output, response) != true) | ||
| 1534 | return connector_status_unknown; | ||
| 1535 | sdvo_priv->attached_output = response; | ||
| 1536 | } | ||
| 1537 | return intel_sdvo_hdmi_sink_detect(connector, response); | ||
| 1400 | } | 1538 | } |
| 1401 | 1539 | ||
| 1402 | static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) | 1540 | static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) |
| @@ -1549,6 +1687,8 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) | |||
| 1549 | { | 1687 | { |
| 1550 | struct intel_output *intel_output = to_intel_output(connector); | 1688 | struct intel_output *intel_output = to_intel_output(connector); |
| 1551 | struct drm_i915_private *dev_priv = connector->dev->dev_private; | 1689 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
| 1690 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
| 1691 | struct drm_display_mode *newmode; | ||
| 1552 | 1692 | ||
| 1553 | /* | 1693 | /* |
| 1554 | * Attempt to get the mode list from DDC. | 1694 | * Attempt to get the mode list from DDC. |
| @@ -1557,11 +1697,10 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) | |||
| 1557 | */ | 1697 | */ |
| 1558 | intel_ddc_get_modes(intel_output); | 1698 | intel_ddc_get_modes(intel_output); |
| 1559 | if (list_empty(&connector->probed_modes) == false) | 1699 | if (list_empty(&connector->probed_modes) == false) |
| 1560 | return; | 1700 | goto end; |
| 1561 | 1701 | ||
| 1562 | /* Fetch modes from VBT */ | 1702 | /* Fetch modes from VBT */ |
| 1563 | if (dev_priv->sdvo_lvds_vbt_mode != NULL) { | 1703 | if (dev_priv->sdvo_lvds_vbt_mode != NULL) { |
| 1564 | struct drm_display_mode *newmode; | ||
| 1565 | newmode = drm_mode_duplicate(connector->dev, | 1704 | newmode = drm_mode_duplicate(connector->dev, |
| 1566 | dev_priv->sdvo_lvds_vbt_mode); | 1705 | dev_priv->sdvo_lvds_vbt_mode); |
| 1567 | if (newmode != NULL) { | 1706 | if (newmode != NULL) { |
| @@ -1571,6 +1710,16 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) | |||
| 1571 | drm_mode_probed_add(connector, newmode); | 1710 | drm_mode_probed_add(connector, newmode); |
| 1572 | } | 1711 | } |
| 1573 | } | 1712 | } |
| 1713 | |||
| 1714 | end: | ||
| 1715 | list_for_each_entry(newmode, &connector->probed_modes, head) { | ||
| 1716 | if (newmode->type & DRM_MODE_TYPE_PREFERRED) { | ||
| 1717 | sdvo_priv->sdvo_lvds_fixed_mode = | ||
| 1718 | drm_mode_duplicate(connector->dev, newmode); | ||
| 1719 | break; | ||
| 1720 | } | ||
| 1721 | } | ||
| 1722 | |||
| 1574 | } | 1723 | } |
| 1575 | 1724 | ||
| 1576 | static int intel_sdvo_get_modes(struct drm_connector *connector) | 1725 | static int intel_sdvo_get_modes(struct drm_connector *connector) |
| @@ -1593,14 +1742,20 @@ static int intel_sdvo_get_modes(struct drm_connector *connector) | |||
| 1593 | static void intel_sdvo_destroy(struct drm_connector *connector) | 1742 | static void intel_sdvo_destroy(struct drm_connector *connector) |
| 1594 | { | 1743 | { |
| 1595 | struct intel_output *intel_output = to_intel_output(connector); | 1744 | struct intel_output *intel_output = to_intel_output(connector); |
| 1745 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
| 1596 | 1746 | ||
| 1597 | if (intel_output->i2c_bus) | 1747 | if (intel_output->i2c_bus) |
| 1598 | intel_i2c_destroy(intel_output->i2c_bus); | 1748 | intel_i2c_destroy(intel_output->i2c_bus); |
| 1599 | if (intel_output->ddc_bus) | 1749 | if (intel_output->ddc_bus) |
| 1600 | intel_i2c_destroy(intel_output->ddc_bus); | 1750 | intel_i2c_destroy(intel_output->ddc_bus); |
| 1601 | 1751 | ||
| 1752 | if (sdvo_priv->sdvo_lvds_fixed_mode != NULL) | ||
| 1753 | drm_mode_destroy(connector->dev, | ||
| 1754 | sdvo_priv->sdvo_lvds_fixed_mode); | ||
| 1755 | |||
| 1602 | drm_sysfs_connector_remove(connector); | 1756 | drm_sysfs_connector_remove(connector); |
| 1603 | drm_connector_cleanup(connector); | 1757 | drm_connector_cleanup(connector); |
| 1758 | |||
| 1604 | kfree(intel_output); | 1759 | kfree(intel_output); |
| 1605 | } | 1760 | } |
| 1606 | 1761 | ||
| @@ -1776,16 +1931,101 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, int output_device) | |||
| 1776 | return 0x72; | 1931 | return 0x72; |
| 1777 | } | 1932 | } |
| 1778 | 1933 | ||
| 1934 | static bool | ||
| 1935 | intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags) | ||
| 1936 | { | ||
| 1937 | struct drm_connector *connector = &intel_output->base; | ||
| 1938 | struct drm_encoder *encoder = &intel_output->enc; | ||
| 1939 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
| 1940 | bool ret = true, registered = false; | ||
| 1941 | |||
| 1942 | sdvo_priv->is_tv = false; | ||
| 1943 | intel_output->needs_tv_clock = false; | ||
| 1944 | sdvo_priv->is_lvds = false; | ||
| 1945 | |||
| 1946 | if (device_is_registered(&connector->kdev)) { | ||
| 1947 | drm_sysfs_connector_remove(connector); | ||
| 1948 | registered = true; | ||
| 1949 | } | ||
| 1950 | |||
| 1951 | if (flags & | ||
| 1952 | (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) { | ||
| 1953 | if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) | ||
| 1954 | sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS0; | ||
| 1955 | else | ||
| 1956 | sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS1; | ||
| 1957 | |||
| 1958 | encoder->encoder_type = DRM_MODE_ENCODER_TMDS; | ||
| 1959 | connector->connector_type = DRM_MODE_CONNECTOR_DVID; | ||
| 1960 | |||
| 1961 | if (intel_sdvo_get_supp_encode(intel_output, | ||
| 1962 | &sdvo_priv->encode) && | ||
| 1963 | intel_sdvo_get_digital_encoding_mode(intel_output) && | ||
| 1964 | sdvo_priv->is_hdmi) { | ||
| 1965 | /* enable hdmi encoding mode if supported */ | ||
| 1966 | intel_sdvo_set_encode(intel_output, SDVO_ENCODE_HDMI); | ||
| 1967 | intel_sdvo_set_colorimetry(intel_output, | ||
| 1968 | SDVO_COLORIMETRY_RGB256); | ||
| 1969 | connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; | ||
| 1970 | } | ||
| 1971 | } else if (flags & SDVO_OUTPUT_SVID0) { | ||
| 1972 | |||
| 1973 | sdvo_priv->controlled_output = SDVO_OUTPUT_SVID0; | ||
| 1974 | encoder->encoder_type = DRM_MODE_ENCODER_TVDAC; | ||
| 1975 | connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO; | ||
| 1976 | sdvo_priv->is_tv = true; | ||
| 1977 | intel_output->needs_tv_clock = true; | ||
| 1978 | } else if (flags & SDVO_OUTPUT_RGB0) { | ||
| 1979 | |||
| 1980 | sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0; | ||
| 1981 | encoder->encoder_type = DRM_MODE_ENCODER_DAC; | ||
| 1982 | connector->connector_type = DRM_MODE_CONNECTOR_VGA; | ||
| 1983 | } else if (flags & SDVO_OUTPUT_RGB1) { | ||
| 1984 | |||
| 1985 | sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1; | ||
| 1986 | encoder->encoder_type = DRM_MODE_ENCODER_DAC; | ||
| 1987 | connector->connector_type = DRM_MODE_CONNECTOR_VGA; | ||
| 1988 | } else if (flags & SDVO_OUTPUT_LVDS0) { | ||
| 1989 | |||
| 1990 | sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS0; | ||
| 1991 | encoder->encoder_type = DRM_MODE_ENCODER_LVDS; | ||
| 1992 | connector->connector_type = DRM_MODE_CONNECTOR_LVDS; | ||
| 1993 | sdvo_priv->is_lvds = true; | ||
| 1994 | } else if (flags & SDVO_OUTPUT_LVDS1) { | ||
| 1995 | |||
| 1996 | sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1; | ||
| 1997 | encoder->encoder_type = DRM_MODE_ENCODER_LVDS; | ||
| 1998 | connector->connector_type = DRM_MODE_CONNECTOR_LVDS; | ||
| 1999 | sdvo_priv->is_lvds = true; | ||
| 2000 | } else { | ||
| 2001 | |||
| 2002 | unsigned char bytes[2]; | ||
| 2003 | |||
| 2004 | sdvo_priv->controlled_output = 0; | ||
| 2005 | memcpy(bytes, &sdvo_priv->caps.output_flags, 2); | ||
| 2006 | DRM_DEBUG_KMS(I915_SDVO, | ||
| 2007 | "%s: Unknown SDVO output type (0x%02x%02x)\n", | ||
| 2008 | SDVO_NAME(sdvo_priv), | ||
| 2009 | bytes[0], bytes[1]); | ||
| 2010 | ret = false; | ||
| 2011 | } | ||
| 2012 | |||
| 2013 | if (ret && registered) | ||
| 2014 | ret = drm_sysfs_connector_add(connector) == 0 ? true : false; | ||
| 2015 | |||
| 2016 | |||
| 2017 | return ret; | ||
| 2018 | |||
| 2019 | } | ||
| 2020 | |||
| 1779 | bool intel_sdvo_init(struct drm_device *dev, int output_device) | 2021 | bool intel_sdvo_init(struct drm_device *dev, int output_device) |
| 1780 | { | 2022 | { |
| 1781 | struct drm_connector *connector; | 2023 | struct drm_connector *connector; |
| 1782 | struct intel_output *intel_output; | 2024 | struct intel_output *intel_output; |
| 1783 | struct intel_sdvo_priv *sdvo_priv; | 2025 | struct intel_sdvo_priv *sdvo_priv; |
| 1784 | 2026 | ||
| 1785 | int connector_type; | ||
| 1786 | u8 ch[0x40]; | 2027 | u8 ch[0x40]; |
| 1787 | int i; | 2028 | int i; |
| 1788 | int encoder_type; | ||
| 1789 | 2029 | ||
| 1790 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); | 2030 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); |
| 1791 | if (!intel_output) { | 2031 | if (!intel_output) { |
| @@ -1835,88 +2075,28 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
| 1835 | intel_output->ddc_bus->algo = &intel_sdvo_i2c_bit_algo; | 2075 | intel_output->ddc_bus->algo = &intel_sdvo_i2c_bit_algo; |
| 1836 | 2076 | ||
| 1837 | /* In defaut case sdvo lvds is false */ | 2077 | /* In defaut case sdvo lvds is false */ |
| 1838 | sdvo_priv->is_lvds = false; | ||
| 1839 | intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps); | 2078 | intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps); |
| 1840 | 2079 | ||
| 1841 | if (sdvo_priv->caps.output_flags & | 2080 | if (intel_sdvo_output_setup(intel_output, |
| 1842 | (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) { | 2081 | sdvo_priv->caps.output_flags) != true) { |
| 1843 | if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) | 2082 | DRM_DEBUG("SDVO output failed to setup on SDVO%c\n", |
| 1844 | sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS0; | 2083 | output_device == SDVOB ? 'B' : 'C'); |
| 1845 | else | ||
| 1846 | sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS1; | ||
| 1847 | |||
| 1848 | encoder_type = DRM_MODE_ENCODER_TMDS; | ||
| 1849 | connector_type = DRM_MODE_CONNECTOR_DVID; | ||
| 1850 | |||
| 1851 | if (intel_sdvo_get_supp_encode(intel_output, | ||
| 1852 | &sdvo_priv->encode) && | ||
| 1853 | intel_sdvo_get_digital_encoding_mode(intel_output) && | ||
| 1854 | sdvo_priv->is_hdmi) { | ||
| 1855 | /* enable hdmi encoding mode if supported */ | ||
| 1856 | intel_sdvo_set_encode(intel_output, SDVO_ENCODE_HDMI); | ||
| 1857 | intel_sdvo_set_colorimetry(intel_output, | ||
| 1858 | SDVO_COLORIMETRY_RGB256); | ||
| 1859 | connector_type = DRM_MODE_CONNECTOR_HDMIA; | ||
| 1860 | } | ||
| 1861 | } | ||
| 1862 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_SVID0) | ||
| 1863 | { | ||
| 1864 | sdvo_priv->controlled_output = SDVO_OUTPUT_SVID0; | ||
| 1865 | encoder_type = DRM_MODE_ENCODER_TVDAC; | ||
| 1866 | connector_type = DRM_MODE_CONNECTOR_SVIDEO; | ||
| 1867 | sdvo_priv->is_tv = true; | ||
| 1868 | intel_output->needs_tv_clock = true; | ||
| 1869 | } | ||
| 1870 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0) | ||
| 1871 | { | ||
| 1872 | sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0; | ||
| 1873 | encoder_type = DRM_MODE_ENCODER_DAC; | ||
| 1874 | connector_type = DRM_MODE_CONNECTOR_VGA; | ||
| 1875 | } | ||
| 1876 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) | ||
| 1877 | { | ||
| 1878 | sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1; | ||
| 1879 | encoder_type = DRM_MODE_ENCODER_DAC; | ||
| 1880 | connector_type = DRM_MODE_CONNECTOR_VGA; | ||
| 1881 | } | ||
| 1882 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_LVDS0) | ||
| 1883 | { | ||
| 1884 | sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS0; | ||
| 1885 | encoder_type = DRM_MODE_ENCODER_LVDS; | ||
| 1886 | connector_type = DRM_MODE_CONNECTOR_LVDS; | ||
| 1887 | sdvo_priv->is_lvds = true; | ||
| 1888 | } | ||
| 1889 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_LVDS1) | ||
| 1890 | { | ||
| 1891 | sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1; | ||
| 1892 | encoder_type = DRM_MODE_ENCODER_LVDS; | ||
| 1893 | connector_type = DRM_MODE_CONNECTOR_LVDS; | ||
| 1894 | sdvo_priv->is_lvds = true; | ||
| 1895 | } | ||
| 1896 | else | ||
| 1897 | { | ||
| 1898 | unsigned char bytes[2]; | ||
| 1899 | |||
| 1900 | sdvo_priv->controlled_output = 0; | ||
| 1901 | memcpy (bytes, &sdvo_priv->caps.output_flags, 2); | ||
| 1902 | DRM_DEBUG_KMS(I915_SDVO, | ||
| 1903 | "%s: Unknown SDVO output type (0x%02x%02x)\n", | ||
| 1904 | SDVO_NAME(sdvo_priv), | ||
| 1905 | bytes[0], bytes[1]); | ||
| 1906 | encoder_type = DRM_MODE_ENCODER_NONE; | ||
| 1907 | connector_type = DRM_MODE_CONNECTOR_Unknown; | ||
| 1908 | goto err_i2c; | 2084 | goto err_i2c; |
| 1909 | } | 2085 | } |
| 1910 | 2086 | ||
| 2087 | |||
| 1911 | connector = &intel_output->base; | 2088 | connector = &intel_output->base; |
| 1912 | drm_connector_init(dev, connector, &intel_sdvo_connector_funcs, | 2089 | drm_connector_init(dev, connector, &intel_sdvo_connector_funcs, |
| 1913 | connector_type); | 2090 | connector->connector_type); |
| 2091 | |||
| 1914 | drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs); | 2092 | drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs); |
| 1915 | connector->interlace_allowed = 0; | 2093 | connector->interlace_allowed = 0; |
| 1916 | connector->doublescan_allowed = 0; | 2094 | connector->doublescan_allowed = 0; |
| 1917 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | 2095 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; |
| 1918 | 2096 | ||
| 1919 | drm_encoder_init(dev, &intel_output->enc, &intel_sdvo_enc_funcs, encoder_type); | 2097 | drm_encoder_init(dev, &intel_output->enc, |
| 2098 | &intel_sdvo_enc_funcs, intel_output->enc.encoder_type); | ||
| 2099 | |||
| 1920 | drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs); | 2100 | drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs); |
| 1921 | 2101 | ||
| 1922 | drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc); | 2102 | drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc); |
