aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_hdmi.c
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/gpu/drm/i915/intel_hdmi.c
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/gpu/drm/i915/intel_hdmi.c')
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c60
1 files changed, 59 insertions, 1 deletions
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)