diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sdvo.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 76 |
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 | ||
144 | struct intel_sdvo_connector { | 149 | struct 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 | ||
897 | static 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 | |||
892 | static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) | 936 | static 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 | ||
931 | static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) | 958 | static 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)) |