aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h16
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h33
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c60
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c126
4 files changed, 130 insertions, 105 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index c52e209321c1..25ed911a3112 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1353,6 +1353,22 @@
1353#define LVDS_B0B3_POWER_DOWN (0 << 2) 1353#define LVDS_B0B3_POWER_DOWN (0 << 2)
1354#define LVDS_B0B3_POWER_UP (3 << 2) 1354#define LVDS_B0B3_POWER_UP (3 << 2)
1355 1355
1356/* Video Data Island Packet control */
1357#define VIDEO_DIP_DATA 0x61178
1358#define VIDEO_DIP_CTL 0x61170
1359#define VIDEO_DIP_ENABLE (1 << 31)
1360#define VIDEO_DIP_PORT_B (1 << 29)
1361#define VIDEO_DIP_PORT_C (2 << 29)
1362#define VIDEO_DIP_ENABLE_AVI (1 << 21)
1363#define VIDEO_DIP_ENABLE_VENDOR (2 << 21)
1364#define VIDEO_DIP_ENABLE_SPD (8 << 21)
1365#define VIDEO_DIP_SELECT_AVI (0 << 19)
1366#define VIDEO_DIP_SELECT_VENDOR (1 << 19)
1367#define VIDEO_DIP_SELECT_SPD (3 << 19)
1368#define VIDEO_DIP_FREQ_ONCE (0 << 16)
1369#define VIDEO_DIP_FREQ_VSYNC (1 << 16)
1370#define VIDEO_DIP_FREQ_2VSYNC (2 << 16)
1371
1356/* Panel power sequencing */ 1372/* Panel power sequencing */
1357#define PP_STATUS 0x61200 1373#define PP_STATUS 0x61200
1358#define PP_ON (1 << 31) 1374#define PP_ON (1 << 31)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0581e5e5ac55..9af9f86a8765 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -178,6 +178,38 @@ struct intel_crtc {
178#define to_intel_encoder(x) container_of(x, struct intel_encoder, base) 178#define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
179#define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) 179#define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
180 180
181#define DIP_TYPE_AVI 0x82
182#define DIP_VERSION_AVI 0x2
183#define DIP_LEN_AVI 13
184
185struct dip_infoframe {
186 uint8_t type; /* HB0 */
187 uint8_t ver; /* HB1 */
188 uint8_t len; /* HB2 - body len, not including checksum */
189 uint8_t ecc; /* Header ECC */
190 uint8_t checksum; /* PB0 */
191 union {
192 struct {
193 /* PB1 - Y 6:5, A 4:4, B 3:2, S 1:0 */
194 uint8_t Y_A_B_S;
195 /* PB2 - C 7:6, M 5:4, R 3:0 */
196 uint8_t C_M_R;
197 /* PB3 - ITC 7:7, EC 6:4, Q 3:2, SC 1:0 */
198 uint8_t ITC_EC_Q_SC;
199 /* PB4 - VIC 6:0 */
200 uint8_t VIC;
201 /* PB5 - PR 3:0 */
202 uint8_t PR;
203 /* PB6 to PB13 */
204 uint16_t top_bar_end;
205 uint16_t bottom_bar_start;
206 uint16_t left_bar_end;
207 uint16_t right_bar_start;
208 } avi;
209 uint8_t payload[27];
210 } __attribute__ ((packed)) body;
211} __attribute__((packed));
212
181static inline struct drm_crtc * 213static inline struct drm_crtc *
182intel_get_crtc_for_pipe(struct drm_device *dev, int pipe) 214intel_get_crtc_for_pipe(struct drm_device *dev, int pipe)
183{ 215{
@@ -200,6 +232,7 @@ extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus);
200 232
201extern void intel_crt_init(struct drm_device *dev); 233extern void intel_crt_init(struct drm_device *dev);
202extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); 234extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
235void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
203extern bool intel_sdvo_init(struct drm_device *dev, int output_device); 236extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
204extern void intel_dvo_init(struct drm_device *dev); 237extern void intel_dvo_init(struct drm_device *dev);
205extern void intel_tv_init(struct drm_device *dev); 238extern void intel_tv_init(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 6c3b2ecd59d5..0d0273e7b029 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -58,6 +58,60 @@ static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector)
58 struct intel_hdmi, base); 58 struct intel_hdmi, base);
59} 59}
60 60
61void intel_dip_infoframe_csum(struct dip_infoframe *avi_if)
62{
63 uint8_t *data = (uint8_t *)avi_if;
64 uint8_t sum = 0;
65 unsigned i;
66
67 avi_if->checksum = 0;
68 avi_if->ecc = 0;
69
70 for (i = 0; i < sizeof(*avi_if); i++)
71 sum += data[i];
72
73 avi_if->checksum = 0x100 - sum;
74}
75
76static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
77{
78 struct dip_infoframe avi_if = {
79 .type = DIP_TYPE_AVI,
80 .ver = DIP_VERSION_AVI,
81 .len = DIP_LEN_AVI,
82 };
83 uint32_t *data = (uint32_t *)&avi_if;
84 struct drm_device *dev = encoder->dev;
85 struct drm_i915_private *dev_priv = dev->dev_private;
86 struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
87 u32 port;
88 unsigned i;
89
90 if (!intel_hdmi->has_hdmi_sink)
91 return;
92
93 /* XXX first guess at handling video port, is this corrent? */
94 if (intel_hdmi->sdvox_reg == SDVOB)
95 port = VIDEO_DIP_PORT_B;
96 else if (intel_hdmi->sdvox_reg == SDVOC)
97 port = VIDEO_DIP_PORT_C;
98 else
99 return;
100
101 I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | port |
102 VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC);
103
104 intel_dip_infoframe_csum(&avi_if);
105 for (i = 0; i < sizeof(avi_if); i += 4) {
106 I915_WRITE(VIDEO_DIP_DATA, *data);
107 data++;
108 }
109
110 I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | port |
111 VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC |
112 VIDEO_DIP_ENABLE_AVI);
113}
114
61static void intel_hdmi_mode_set(struct drm_encoder *encoder, 115static void intel_hdmi_mode_set(struct drm_encoder *encoder,
62 struct drm_display_mode *mode, 116 struct drm_display_mode *mode,
63 struct drm_display_mode *adjusted_mode) 117 struct drm_display_mode *adjusted_mode)
@@ -79,8 +133,10 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
79 if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev)) 133 if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev))
80 sdvox |= HDMI_MODE_SELECT; 134 sdvox |= HDMI_MODE_SELECT;
81 135
82 if (intel_hdmi->has_audio) 136 if (intel_hdmi->has_audio) {
83 sdvox |= SDVO_AUDIO_ENABLE; 137 sdvox |= SDVO_AUDIO_ENABLE;
138 sdvox |= SDVO_NULL_PACKETS_DURING_VSYNC;
139 }
84 140
85 if (intel_crtc->pipe == 1) { 141 if (intel_crtc->pipe == 1) {
86 if (HAS_PCH_CPT(dev)) 142 if (HAS_PCH_CPT(dev))
@@ -91,6 +147,8 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
91 147
92 I915_WRITE(intel_hdmi->sdvox_reg, sdvox); 148 I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
93 POSTING_READ(intel_hdmi->sdvox_reg); 149 POSTING_READ(intel_hdmi->sdvox_reg);
150
151 intel_hdmi_set_avi_infoframe(encoder);
94} 152}
95 153
96static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) 154static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
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 &&