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.c126
1 files changed, 22 insertions, 104 deletions
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index c245383cf7ed..6739a7455174 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -854,115 +854,33 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
854} 854}
855#endif 855#endif
856 856
857static bool intel_sdvo_set_hdmi_buf(struct intel_sdvo *intel_sdvo, 857static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
858 int index,
859 uint8_t *data, int8_t size, uint8_t tx_rate)
860{
861 uint8_t set_buf_index[2];
862
863 set_buf_index[0] = index;
864 set_buf_index[1] = 0;
865
866 if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_INDEX,
867 set_buf_index, 2))
868 return false;
869
870 for (; size > 0; size -= 8) {
871 if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_DATA, data, 8))
872 return false;
873
874 data += 8;
875 }
876
877 return intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_TXRATE, &tx_rate, 1);
878}
879
880static uint8_t intel_sdvo_calc_hbuf_csum(uint8_t *data, uint8_t size)
881{
882 uint8_t csum = 0;
883 int i;
884
885 for (i = 0; i < size; i++)
886 csum += data[i];
887
888 return 0x100 - csum;
889}
890
891#define DIP_TYPE_AVI 0x82
892#define DIP_VERSION_AVI 0x2
893#define DIP_LEN_AVI 13
894
895struct dip_infoframe {
896 uint8_t type;
897 uint8_t version;
898 uint8_t len;
899 uint8_t checksum;
900 union {
901 struct {
902 /* Packet Byte #1 */
903 uint8_t S:2;
904 uint8_t B:2;
905 uint8_t A:1;
906 uint8_t Y:2;
907 uint8_t rsvd1:1;
908 /* Packet Byte #2 */
909 uint8_t R:4;
910 uint8_t M:2;
911 uint8_t C:2;
912 /* Packet Byte #3 */
913 uint8_t SC:2;
914 uint8_t Q:2;
915 uint8_t EC:3;
916 uint8_t ITC:1;
917 /* Packet Byte #4 */
918 uint8_t VIC:7;
919 uint8_t rsvd2:1;
920 /* Packet Byte #5 */
921 uint8_t PR:4;
922 uint8_t rsvd3:4;
923 /* Packet Byte #6~13 */
924 uint16_t top_bar_end;
925 uint16_t bottom_bar_start;
926 uint16_t left_bar_end;
927 uint16_t right_bar_start;
928 } avi;
929 struct {
930 /* Packet Byte #1 */
931 uint8_t channel_count:3;
932 uint8_t rsvd1:1;
933 uint8_t coding_type:4;
934 /* Packet Byte #2 */
935 uint8_t sample_size:2; /* SS0, SS1 */
936 uint8_t sample_frequency:3;
937 uint8_t rsvd2:3;
938 /* Packet Byte #3 */
939 uint8_t coding_type_private:5;
940 uint8_t rsvd3:3;
941 /* Packet Byte #4 */
942 uint8_t channel_allocation;
943 /* Packet Byte #5 */
944 uint8_t rsvd4:3;
945 uint8_t level_shift:4;
946 uint8_t downmix_inhibit:1;
947 } audio;
948 uint8_t payload[28];
949 } __attribute__ ((packed)) u;
950} __attribute__((packed));
951
952static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo,
953 struct drm_display_mode * mode)
954{ 858{
955 struct dip_infoframe avi_if = { 859 struct dip_infoframe avi_if = {
956 .type = DIP_TYPE_AVI, 860 .type = DIP_TYPE_AVI,
957 .version = DIP_VERSION_AVI, 861 .ver = DIP_VERSION_AVI,
958 .len = DIP_LEN_AVI, 862 .len = DIP_LEN_AVI,
959 }; 863 };
864 uint8_t tx_rate = SDVO_HBUF_TX_VSYNC;
865 uint8_t set_buf_index[2] = { 1, 0 };
866 uint64_t *data = (uint64_t *)&avi_if;
867 unsigned i;
868
869 intel_dip_infoframe_csum(&avi_if);
870
871 if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_INDEX,
872 set_buf_index, 2))
873 return false;
874
875 for (i = 0; i < sizeof(avi_if); i += 8) {
876 if (!intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_DATA,
877 data, 8))
878 return false;
879 data++;
880 }
960 881
961 avi_if.checksum = intel_sdvo_calc_hbuf_csum((uint8_t *)&avi_if, 882 return intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_HBUF_TXRATE,
962 4 + avi_if.len); 883 &tx_rate, 1);
963 return intel_sdvo_set_hdmi_buf(intel_sdvo, 1, (uint8_t *)&avi_if,
964 4 + avi_if.len,
965 SDVO_HBUF_TX_VSYNC);
966} 884}
967 885
968static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) 886static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo)
@@ -1116,7 +1034,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
1116 return; 1034 return;
1117 1035
1118 if (intel_sdvo->is_hdmi && 1036 if (intel_sdvo->is_hdmi &&
1119 !intel_sdvo_set_avi_infoframe(intel_sdvo, mode)) 1037 !intel_sdvo_set_avi_infoframe(intel_sdvo))
1120 return; 1038 return;
1121 1039
1122 if (intel_sdvo->is_tv && 1040 if (intel_sdvo->is_tv &&