diff options
author | Dave Airlie <airlied@redhat.com> | 2009-08-19 23:38:04 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-08-19 23:38:04 -0400 |
commit | 51c8b4071d84d46cc100baa5931ad06b2a823c95 (patch) | |
tree | 098cf9d41ce1c548d922708a770a9efe35e434df /drivers/gpu/drm/i915/intel_sdvo.c | |
parent | a987fcaa805fcb24ba885c2e29fd4fdb6816f08f (diff) | |
parent | 6c30c53fd5ae6a99a23ad78e90c428d2c8ffb07f (diff) |
Merge Linus master to drm-next
linux-next conflict reported needed resolution.
Conflicts:
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/ttm/ttm_bo.c
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sdvo.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 252 |
1 files changed, 171 insertions, 81 deletions
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index abef69c8a49a..91238f0c39a5 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" |
@@ -54,6 +55,12 @@ struct intel_sdvo_priv { | |||
54 | /* Pixel clock limitations reported by the SDVO device, in kHz */ | 55 | /* Pixel clock limitations reported by the SDVO device, in kHz */ |
55 | int pixel_clock_min, pixel_clock_max; | 56 | int pixel_clock_min, pixel_clock_max; |
56 | 57 | ||
58 | /* | ||
59 | * For multiple function SDVO device, | ||
60 | * this is for current attached outputs. | ||
61 | */ | ||
62 | uint16_t attached_output; | ||
63 | |||
57 | /** | 64 | /** |
58 | * This is set if we're going to treat the device as TV-out. | 65 | * This is set if we're going to treat the device as TV-out. |
59 | * | 66 | * |
@@ -113,6 +120,9 @@ struct intel_sdvo_priv { | |||
113 | u32 save_SDVOX; | 120 | u32 save_SDVOX; |
114 | }; | 121 | }; |
115 | 122 | ||
123 | static bool | ||
124 | intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags); | ||
125 | |||
116 | /** | 126 | /** |
117 | * Writes the SDVOB or SDVOC with the given value, but always writes both | 127 | * Writes the SDVOB or SDVOC with the given value, but always writes both |
118 | * SDVOB and SDVOC to work around apparent hardware issues (according to | 128 | * SDVOB and SDVOC to work around apparent hardware issues (according to |
@@ -1434,41 +1444,96 @@ void intel_sdvo_set_hotplug(struct drm_connector *connector, int on) | |||
1434 | intel_sdvo_read_response(intel_output, &response, 2); | 1444 | intel_sdvo_read_response(intel_output, &response, 2); |
1435 | } | 1445 | } |
1436 | 1446 | ||
1437 | static void | 1447 | static bool |
1438 | intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) | 1448 | intel_sdvo_multifunc_encoder(struct intel_output *intel_output) |
1449 | { | ||
1450 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
1451 | int caps = 0; | ||
1452 | |||
1453 | if (sdvo_priv->caps.output_flags & | ||
1454 | (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) | ||
1455 | caps++; | ||
1456 | if (sdvo_priv->caps.output_flags & | ||
1457 | (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1)) | ||
1458 | caps++; | ||
1459 | if (sdvo_priv->caps.output_flags & | ||
1460 | (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_SVID0)) | ||
1461 | caps++; | ||
1462 | if (sdvo_priv->caps.output_flags & | ||
1463 | (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_CVBS1)) | ||
1464 | caps++; | ||
1465 | if (sdvo_priv->caps.output_flags & | ||
1466 | (SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_YPRPB1)) | ||
1467 | caps++; | ||
1468 | |||
1469 | if (sdvo_priv->caps.output_flags & | ||
1470 | (SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1)) | ||
1471 | caps++; | ||
1472 | |||
1473 | if (sdvo_priv->caps.output_flags & | ||
1474 | (SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1)) | ||
1475 | caps++; | ||
1476 | |||
1477 | return (caps > 1); | ||
1478 | } | ||
1479 | |||
1480 | enum drm_connector_status | ||
1481 | intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response) | ||
1439 | { | 1482 | { |
1440 | struct intel_output *intel_output = to_intel_output(connector); | 1483 | struct intel_output *intel_output = to_intel_output(connector); |
1441 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | 1484 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; |
1485 | enum drm_connector_status status = connector_status_connected; | ||
1442 | struct edid *edid = NULL; | 1486 | struct edid *edid = NULL; |
1443 | 1487 | ||
1444 | edid = drm_get_edid(&intel_output->base, | 1488 | edid = drm_get_edid(&intel_output->base, |
1445 | intel_output->ddc_bus); | 1489 | intel_output->ddc_bus); |
1446 | if (edid != NULL) { | 1490 | if (edid != NULL) { |
1447 | sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid); | 1491 | /* Don't report the output as connected if it's a DVI-I |
1492 | * connector with a non-digital EDID coming out. | ||
1493 | */ | ||
1494 | if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) { | ||
1495 | if (edid->input & DRM_EDID_INPUT_DIGITAL) | ||
1496 | sdvo_priv->is_hdmi = | ||
1497 | drm_detect_hdmi_monitor(edid); | ||
1498 | else | ||
1499 | status = connector_status_disconnected; | ||
1500 | } | ||
1501 | |||
1448 | kfree(edid); | 1502 | kfree(edid); |
1449 | intel_output->base.display_info.raw_edid = NULL; | 1503 | intel_output->base.display_info.raw_edid = NULL; |
1450 | } | 1504 | |
1505 | } else if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) | ||
1506 | status = connector_status_disconnected; | ||
1507 | |||
1508 | return status; | ||
1451 | } | 1509 | } |
1452 | 1510 | ||
1453 | static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector) | 1511 | static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector) |
1454 | { | 1512 | { |
1455 | u8 response[2]; | 1513 | uint16_t response; |
1456 | u8 status; | 1514 | u8 status; |
1457 | struct intel_output *intel_output = to_intel_output(connector); | 1515 | struct intel_output *intel_output = to_intel_output(connector); |
1516 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
1458 | 1517 | ||
1459 | intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0); | 1518 | intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0); |
1460 | status = intel_sdvo_read_response(intel_output, &response, 2); | 1519 | status = intel_sdvo_read_response(intel_output, &response, 2); |
1461 | 1520 | ||
1462 | DRM_DEBUG_KMS("SDVO response %d %d\n", response[0], response[1]); | 1521 | DRM_DEBUG_KMS("SDVO response %d %d\n", response & 0xff, response >> 8); |
1463 | 1522 | ||
1464 | if (status != SDVO_CMD_STATUS_SUCCESS) | 1523 | if (status != SDVO_CMD_STATUS_SUCCESS) |
1465 | return connector_status_unknown; | 1524 | return connector_status_unknown; |
1466 | 1525 | ||
1467 | if ((response[0] != 0) || (response[1] != 0)) { | 1526 | if (response == 0) |
1468 | intel_sdvo_hdmi_sink_detect(connector); | ||
1469 | return connector_status_connected; | ||
1470 | } else | ||
1471 | return connector_status_disconnected; | 1527 | return connector_status_disconnected; |
1528 | |||
1529 | if (intel_sdvo_multifunc_encoder(intel_output) && | ||
1530 | sdvo_priv->attached_output != response) { | ||
1531 | if (sdvo_priv->controlled_output != response && | ||
1532 | intel_sdvo_output_setup(intel_output, response) != true) | ||
1533 | return connector_status_unknown; | ||
1534 | sdvo_priv->attached_output = response; | ||
1535 | } | ||
1536 | return intel_sdvo_hdmi_sink_detect(connector, response); | ||
1472 | } | 1537 | } |
1473 | 1538 | ||
1474 | static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) | 1539 | static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) |
@@ -1865,16 +1930,100 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, int output_device) | |||
1865 | return 0x72; | 1930 | return 0x72; |
1866 | } | 1931 | } |
1867 | 1932 | ||
1933 | static bool | ||
1934 | intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags) | ||
1935 | { | ||
1936 | struct drm_connector *connector = &intel_output->base; | ||
1937 | struct drm_encoder *encoder = &intel_output->enc; | ||
1938 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
1939 | bool ret = true, registered = false; | ||
1940 | |||
1941 | sdvo_priv->is_tv = false; | ||
1942 | intel_output->needs_tv_clock = false; | ||
1943 | sdvo_priv->is_lvds = false; | ||
1944 | |||
1945 | if (device_is_registered(&connector->kdev)) { | ||
1946 | drm_sysfs_connector_remove(connector); | ||
1947 | registered = true; | ||
1948 | } | ||
1949 | |||
1950 | if (flags & | ||
1951 | (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) { | ||
1952 | if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) | ||
1953 | sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS0; | ||
1954 | else | ||
1955 | sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS1; | ||
1956 | |||
1957 | encoder->encoder_type = DRM_MODE_ENCODER_TMDS; | ||
1958 | connector->connector_type = DRM_MODE_CONNECTOR_DVID; | ||
1959 | |||
1960 | if (intel_sdvo_get_supp_encode(intel_output, | ||
1961 | &sdvo_priv->encode) && | ||
1962 | intel_sdvo_get_digital_encoding_mode(intel_output) && | ||
1963 | sdvo_priv->is_hdmi) { | ||
1964 | /* enable hdmi encoding mode if supported */ | ||
1965 | intel_sdvo_set_encode(intel_output, SDVO_ENCODE_HDMI); | ||
1966 | intel_sdvo_set_colorimetry(intel_output, | ||
1967 | SDVO_COLORIMETRY_RGB256); | ||
1968 | connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; | ||
1969 | } | ||
1970 | } else if (flags & SDVO_OUTPUT_SVID0) { | ||
1971 | |||
1972 | sdvo_priv->controlled_output = SDVO_OUTPUT_SVID0; | ||
1973 | encoder->encoder_type = DRM_MODE_ENCODER_TVDAC; | ||
1974 | connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO; | ||
1975 | sdvo_priv->is_tv = true; | ||
1976 | intel_output->needs_tv_clock = true; | ||
1977 | } else if (flags & SDVO_OUTPUT_RGB0) { | ||
1978 | |||
1979 | sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0; | ||
1980 | encoder->encoder_type = DRM_MODE_ENCODER_DAC; | ||
1981 | connector->connector_type = DRM_MODE_CONNECTOR_VGA; | ||
1982 | } else if (flags & SDVO_OUTPUT_RGB1) { | ||
1983 | |||
1984 | sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1; | ||
1985 | encoder->encoder_type = DRM_MODE_ENCODER_DAC; | ||
1986 | connector->connector_type = DRM_MODE_CONNECTOR_VGA; | ||
1987 | } else if (flags & SDVO_OUTPUT_LVDS0) { | ||
1988 | |||
1989 | sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS0; | ||
1990 | encoder->encoder_type = DRM_MODE_ENCODER_LVDS; | ||
1991 | connector->connector_type = DRM_MODE_CONNECTOR_LVDS; | ||
1992 | sdvo_priv->is_lvds = true; | ||
1993 | } else if (flags & SDVO_OUTPUT_LVDS1) { | ||
1994 | |||
1995 | sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1; | ||
1996 | encoder->encoder_type = DRM_MODE_ENCODER_LVDS; | ||
1997 | connector->connector_type = DRM_MODE_CONNECTOR_LVDS; | ||
1998 | sdvo_priv->is_lvds = true; | ||
1999 | } else { | ||
2000 | |||
2001 | unsigned char bytes[2]; | ||
2002 | |||
2003 | sdvo_priv->controlled_output = 0; | ||
2004 | memcpy(bytes, &sdvo_priv->caps.output_flags, 2); | ||
2005 | DRM_DEBUG_KMS("%s: Unknown SDVO output type (0x%02x%02x)\n", | ||
2006 | SDVO_NAME(sdvo_priv), | ||
2007 | bytes[0], bytes[1]); | ||
2008 | ret = false; | ||
2009 | } | ||
2010 | |||
2011 | if (ret && registered) | ||
2012 | ret = drm_sysfs_connector_add(connector) == 0 ? true : false; | ||
2013 | |||
2014 | |||
2015 | return ret; | ||
2016 | |||
2017 | } | ||
2018 | |||
1868 | bool intel_sdvo_init(struct drm_device *dev, int output_device) | 2019 | bool intel_sdvo_init(struct drm_device *dev, int output_device) |
1869 | { | 2020 | { |
1870 | struct drm_connector *connector; | 2021 | struct drm_connector *connector; |
1871 | struct intel_output *intel_output; | 2022 | struct intel_output *intel_output; |
1872 | struct intel_sdvo_priv *sdvo_priv; | 2023 | struct intel_sdvo_priv *sdvo_priv; |
1873 | 2024 | ||
1874 | int connector_type; | ||
1875 | u8 ch[0x40]; | 2025 | u8 ch[0x40]; |
1876 | int i; | 2026 | int i; |
1877 | int encoder_type; | ||
1878 | 2027 | ||
1879 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); | 2028 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); |
1880 | if (!intel_output) { | 2029 | if (!intel_output) { |
@@ -1923,87 +2072,28 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
1923 | intel_output->ddc_bus->algo = &intel_sdvo_i2c_bit_algo; | 2072 | intel_output->ddc_bus->algo = &intel_sdvo_i2c_bit_algo; |
1924 | 2073 | ||
1925 | /* In defaut case sdvo lvds is false */ | 2074 | /* In defaut case sdvo lvds is false */ |
1926 | sdvo_priv->is_lvds = false; | ||
1927 | intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps); | 2075 | intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps); |
1928 | 2076 | ||
1929 | if (sdvo_priv->caps.output_flags & | 2077 | if (intel_sdvo_output_setup(intel_output, |
1930 | (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) { | 2078 | sdvo_priv->caps.output_flags) != true) { |
1931 | if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) | 2079 | DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n", |
1932 | sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS0; | 2080 | output_device == SDVOB ? 'B' : 'C'); |
1933 | else | ||
1934 | sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS1; | ||
1935 | |||
1936 | encoder_type = DRM_MODE_ENCODER_TMDS; | ||
1937 | connector_type = DRM_MODE_CONNECTOR_DVID; | ||
1938 | |||
1939 | if (intel_sdvo_get_supp_encode(intel_output, | ||
1940 | &sdvo_priv->encode) && | ||
1941 | intel_sdvo_get_digital_encoding_mode(intel_output) && | ||
1942 | sdvo_priv->is_hdmi) { | ||
1943 | /* enable hdmi encoding mode if supported */ | ||
1944 | intel_sdvo_set_encode(intel_output, SDVO_ENCODE_HDMI); | ||
1945 | intel_sdvo_set_colorimetry(intel_output, | ||
1946 | SDVO_COLORIMETRY_RGB256); | ||
1947 | connector_type = DRM_MODE_CONNECTOR_HDMIA; | ||
1948 | } | ||
1949 | } | ||
1950 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_SVID0) | ||
1951 | { | ||
1952 | sdvo_priv->controlled_output = SDVO_OUTPUT_SVID0; | ||
1953 | encoder_type = DRM_MODE_ENCODER_TVDAC; | ||
1954 | connector_type = DRM_MODE_CONNECTOR_SVIDEO; | ||
1955 | sdvo_priv->is_tv = true; | ||
1956 | intel_output->needs_tv_clock = true; | ||
1957 | } | ||
1958 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0) | ||
1959 | { | ||
1960 | sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0; | ||
1961 | encoder_type = DRM_MODE_ENCODER_DAC; | ||
1962 | connector_type = DRM_MODE_CONNECTOR_VGA; | ||
1963 | } | ||
1964 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) | ||
1965 | { | ||
1966 | sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1; | ||
1967 | encoder_type = DRM_MODE_ENCODER_DAC; | ||
1968 | connector_type = DRM_MODE_CONNECTOR_VGA; | ||
1969 | } | ||
1970 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_LVDS0) | ||
1971 | { | ||
1972 | sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS0; | ||
1973 | encoder_type = DRM_MODE_ENCODER_LVDS; | ||
1974 | connector_type = DRM_MODE_CONNECTOR_LVDS; | ||
1975 | sdvo_priv->is_lvds = true; | ||
1976 | } | ||
1977 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_LVDS1) | ||
1978 | { | ||
1979 | sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1; | ||
1980 | encoder_type = DRM_MODE_ENCODER_LVDS; | ||
1981 | connector_type = DRM_MODE_CONNECTOR_LVDS; | ||
1982 | sdvo_priv->is_lvds = true; | ||
1983 | } | ||
1984 | else | ||
1985 | { | ||
1986 | unsigned char bytes[2]; | ||
1987 | |||
1988 | sdvo_priv->controlled_output = 0; | ||
1989 | memcpy (bytes, &sdvo_priv->caps.output_flags, 2); | ||
1990 | DRM_DEBUG_KMS("%s: Unknown SDVO output type (0x%02x%02x)\n", | ||
1991 | SDVO_NAME(sdvo_priv), | ||
1992 | bytes[0], bytes[1]); | ||
1993 | encoder_type = DRM_MODE_ENCODER_NONE; | ||
1994 | connector_type = DRM_MODE_CONNECTOR_Unknown; | ||
1995 | goto err_i2c; | 2081 | goto err_i2c; |
1996 | } | 2082 | } |
1997 | 2083 | ||
2084 | |||
1998 | connector = &intel_output->base; | 2085 | connector = &intel_output->base; |
1999 | drm_connector_init(dev, connector, &intel_sdvo_connector_funcs, | 2086 | drm_connector_init(dev, connector, &intel_sdvo_connector_funcs, |
2000 | connector_type); | 2087 | connector->connector_type); |
2088 | |||
2001 | drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs); | 2089 | drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs); |
2002 | connector->interlace_allowed = 0; | 2090 | connector->interlace_allowed = 0; |
2003 | connector->doublescan_allowed = 0; | 2091 | connector->doublescan_allowed = 0; |
2004 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | 2092 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; |
2005 | 2093 | ||
2006 | drm_encoder_init(dev, &intel_output->enc, &intel_sdvo_enc_funcs, encoder_type); | 2094 | drm_encoder_init(dev, &intel_output->enc, |
2095 | &intel_sdvo_enc_funcs, intel_output->enc.encoder_type); | ||
2096 | |||
2007 | drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs); | 2097 | drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs); |
2008 | 2098 | ||
2009 | drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc); | 2099 | drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc); |