diff options
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 231 |
1 files changed, 153 insertions, 78 deletions
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 4f0c30948bc4..b68746f0380e 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -55,6 +55,12 @@ struct intel_sdvo_priv { | |||
55 | /* Pixel clock limitations reported by the SDVO device, in kHz */ | 55 | /* Pixel clock limitations reported by the SDVO device, in kHz */ |
56 | int pixel_clock_min, pixel_clock_max; | 56 | int pixel_clock_min, pixel_clock_max; |
57 | 57 | ||
58 | /* | ||
59 | * For multiple function SDVO device, | ||
60 | * this is for current attached outputs. | ||
61 | */ | ||
62 | uint16_t attached_output; | ||
63 | |||
58 | /** | 64 | /** |
59 | * 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. |
60 | * | 66 | * |
@@ -114,6 +120,9 @@ struct intel_sdvo_priv { | |||
114 | u32 save_SDVOX; | 120 | u32 save_SDVOX; |
115 | }; | 121 | }; |
116 | 122 | ||
123 | static bool | ||
124 | intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags); | ||
125 | |||
117 | /** | 126 | /** |
118 | * 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 |
119 | * SDVOB and SDVOC to work around apparent hardware issues (according to | 128 | * SDVOB and SDVOC to work around apparent hardware issues (according to |
@@ -1435,6 +1444,39 @@ void intel_sdvo_set_hotplug(struct drm_connector *connector, int on) | |||
1435 | intel_sdvo_read_response(intel_output, &response, 2); | 1444 | intel_sdvo_read_response(intel_output, &response, 2); |
1436 | } | 1445 | } |
1437 | 1446 | ||
1447 | static bool | ||
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 | |||
1438 | static void | 1480 | static void |
1439 | intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) | 1481 | intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) |
1440 | { | 1482 | { |
@@ -1453,23 +1495,31 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) | |||
1453 | 1495 | ||
1454 | static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector) | 1496 | static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector) |
1455 | { | 1497 | { |
1456 | u8 response[2]; | 1498 | uint16_t response; |
1457 | u8 status; | 1499 | u8 status; |
1458 | struct intel_output *intel_output = to_intel_output(connector); | 1500 | struct intel_output *intel_output = to_intel_output(connector); |
1501 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
1459 | 1502 | ||
1460 | intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0); | 1503 | intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0); |
1461 | status = intel_sdvo_read_response(intel_output, &response, 2); | 1504 | status = intel_sdvo_read_response(intel_output, &response, 2); |
1462 | 1505 | ||
1463 | DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]); | 1506 | DRM_DEBUG("SDVO response %d %d\n", response & 0xff, response >> 8); |
1464 | 1507 | ||
1465 | if (status != SDVO_CMD_STATUS_SUCCESS) | 1508 | if (status != SDVO_CMD_STATUS_SUCCESS) |
1466 | return connector_status_unknown; | 1509 | return connector_status_unknown; |
1467 | 1510 | ||
1468 | if ((response[0] != 0) || (response[1] != 0)) { | 1511 | if (response == 0) |
1469 | intel_sdvo_hdmi_sink_detect(connector); | ||
1470 | return connector_status_connected; | ||
1471 | } else | ||
1472 | return connector_status_disconnected; | 1512 | return connector_status_disconnected; |
1513 | |||
1514 | if (intel_sdvo_multifunc_encoder(intel_output) && | ||
1515 | sdvo_priv->attached_output != response) { | ||
1516 | if (sdvo_priv->controlled_output != response && | ||
1517 | intel_sdvo_output_setup(intel_output, response) != true) | ||
1518 | return connector_status_unknown; | ||
1519 | sdvo_priv->attached_output = response; | ||
1520 | } | ||
1521 | intel_sdvo_hdmi_sink_detect(connector); | ||
1522 | return connector_status_connected; | ||
1473 | } | 1523 | } |
1474 | 1524 | ||
1475 | static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) | 1525 | static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) |
@@ -1866,16 +1916,101 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, int output_device) | |||
1866 | return 0x72; | 1916 | return 0x72; |
1867 | } | 1917 | } |
1868 | 1918 | ||
1919 | static bool | ||
1920 | intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags) | ||
1921 | { | ||
1922 | struct drm_connector *connector = &intel_output->base; | ||
1923 | struct drm_encoder *encoder = &intel_output->enc; | ||
1924 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
1925 | bool ret = true, registered = false; | ||
1926 | |||
1927 | sdvo_priv->is_tv = false; | ||
1928 | intel_output->needs_tv_clock = false; | ||
1929 | sdvo_priv->is_lvds = false; | ||
1930 | |||
1931 | if (device_is_registered(&connector->kdev)) { | ||
1932 | drm_sysfs_connector_remove(connector); | ||
1933 | registered = true; | ||
1934 | } | ||
1935 | |||
1936 | if (flags & | ||
1937 | (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) { | ||
1938 | if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) | ||
1939 | sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS0; | ||
1940 | else | ||
1941 | sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS1; | ||
1942 | |||
1943 | encoder->encoder_type = DRM_MODE_ENCODER_TMDS; | ||
1944 | connector->connector_type = DRM_MODE_CONNECTOR_DVID; | ||
1945 | |||
1946 | if (intel_sdvo_get_supp_encode(intel_output, | ||
1947 | &sdvo_priv->encode) && | ||
1948 | intel_sdvo_get_digital_encoding_mode(intel_output) && | ||
1949 | sdvo_priv->is_hdmi) { | ||
1950 | /* enable hdmi encoding mode if supported */ | ||
1951 | intel_sdvo_set_encode(intel_output, SDVO_ENCODE_HDMI); | ||
1952 | intel_sdvo_set_colorimetry(intel_output, | ||
1953 | SDVO_COLORIMETRY_RGB256); | ||
1954 | connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; | ||
1955 | } | ||
1956 | } else if (flags & SDVO_OUTPUT_SVID0) { | ||
1957 | |||
1958 | sdvo_priv->controlled_output = SDVO_OUTPUT_SVID0; | ||
1959 | encoder->encoder_type = DRM_MODE_ENCODER_TVDAC; | ||
1960 | connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO; | ||
1961 | sdvo_priv->is_tv = true; | ||
1962 | intel_output->needs_tv_clock = true; | ||
1963 | } else if (flags & SDVO_OUTPUT_RGB0) { | ||
1964 | |||
1965 | sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0; | ||
1966 | encoder->encoder_type = DRM_MODE_ENCODER_DAC; | ||
1967 | connector->connector_type = DRM_MODE_CONNECTOR_VGA; | ||
1968 | } else if (flags & SDVO_OUTPUT_RGB1) { | ||
1969 | |||
1970 | sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1; | ||
1971 | encoder->encoder_type = DRM_MODE_ENCODER_DAC; | ||
1972 | connector->connector_type = DRM_MODE_CONNECTOR_VGA; | ||
1973 | } else if (flags & SDVO_OUTPUT_LVDS0) { | ||
1974 | |||
1975 | sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS0; | ||
1976 | encoder->encoder_type = DRM_MODE_ENCODER_LVDS; | ||
1977 | connector->connector_type = DRM_MODE_CONNECTOR_LVDS; | ||
1978 | sdvo_priv->is_lvds = true; | ||
1979 | } else if (flags & SDVO_OUTPUT_LVDS1) { | ||
1980 | |||
1981 | sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1; | ||
1982 | encoder->encoder_type = DRM_MODE_ENCODER_LVDS; | ||
1983 | connector->connector_type = DRM_MODE_CONNECTOR_LVDS; | ||
1984 | sdvo_priv->is_lvds = true; | ||
1985 | } else { | ||
1986 | |||
1987 | unsigned char bytes[2]; | ||
1988 | |||
1989 | sdvo_priv->controlled_output = 0; | ||
1990 | memcpy(bytes, &sdvo_priv->caps.output_flags, 2); | ||
1991 | DRM_DEBUG_KMS(I915_SDVO, | ||
1992 | "%s: Unknown SDVO output type (0x%02x%02x)\n", | ||
1993 | SDVO_NAME(sdvo_priv), | ||
1994 | bytes[0], bytes[1]); | ||
1995 | ret = false; | ||
1996 | } | ||
1997 | |||
1998 | if (ret && registered) | ||
1999 | ret = drm_sysfs_connector_add(connector) == 0 ? true : false; | ||
2000 | |||
2001 | |||
2002 | return ret; | ||
2003 | |||
2004 | } | ||
2005 | |||
1869 | bool intel_sdvo_init(struct drm_device *dev, int output_device) | 2006 | bool intel_sdvo_init(struct drm_device *dev, int output_device) |
1870 | { | 2007 | { |
1871 | struct drm_connector *connector; | 2008 | struct drm_connector *connector; |
1872 | struct intel_output *intel_output; | 2009 | struct intel_output *intel_output; |
1873 | struct intel_sdvo_priv *sdvo_priv; | 2010 | struct intel_sdvo_priv *sdvo_priv; |
1874 | 2011 | ||
1875 | int connector_type; | ||
1876 | u8 ch[0x40]; | 2012 | u8 ch[0x40]; |
1877 | int i; | 2013 | int i; |
1878 | int encoder_type; | ||
1879 | 2014 | ||
1880 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); | 2015 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); |
1881 | if (!intel_output) { | 2016 | if (!intel_output) { |
@@ -1925,88 +2060,28 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
1925 | intel_output->ddc_bus->algo = &intel_sdvo_i2c_bit_algo; | 2060 | intel_output->ddc_bus->algo = &intel_sdvo_i2c_bit_algo; |
1926 | 2061 | ||
1927 | /* In defaut case sdvo lvds is false */ | 2062 | /* In defaut case sdvo lvds is false */ |
1928 | sdvo_priv->is_lvds = false; | ||
1929 | intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps); | 2063 | intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps); |
1930 | 2064 | ||
1931 | if (sdvo_priv->caps.output_flags & | 2065 | if (intel_sdvo_output_setup(intel_output, |
1932 | (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) { | 2066 | sdvo_priv->caps.output_flags) != true) { |
1933 | if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) | 2067 | DRM_DEBUG("SDVO output failed to setup on SDVO%c\n", |
1934 | sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS0; | 2068 | output_device == SDVOB ? 'B' : 'C'); |
1935 | else | ||
1936 | sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS1; | ||
1937 | |||
1938 | encoder_type = DRM_MODE_ENCODER_TMDS; | ||
1939 | connector_type = DRM_MODE_CONNECTOR_DVID; | ||
1940 | |||
1941 | if (intel_sdvo_get_supp_encode(intel_output, | ||
1942 | &sdvo_priv->encode) && | ||
1943 | intel_sdvo_get_digital_encoding_mode(intel_output) && | ||
1944 | sdvo_priv->is_hdmi) { | ||
1945 | /* enable hdmi encoding mode if supported */ | ||
1946 | intel_sdvo_set_encode(intel_output, SDVO_ENCODE_HDMI); | ||
1947 | intel_sdvo_set_colorimetry(intel_output, | ||
1948 | SDVO_COLORIMETRY_RGB256); | ||
1949 | connector_type = DRM_MODE_CONNECTOR_HDMIA; | ||
1950 | } | ||
1951 | } | ||
1952 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_SVID0) | ||
1953 | { | ||
1954 | sdvo_priv->controlled_output = SDVO_OUTPUT_SVID0; | ||
1955 | encoder_type = DRM_MODE_ENCODER_TVDAC; | ||
1956 | connector_type = DRM_MODE_CONNECTOR_SVIDEO; | ||
1957 | sdvo_priv->is_tv = true; | ||
1958 | intel_output->needs_tv_clock = true; | ||
1959 | } | ||
1960 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0) | ||
1961 | { | ||
1962 | sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0; | ||
1963 | encoder_type = DRM_MODE_ENCODER_DAC; | ||
1964 | connector_type = DRM_MODE_CONNECTOR_VGA; | ||
1965 | } | ||
1966 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) | ||
1967 | { | ||
1968 | sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1; | ||
1969 | encoder_type = DRM_MODE_ENCODER_DAC; | ||
1970 | connector_type = DRM_MODE_CONNECTOR_VGA; | ||
1971 | } | ||
1972 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_LVDS0) | ||
1973 | { | ||
1974 | sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS0; | ||
1975 | encoder_type = DRM_MODE_ENCODER_LVDS; | ||
1976 | connector_type = DRM_MODE_CONNECTOR_LVDS; | ||
1977 | sdvo_priv->is_lvds = true; | ||
1978 | } | ||
1979 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_LVDS1) | ||
1980 | { | ||
1981 | sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1; | ||
1982 | encoder_type = DRM_MODE_ENCODER_LVDS; | ||
1983 | connector_type = DRM_MODE_CONNECTOR_LVDS; | ||
1984 | sdvo_priv->is_lvds = true; | ||
1985 | } | ||
1986 | else | ||
1987 | { | ||
1988 | unsigned char bytes[2]; | ||
1989 | |||
1990 | sdvo_priv->controlled_output = 0; | ||
1991 | memcpy (bytes, &sdvo_priv->caps.output_flags, 2); | ||
1992 | DRM_DEBUG_KMS(I915_SDVO, | ||
1993 | "%s: Unknown SDVO output type (0x%02x%02x)\n", | ||
1994 | SDVO_NAME(sdvo_priv), | ||
1995 | bytes[0], bytes[1]); | ||
1996 | encoder_type = DRM_MODE_ENCODER_NONE; | ||
1997 | connector_type = DRM_MODE_CONNECTOR_Unknown; | ||
1998 | goto err_i2c; | 2069 | goto err_i2c; |
1999 | } | 2070 | } |
2000 | 2071 | ||
2072 | |||
2001 | connector = &intel_output->base; | 2073 | connector = &intel_output->base; |
2002 | drm_connector_init(dev, connector, &intel_sdvo_connector_funcs, | 2074 | drm_connector_init(dev, connector, &intel_sdvo_connector_funcs, |
2003 | connector_type); | 2075 | connector->connector_type); |
2076 | |||
2004 | drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs); | 2077 | drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs); |
2005 | connector->interlace_allowed = 0; | 2078 | connector->interlace_allowed = 0; |
2006 | connector->doublescan_allowed = 0; | 2079 | connector->doublescan_allowed = 0; |
2007 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | 2080 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; |
2008 | 2081 | ||
2009 | drm_encoder_init(dev, &intel_output->enc, &intel_sdvo_enc_funcs, encoder_type); | 2082 | drm_encoder_init(dev, &intel_output->enc, |
2083 | &intel_sdvo_enc_funcs, intel_output->enc.encoder_type); | ||
2084 | |||
2010 | drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs); | 2085 | drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs); |
2011 | 2086 | ||
2012 | drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc); | 2087 | drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc); |