aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorZhao Yakui <yakui.zhao@intel.com>2009-08-24 01:50:26 -0400
committerEric Anholt <eric@anholt.net>2009-09-04 16:05:11 -0400
commitce6feabd1b38f9adf4a962d71bc4762047e8f889 (patch)
tree068d83b9daad99c36323ae5d269e757b6c9b74d0 /drivers/gpu
parent213c2e643145fc7d8a67f2d5d54ee0f6d7193e2e (diff)
drm/i915: Enable PAL and SECAM format and add the propery for SDVO-TV
Currently SDVO TV only support NTSC-M format. In this patch we introduce PAL and SECAM formats available and create seting-format property at init time. When user dynamically chose preferred format by xrandr command, it will refine all modelines provided by SDVO device, then instruct SDVO device to execute. At the same time the property is added for SDVO-TV so that the SDVO-TV mode can be changed by using xrandr. https://bugs.freedesktop.org/show_bug.cgi?id=22891 Signed-off-by: Ma Ling <ling.ma@intel.com> review-by: Zhao Yakui <yakui.zhao@intel.com> Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c201
1 files changed, 153 insertions, 48 deletions
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index d3b74ba62b4a..cabe32df7cd5 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -38,6 +38,18 @@
38 38
39#undef SDVO_DEBUG 39#undef SDVO_DEBUG
40#define I915_SDVO "i915_sdvo" 40#define I915_SDVO "i915_sdvo"
41static char *tv_format_names[] = {
42 "NTSC_M" , "NTSC_J" , "NTSC_443",
43 "PAL_B" , "PAL_D" , "PAL_G" ,
44 "PAL_H" , "PAL_I" , "PAL_M" ,
45 "PAL_N" , "PAL_NC" , "PAL_60" ,
46 "SECAM_B" , "SECAM_D" , "SECAM_G" ,
47 "SECAM_K" , "SECAM_K1", "SECAM_L" ,
48 "SECAM_60"
49};
50
51#define TV_FORMAT_NUM (sizeof(tv_format_names) / sizeof(*tv_format_names))
52
41struct intel_sdvo_priv { 53struct intel_sdvo_priv {
42 u8 slave_addr; 54 u8 slave_addr;
43 55
@@ -71,6 +83,15 @@ struct intel_sdvo_priv {
71 */ 83 */
72 bool is_tv; 84 bool is_tv;
73 85
86 /* This is for current tv format name */
87 char *tv_format_name;
88
89 /* This contains all current supported TV format */
90 char *tv_format_supported[TV_FORMAT_NUM];
91 int format_supported_num;
92 struct drm_property *tv_format_property;
93 struct drm_property *tv_format_name_property[TV_FORMAT_NUM];
94
74 /** 95 /**
75 * This is set if we treat the device as HDMI, instead of DVI. 96 * This is set if we treat the device as HDMI, instead of DVI.
76 */ 97 */
@@ -97,14 +118,6 @@ struct intel_sdvo_priv {
97 */ 118 */
98 struct intel_sdvo_sdtv_resolution_reply sdtv_resolutions; 119 struct intel_sdvo_sdtv_resolution_reply sdtv_resolutions;
99 120
100 /**
101 * Current selected TV format.
102 *
103 * This is stored in the same structure that's passed to the device, for
104 * convenience.
105 */
106 struct intel_sdvo_tv_format tv_format;
107
108 /* 121 /*
109 * supported encoding mode, used to determine whether HDMI is 122 * supported encoding mode, used to determine whether HDMI is
110 * supported 123 * supported
@@ -945,23 +958,28 @@ static void intel_sdvo_set_avi_infoframe(struct intel_output *output,
945 958
946static void intel_sdvo_set_tv_format(struct intel_output *output) 959static void intel_sdvo_set_tv_format(struct intel_output *output)
947{ 960{
961
962 struct intel_sdvo_tv_format format;
948 struct intel_sdvo_priv *sdvo_priv = output->dev_priv; 963 struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
949 struct intel_sdvo_tv_format *format, unset; 964 uint32_t format_map, i;
950 u8 status; 965 uint8_t status;
951 966
952 format = &sdvo_priv->tv_format; 967 for (i = 0; i < TV_FORMAT_NUM; i++)
953 memset(&unset, 0, sizeof(unset)); 968 if (tv_format_names[i] == sdvo_priv->tv_format_name)
954 if (memcmp(format, &unset, sizeof(*format))) { 969 break;
955 DRM_DEBUG("%s: Choosing default TV format of NTSC-M\n", 970
956 SDVO_NAME(sdvo_priv)); 971 format_map = 1 << i;
957 format->ntsc_m = 1; 972 memset(&format, 0, sizeof(format));
958 intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, format, 973 memcpy(&format, &format_map, sizeof(format_map) > sizeof(format) ?
959 sizeof(*format)); 974 sizeof(format) : sizeof(format_map));
960 status = intel_sdvo_read_response(output, NULL, 0); 975
961 if (status != SDVO_CMD_STATUS_SUCCESS) 976 intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, &format_map,
962 DRM_DEBUG("%s: Failed to set TV format\n", 977 sizeof(format));
963 SDVO_NAME(sdvo_priv)); 978
964 } 979 status = intel_sdvo_read_response(output, NULL, 0);
980 if (status != SDVO_CMD_STATUS_SUCCESS)
981 DRM_DEBUG("%s: Failed to set TV format\n",
982 SDVO_NAME(sdvo_priv));
965} 983}
966 984
967static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, 985static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
@@ -1516,7 +1534,8 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect
1516 struct intel_output *intel_output = to_intel_output(connector); 1534 struct intel_output *intel_output = to_intel_output(connector);
1517 struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; 1535 struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
1518 1536
1519 intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0); 1537 intel_sdvo_write_cmd(intel_output,
1538 SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
1520 status = intel_sdvo_read_response(intel_output, &response, 2); 1539 status = intel_sdvo_read_response(intel_output, &response, 2);
1521 1540
1522 DRM_DEBUG("SDVO response %d %d\n", response & 0xff, response >> 8); 1541 DRM_DEBUG("SDVO response %d %d\n", response & 0xff, response >> 8);
@@ -1567,25 +1586,6 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
1567#endif 1586#endif
1568} 1587}
1569 1588
1570/**
1571 * This function checks the current TV format, and chooses a default if
1572 * it hasn't been set.
1573 */
1574static void
1575intel_sdvo_check_tv_format(struct intel_output *output)
1576{
1577 struct intel_sdvo_priv *dev_priv = output->dev_priv;
1578 struct intel_sdvo_tv_format format;
1579 uint8_t status;
1580
1581 intel_sdvo_write_cmd(output, SDVO_CMD_GET_TV_FORMAT, NULL, 0);
1582 status = intel_sdvo_read_response(output, &format, sizeof(format));
1583 if (status != SDVO_CMD_STATUS_SUCCESS)
1584 return;
1585
1586 memcpy(&dev_priv->tv_format, &format, sizeof(format));
1587}
1588
1589/* 1589/*
1590 * Set of SDVO TV modes. 1590 * Set of SDVO TV modes.
1591 * Note! This is in reply order (see loop in get_tv_modes). 1591 * Note! This is in reply order (see loop in get_tv_modes).
@@ -1656,17 +1656,26 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
1656 struct intel_output *output = to_intel_output(connector); 1656 struct intel_output *output = to_intel_output(connector);
1657 struct intel_sdvo_priv *sdvo_priv = output->dev_priv; 1657 struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
1658 struct intel_sdvo_sdtv_resolution_request tv_res; 1658 struct intel_sdvo_sdtv_resolution_request tv_res;
1659 uint32_t reply = 0; 1659 uint32_t reply = 0, format_map = 0;
1660 int i;
1660 uint8_t status; 1661 uint8_t status;
1661 int i = 0;
1662 1662
1663 intel_sdvo_check_tv_format(output);
1664 1663
1665 /* Read the list of supported input resolutions for the selected TV 1664 /* Read the list of supported input resolutions for the selected TV
1666 * format. 1665 * format.
1667 */ 1666 */
1668 memset(&tv_res, 0, sizeof(tv_res)); 1667 for (i = 0; i < TV_FORMAT_NUM; i++)
1669 memcpy(&tv_res, &sdvo_priv->tv_format, sizeof(tv_res)); 1668 if (tv_format_names[i] == sdvo_priv->tv_format_name)
1669 break;
1670
1671 format_map = (1 << i);
1672 memcpy(&tv_res, &format_map,
1673 sizeof(struct intel_sdvo_sdtv_resolution_request) >
1674 sizeof(format_map) ? sizeof(format_map) :
1675 sizeof(struct intel_sdvo_sdtv_resolution_request));
1676
1677 intel_sdvo_set_target_output(output, sdvo_priv->controlled_output);
1678
1670 intel_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT, 1679 intel_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT,
1671 &tv_res, sizeof(tv_res)); 1680 &tv_res, sizeof(tv_res));
1672 status = intel_sdvo_read_response(output, &reply, 3); 1681 status = intel_sdvo_read_response(output, &reply, 3);
@@ -1681,6 +1690,7 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
1681 if (nmode) 1690 if (nmode)
1682 drm_mode_probed_add(connector, nmode); 1691 drm_mode_probed_add(connector, nmode);
1683 } 1692 }
1693
1684} 1694}
1685 1695
1686static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) 1696static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
@@ -1753,12 +1763,55 @@ static void intel_sdvo_destroy(struct drm_connector *connector)
1753 drm_mode_destroy(connector->dev, 1763 drm_mode_destroy(connector->dev,
1754 sdvo_priv->sdvo_lvds_fixed_mode); 1764 sdvo_priv->sdvo_lvds_fixed_mode);
1755 1765
1766 if (sdvo_priv->tv_format_property)
1767 drm_property_destroy(connector->dev,
1768 sdvo_priv->tv_format_property);
1769
1756 drm_sysfs_connector_remove(connector); 1770 drm_sysfs_connector_remove(connector);
1757 drm_connector_cleanup(connector); 1771 drm_connector_cleanup(connector);
1758 1772
1759 kfree(intel_output); 1773 kfree(intel_output);
1760} 1774}
1761 1775
1776static int
1777intel_sdvo_set_property(struct drm_connector *connector,
1778 struct drm_property *property,
1779 uint64_t val)
1780{
1781 struct intel_output *intel_output = to_intel_output(connector);
1782 struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
1783 struct drm_encoder *encoder = &intel_output->enc;
1784 struct drm_crtc *crtc = encoder->crtc;
1785 int ret = 0;
1786 bool changed = false;
1787
1788 ret = drm_connector_property_set_value(connector, property, val);
1789 if (ret < 0)
1790 goto out;
1791
1792 if (property == sdvo_priv->tv_format_property) {
1793 if (val >= TV_FORMAT_NUM) {
1794 ret = -EINVAL;
1795 goto out;
1796 }
1797 if (sdvo_priv->tv_format_name ==
1798 sdvo_priv->tv_format_supported[val])
1799 goto out;
1800
1801 sdvo_priv->tv_format_name = sdvo_priv->tv_format_supported[val];
1802 changed = true;
1803 } else {
1804 ret = -EINVAL;
1805 goto out;
1806 }
1807
1808 if (changed && crtc)
1809 drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
1810 crtc->y, crtc->fb);
1811out:
1812 return ret;
1813}
1814
1762static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = { 1815static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
1763 .dpms = intel_sdvo_dpms, 1816 .dpms = intel_sdvo_dpms,
1764 .mode_fixup = intel_sdvo_mode_fixup, 1817 .mode_fixup = intel_sdvo_mode_fixup,
@@ -1773,6 +1826,7 @@ static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
1773 .restore = intel_sdvo_restore, 1826 .restore = intel_sdvo_restore,
1774 .detect = intel_sdvo_detect, 1827 .detect = intel_sdvo_detect,
1775 .fill_modes = drm_helper_probe_single_connector_modes, 1828 .fill_modes = drm_helper_probe_single_connector_modes,
1829 .set_property = intel_sdvo_set_property,
1776 .destroy = intel_sdvo_destroy, 1830 .destroy = intel_sdvo_destroy,
1777}; 1831};
1778 1832
@@ -2029,6 +2083,55 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
2029 2083
2030} 2084}
2031 2085
2086static void intel_sdvo_tv_create_property(struct drm_connector *connector)
2087{
2088 struct intel_output *intel_output = to_intel_output(connector);
2089 struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
2090 struct intel_sdvo_tv_format format;
2091 uint32_t format_map, i;
2092 uint8_t status;
2093
2094 intel_sdvo_set_target_output(intel_output,
2095 sdvo_priv->controlled_output);
2096
2097 intel_sdvo_write_cmd(intel_output,
2098 SDVO_CMD_GET_SUPPORTED_TV_FORMATS, NULL, 0);
2099 status = intel_sdvo_read_response(intel_output,
2100 &format, sizeof(format));
2101 if (status != SDVO_CMD_STATUS_SUCCESS)
2102 return;
2103
2104 memcpy(&format_map, &format, sizeof(format) > sizeof(format_map) ?
2105 sizeof(format_map) : sizeof(format));
2106
2107 if (format_map == 0)
2108 return;
2109
2110 sdvo_priv->format_supported_num = 0;
2111 for (i = 0 ; i < TV_FORMAT_NUM; i++)
2112 if (format_map & (1 << i)) {
2113 sdvo_priv->tv_format_supported
2114 [sdvo_priv->format_supported_num++] =
2115 tv_format_names[i];
2116 }
2117
2118
2119 sdvo_priv->tv_format_property =
2120 drm_property_create(
2121 connector->dev, DRM_MODE_PROP_ENUM,
2122 "mode", sdvo_priv->format_supported_num);
2123
2124 for (i = 0; i < sdvo_priv->format_supported_num; i++)
2125 drm_property_add_enum(
2126 sdvo_priv->tv_format_property, i,
2127 i, sdvo_priv->tv_format_supported[i]);
2128
2129 sdvo_priv->tv_format_name = sdvo_priv->tv_format_supported[0];
2130 drm_connector_attach_property(
2131 connector, sdvo_priv->tv_format_property, 0);
2132
2133}
2134
2032bool intel_sdvo_init(struct drm_device *dev, int output_device) 2135bool intel_sdvo_init(struct drm_device *dev, int output_device)
2033{ 2136{
2034 struct drm_connector *connector; 2137 struct drm_connector *connector;
@@ -2111,6 +2214,8 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
2111 drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs); 2214 drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs);
2112 2215
2113 drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc); 2216 drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
2217 if (sdvo_priv->is_tv)
2218 intel_sdvo_tv_create_property(connector);
2114 drm_sysfs_connector_add(connector); 2219 drm_sysfs_connector_add(connector);
2115 2220
2116 intel_sdvo_select_ddc_bus(sdvo_priv); 2221 intel_sdvo_select_ddc_bus(sdvo_priv);