diff options
| -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); |
