diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r600_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r600_hdmi.c | 80 |
1 files changed, 18 insertions, 62 deletions
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 1c49f4d2945a..30580d1a14f0 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c | |||
@@ -380,73 +380,29 @@ void r600_hdmi_audio_workaround(struct drm_encoder *encoder) | |||
380 | value, ~HDMI0_AUDIO_TEST_EN); | 380 | value, ~HDMI0_AUDIO_TEST_EN); |
381 | } | 381 | } |
382 | 382 | ||
383 | void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock) | 383 | void r600_hdmi_audio_set_dto(struct radeon_device *rdev, |
384 | struct radeon_crtc *crtc, unsigned int clock) | ||
384 | { | 385 | { |
385 | struct drm_device *dev = encoder->dev; | 386 | struct radeon_encoder *radeon_encoder; |
386 | struct radeon_device *rdev = dev->dev_private; | 387 | struct radeon_encoder_atom_dig *dig; |
387 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
388 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
389 | u32 base_rate = 24000; | ||
390 | u32 max_ratio = clock / base_rate; | ||
391 | u32 dto_phase; | ||
392 | u32 dto_modulo = clock; | ||
393 | u32 wallclock_ratio; | ||
394 | u32 dto_cntl; | ||
395 | 388 | ||
396 | if (!dig || !dig->afmt) | 389 | if (!crtc) |
397 | return; | 390 | return; |
398 | 391 | ||
399 | if (max_ratio >= 8) { | 392 | radeon_encoder = to_radeon_encoder(crtc->encoder); |
400 | dto_phase = 192 * 1000; | 393 | dig = radeon_encoder->enc_priv; |
401 | wallclock_ratio = 3; | ||
402 | } else if (max_ratio >= 4) { | ||
403 | dto_phase = 96 * 1000; | ||
404 | wallclock_ratio = 2; | ||
405 | } else if (max_ratio >= 2) { | ||
406 | dto_phase = 48 * 1000; | ||
407 | wallclock_ratio = 1; | ||
408 | } else { | ||
409 | dto_phase = 24 * 1000; | ||
410 | wallclock_ratio = 0; | ||
411 | } | ||
412 | 394 | ||
413 | /* there are two DTOs selected by DCCG_AUDIO_DTO_SELECT. | 395 | if (!dig) |
414 | * doesn't matter which one you use. Just use the first one. | 396 | return; |
415 | */ | 397 | |
416 | /* XXX two dtos; generally use dto0 for hdmi */ | 398 | if (dig->dig_encoder == 0) { |
417 | /* Express [24MHz / target pixel clock] as an exact rational | 399 | WREG32(DCCG_AUDIO_DTO0_PHASE, 24000 * 100); |
418 | * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE | 400 | WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100); |
419 | * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator | 401 | WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */ |
420 | */ | ||
421 | if (ASIC_IS_DCE32(rdev)) { | ||
422 | if (dig->dig_encoder == 0) { | ||
423 | dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; | ||
424 | dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); | ||
425 | WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl); | ||
426 | WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase); | ||
427 | WREG32(DCCG_AUDIO_DTO0_MODULE, dto_modulo); | ||
428 | WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */ | ||
429 | } else { | ||
430 | dto_cntl = RREG32(DCCG_AUDIO_DTO1_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK; | ||
431 | dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio); | ||
432 | WREG32(DCCG_AUDIO_DTO1_CNTL, dto_cntl); | ||
433 | WREG32(DCCG_AUDIO_DTO1_PHASE, dto_phase); | ||
434 | WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo); | ||
435 | WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ | ||
436 | } | ||
437 | } else { | 402 | } else { |
438 | /* according to the reg specs, this should DCE3.2 only, but in | 403 | WREG32(DCCG_AUDIO_DTO1_PHASE, 24000 * 100); |
439 | * practice it seems to cover DCE2.0/3.0/3.1 as well. | 404 | WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100); |
440 | */ | 405 | WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ |
441 | if (dig->dig_encoder == 0) { | ||
442 | WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100); | ||
443 | WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100); | ||
444 | WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */ | ||
445 | } else { | ||
446 | WREG32(DCCG_AUDIO_DTO1_PHASE, base_rate * 100); | ||
447 | WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100); | ||
448 | WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ | ||
449 | } | ||
450 | } | 406 | } |
451 | } | 407 | } |
452 | 408 | ||
@@ -477,7 +433,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod | |||
477 | dig->afmt->pin = radeon_audio_get_pin(encoder); | 433 | dig->afmt->pin = radeon_audio_get_pin(encoder); |
478 | radeon_audio_enable(rdev, dig->afmt->pin, 0); | 434 | radeon_audio_enable(rdev, dig->afmt->pin, 0); |
479 | 435 | ||
480 | r600_audio_set_dto(encoder, mode->clock); | 436 | radeon_audio_set_dto(encoder, mode->clock); |
481 | 437 | ||
482 | WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset, | 438 | WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset, |
483 | HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */ | 439 | HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */ |