aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_sdvo.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sdvo.c')
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c219
1 files changed, 90 insertions, 129 deletions
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index a84224f3760..de158b76bcd 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -107,6 +107,7 @@ struct intel_sdvo {
107 * This is set if we treat the device as HDMI, instead of DVI. 107 * This is set if we treat the device as HDMI, instead of DVI.
108 */ 108 */
109 bool is_hdmi; 109 bool is_hdmi;
110 bool has_audio;
110 111
111 /** 112 /**
112 * This is set if we detect output of sdvo device as LVDS and 113 * This is set if we detect output of sdvo device as LVDS and
@@ -119,12 +120,6 @@ struct intel_sdvo {
119 */ 120 */
120 struct drm_display_mode *sdvo_lvds_fixed_mode; 121 struct drm_display_mode *sdvo_lvds_fixed_mode;
121 122
122 /*
123 * supported encoding mode, used to determine whether HDMI is
124 * supported
125 */
126 struct intel_sdvo_encode encode;
127
128 /* DDC bus used by this SDVO encoder */ 123 /* DDC bus used by this SDVO encoder */
129 uint8_t ddc_bus; 124 uint8_t ddc_bus;
130 125
@@ -138,11 +133,15 @@ struct intel_sdvo_connector {
138 /* Mark the type of connector */ 133 /* Mark the type of connector */
139 uint16_t output_flag; 134 uint16_t output_flag;
140 135
136 int force_audio;
137
141 /* This contains all current supported TV format */ 138 /* This contains all current supported TV format */
142 u8 tv_format_supported[TV_FORMAT_NUM]; 139 u8 tv_format_supported[TV_FORMAT_NUM];
143 int format_supported_num; 140 int format_supported_num;
144 struct drm_property *tv_format; 141 struct drm_property *tv_format;
145 142
143 struct drm_property *force_audio_property;
144
146 /* add the property for the SDVO-TV */ 145 /* add the property for the SDVO-TV */
147 struct drm_property *left; 146 struct drm_property *left;
148 struct drm_property *right; 147 struct drm_property *right;
@@ -794,17 +793,13 @@ static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode,
794 mode->flags |= DRM_MODE_FLAG_PVSYNC; 793 mode->flags |= DRM_MODE_FLAG_PVSYNC;
795} 794}
796 795
797static bool intel_sdvo_get_supp_encode(struct intel_sdvo *intel_sdvo, 796static bool intel_sdvo_check_supp_encode(struct intel_sdvo *intel_sdvo)
798 struct intel_sdvo_encode *encode)
799{ 797{
800 if (intel_sdvo_get_value(intel_sdvo, 798 struct intel_sdvo_encode encode;
801 SDVO_CMD_GET_SUPP_ENCODE,
802 encode, sizeof(*encode)))
803 return true;
804 799
805 /* non-support means DVI */ 800 return intel_sdvo_get_value(intel_sdvo,
806 memset(encode, 0, sizeof(*encode)); 801 SDVO_CMD_GET_SUPP_ENCODE,
807 return false; 802 &encode, sizeof(encode));
808} 803}
809 804
810static bool intel_sdvo_set_encode(struct intel_sdvo *intel_sdvo, 805static bool intel_sdvo_set_encode(struct intel_sdvo *intel_sdvo,
@@ -849,115 +844,33 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
849} 844}
850#endif 845#endif
851 846
852static bool intel_sdvo_set_hdmi_buf(struct intel_sdvo *intel_sdvo, 847static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
853 int index,
854 uint8_t *data, int8_t size, uint8_t tx_rate)
855{
856 uint8_t set_buf_index[2];
857
858 set_buf_index[0] = index;
859 set_buf_index[1] = 0;
860
861 if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_INDEX,
862 set_buf_index, 2))
863 return false;
864
865 for (; size > 0; size -= 8) {
866 if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_DATA, data, 8))
867 return false;
868
869 data += 8;
870 }
871
872 return intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_TXRATE, &tx_rate, 1);
873}
874
875static uint8_t intel_sdvo_calc_hbuf_csum(uint8_t *data, uint8_t size)
876{
877 uint8_t csum = 0;
878 int i;
879
880 for (i = 0; i < size; i++)
881 csum += data[i];
882
883 return 0x100 - csum;
884}
885
886#define DIP_TYPE_AVI 0x82
887#define DIP_VERSION_AVI 0x2
888#define DIP_LEN_AVI 13
889
890struct dip_infoframe {
891 uint8_t type;
892 uint8_t version;
893 uint8_t len;
894 uint8_t checksum;
895 union {
896 struct {
897 /* Packet Byte #1 */
898 uint8_t S:2;
899 uint8_t B:2;
900 uint8_t A:1;
901 uint8_t Y:2;
902 uint8_t rsvd1:1;
903 /* Packet Byte #2 */
904 uint8_t R:4;
905 uint8_t M:2;
906 uint8_t C:2;
907 /* Packet Byte #3 */
908 uint8_t SC:2;
909 uint8_t Q:2;
910 uint8_t EC:3;
911 uint8_t ITC:1;
912 /* Packet Byte #4 */
913 uint8_t VIC:7;
914 uint8_t rsvd2:1;
915 /* Packet Byte #5 */
916 uint8_t PR:4;
917 uint8_t rsvd3:4;
918 /* Packet Byte #6~13 */
919 uint16_t top_bar_end;
920 uint16_t bottom_bar_start;
921 uint16_t left_bar_end;
922 uint16_t right_bar_start;
923 } avi;
924 struct {
925 /* Packet Byte #1 */
926 uint8_t channel_count:3;
927 uint8_t rsvd1:1;
928 uint8_t coding_type:4;
929 /* Packet Byte #2 */
930 uint8_t sample_size:2; /* SS0, SS1 */
931 uint8_t sample_frequency:3;
932 uint8_t rsvd2:3;
933 /* Packet Byte #3 */
934 uint8_t coding_type_private:5;
935 uint8_t rsvd3:3;
936 /* Packet Byte #4 */
937 uint8_t channel_allocation;
938 /* Packet Byte #5 */
939 uint8_t rsvd4:3;
940 uint8_t level_shift:4;
941 uint8_t downmix_inhibit:1;
942 } audio;
943 uint8_t payload[28];
944 } __attribute__ ((packed)) u;
945} __attribute__((packed));
946
947static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo,
948 struct drm_display_mode * mode)
949{ 848{
950 struct dip_infoframe avi_if = { 849 struct dip_infoframe avi_if = {
951 .type = DIP_TYPE_AVI, 850 .type = DIP_TYPE_AVI,
952 .version = DIP_VERSION_AVI, 851 .ver = DIP_VERSION_AVI,
953 .len = DIP_LEN_AVI, 852 .len = DIP_LEN_AVI,
954 }; 853 };
854 uint8_t tx_rate = SDVO_HBUF_TX_VSYNC;
855 uint8_t set_buf_index[2] = { 1, 0 };
856 uint64_t *data = (uint64_t *)&avi_if;
857 unsigned i;
858
859 intel_dip_infoframe_csum(&avi_if);
860
861 if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_INDEX,
862 set_buf_index, 2))
863 return false;
955 864
956 avi_if.checksum = intel_sdvo_calc_hbuf_csum((uint8_t *)&avi_if, 865 for (i = 0; i < sizeof(avi_if); i += 8) {
957 4 + avi_if.len); 866 if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_DATA,
958 return intel_sdvo_set_hdmi_buf(intel_sdvo, 1, (uint8_t *)&avi_if, 867 data, 8))
959 4 + avi_if.len, 868 return false;
960 SDVO_HBUF_TX_VSYNC); 869 data++;
870 }
871
872 return intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_TXRATE,
873 &tx_rate, 1);
961} 874}
962 875
963static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) 876static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo)
@@ -1111,7 +1024,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
1111 return; 1024 return;
1112 1025
1113 if (intel_sdvo->is_hdmi && 1026 if (intel_sdvo->is_hdmi &&
1114 !intel_sdvo_set_avi_infoframe(intel_sdvo, mode)) 1027 !intel_sdvo_set_avi_infoframe(intel_sdvo))
1115 return; 1028 return;
1116 1029
1117 if (intel_sdvo->is_tv && 1030 if (intel_sdvo->is_tv &&
@@ -1150,7 +1063,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
1150 } 1063 }
1151 if (intel_crtc->pipe == 1) 1064 if (intel_crtc->pipe == 1)
1152 sdvox |= SDVO_PIPE_B_SELECT; 1065 sdvox |= SDVO_PIPE_B_SELECT;
1153 if (intel_sdvo->is_hdmi) 1066 if (intel_sdvo->has_audio)
1154 sdvox |= SDVO_AUDIO_ENABLE; 1067 sdvox |= SDVO_AUDIO_ENABLE;
1155 1068
1156 if (INTEL_INFO(dev)->gen >= 4) { 1069 if (INTEL_INFO(dev)->gen >= 4) {
@@ -1476,11 +1389,18 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
1476 if (edid->input & DRM_EDID_INPUT_DIGITAL) { 1389 if (edid->input & DRM_EDID_INPUT_DIGITAL) {
1477 status = connector_status_connected; 1390 status = connector_status_connected;
1478 intel_sdvo->is_hdmi = drm_detect_hdmi_monitor(edid); 1391 intel_sdvo->is_hdmi = drm_detect_hdmi_monitor(edid);
1392 intel_sdvo->has_audio = drm_detect_monitor_audio(edid);
1479 } 1393 }
1480 connector->display_info.raw_edid = NULL; 1394 connector->display_info.raw_edid = NULL;
1481 kfree(edid); 1395 kfree(edid);
1482 } 1396 }
1483 1397
1398 if (status == connector_status_connected) {
1399 struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
1400 if (intel_sdvo_connector->force_audio)
1401 intel_sdvo->has_audio = intel_sdvo_connector->force_audio > 0;
1402 }
1403
1484 return status; 1404 return status;
1485} 1405}
1486 1406
@@ -1787,6 +1707,21 @@ intel_sdvo_set_property(struct drm_connector *connector,
1787 if (ret) 1707 if (ret)
1788 return ret; 1708 return ret;
1789 1709
1710 if (property == intel_sdvo_connector->force_audio_property) {
1711 if (val == intel_sdvo_connector->force_audio)
1712 return 0;
1713
1714 intel_sdvo_connector->force_audio = val;
1715
1716 if (val > 0 && intel_sdvo->has_audio)
1717 return 0;
1718 if (val < 0 && !intel_sdvo->has_audio)
1719 return 0;
1720
1721 intel_sdvo->has_audio = val > 0;
1722 goto done;
1723 }
1724
1790#define CHECK_PROPERTY(name, NAME) \ 1725#define CHECK_PROPERTY(name, NAME) \
1791 if (intel_sdvo_connector->name == property) { \ 1726 if (intel_sdvo_connector->name == property) { \
1792 if (intel_sdvo_connector->cur_##name == temp_value) return 0; \ 1727 if (intel_sdvo_connector->cur_##name == temp_value) return 0; \
@@ -2013,12 +1948,22 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
2013} 1948}
2014 1949
2015static bool 1950static bool
2016intel_sdvo_get_digital_encoding_mode(struct intel_sdvo *intel_sdvo, int device) 1951intel_sdvo_is_hdmi_connector(struct intel_sdvo *intel_sdvo, int device)
2017{ 1952{
2018 return intel_sdvo_set_target_output(intel_sdvo, 1953 int is_hdmi;
2019 device == 0 ? SDVO_OUTPUT_TMDS0 : SDVO_OUTPUT_TMDS1) && 1954
2020 intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ENCODE, 1955 if (!intel_sdvo_check_supp_encode(intel_sdvo))
2021 &intel_sdvo->is_hdmi, 1); 1956 return false;
1957
1958 if (!intel_sdvo_set_target_output(intel_sdvo,
1959 device == 0 ? SDVO_OUTPUT_TMDS0 : SDVO_OUTPUT_TMDS1))
1960 return false;
1961
1962 is_hdmi = 0;
1963 if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ENCODE, &is_hdmi, 1))
1964 return false;
1965
1966 return !!is_hdmi;
2022} 1967}
2023 1968
2024static u8 1969static u8
@@ -2078,6 +2023,21 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
2078 drm_sysfs_connector_add(&connector->base.base); 2023 drm_sysfs_connector_add(&connector->base.base);
2079} 2024}
2080 2025
2026static void
2027intel_sdvo_add_hdmi_properties(struct intel_sdvo_connector *connector)
2028{
2029 struct drm_device *dev = connector->base.base.dev;
2030
2031 connector->force_audio_property =
2032 drm_property_create(dev, DRM_MODE_PROP_RANGE, "force_audio", 2);
2033 if (connector->force_audio_property) {
2034 connector->force_audio_property->values[0] = -1;
2035 connector->force_audio_property->values[1] = 1;
2036 drm_connector_attach_property(&connector->base.base,
2037 connector->force_audio_property, 0);
2038 }
2039}
2040
2081static bool 2041static bool
2082intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) 2042intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
2083{ 2043{
@@ -2104,20 +2064,21 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
2104 encoder->encoder_type = DRM_MODE_ENCODER_TMDS; 2064 encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
2105 connector->connector_type = DRM_MODE_CONNECTOR_DVID; 2065 connector->connector_type = DRM_MODE_CONNECTOR_DVID;
2106 2066
2107 if (intel_sdvo_get_supp_encode(intel_sdvo, &intel_sdvo->encode) 2067 if (intel_sdvo_is_hdmi_connector(intel_sdvo, device)) {
2108 && intel_sdvo_get_digital_encoding_mode(intel_sdvo, device)
2109 && intel_sdvo->is_hdmi) {
2110 /* enable hdmi encoding mode if supported */ 2068 /* enable hdmi encoding mode if supported */
2111 intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_HDMI); 2069 intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_HDMI);
2112 intel_sdvo_set_colorimetry(intel_sdvo, 2070 intel_sdvo_set_colorimetry(intel_sdvo,
2113 SDVO_COLORIMETRY_RGB256); 2071 SDVO_COLORIMETRY_RGB256);
2114 connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; 2072 connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
2073 intel_sdvo->is_hdmi = true;
2115 } 2074 }
2116 intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | 2075 intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
2117 (1 << INTEL_ANALOG_CLONE_BIT)); 2076 (1 << INTEL_ANALOG_CLONE_BIT));
2118 2077
2119 intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); 2078 intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
2120 2079
2080 intel_sdvo_add_hdmi_properties(intel_sdvo_connector);
2081
2121 return true; 2082 return true;
2122} 2083}
2123 2084