Rev 5271 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5271 | Rev 6104 | ||
---|---|---|---|
Line 22... | Line 22... | ||
22 | * OTHER DEALINGS IN THE SOFTWARE. |
22 | * OTHER DEALINGS IN THE SOFTWARE. |
23 | * |
23 | * |
24 | * Authors: Christian König |
24 | * Authors: Christian König |
25 | */ |
25 | */ |
26 | #include |
26 | #include |
- | 27 | #include |
|
27 | #include |
28 | #include |
28 | #include |
29 | #include |
29 | #include "radeon.h" |
30 | #include "radeon.h" |
30 | #include "radeon_asic.h" |
31 | #include "radeon_asic.h" |
- | 32 | #include "radeon_audio.h" |
|
31 | #include "r600d.h" |
33 | #include "r600d.h" |
32 | #include "atom.h" |
34 | #include "atom.h" |
Line 33... | Line 35... | ||
33 | 35 | ||
34 | /* |
36 | /* |
Line 52... | Line 54... | ||
52 | AUDIO_STATUS_NONAUDIO = 0x20, |
54 | AUDIO_STATUS_NONAUDIO = 0x20, |
53 | AUDIO_STATUS_PROFESSIONAL = 0x40, |
55 | AUDIO_STATUS_PROFESSIONAL = 0x40, |
54 | AUDIO_STATUS_LEVEL = 0x80 |
56 | AUDIO_STATUS_LEVEL = 0x80 |
55 | }; |
57 | }; |
Line 56... | Line -... | ||
56 | - | ||
57 | static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { |
- | |
58 | /* 32kHz 44.1kHz 48kHz */ |
- | |
59 | /* Clock N CTS N CTS N CTS */ |
- | |
60 | { 25175, 4096, 25175, 28224, 125875, 6144, 25175 }, /* 25,20/1.001 MHz */ |
- | |
61 | { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */ |
- | |
62 | { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */ |
- | |
63 | { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */ |
- | |
64 | { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */ |
- | |
65 | { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */ |
- | |
66 | { 74176, 4096, 74176, 5733, 75335, 6144, 74176 }, /* 74.25/1.001 MHz */ |
- | |
67 | { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ |
- | |
68 | { 148352, 4096, 148352, 5733, 150670, 6144, 148352 }, /* 148.50/1.001 MHz */ |
- | |
69 | { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ |
- | |
70 | }; |
- | |
71 | - | ||
72 | - | ||
73 | /* |
- | |
74 | * check if the chipset is supported |
- | |
75 | */ |
- | |
76 | static int r600_audio_chipset_supported(struct radeon_device *rdev) |
- | |
77 | { |
- | |
78 | return ASIC_IS_DCE2(rdev) && !ASIC_IS_NODCE(rdev); |
- | |
79 | } |
- | |
80 | 58 | ||
81 | static struct r600_audio_pin r600_audio_status(struct radeon_device *rdev) |
59 | static struct r600_audio_pin r600_audio_status(struct radeon_device *rdev) |
82 | { |
60 | { |
83 | struct r600_audio_pin status; |
61 | struct r600_audio_pin status; |
Line 188... | Line 166... | ||
188 | } |
166 | } |
Line 189... | Line 167... | ||
189 | 167 | ||
190 | WREG32(AZ_HOT_PLUG_CONTROL, tmp); |
168 | WREG32(AZ_HOT_PLUG_CONTROL, tmp); |
Line 191... | Line -... | ||
191 | } |
- | |
192 | - | ||
193 | /* |
- | |
194 | * initialize the audio vars |
- | |
195 | */ |
- | |
196 | int r600_audio_init(struct radeon_device *rdev) |
- | |
197 | { |
- | |
198 | if (!radeon_audio || !r600_audio_chipset_supported(rdev)) |
- | |
199 | return 0; |
- | |
200 | - | ||
201 | rdev->audio.enabled = true; |
- | |
202 | - | ||
203 | rdev->audio.num_pins = 1; |
- | |
204 | rdev->audio.pin[0].channels = -1; |
- | |
205 | rdev->audio.pin[0].rate = -1; |
- | |
206 | rdev->audio.pin[0].bits_per_sample = -1; |
- | |
207 | rdev->audio.pin[0].status_bits = 0; |
- | |
208 | rdev->audio.pin[0].category_code = 0; |
- | |
209 | rdev->audio.pin[0].id = 0; |
- | |
210 | /* disable audio. it will be set up later */ |
- | |
211 | r600_audio_enable(rdev, &rdev->audio.pin[0], 0); |
- | |
212 | - | ||
213 | return 0; |
- | |
214 | } |
- | |
215 | - | ||
216 | /* |
- | |
217 | * release the audio timer |
- | |
218 | * TODO: How to do this correctly on SMP systems? |
- | |
219 | */ |
- | |
220 | void r600_audio_fini(struct radeon_device *rdev) |
- | |
221 | { |
- | |
222 | if (!rdev->audio.enabled) |
- | |
223 | return; |
- | |
224 | - | ||
225 | r600_audio_enable(rdev, &rdev->audio.pin[0], 0); |
- | |
226 | - | ||
227 | rdev->audio.enabled = false; |
- | |
228 | } |
169 | } |
229 | 170 | ||
230 | struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev) |
171 | struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev) |
231 | { |
172 | { |
232 | /* only one pin on 6xx-NI */ |
173 | /* only one pin on 6xx-NI */ |
Line 233... | Line -... | ||
233 | return &rdev->audio.pin[0]; |
- | |
234 | } |
- | |
235 | - | ||
236 | /* |
174 | return &rdev->audio.pin[0]; |
237 | * calculate CTS and N values if they are not found in the table |
- | |
238 | */ |
- | |
239 | static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int *N, int freq) |
- | |
240 | { |
- | |
241 | int n, cts; |
- | |
242 | unsigned long div, mul; |
- | |
243 | - | ||
244 | /* Safe, but overly large values */ |
- | |
245 | n = 128 * freq; |
- | |
246 | cts = clock * 1000; |
- | |
247 | - | ||
248 | /* Smallest valid fraction */ |
- | |
249 | div = gcd(n, cts); |
- | |
250 | - | ||
251 | n /= div; |
- | |
252 | cts /= div; |
- | |
253 | - | ||
254 | /* |
- | |
255 | * The optimal N is 128*freq/1000. Calculate the closest larger |
- | |
256 | * value that doesn't truncate any bits. |
- | |
257 | */ |
- | |
258 | mul = ((128*freq/1000) + (n-1))/n; |
- | |
259 | - | ||
260 | n *= mul; |
- | |
261 | cts *= mul; |
- | |
262 | - | ||
263 | /* Check that we are in spec (not always possible) */ |
- | |
264 | if (n < (128*freq/1500)) |
- | |
265 | printk(KERN_WARNING "Calculated ACR N value is too small. You may experience audio problems.\n"); |
- | |
266 | if (n > (128*freq/300)) |
- | |
267 | printk(KERN_WARNING "Calculated ACR N value is too large. You may experience audio problems.\n"); |
- | |
268 | - | ||
269 | *N = n; |
- | |
270 | *CTS = cts; |
- | |
271 | - | ||
272 | DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n", |
- | |
273 | *N, *CTS, freq); |
- | |
274 | } |
- | |
275 | 175 | } |
|
276 | struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock) |
- | |
277 | { |
- | |
278 | struct radeon_hdmi_acr res; |
- | |
279 | u8 i; |
- | |
280 | - | ||
281 | /* Precalculated values for common clocks */ |
- | |
282 | for (i = 0; i < ARRAY_SIZE(r600_hdmi_predefined_acr); i++) { |
- | |
283 | if (r600_hdmi_predefined_acr[i].clock == clock) |
- | |
284 | return r600_hdmi_predefined_acr[i]; |
- | |
285 | } |
- | |
286 | - | ||
287 | /* And odd clocks get manually calculated */ |
- | |
288 | r600_hdmi_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000); |
- | |
289 | r600_hdmi_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100); |
- | |
290 | r600_hdmi_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000); |
- | |
291 | - | ||
292 | return res; |
- | |
293 | } |
- | |
294 | - | ||
295 | /* |
- | |
296 | * update the N and CTS parameters for a given pixel clock rate |
176 | |
297 | */ |
177 | void r600_hdmi_update_acr(struct drm_encoder *encoder, long offset, |
298 | void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock) |
178 | const struct radeon_hdmi_acr *acr) |
- | 179 | { |
|
299 | { |
180 | struct drm_device *dev = encoder->dev; |
300 | struct drm_device *dev = encoder->dev; |
181 | struct radeon_device *rdev = dev->dev_private; |
301 | struct radeon_device *rdev = dev->dev_private; |
182 | |
302 | struct radeon_hdmi_acr acr = r600_hdmi_acr(clock); |
183 | /* DCE 3.0 uses register that's normally for CRC_CONTROL */ |
- | 184 | uint32_t acr_ctl = ASIC_IS_DCE3(rdev) ? DCE3_HDMI0_ACR_PACKET_CONTROL : |
|
- | 185 | HDMI0_ACR_PACKET_CONTROL; |
|
- | 186 | WREG32_P(acr_ctl + offset, |
|
- | 187 | HDMI0_ACR_SOURCE | /* select SW CTS value */ |
|
Line 303... | Line 188... | ||
303 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
188 | HDMI0_ACR_AUTO_SEND, /* allow hw to sent ACR packets when required */ |
304 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
189 | ~(HDMI0_ACR_SOURCE | |
305 | uint32_t offset = dig->afmt->offset; |
190 | HDMI0_ACR_AUTO_SEND)); |
306 | 191 | ||
307 | WREG32_P(HDMI0_ACR_32_0 + offset, |
192 | WREG32_P(HDMI0_ACR_32_0 + offset, |
308 | HDMI0_ACR_CTS_32(acr.cts_32khz), |
193 | HDMI0_ACR_CTS_32(acr->cts_32khz), |
Line 309... | Line 194... | ||
309 | ~HDMI0_ACR_CTS_32_MASK); |
194 | ~HDMI0_ACR_CTS_32_MASK); |
310 | WREG32_P(HDMI0_ACR_32_1 + offset, |
195 | WREG32_P(HDMI0_ACR_32_1 + offset, |
311 | HDMI0_ACR_N_32(acr.n_32khz), |
196 | HDMI0_ACR_N_32(acr->n_32khz), |
312 | ~HDMI0_ACR_N_32_MASK); |
197 | ~HDMI0_ACR_N_32_MASK); |
313 | 198 | ||
314 | WREG32_P(HDMI0_ACR_44_0 + offset, |
199 | WREG32_P(HDMI0_ACR_44_0 + offset, |
Line 315... | Line 200... | ||
315 | HDMI0_ACR_CTS_44(acr.cts_44_1khz), |
200 | HDMI0_ACR_CTS_44(acr->cts_44_1khz), |
316 | ~HDMI0_ACR_CTS_44_MASK); |
201 | ~HDMI0_ACR_CTS_44_MASK); |
317 | WREG32_P(HDMI0_ACR_44_1 + offset, |
202 | WREG32_P(HDMI0_ACR_44_1 + offset, |
318 | HDMI0_ACR_N_44(acr.n_44_1khz), |
203 | HDMI0_ACR_N_44(acr->n_44_1khz), |
319 | ~HDMI0_ACR_N_44_MASK); |
204 | ~HDMI0_ACR_N_44_MASK); |
320 | 205 | ||
321 | WREG32_P(HDMI0_ACR_48_0 + offset, |
206 | WREG32_P(HDMI0_ACR_48_0 + offset, |
Line 322... | Line 207... | ||
322 | HDMI0_ACR_CTS_48(acr.cts_48khz), |
207 | HDMI0_ACR_CTS_48(acr->cts_48khz), |
323 | ~HDMI0_ACR_CTS_48_MASK); |
208 | ~HDMI0_ACR_CTS_48_MASK); |
324 | WREG32_P(HDMI0_ACR_48_1 + offset, |
209 | WREG32_P(HDMI0_ACR_48_1 + offset, |
325 | HDMI0_ACR_N_48(acr.n_48khz), |
210 | HDMI0_ACR_N_48(acr->n_48khz), |
326 | ~HDMI0_ACR_N_48_MASK); |
211 | ~HDMI0_ACR_N_48_MASK); |
327 | } |
212 | } |
328 | - | ||
329 | /* |
- | |
330 | * build a HDMI Video Info Frame |
- | |
331 | */ |
- | |
332 | void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, |
- | |
333 | size_t size) |
213 | |
334 | { |
- | |
Line 335... | Line 214... | ||
335 | struct drm_device *dev = encoder->dev; |
214 | /* |
336 | struct radeon_device *rdev = dev->dev_private; |
215 | * build a HDMI Video Info Frame |
337 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
216 | */ |
338 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
217 | void r600_set_avi_packet(struct radeon_device *rdev, u32 offset, |
339 | uint32_t offset = dig->afmt->offset; |
218 | unsigned char *buffer, size_t size) |
340 | uint8_t *frame = buffer + 3; |
219 | { |
341 | uint8_t *header = buffer; |
220 | uint8_t *frame = buffer + 3; |
342 | 221 | ||
- | 222 | WREG32(HDMI0_AVI_INFO0 + offset, |
|
- | 223 | frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24)); |
|
- | 224 | WREG32(HDMI0_AVI_INFO1 + offset, |
|
- | 225 | frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x7] << 24)); |
|
- | 226 | WREG32(HDMI0_AVI_INFO2 + offset, |
|
- | 227 | frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24)); |
|
- | 228 | WREG32(HDMI0_AVI_INFO3 + offset, |
|
- | 229 | frame[0xC] | (frame[0xD] << 8) | (buffer[1] << 24)); |
|
343 | WREG32(HDMI0_AVI_INFO0 + offset, |
230 | |
Line 344... | Line 231... | ||
344 | frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24)); |
231 | WREG32_OR(HDMI0_INFOFRAME_CONTROL1 + offset, |
345 | WREG32(HDMI0_AVI_INFO1 + offset, |
232 | HDMI0_AVI_INFO_LINE(2)); /* anything other than 0 */ |
346 | frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x7] << 24)); |
233 | |
Line 422... | Line 309... | ||
422 | value = HDMI0_AUDIO_TEST_EN; /* enable workaround */ |
309 | value = HDMI0_AUDIO_TEST_EN; /* enable workaround */ |
423 | WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset, |
310 | WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset, |
424 | value, ~HDMI0_AUDIO_TEST_EN); |
311 | value, ~HDMI0_AUDIO_TEST_EN); |
425 | } |
312 | } |
Line 426... | Line 313... | ||
426 | 313 | ||
- | 314 | void r600_hdmi_audio_set_dto(struct radeon_device *rdev, |
|
427 | void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock) |
315 | struct radeon_crtc *crtc, unsigned int clock) |
428 | { |
- | |
429 | struct drm_device *dev = encoder->dev; |
316 | { |
430 | struct radeon_device *rdev = dev->dev_private; |
- | |
431 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
317 | struct radeon_encoder *radeon_encoder; |
432 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
- | |
433 | u32 base_rate = 24000; |
- | |
434 | u32 max_ratio = clock / base_rate; |
- | |
435 | u32 dto_phase; |
- | |
436 | u32 dto_modulo = clock; |
- | |
437 | u32 wallclock_ratio; |
- | |
Line 438... | Line 318... | ||
438 | u32 dto_cntl; |
318 | struct radeon_encoder_atom_dig *dig; |
439 | 319 | ||
Line 440... | Line -... | ||
440 | if (!dig || !dig->afmt) |
- | |
441 | return; |
- | |
442 | - | ||
443 | if (max_ratio >= 8) { |
320 | if (!crtc) |
444 | dto_phase = 192 * 1000; |
- | |
445 | wallclock_ratio = 3; |
- | |
446 | } else if (max_ratio >= 4) { |
321 | return; |
447 | dto_phase = 96 * 1000; |
- | |
448 | wallclock_ratio = 2; |
- | |
- | 322 | ||
449 | } else if (max_ratio >= 2) { |
323 | radeon_encoder = to_radeon_encoder(crtc->encoder); |
450 | dto_phase = 48 * 1000; |
- | |
451 | wallclock_ratio = 1; |
324 | dig = radeon_encoder->enc_priv; |
452 | } else { |
- | |
Line 453... | Line -... | ||
453 | dto_phase = 24 * 1000; |
- | |
454 | wallclock_ratio = 0; |
- | |
455 | } |
- | |
456 | - | ||
457 | /* there are two DTOs selected by DCCG_AUDIO_DTO_SELECT. |
- | |
458 | * doesn't matter which one you use. Just use the first one. |
- | |
459 | */ |
- | |
460 | /* XXX two dtos; generally use dto0 for hdmi */ |
- | |
461 | /* Express [24MHz / target pixel clock] as an exact rational |
- | |
462 | * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE |
- | |
463 | * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator |
- | |
464 | */ |
- | |
465 | if (ASIC_IS_DCE32(rdev)) { |
- | |
466 | if (dig->dig_encoder == 0) { |
- | |
467 | dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; |
- | |
468 | dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); |
- | |
469 | WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl); |
- | |
470 | WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase); |
- | |
471 | WREG32(DCCG_AUDIO_DTO0_MODULE, dto_modulo); |
- | |
472 | WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */ |
- | |
473 | } else { |
- | |
474 | dto_cntl = RREG32(DCCG_AUDIO_DTO1_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; |
- | |
475 | dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); |
- | |
476 | WREG32(DCCG_AUDIO_DTO1_CNTL, dto_cntl); |
- | |
477 | WREG32(DCCG_AUDIO_DTO1_PHASE, dto_phase); |
- | |
478 | WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo); |
- | |
479 | WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ |
- | |
480 | } |
- | |
481 | } else { |
325 | |
482 | /* according to the reg specs, this should DCE3.2 only, but in |
326 | if (!dig) |
483 | * practice it seems to cover DCE2.0/3.0/3.1 as well. |
327 | return; |
484 | */ |
328 | |
485 | if (dig->dig_encoder == 0) { |
329 | if (dig->dig_encoder == 0) { |
486 | WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100); |
330 | WREG32(DCCG_AUDIO_DTO0_PHASE, 24000 * 100); |
487 | WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100); |
331 | WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100); |
488 | WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */ |
332 | WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */ |
489 | } else { |
333 | } else { |
490 | WREG32(DCCG_AUDIO_DTO1_PHASE, base_rate * 100); |
334 | WREG32(DCCG_AUDIO_DTO1_PHASE, 24000 * 100); |
491 | WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100); |
- | |
Line 492... | Line -... | ||
492 | WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ |
- | |
493 | } |
- | |
494 | } |
- | |
495 | } |
335 | WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100); |
496 | 336 | WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ |
|
497 | /* |
337 | } |
498 | * update the info frames with the data from the current display mode |
338 | } |
499 | */ |
- | |
500 | void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) |
- | |
501 | { |
- | |
502 | struct drm_device *dev = encoder->dev; |
- | |
503 | struct radeon_device *rdev = dev->dev_private; |
- | |
504 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
- | |
505 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
- | |
506 | u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; |
- | |
507 | struct hdmi_avi_infoframe frame; |
- | |
508 | uint32_t offset; |
- | |
509 | uint32_t acr_ctl; |
- | |
510 | ssize_t err; |
- | |
511 | - | ||
512 | if (!dig || !dig->afmt) |
- | |
513 | return; |
- | |
Line 514... | Line 339... | ||
514 | 339 | ||
515 | /* Silent, r600_hdmi_enable will raise WARN for us */ |
340 | void r600_set_vbi_packet(struct drm_encoder *encoder, u32 offset) |
516 | if (!dig->afmt->enabled) |
341 | { |
- | 342 | struct drm_device *dev = encoder->dev; |
|
- | 343 | struct radeon_device *rdev = dev->dev_private; |
|
Line 517... | Line 344... | ||
517 | return; |
344 | |
- | 345 | WREG32_OR(HDMI0_VBI_PACKET_CONTROL + offset, |
|
- | 346 | HDMI0_NULL_SEND | /* send null packets when required */ |
|
- | 347 | HDMI0_GC_SEND | /* send general control packets */ |
|
Line 518... | Line 348... | ||
518 | offset = dig->afmt->offset; |
348 | HDMI0_GC_CONT); /* send general control packets every frame */ |
519 | 349 | } |
|
520 | /* disable audio prior to setting up hw */ |
350 | |
521 | dig->afmt->pin = r600_audio_get_pin(rdev); |
351 | void r600_set_audio_packet(struct drm_encoder *encoder, u32 offset) |
Line 531... | Line 361... | ||
531 | ~(HDMI0_AUDIO_SAMPLE_SEND | |
361 | ~(HDMI0_AUDIO_SAMPLE_SEND | |
532 | HDMI0_AUDIO_DELAY_EN_MASK | |
362 | HDMI0_AUDIO_DELAY_EN_MASK | |
533 | HDMI0_AUDIO_PACKETS_PER_LINE_MASK | |
363 | HDMI0_AUDIO_PACKETS_PER_LINE_MASK | |
534 | HDMI0_60958_CS_UPDATE)); |
364 | HDMI0_60958_CS_UPDATE)); |
Line 535... | Line -... | ||
535 | - | ||
536 | /* DCE 3.0 uses register that's normally for CRC_CONTROL */ |
- | |
537 | acr_ctl = ASIC_IS_DCE3(rdev) ? DCE3_HDMI0_ACR_PACKET_CONTROL : |
- | |
538 | HDMI0_ACR_PACKET_CONTROL; |
- | |
539 | WREG32_P(acr_ctl + offset, |
- | |
540 | HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */ |
- | |
541 | HDMI0_ACR_AUTO_SEND, /* allow hw to sent ACR packets when required */ |
- | |
542 | ~(HDMI0_ACR_SOURCE | |
- | |
543 | HDMI0_ACR_AUTO_SEND)); |
- | |
544 | - | ||
545 | WREG32_OR(HDMI0_VBI_PACKET_CONTROL + offset, |
- | |
546 | HDMI0_NULL_SEND | /* send null packets when required */ |
- | |
547 | HDMI0_GC_SEND | /* send general control packets */ |
- | |
548 | HDMI0_GC_CONT); /* send general control packets every frame */ |
- | |
549 | 365 | ||
550 | WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset, |
- | |
551 | HDMI0_AVI_INFO_SEND | /* enable AVI info frames */ |
- | |
552 | HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */ |
366 | WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset, |
553 | HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ |
367 | HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */ |
Line 554... | Line 368... | ||
554 | HDMI0_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */ |
368 | HDMI0_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */ |
555 | - | ||
556 | WREG32_P(HDMI0_INFOFRAME_CONTROL1 + offset, |
369 | |
557 | HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */ |
- | |
558 | HDMI0_AUDIO_INFO_LINE(2), /* anything other than 0 */ |
370 | WREG32_P(HDMI0_INFOFRAME_CONTROL1 + offset, |
559 | ~(HDMI0_AVI_INFO_LINE_MASK | |
- | |
560 | HDMI0_AUDIO_INFO_LINE_MASK)); |
- | |
561 | - | ||
562 | WREG32_AND(HDMI0_GC + offset, |
- | |
563 | ~HDMI0_GC_AVMUTE); /* unset HDMI0_GC_AVMUTE */ |
- | |
564 | - | ||
565 | err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); |
- | |
566 | if (err < 0) { |
- | |
567 | DRM_ERROR("failed to setup AVI infoframe: %zd\n", err); |
- | |
568 | return; |
- | |
569 | } |
- | |
570 | - | ||
571 | err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer)); |
- | |
572 | if (err < 0) { |
- | |
573 | DRM_ERROR("failed to pack AVI infoframe: %zd\n", err); |
- | |
574 | return; |
- | |
575 | } |
- | |
576 | - | ||
577 | r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer)); |
- | |
Line 578... | Line 371... | ||
578 | 371 | HDMI0_AUDIO_INFO_LINE(2), /* anything other than 0 */ |
|
579 | /* fglrx duplicates INFOFRAME_CONTROL0 & INFOFRAME_CONTROL1 ops here */ |
372 | ~HDMI0_AUDIO_INFO_LINE_MASK); |
580 | 373 | ||
581 | WREG32_AND(HDMI0_GENERIC_PACKET_CONTROL + offset, |
374 | WREG32_AND(HDMI0_GENERIC_PACKET_CONTROL + offset, |
582 | ~(HDMI0_GENERIC0_SEND | |
375 | ~(HDMI0_GENERIC0_SEND | |
583 | HDMI0_GENERIC0_CONT | |
376 | HDMI0_GENERIC0_CONT | |
584 | HDMI0_GENERIC0_UPDATE | |
377 | HDMI0_GENERIC0_UPDATE | |
585 | HDMI0_GENERIC1_SEND | |
378 | HDMI0_GENERIC1_SEND | |
Line 586... | Line -... | ||
586 | HDMI0_GENERIC1_CONT | |
- | |
587 | HDMI0_GENERIC0_LINE_MASK | |
- | |
588 | HDMI0_GENERIC1_LINE_MASK)); |
379 | HDMI0_GENERIC1_CONT | |
589 | 380 | HDMI0_GENERIC0_LINE_MASK | |
|
590 | r600_hdmi_update_ACR(encoder, mode->clock); |
381 | HDMI0_GENERIC1_LINE_MASK)); |
591 | 382 | ||
Line 592... | Line 383... | ||
592 | WREG32_P(HDMI0_60958_0 + offset, |
383 | WREG32_P(HDMI0_60958_0 + offset, |
593 | HDMI0_60958_CS_CHANNEL_NUMBER_L(1), |
384 | HDMI0_60958_CS_CHANNEL_NUMBER_L(1), |
594 | ~(HDMI0_60958_CS_CHANNEL_NUMBER_L_MASK | |
385 | ~(HDMI0_60958_CS_CHANNEL_NUMBER_L_MASK | |
- | 386 | HDMI0_60958_CS_CLOCK_ACCURACY_MASK)); |
|
Line 595... | Line 387... | ||
595 | HDMI0_60958_CS_CLOCK_ACCURACY_MASK)); |
387 | |
596 | - | ||
597 | WREG32_P(HDMI0_60958_1 + offset, |
- | |
- | 388 | WREG32_P(HDMI0_60958_1 + offset, |
|
598 | HDMI0_60958_CS_CHANNEL_NUMBER_R(2), |
389 | HDMI0_60958_CS_CHANNEL_NUMBER_R(2), |
599 | ~HDMI0_60958_CS_CHANNEL_NUMBER_R_MASK); |
390 | ~HDMI0_60958_CS_CHANNEL_NUMBER_R_MASK); |
Line -... | Line 391... | ||
- | 391 | } |
|
600 | 392 | ||
- | 393 | void r600_set_mute(struct drm_encoder *encoder, u32 offset, bool mute) |
|
601 | /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ |
394 | { |
602 | WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF); |
395 | struct drm_device *dev = encoder->dev; |
Line 603... | Line 396... | ||
603 | WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF); |
396 | struct radeon_device *rdev = dev->dev_private; |
604 | WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001); |
397 | |
605 | WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001); |
398 | if (mute) |
Line 682... | Line 475... | ||
682 | u32 hdmi = HDMI0_ERROR_ACK; |
475 | u32 hdmi = HDMI0_ERROR_ACK; |
Line 683... | Line 476... | ||
683 | 476 | ||
684 | if (!dig || !dig->afmt) |
477 | if (!dig || !dig->afmt) |
Line 685... | Line -... | ||
685 | return; |
- | |
686 | - | ||
687 | /* Silent, r600_hdmi_enable will raise WARN for us */ |
- | |
688 | if (enable && dig->afmt->enabled) |
- | |
689 | return; |
- | |
690 | if (!enable && !dig->afmt->enabled) |
- | |
691 | return; |
- | |
692 | - | ||
693 | if (!enable && dig->afmt->pin) { |
- | |
694 | r600_audio_enable(rdev, dig->afmt->pin, 0); |
- | |
695 | dig->afmt->pin = NULL; |
- | |
696 | } |
478 | return; |
697 | 479 | ||
698 | /* Older chipsets require setting HDMI and routing manually */ |
480 | /* Older chipsets require setting HDMI and routing manually */ |
699 | if (!ASIC_IS_DCE3(rdev)) { |
481 | if (!ASIC_IS_DCE3(rdev)) { |
700 | if (enable) |
482 | if (enable) |