diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpu/drm/radeon/atombios.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/atombios_crtc.c | 68 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_atombios.c | 42 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_mode.h | 11 |
4 files changed, 111 insertions, 12 deletions
diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index 5d402086bc47..c11ddddfb3b6 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h | |||
| @@ -2314,7 +2314,7 @@ typedef struct _ATOM_SPREAD_SPECTRUM_ASSIGNMENT { | |||
| 2314 | UCHAR ucSS_Step; | 2314 | UCHAR ucSS_Step; |
| 2315 | UCHAR ucSS_Delay; | 2315 | UCHAR ucSS_Delay; |
| 2316 | UCHAR ucSS_Id; | 2316 | UCHAR ucSS_Id; |
| 2317 | UCHAR ucRecommandedRef_Div; | 2317 | UCHAR ucRecommendedRef_Div; |
| 2318 | UCHAR ucSS_Range; /* it was reserved for V11 */ | 2318 | UCHAR ucSS_Range; /* it was reserved for V11 */ |
| 2319 | } ATOM_SPREAD_SPECTRUM_ASSIGNMENT; | 2319 | } ATOM_SPREAD_SPECTRUM_ASSIGNMENT; |
| 2320 | 2320 | ||
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)) |
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index cec67917179f..18729259c2fc 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
| @@ -771,6 +771,46 @@ bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder, | |||
| 771 | return false; | 771 | return false; |
| 772 | } | 772 | } |
| 773 | 773 | ||
| 774 | static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct | ||
| 775 | radeon_encoder | ||
| 776 | *encoder, | ||
| 777 | int id) | ||
| 778 | { | ||
| 779 | struct drm_device *dev = encoder->base.dev; | ||
| 780 | struct radeon_device *rdev = dev->dev_private; | ||
| 781 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
| 782 | int index = GetIndexIntoMasterTable(DATA, PPLL_SS_Info); | ||
| 783 | uint16_t data_offset; | ||
| 784 | struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info; | ||
| 785 | uint8_t frev, crev; | ||
| 786 | struct radeon_atom_ss *ss = NULL; | ||
| 787 | |||
| 788 | if (id > ATOM_MAX_SS_ENTRY) | ||
| 789 | return NULL; | ||
| 790 | |||
| 791 | atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, | ||
| 792 | &crev, &data_offset); | ||
| 793 | |||
| 794 | ss_info = | ||
| 795 | (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset); | ||
| 796 | |||
| 797 | if (ss_info) { | ||
| 798 | ss = | ||
| 799 | kzalloc(sizeof(struct radeon_atom_ss), GFP_KERNEL); | ||
| 800 | |||
| 801 | if (!ss) | ||
| 802 | return NULL; | ||
| 803 | |||
| 804 | ss->percentage = le16_to_cpu(ss_info->asSS_Info[id].usSpreadSpectrumPercentage); | ||
| 805 | ss->type = ss_info->asSS_Info[id].ucSpreadSpectrumType; | ||
| 806 | ss->step = ss_info->asSS_Info[id].ucSS_Step; | ||
| 807 | ss->delay = ss_info->asSS_Info[id].ucSS_Delay; | ||
| 808 | ss->range = ss_info->asSS_Info[id].ucSS_Range; | ||
| 809 | ss->refdiv = ss_info->asSS_Info[id].ucRecommendedRef_Div; | ||
| 810 | } | ||
| 811 | return ss; | ||
| 812 | } | ||
| 813 | |||
| 774 | union lvds_info { | 814 | union lvds_info { |
| 775 | struct _ATOM_LVDS_INFO info; | 815 | struct _ATOM_LVDS_INFO info; |
| 776 | struct _ATOM_LVDS_INFO_V12 info_12; | 816 | struct _ATOM_LVDS_INFO_V12 info_12; |
| @@ -826,6 +866,8 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct | |||
| 826 | /* set crtc values */ | 866 | /* set crtc values */ |
| 827 | drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V); | 867 | drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V); |
| 828 | 868 | ||
| 869 | lvds->ss = radeon_atombios_get_ss_info(encoder, lvds_info->info.ucSS_Id); | ||
| 870 | |||
| 829 | encoder->native_mode = lvds->native_mode; | 871 | encoder->native_mode = lvds->native_mode; |
| 830 | } | 872 | } |
| 831 | return lvds; | 873 | return lvds; |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index b6868fbe7346..2ea5707c018c 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
| @@ -260,6 +260,16 @@ struct radeon_encoder_int_tmds { | |||
| 260 | struct radeon_tmds_pll tmds_pll[4]; | 260 | struct radeon_tmds_pll tmds_pll[4]; |
| 261 | }; | 261 | }; |
| 262 | 262 | ||
| 263 | /* spread spectrum */ | ||
| 264 | struct radeon_atom_ss { | ||
| 265 | uint16_t percentage; | ||
| 266 | uint8_t type; | ||
| 267 | uint8_t step; | ||
| 268 | uint8_t delay; | ||
| 269 | uint8_t range; | ||
| 270 | uint8_t refdiv; | ||
| 271 | }; | ||
| 272 | |||
| 263 | struct radeon_encoder_atom_dig { | 273 | struct radeon_encoder_atom_dig { |
| 264 | /* atom dig */ | 274 | /* atom dig */ |
| 265 | bool coherent_mode; | 275 | bool coherent_mode; |
| @@ -267,6 +277,7 @@ struct radeon_encoder_atom_dig { | |||
| 267 | /* atom lvds */ | 277 | /* atom lvds */ |
| 268 | uint32_t lvds_misc; | 278 | uint32_t lvds_misc; |
| 269 | uint16_t panel_pwr_delay; | 279 | uint16_t panel_pwr_delay; |
| 280 | struct radeon_atom_ss *ss; | ||
| 270 | /* panel mode */ | 281 | /* panel mode */ |
| 271 | struct drm_display_mode native_mode; | 282 | struct drm_display_mode native_mode; |
| 272 | }; | 283 | }; |
