diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 60 |
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 | ||
61 | void 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 | |||
76 | static 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 | |||
61 | static void intel_hdmi_mode_set(struct drm_encoder *encoder, | 115 | static 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 | ||
96 | static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) | 154 | static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) |