diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2009-10-16 11:15:25 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-10-25 23:28:22 -0400 |
commit | ebbe1cb936dfc96d809ccf4d64a9755f8ba0c0ff (patch) | |
tree | 42c9ef8b5552c84a2e02b5e35f17bfddc28927b5 /drivers/gpu/drm/radeon/atombios_crtc.c | |
parent | c290dadf4cac25cc91529d84004795ab43fc0821 (diff) |
drm/radeon/kms/atom: add support for spread spectrum (v2)
Spread spectrum is a periodic disturbance added
to the feedback divider to change the pixel clock
periodically to reduce interference.
Only enabled on LVDS.
v2: add support for r4xx and fix DCE 3
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c')
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_crtc.c | 68 |
1 files changed, 57 insertions, 11 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 9c26e538a1e0..e5a3c301b7a9 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -351,6 +351,61 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc, | |||
351 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 351 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
352 | } | 352 | } |
353 | 353 | ||
354 | static void atombios_set_ss(struct drm_crtc *crtc, int enable) | ||
355 | { | ||
356 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
357 | struct drm_device *dev = crtc->dev; | ||
358 | struct radeon_device *rdev = dev->dev_private; | ||
359 | struct drm_encoder *encoder = NULL; | ||
360 | struct radeon_encoder *radeon_encoder = NULL; | ||
361 | struct radeon_encoder_atom_dig *dig = NULL; | ||
362 | int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL); | ||
363 | ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION args; | ||
364 | ENABLE_LVDS_SS_PARAMETERS legacy_args; | ||
365 | uint16_t percentage = 0; | ||
366 | uint8_t type = 0, step = 0, delay = 0, range = 0; | ||
367 | |||
368 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
369 | if (encoder->crtc == crtc) { | ||
370 | radeon_encoder = to_radeon_encoder(encoder); | ||
371 | dig = radeon_encoder->enc_priv; | ||
372 | /* only enable spread spectrum on LVDS */ | ||
373 | if (dig && dig->ss) { | ||
374 | percentage = dig->ss->percentage; | ||
375 | type = dig->ss->type; | ||
376 | step = dig->ss->step; | ||
377 | delay = dig->ss->delay; | ||
378 | range = dig->ss->range; | ||
379 | } else if (enable) | ||
380 | return; | ||
381 | break; | ||
382 | } | ||
383 | } | ||
384 | |||
385 | if (!radeon_encoder) | ||
386 | return; | ||
387 | |||
388 | if (ASIC_IS_AVIVO(rdev)) { | ||
389 | memset(&args, 0, sizeof(args)); | ||
390 | args.usSpreadSpectrumPercentage = percentage; | ||
391 | args.ucSpreadSpectrumType = type; | ||
392 | args.ucSpreadSpectrumStep = step; | ||
393 | args.ucSpreadSpectrumDelay = delay; | ||
394 | args.ucSpreadSpectrumRange = range; | ||
395 | args.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | ||
396 | args.ucEnable = enable; | ||
397 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
398 | } else { | ||
399 | memset(&legacy_args, 0, sizeof(legacy_args)); | ||
400 | legacy_args.usSpreadSpectrumPercentage = percentage; | ||
401 | legacy_args.ucSpreadSpectrumType = type; | ||
402 | legacy_args.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2; | ||
403 | legacy_args.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4; | ||
404 | legacy_args.ucEnable = enable; | ||
405 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&legacy_args); | ||
406 | } | ||
407 | } | ||
408 | |||
354 | void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | 409 | void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) |
355 | { | 410 | { |
356 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 411 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
@@ -373,8 +428,6 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
373 | memset(&args, 0, sizeof(args)); | 428 | memset(&args, 0, sizeof(args)); |
374 | 429 | ||
375 | if (ASIC_IS_AVIVO(rdev)) { | 430 | if (ASIC_IS_AVIVO(rdev)) { |
376 | uint32_t ss_cntl; | ||
377 | |||
378 | if ((rdev->family == CHIP_RS600) || | 431 | if ((rdev->family == CHIP_RS600) || |
379 | (rdev->family == CHIP_RS690) || | 432 | (rdev->family == CHIP_RS690) || |
380 | (rdev->family == CHIP_RS740)) | 433 | (rdev->family == CHIP_RS740)) |
@@ -385,15 +438,6 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
385 | pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; | 438 | pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; |
386 | else | 439 | else |
387 | pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; | 440 | pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; |
388 | |||
389 | /* disable spread spectrum clocking for now -- thanks Hedy Lamarr */ | ||
390 | if (radeon_crtc->crtc_id == 0) { | ||
391 | ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL); | ||
392 | WREG32(AVIVO_P1PLL_INT_SS_CNTL, ss_cntl & ~1); | ||
393 | } else { | ||
394 | ss_cntl = RREG32(AVIVO_P2PLL_INT_SS_CNTL); | ||
395 | WREG32(AVIVO_P2PLL_INT_SS_CNTL, ss_cntl & ~1); | ||
396 | } | ||
397 | } else { | 441 | } else { |
398 | pll_flags |= RADEON_PLL_LEGACY; | 442 | pll_flags |= RADEON_PLL_LEGACY; |
399 | 443 | ||
@@ -641,7 +685,9 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, | |||
641 | 685 | ||
642 | /* TODO color tiling */ | 686 | /* TODO color tiling */ |
643 | 687 | ||
688 | atombios_set_ss(crtc, 0); | ||
644 | atombios_crtc_set_pll(crtc, adjusted_mode); | 689 | atombios_crtc_set_pll(crtc, adjusted_mode); |
690 | atombios_set_ss(crtc, 1); | ||
645 | atombios_crtc_set_timing(crtc, adjusted_mode); | 691 | atombios_crtc_set_timing(crtc, adjusted_mode); |
646 | 692 | ||
647 | if (ASIC_IS_AVIVO(rdev)) | 693 | if (ASIC_IS_AVIVO(rdev)) |