aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2010-09-24 15:44:32 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2010-10-22 04:14:30 -0400
commit3c17fe4b8f40a112a85758a9ab2aebf772bdd647 (patch)
tree11200d46545ce7d139cd5be8268ee43c402fa433 /drivers
parentdc3f82c2e5c3f06e43855f417e4fcfc244383916 (diff)
i915: enable AVI infoframe for intel_hdmi.c [v4]
This patch enables the sending of AVI infoframes in drivers/gpu/drm/i915/intel_hdmi.c. My receiver currently loses sync when the HDMI output on my computer (DG45FC motherboard) is switched from 800x600 (the BIOS resolution) to 1920x1080 as part of the boot. Fixable by switching inputs on the receiver a couple of times. With this patch, my receiver has not lost sync yet (> 40 tries). Fourth version, now based on drm-intel-next from: git://git.kernel.org/pub/scm/linux/kernel/git/ickle/drm-intel.git Two questions still remain: I'm assuming that the sdvo hardware also stores a header ECC byte in the MSB of the first dword - is this correct? Does the SDVOB and SDVOC handling in intel_hdmi_set_avi_infoframe() look correct? Signed-off-by: David Härdeman <david@hardeman.nu> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers')
-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