aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_hdmi.c
diff options
context:
space:
mode:
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)