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.c76
1 files changed, 52 insertions, 24 deletions
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 0007a4d9bf6e..79d308da29ff 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -139,6 +139,11 @@ struct intel_sdvo {
139 139
140 /* DDC bus used by this SDVO encoder */ 140 /* DDC bus used by this SDVO encoder */
141 uint8_t ddc_bus; 141 uint8_t ddc_bus;
142
143 /*
144 * the sdvo flag gets lost in round trip: dtd->adjusted_mode->dtd
145 */
146 uint8_t dtd_sdvo_flags;
142}; 147};
143 148
144struct intel_sdvo_connector { 149struct intel_sdvo_connector {
@@ -889,6 +894,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
889} 894}
890#endif 895#endif
891 896
897static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
898 unsigned if_index, uint8_t tx_rate,
899 uint8_t *data, unsigned length)
900{
901 uint8_t set_buf_index[2] = { if_index, 0 };
902 uint8_t hbuf_size, tmp[8];
903 int i;
904
905 if (!intel_sdvo_set_value(intel_sdvo,
906 SDVO_CMD_SET_HBUF_INDEX,
907 set_buf_index, 2))
908 return false;
909
910 if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO,
911 &hbuf_size, 1))
912 return false;
913
914 /* Buffer size is 0 based, hooray! */
915 hbuf_size++;
916
917 DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n",
918 if_index, length, hbuf_size);
919
920 for (i = 0; i < hbuf_size; i += 8) {
921 memset(tmp, 0, 8);
922 if (i < length)
923 memcpy(tmp, data + i, min_t(unsigned, 8, length - i));
924
925 if (!intel_sdvo_set_value(intel_sdvo,
926 SDVO_CMD_SET_HBUF_DATA,
927 tmp, 8))
928 return false;
929 }
930
931 return intel_sdvo_set_value(intel_sdvo,
932 SDVO_CMD_SET_HBUF_TXRATE,
933 &tx_rate, 1);
934}
935
892static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) 936static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
893{ 937{
894 struct dip_infoframe avi_if = { 938 struct dip_infoframe avi_if = {
@@ -896,11 +940,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
896 .ver = DIP_VERSION_AVI, 940 .ver = DIP_VERSION_AVI,
897 .len = DIP_LEN_AVI, 941 .len = DIP_LEN_AVI,
898 }; 942 };
899 uint8_t tx_rate = SDVO_HBUF_TX_VSYNC;
900 uint8_t set_buf_index[2] = { 1, 0 };
901 uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)]; 943 uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)];
902 uint64_t *data = (uint64_t *)sdvo_data;
903 unsigned i;
904 944
905 intel_dip_infoframe_csum(&avi_if); 945 intel_dip_infoframe_csum(&avi_if);
906 946
@@ -910,22 +950,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
910 sdvo_data[3] = avi_if.checksum; 950 sdvo_data[3] = avi_if.checksum;
911 memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi)); 951 memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi));
912 952
913 if (!intel_sdvo_set_value(intel_sdvo, 953 return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF,
914 SDVO_CMD_SET_HBUF_INDEX, 954 SDVO_HBUF_TX_VSYNC,
915 set_buf_index, 2)) 955 sdvo_data, sizeof(sdvo_data));
916 return false;
917
918 for (i = 0; i < sizeof(sdvo_data); i += 8) {
919 if (!intel_sdvo_set_value(intel_sdvo,
920 SDVO_CMD_SET_HBUF_DATA,
921 data, 8))
922 return false;
923 data++;
924 }
925
926 return intel_sdvo_set_value(intel_sdvo,
927 SDVO_CMD_SET_HBUF_TXRATE,
928 &tx_rate, 1);
929} 956}
930 957
931static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) 958static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo)
@@ -984,6 +1011,7 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo,
984 return false; 1011 return false;
985 1012
986 intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); 1013 intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
1014 intel_sdvo->dtd_sdvo_flags = input_dtd.part2.sdvo_flags;
987 1015
988 return true; 1016 return true;
989} 1017}
@@ -1092,6 +1120,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
1092 * adjusted_mode. 1120 * adjusted_mode.
1093 */ 1121 */
1094 intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); 1122 intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
1123 if (intel_sdvo->is_tv || intel_sdvo->is_lvds)
1124 input_dtd.part2.sdvo_flags = intel_sdvo->dtd_sdvo_flags;
1095 if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd)) 1125 if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd))
1096 DRM_INFO("Setting input timings on %s failed\n", 1126 DRM_INFO("Setting input timings on %s failed\n",
1097 SDVO_NAME(intel_sdvo)); 1127 SDVO_NAME(intel_sdvo));
@@ -2277,10 +2307,8 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
2277 intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1; 2307 intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
2278 } 2308 }
2279 2309
2280 /* SDVO LVDS is cloneable because the SDVO encoder does the upscaling, 2310 /* SDVO LVDS is not cloneable because the input mode gets adjusted by the encoder */
2281 * as opposed to native LVDS, where we upscale with the panel-fitter 2311 intel_sdvo->base.cloneable = false;
2282 * (and hence only the native LVDS resolution could be cloned). */
2283 intel_sdvo->base.cloneable = true;
2284 2312
2285 intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); 2313 intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
2286 if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) 2314 if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))