diff options
author | Thierry Reding <thierry.reding@avionic-design.de> | 2013-01-14 07:36:30 -0500 |
---|---|---|
committer | Thierry Reding <thierry.reding@avionic-design.de> | 2013-02-22 02:20:20 -0500 |
commit | e3b2e0347e3b3b81cc322b413abf98a349d275df (patch) | |
tree | 11e6141f0a4fabc371952514a7ff61918bef4b90 | |
parent | ac24c2204a76e5b42aa103bf963ae0eda1b827f3 (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.c | 85 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600_hdmi.c | 134 |
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 | */ | ||
59 | static 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 | */ |
74 | static void evergreen_hdmi_videoinfoframe( | 60 | static 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 | */ | ||
126 | static 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 | */ |
141 | static void r600_hdmi_videoinfoframe( | 127 | static 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 | */ |
218 | static void r600_hdmi_audioinfoframe( | 158 | static 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 | ||