diff options
author | Damien Lespiau <damien.lespiau@intel.com> | 2013-08-06 15:32:18 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-08-08 08:04:47 -0400 |
commit | 178f736ab96637bc17bcf00c3b58af0137e880e0 (patch) | |
tree | b41efc62c4315d1705cf46dfbd2c57f974cbad1c /drivers/gpu/drm/i915/intel_hdmi.c | |
parent | 03a7a189c22bf911025c695841c18a681498a102 (diff) |
drm/i915/hdmi: Change the write_infoframe vfunc to take a buffer and a type
First step in the move to the shared infoframe infrastructure, let's
move the different infoframe helpers and the write_infoframe() vfunc to
a type (enum hdmi_infoframe_type) and a buffer + len instead of using
our struct dip_infoframe.
v2: constify the infoframe pointer and don't mix signs (Ville Syrjälä)
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni at intel.com>
Signed-off-by: Thierry Reding <thierry.reding at avionic-design.de>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 106 |
1 files changed, 56 insertions, 50 deletions
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 5cad59fd6bd2..951f4817e1b6 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/i2c.h> | 29 | #include <linux/i2c.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/hdmi.h> | ||
32 | #include <drm/drmP.h> | 33 | #include <drm/drmP.h> |
33 | #include <drm/drm_crtc.h> | 34 | #include <drm/drm_crtc.h> |
34 | #include <drm/drm_edid.h> | 35 | #include <drm/drm_edid.h> |
@@ -81,74 +82,75 @@ void intel_dip_infoframe_csum(struct dip_infoframe *frame) | |||
81 | frame->checksum = 0x100 - sum; | 82 | frame->checksum = 0x100 - sum; |
82 | } | 83 | } |
83 | 84 | ||
84 | static u32 g4x_infoframe_index(struct dip_infoframe *frame) | 85 | static u32 g4x_infoframe_index(enum hdmi_infoframe_type type) |
85 | { | 86 | { |
86 | switch (frame->type) { | 87 | switch (type) { |
87 | case DIP_TYPE_AVI: | 88 | case HDMI_INFOFRAME_TYPE_AVI: |
88 | return VIDEO_DIP_SELECT_AVI; | 89 | return VIDEO_DIP_SELECT_AVI; |
89 | case DIP_TYPE_SPD: | 90 | case HDMI_INFOFRAME_TYPE_SPD: |
90 | return VIDEO_DIP_SELECT_SPD; | 91 | return VIDEO_DIP_SELECT_SPD; |
91 | default: | 92 | default: |
92 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); | 93 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", type); |
93 | return 0; | 94 | return 0; |
94 | } | 95 | } |
95 | } | 96 | } |
96 | 97 | ||
97 | static u32 g4x_infoframe_enable(struct dip_infoframe *frame) | 98 | static u32 g4x_infoframe_enable(enum hdmi_infoframe_type type) |
98 | { | 99 | { |
99 | switch (frame->type) { | 100 | switch (type) { |
100 | case DIP_TYPE_AVI: | 101 | case HDMI_INFOFRAME_TYPE_AVI: |
101 | return VIDEO_DIP_ENABLE_AVI; | 102 | return VIDEO_DIP_ENABLE_AVI; |
102 | case DIP_TYPE_SPD: | 103 | case HDMI_INFOFRAME_TYPE_SPD: |
103 | return VIDEO_DIP_ENABLE_SPD; | 104 | return VIDEO_DIP_ENABLE_SPD; |
104 | default: | 105 | default: |
105 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); | 106 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", type); |
106 | return 0; | 107 | return 0; |
107 | } | 108 | } |
108 | } | 109 | } |
109 | 110 | ||
110 | static u32 hsw_infoframe_enable(struct dip_infoframe *frame) | 111 | static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type) |
111 | { | 112 | { |
112 | switch (frame->type) { | 113 | switch (type) { |
113 | case DIP_TYPE_AVI: | 114 | case HDMI_INFOFRAME_TYPE_AVI: |
114 | return VIDEO_DIP_ENABLE_AVI_HSW; | 115 | return VIDEO_DIP_ENABLE_AVI_HSW; |
115 | case DIP_TYPE_SPD: | 116 | case HDMI_INFOFRAME_TYPE_SPD: |
116 | return VIDEO_DIP_ENABLE_SPD_HSW; | 117 | return VIDEO_DIP_ENABLE_SPD_HSW; |
117 | default: | 118 | default: |
118 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); | 119 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", type); |
119 | return 0; | 120 | return 0; |
120 | } | 121 | } |
121 | } | 122 | } |
122 | 123 | ||
123 | static u32 hsw_infoframe_data_reg(struct dip_infoframe *frame, | 124 | static u32 hsw_infoframe_data_reg(enum hdmi_infoframe_type type, |
124 | enum transcoder cpu_transcoder) | 125 | enum transcoder cpu_transcoder) |
125 | { | 126 | { |
126 | switch (frame->type) { | 127 | switch (type) { |
127 | case DIP_TYPE_AVI: | 128 | case HDMI_INFOFRAME_TYPE_AVI: |
128 | return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder); | 129 | return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder); |
129 | case DIP_TYPE_SPD: | 130 | case HDMI_INFOFRAME_TYPE_SPD: |
130 | return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder); | 131 | return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder); |
131 | default: | 132 | default: |
132 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); | 133 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", type); |
133 | return 0; | 134 | return 0; |
134 | } | 135 | } |
135 | } | 136 | } |
136 | 137 | ||
137 | static void g4x_write_infoframe(struct drm_encoder *encoder, | 138 | static void g4x_write_infoframe(struct drm_encoder *encoder, |
138 | struct dip_infoframe *frame) | 139 | enum hdmi_infoframe_type type, |
140 | const uint8_t *frame, ssize_t len) | ||
139 | { | 141 | { |
140 | uint32_t *data = (uint32_t *)frame; | 142 | uint32_t *data = (uint32_t *)frame; |
141 | struct drm_device *dev = encoder->dev; | 143 | struct drm_device *dev = encoder->dev; |
142 | struct drm_i915_private *dev_priv = dev->dev_private; | 144 | struct drm_i915_private *dev_priv = dev->dev_private; |
143 | u32 val = I915_READ(VIDEO_DIP_CTL); | 145 | u32 val = I915_READ(VIDEO_DIP_CTL); |
144 | unsigned i, len = DIP_HEADER_SIZE + frame->len; | 146 | int i; |
145 | 147 | ||
146 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); | 148 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
147 | 149 | ||
148 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ | 150 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
149 | val |= g4x_infoframe_index(frame); | 151 | val |= g4x_infoframe_index(type); |
150 | 152 | ||
151 | val &= ~g4x_infoframe_enable(frame); | 153 | val &= ~g4x_infoframe_enable(type); |
152 | 154 | ||
153 | I915_WRITE(VIDEO_DIP_CTL, val); | 155 | I915_WRITE(VIDEO_DIP_CTL, val); |
154 | 156 | ||
@@ -162,7 +164,7 @@ static void g4x_write_infoframe(struct drm_encoder *encoder, | |||
162 | I915_WRITE(VIDEO_DIP_DATA, 0); | 164 | I915_WRITE(VIDEO_DIP_DATA, 0); |
163 | mmiowb(); | 165 | mmiowb(); |
164 | 166 | ||
165 | val |= g4x_infoframe_enable(frame); | 167 | val |= g4x_infoframe_enable(type); |
166 | val &= ~VIDEO_DIP_FREQ_MASK; | 168 | val &= ~VIDEO_DIP_FREQ_MASK; |
167 | val |= VIDEO_DIP_FREQ_VSYNC; | 169 | val |= VIDEO_DIP_FREQ_VSYNC; |
168 | 170 | ||
@@ -171,22 +173,22 @@ static void g4x_write_infoframe(struct drm_encoder *encoder, | |||
171 | } | 173 | } |
172 | 174 | ||
173 | static void ibx_write_infoframe(struct drm_encoder *encoder, | 175 | static void ibx_write_infoframe(struct drm_encoder *encoder, |
174 | struct dip_infoframe *frame) | 176 | enum hdmi_infoframe_type type, |
177 | const uint8_t *frame, ssize_t len) | ||
175 | { | 178 | { |
176 | uint32_t *data = (uint32_t *)frame; | 179 | uint32_t *data = (uint32_t *)frame; |
177 | struct drm_device *dev = encoder->dev; | 180 | struct drm_device *dev = encoder->dev; |
178 | struct drm_i915_private *dev_priv = dev->dev_private; | 181 | struct drm_i915_private *dev_priv = dev->dev_private; |
179 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 182 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
180 | int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); | 183 | int i, reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
181 | unsigned i, len = DIP_HEADER_SIZE + frame->len; | ||
182 | u32 val = I915_READ(reg); | 184 | u32 val = I915_READ(reg); |
183 | 185 | ||
184 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); | 186 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
185 | 187 | ||
186 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ | 188 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
187 | val |= g4x_infoframe_index(frame); | 189 | val |= g4x_infoframe_index(type); |
188 | 190 | ||
189 | val &= ~g4x_infoframe_enable(frame); | 191 | val &= ~g4x_infoframe_enable(type); |
190 | 192 | ||
191 | I915_WRITE(reg, val); | 193 | I915_WRITE(reg, val); |
192 | 194 | ||
@@ -200,7 +202,7 @@ static void ibx_write_infoframe(struct drm_encoder *encoder, | |||
200 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0); | 202 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0); |
201 | mmiowb(); | 203 | mmiowb(); |
202 | 204 | ||
203 | val |= g4x_infoframe_enable(frame); | 205 | val |= g4x_infoframe_enable(type); |
204 | val &= ~VIDEO_DIP_FREQ_MASK; | 206 | val &= ~VIDEO_DIP_FREQ_MASK; |
205 | val |= VIDEO_DIP_FREQ_VSYNC; | 207 | val |= VIDEO_DIP_FREQ_VSYNC; |
206 | 208 | ||
@@ -209,25 +211,25 @@ static void ibx_write_infoframe(struct drm_encoder *encoder, | |||
209 | } | 211 | } |
210 | 212 | ||
211 | static void cpt_write_infoframe(struct drm_encoder *encoder, | 213 | static void cpt_write_infoframe(struct drm_encoder *encoder, |
212 | struct dip_infoframe *frame) | 214 | enum hdmi_infoframe_type type, |
215 | const uint8_t *frame, ssize_t len) | ||
213 | { | 216 | { |
214 | uint32_t *data = (uint32_t *)frame; | 217 | uint32_t *data = (uint32_t *)frame; |
215 | struct drm_device *dev = encoder->dev; | 218 | struct drm_device *dev = encoder->dev; |
216 | struct drm_i915_private *dev_priv = dev->dev_private; | 219 | struct drm_i915_private *dev_priv = dev->dev_private; |
217 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 220 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
218 | int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); | 221 | int i, reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
219 | unsigned i, len = DIP_HEADER_SIZE + frame->len; | ||
220 | u32 val = I915_READ(reg); | 222 | u32 val = I915_READ(reg); |
221 | 223 | ||
222 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); | 224 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
223 | 225 | ||
224 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ | 226 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
225 | val |= g4x_infoframe_index(frame); | 227 | val |= g4x_infoframe_index(type); |
226 | 228 | ||
227 | /* The DIP control register spec says that we need to update the AVI | 229 | /* The DIP control register spec says that we need to update the AVI |
228 | * infoframe without clearing its enable bit */ | 230 | * infoframe without clearing its enable bit */ |
229 | if (frame->type != DIP_TYPE_AVI) | 231 | if (type != HDMI_INFOFRAME_TYPE_AVI) |
230 | val &= ~g4x_infoframe_enable(frame); | 232 | val &= ~g4x_infoframe_enable(type); |
231 | 233 | ||
232 | I915_WRITE(reg, val); | 234 | I915_WRITE(reg, val); |
233 | 235 | ||
@@ -241,7 +243,7 @@ static void cpt_write_infoframe(struct drm_encoder *encoder, | |||
241 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0); | 243 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0); |
242 | mmiowb(); | 244 | mmiowb(); |
243 | 245 | ||
244 | val |= g4x_infoframe_enable(frame); | 246 | val |= g4x_infoframe_enable(type); |
245 | val &= ~VIDEO_DIP_FREQ_MASK; | 247 | val &= ~VIDEO_DIP_FREQ_MASK; |
246 | val |= VIDEO_DIP_FREQ_VSYNC; | 248 | val |= VIDEO_DIP_FREQ_VSYNC; |
247 | 249 | ||
@@ -250,22 +252,22 @@ static void cpt_write_infoframe(struct drm_encoder *encoder, | |||
250 | } | 252 | } |
251 | 253 | ||
252 | static void vlv_write_infoframe(struct drm_encoder *encoder, | 254 | static void vlv_write_infoframe(struct drm_encoder *encoder, |
253 | struct dip_infoframe *frame) | 255 | enum hdmi_infoframe_type type, |
256 | const uint8_t *frame, ssize_t len) | ||
254 | { | 257 | { |
255 | uint32_t *data = (uint32_t *)frame; | 258 | uint32_t *data = (uint32_t *)frame; |
256 | struct drm_device *dev = encoder->dev; | 259 | struct drm_device *dev = encoder->dev; |
257 | struct drm_i915_private *dev_priv = dev->dev_private; | 260 | struct drm_i915_private *dev_priv = dev->dev_private; |
258 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 261 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
259 | int reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); | 262 | int i, reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); |
260 | unsigned i, len = DIP_HEADER_SIZE + frame->len; | ||
261 | u32 val = I915_READ(reg); | 263 | u32 val = I915_READ(reg); |
262 | 264 | ||
263 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); | 265 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
264 | 266 | ||
265 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ | 267 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
266 | val |= g4x_infoframe_index(frame); | 268 | val |= g4x_infoframe_index(type); |
267 | 269 | ||
268 | val &= ~g4x_infoframe_enable(frame); | 270 | val &= ~g4x_infoframe_enable(type); |
269 | 271 | ||
270 | I915_WRITE(reg, val); | 272 | I915_WRITE(reg, val); |
271 | 273 | ||
@@ -279,7 +281,7 @@ static void vlv_write_infoframe(struct drm_encoder *encoder, | |||
279 | I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), 0); | 281 | I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), 0); |
280 | mmiowb(); | 282 | mmiowb(); |
281 | 283 | ||
282 | val |= g4x_infoframe_enable(frame); | 284 | val |= g4x_infoframe_enable(type); |
283 | val &= ~VIDEO_DIP_FREQ_MASK; | 285 | val &= ~VIDEO_DIP_FREQ_MASK; |
284 | val |= VIDEO_DIP_FREQ_VSYNC; | 286 | val |= VIDEO_DIP_FREQ_VSYNC; |
285 | 287 | ||
@@ -288,21 +290,24 @@ static void vlv_write_infoframe(struct drm_encoder *encoder, | |||
288 | } | 290 | } |
289 | 291 | ||
290 | static void hsw_write_infoframe(struct drm_encoder *encoder, | 292 | static void hsw_write_infoframe(struct drm_encoder *encoder, |
291 | struct dip_infoframe *frame) | 293 | enum hdmi_infoframe_type type, |
294 | const uint8_t *frame, ssize_t len) | ||
292 | { | 295 | { |
293 | uint32_t *data = (uint32_t *)frame; | 296 | uint32_t *data = (uint32_t *)frame; |
294 | struct drm_device *dev = encoder->dev; | 297 | struct drm_device *dev = encoder->dev; |
295 | struct drm_i915_private *dev_priv = dev->dev_private; | 298 | struct drm_i915_private *dev_priv = dev->dev_private; |
296 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 299 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
297 | u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder); | 300 | u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder); |
298 | u32 data_reg = hsw_infoframe_data_reg(frame, intel_crtc->config.cpu_transcoder); | 301 | u32 data_reg; |
299 | unsigned int i, len = DIP_HEADER_SIZE + frame->len; | 302 | int i; |
300 | u32 val = I915_READ(ctl_reg); | 303 | u32 val = I915_READ(ctl_reg); |
301 | 304 | ||
305 | data_reg = hsw_infoframe_data_reg(type, | ||
306 | intel_crtc->config.cpu_transcoder); | ||
302 | if (data_reg == 0) | 307 | if (data_reg == 0) |
303 | return; | 308 | return; |
304 | 309 | ||
305 | val &= ~hsw_infoframe_enable(frame); | 310 | val &= ~hsw_infoframe_enable(type); |
306 | I915_WRITE(ctl_reg, val); | 311 | I915_WRITE(ctl_reg, val); |
307 | 312 | ||
308 | mmiowb(); | 313 | mmiowb(); |
@@ -315,7 +320,7 @@ static void hsw_write_infoframe(struct drm_encoder *encoder, | |||
315 | I915_WRITE(data_reg + i, 0); | 320 | I915_WRITE(data_reg + i, 0); |
316 | mmiowb(); | 321 | mmiowb(); |
317 | 322 | ||
318 | val |= hsw_infoframe_enable(frame); | 323 | val |= hsw_infoframe_enable(type); |
319 | I915_WRITE(ctl_reg, val); | 324 | I915_WRITE(ctl_reg, val); |
320 | POSTING_READ(ctl_reg); | 325 | POSTING_READ(ctl_reg); |
321 | } | 326 | } |
@@ -326,7 +331,8 @@ static void intel_set_infoframe(struct drm_encoder *encoder, | |||
326 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | 331 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
327 | 332 | ||
328 | intel_dip_infoframe_csum(frame); | 333 | intel_dip_infoframe_csum(frame); |
329 | intel_hdmi->write_infoframe(encoder, frame); | 334 | intel_hdmi->write_infoframe(encoder, frame->type, (uint8_t *)frame, |
335 | DIP_HEADER_SIZE + frame->len); | ||
330 | } | 336 | } |
331 | 337 | ||
332 | static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, | 338 | static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, |