aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <thierry.reding@avionic-design.de>2013-01-14 07:36:30 -0500
committerThierry Reding <thierry.reding@avionic-design.de>2013-02-22 02:20:20 -0500
commite3b2e0347e3b3b81cc322b413abf98a349d275df (patch)
tree11e6141f0a4fabc371952514a7ff61918bef4b90
parentac24c2204a76e5b42aa103bf963ae0eda1b827f3 (diff)
drm/radeon: Use generic HDMI infoframe helpers
Use the generic HDMI infoframe helpers to get rid of the duplicate implementation in the radeon driver. Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/radeon/evergreen_hdmi.c85
-rw-r--r--drivers/gpu/drm/radeon/r600_hdmi.c134
2 files changed, 58 insertions, 161 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c
index 327c08b54180..4fdecc2b4040 100644
--- a/drivers/gpu/drm/radeon/evergreen_hdmi.c
+++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c
@@ -24,6 +24,7 @@
24 * Authors: Christian König 24 * Authors: Christian König
25 * Rafał Miłecki 25 * Rafał Miłecki
26 */ 26 */
27#include <linux/hdmi.h>
27#include <drm/drmP.h> 28#include <drm/drmP.h>
28#include <drm/radeon_drm.h> 29#include <drm/radeon_drm.h>
29#include "radeon.h" 30#include "radeon.h"
@@ -54,79 +55,18 @@ static void evergreen_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t cloc
54} 55}
55 56
56/* 57/*
57 * calculate the crc for a given info frame
58 */
59static void evergreen_hdmi_infoframe_checksum(uint8_t packetType,
60 uint8_t versionNumber,
61 uint8_t length,
62 uint8_t *frame)
63{
64 int i;
65 frame[0] = packetType + versionNumber + length;
66 for (i = 1; i <= length; i++)
67 frame[0] += frame[i];
68 frame[0] = 0x100 - frame[0];
69}
70
71/*
72 * build a HDMI Video Info Frame 58 * build a HDMI Video Info Frame
73 */ 59 */
74static void evergreen_hdmi_videoinfoframe( 60static void evergreen_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
75 struct drm_encoder *encoder, 61 void *buffer, size_t size)
76 uint8_t color_format,
77 int active_information_present,
78 uint8_t active_format_aspect_ratio,
79 uint8_t scan_information,
80 uint8_t colorimetry,
81 uint8_t ex_colorimetry,
82 uint8_t quantization,
83 int ITC,
84 uint8_t picture_aspect_ratio,
85 uint8_t video_format_identification,
86 uint8_t pixel_repetition,
87 uint8_t non_uniform_picture_scaling,
88 uint8_t bar_info_data_valid,
89 uint16_t top_bar,
90 uint16_t bottom_bar,
91 uint16_t left_bar,
92 uint16_t right_bar
93)
94{ 62{
95 struct drm_device *dev = encoder->dev; 63 struct drm_device *dev = encoder->dev;
96 struct radeon_device *rdev = dev->dev_private; 64 struct radeon_device *rdev = dev->dev_private;
97 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 65 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
98 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 66 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
99 uint32_t offset = dig->afmt->offset; 67 uint32_t offset = dig->afmt->offset;
68 uint8_t *frame = buffer + 3;
100 69
101 uint8_t frame[14];
102
103 frame[0x0] = 0;
104 frame[0x1] =
105 (scan_information & 0x3) |
106 ((bar_info_data_valid & 0x3) << 2) |
107 ((active_information_present & 0x1) << 4) |
108 ((color_format & 0x3) << 5);
109 frame[0x2] =
110 (active_format_aspect_ratio & 0xF) |
111 ((picture_aspect_ratio & 0x3) << 4) |
112 ((colorimetry & 0x3) << 6);
113 frame[0x3] =
114 (non_uniform_picture_scaling & 0x3) |
115 ((quantization & 0x3) << 2) |
116 ((ex_colorimetry & 0x7) << 4) |
117 ((ITC & 0x1) << 7);
118 frame[0x4] = (video_format_identification & 0x7F);
119 frame[0x5] = (pixel_repetition & 0xF);
120 frame[0x6] = (top_bar & 0xFF);
121 frame[0x7] = (top_bar >> 8);
122 frame[0x8] = (bottom_bar & 0xFF);
123 frame[0x9] = (bottom_bar >> 8);
124 frame[0xA] = (left_bar & 0xFF);
125 frame[0xB] = (left_bar >> 8);
126 frame[0xC] = (right_bar & 0xFF);
127 frame[0xD] = (right_bar >> 8);
128
129 evergreen_hdmi_infoframe_checksum(0x82, 0x02, 0x0D, frame);
130 /* Our header values (type, version, length) should be alright, Intel 70 /* Our header values (type, version, length) should be alright, Intel
131 * is using the same. Checksum function also seems to be OK, it works 71 * is using the same. Checksum function also seems to be OK, it works
132 * fine for audio infoframe. However calculated value is always lower 72 * fine for audio infoframe. However calculated value is always lower
@@ -154,7 +94,10 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
154 struct radeon_device *rdev = dev->dev_private; 94 struct radeon_device *rdev = dev->dev_private;
155 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 95 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
156 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 96 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
97 u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
98 struct hdmi_avi_infoframe frame;
157 uint32_t offset; 99 uint32_t offset;
100 ssize_t err;
158 101
159 /* Silent, r600_hdmi_enable will raise WARN for us */ 102 /* Silent, r600_hdmi_enable will raise WARN for us */
160 if (!dig->afmt->enabled) 103 if (!dig->afmt->enabled)
@@ -200,9 +143,19 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
200 143
201 WREG32(HDMI_GC + offset, 0); /* unset HDMI_GC_AVMUTE */ 144 WREG32(HDMI_GC + offset, 0); /* unset HDMI_GC_AVMUTE */
202 145
203 evergreen_hdmi_videoinfoframe(encoder, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146 err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
204 0, 0, 0, 0, 0, 0); 147 if (err < 0) {
148 DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
149 return;
150 }
151
152 err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
153 if (err < 0) {
154 DRM_ERROR("failed to pack AVI infoframe: %zd\n", err);
155 return;
156 }
205 157
158 evergreen_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer));
206 evergreen_hdmi_update_ACR(encoder, mode->clock); 159 evergreen_hdmi_update_ACR(encoder, mode->clock);
207 160
208 /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ 161 /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index 95970ec47c45..21ecc0e12dc4 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -23,6 +23,7 @@
23 * 23 *
24 * Authors: Christian König 24 * Authors: Christian König
25 */ 25 */
26#include <linux/hdmi.h>
26#include <drm/drmP.h> 27#include <drm/drmP.h>
27#include <drm/radeon_drm.h> 28#include <drm/radeon_drm.h>
28#include "radeon.h" 29#include "radeon.h"
@@ -121,79 +122,18 @@ static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
121} 122}
122 123
123/* 124/*
124 * calculate the crc for a given info frame
125 */
126static void r600_hdmi_infoframe_checksum(uint8_t packetType,
127 uint8_t versionNumber,
128 uint8_t length,
129 uint8_t *frame)
130{
131 int i;
132 frame[0] = packetType + versionNumber + length;
133 for (i = 1; i <= length; i++)
134 frame[0] += frame[i];
135 frame[0] = 0x100 - frame[0];
136}
137
138/*
139 * build a HDMI Video Info Frame 125 * build a HDMI Video Info Frame
140 */ 126 */
141static void r600_hdmi_videoinfoframe( 127static void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
142 struct drm_encoder *encoder, 128 void *buffer, size_t size)
143 enum r600_hdmi_color_format color_format,
144 int active_information_present,
145 uint8_t active_format_aspect_ratio,
146 uint8_t scan_information,
147 uint8_t colorimetry,
148 uint8_t ex_colorimetry,
149 uint8_t quantization,
150 int ITC,
151 uint8_t picture_aspect_ratio,
152 uint8_t video_format_identification,
153 uint8_t pixel_repetition,
154 uint8_t non_uniform_picture_scaling,
155 uint8_t bar_info_data_valid,
156 uint16_t top_bar,
157 uint16_t bottom_bar,
158 uint16_t left_bar,
159 uint16_t right_bar
160)
161{ 129{
162 struct drm_device *dev = encoder->dev; 130 struct drm_device *dev = encoder->dev;
163 struct radeon_device *rdev = dev->dev_private; 131 struct radeon_device *rdev = dev->dev_private;
164 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 132 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
165 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 133 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
166 uint32_t offset = dig->afmt->offset; 134 uint32_t offset = dig->afmt->offset;
135 uint8_t *frame = buffer + 3;
167 136
168 uint8_t frame[14];
169
170 frame[0x0] = 0;
171 frame[0x1] =
172 (scan_information & 0x3) |
173 ((bar_info_data_valid & 0x3) << 2) |
174 ((active_information_present & 0x1) << 4) |
175 ((color_format & 0x3) << 5);
176 frame[0x2] =
177 (active_format_aspect_ratio & 0xF) |
178 ((picture_aspect_ratio & 0x3) << 4) |
179 ((colorimetry & 0x3) << 6);
180 frame[0x3] =
181 (non_uniform_picture_scaling & 0x3) |
182 ((quantization & 0x3) << 2) |
183 ((ex_colorimetry & 0x7) << 4) |
184 ((ITC & 0x1) << 7);
185 frame[0x4] = (video_format_identification & 0x7F);
186 frame[0x5] = (pixel_repetition & 0xF);
187 frame[0x6] = (top_bar & 0xFF);
188 frame[0x7] = (top_bar >> 8);
189 frame[0x8] = (bottom_bar & 0xFF);
190 frame[0x9] = (bottom_bar >> 8);
191 frame[0xA] = (left_bar & 0xFF);
192 frame[0xB] = (left_bar >> 8);
193 frame[0xC] = (right_bar & 0xFF);
194 frame[0xD] = (right_bar >> 8);
195
196 r600_hdmi_infoframe_checksum(0x82, 0x02, 0x0D, frame);
197 /* Our header values (type, version, length) should be alright, Intel 137 /* Our header values (type, version, length) should be alright, Intel
198 * is using the same. Checksum function also seems to be OK, it works 138 * is using the same. Checksum function also seems to be OK, it works
199 * fine for audio infoframe. However calculated value is always lower 139 * fine for audio infoframe. However calculated value is always lower
@@ -215,39 +155,15 @@ static void r600_hdmi_videoinfoframe(
215/* 155/*
216 * build a Audio Info Frame 156 * build a Audio Info Frame
217 */ 157 */
218static void r600_hdmi_audioinfoframe( 158static void r600_hdmi_update_audio_infoframe(struct drm_encoder *encoder,
219 struct drm_encoder *encoder, 159 const void *buffer, size_t size)
220 uint8_t channel_count,
221 uint8_t coding_type,
222 uint8_t sample_size,
223 uint8_t sample_frequency,
224 uint8_t format,
225 uint8_t channel_allocation,
226 uint8_t level_shift,
227 int downmix_inhibit
228)
229{ 160{
230 struct drm_device *dev = encoder->dev; 161 struct drm_device *dev = encoder->dev;
231 struct radeon_device *rdev = dev->dev_private; 162 struct radeon_device *rdev = dev->dev_private;
232 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 163 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
233 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 164 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
234 uint32_t offset = dig->afmt->offset; 165 uint32_t offset = dig->afmt->offset;
235 166 const u8 *frame = buffer + 3;
236 uint8_t frame[11];
237
238 frame[0x0] = 0;
239 frame[0x1] = (channel_count & 0x7) | ((coding_type & 0xF) << 4);
240 frame[0x2] = (sample_size & 0x3) | ((sample_frequency & 0x7) << 2);
241 frame[0x3] = format;
242 frame[0x4] = channel_allocation;
243 frame[0x5] = ((level_shift & 0xF) << 3) | ((downmix_inhibit & 0x1) << 7);
244 frame[0x6] = 0;
245 frame[0x7] = 0;
246 frame[0x8] = 0;
247 frame[0x9] = 0;
248 frame[0xA] = 0;
249
250 r600_hdmi_infoframe_checksum(0x84, 0x01, 0x0A, frame);
251 167
252 WREG32(HDMI0_AUDIO_INFO0 + offset, 168 WREG32(HDMI0_AUDIO_INFO0 + offset,
253 frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24)); 169 frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
@@ -320,7 +236,10 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
320 struct radeon_device *rdev = dev->dev_private; 236 struct radeon_device *rdev = dev->dev_private;
321 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 237 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
322 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 238 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
239 u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
240 struct hdmi_avi_infoframe frame;
323 uint32_t offset; 241 uint32_t offset;
242 ssize_t err;
324 243
325 /* Silent, r600_hdmi_enable will raise WARN for us */ 244 /* Silent, r600_hdmi_enable will raise WARN for us */
326 if (!dig->afmt->enabled) 245 if (!dig->afmt->enabled)
@@ -371,9 +290,19 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
371 290
372 WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */ 291 WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */
373 292
374 r600_hdmi_videoinfoframe(encoder, RGB, 0, 0, 0, 0, 293 err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
375 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 294 if (err < 0) {
295 DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
296 return;
297 }
376 298
299 err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
300 if (err < 0) {
301 DRM_ERROR("failed to pack AVI infoframe: %zd\n", err);
302 return;
303 }
304
305 r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer));
377 r600_hdmi_update_ACR(encoder, mode->clock); 306 r600_hdmi_update_ACR(encoder, mode->clock);
378 307
379 /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ 308 /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
@@ -395,8 +324,11 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
395 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 324 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
396 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 325 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
397 struct r600_audio audio = r600_audio_status(rdev); 326 struct r600_audio audio = r600_audio_status(rdev);
327 uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE];
328 struct hdmi_audio_infoframe frame;
398 uint32_t offset; 329 uint32_t offset;
399 uint32_t iec; 330 uint32_t iec;
331 ssize_t err;
400 332
401 if (!dig->afmt || !dig->afmt->enabled) 333 if (!dig->afmt || !dig->afmt->enabled)
402 return; 334 return;
@@ -462,9 +394,21 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
462 iec |= 0x5 << 16; 394 iec |= 0x5 << 16;
463 WREG32_P(HDMI0_60958_1 + offset, iec, ~0x5000f); 395 WREG32_P(HDMI0_60958_1 + offset, iec, ~0x5000f);
464 396
465 r600_hdmi_audioinfoframe(encoder, audio.channels - 1, 0, 0, 0, 0, 0, 0, 397 err = hdmi_audio_infoframe_init(&frame);
466 0); 398 if (err < 0) {
399 DRM_ERROR("failed to setup audio infoframe\n");
400 return;
401 }
402
403 frame.channels = audio.channels;
404
405 err = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
406 if (err < 0) {
407 DRM_ERROR("failed to pack audio infoframe\n");
408 return;
409 }
467 410
411 r600_hdmi_update_audio_infoframe(encoder, buffer, sizeof(buffer));
468 r600_hdmi_audio_workaround(encoder); 412 r600_hdmi_audio_workaround(encoder);
469} 413}
470 414