diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c')
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_crtc.c | 98 |
1 files changed, 73 insertions, 25 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index dd9fdf560611..fd4ef6d18849 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -353,12 +353,55 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc, | |||
353 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 353 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
354 | } | 354 | } |
355 | 355 | ||
356 | static void atombios_disable_ss(struct drm_crtc *crtc) | ||
357 | { | ||
358 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
359 | struct drm_device *dev = crtc->dev; | ||
360 | struct radeon_device *rdev = dev->dev_private; | ||
361 | u32 ss_cntl; | ||
362 | |||
363 | if (ASIC_IS_DCE4(rdev)) { | ||
364 | switch (radeon_crtc->pll_id) { | ||
365 | case ATOM_PPLL1: | ||
366 | ss_cntl = RREG32(EVERGREEN_P1PLL_SS_CNTL); | ||
367 | ss_cntl &= ~EVERGREEN_PxPLL_SS_EN; | ||
368 | WREG32(EVERGREEN_P1PLL_SS_CNTL, ss_cntl); | ||
369 | break; | ||
370 | case ATOM_PPLL2: | ||
371 | ss_cntl = RREG32(EVERGREEN_P2PLL_SS_CNTL); | ||
372 | ss_cntl &= ~EVERGREEN_PxPLL_SS_EN; | ||
373 | WREG32(EVERGREEN_P2PLL_SS_CNTL, ss_cntl); | ||
374 | break; | ||
375 | case ATOM_DCPLL: | ||
376 | case ATOM_PPLL_INVALID: | ||
377 | return; | ||
378 | } | ||
379 | } else if (ASIC_IS_AVIVO(rdev)) { | ||
380 | switch (radeon_crtc->pll_id) { | ||
381 | case ATOM_PPLL1: | ||
382 | ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL); | ||
383 | ss_cntl &= ~1; | ||
384 | WREG32(AVIVO_P1PLL_INT_SS_CNTL, ss_cntl); | ||
385 | break; | ||
386 | case ATOM_PPLL2: | ||
387 | ss_cntl = RREG32(AVIVO_P2PLL_INT_SS_CNTL); | ||
388 | ss_cntl &= ~1; | ||
389 | WREG32(AVIVO_P2PLL_INT_SS_CNTL, ss_cntl); | ||
390 | break; | ||
391 | case ATOM_DCPLL: | ||
392 | case ATOM_PPLL_INVALID: | ||
393 | return; | ||
394 | } | ||
395 | } | ||
396 | } | ||
397 | |||
398 | |||
356 | union atom_enable_ss { | 399 | union atom_enable_ss { |
357 | ENABLE_LVDS_SS_PARAMETERS legacy; | 400 | ENABLE_LVDS_SS_PARAMETERS legacy; |
358 | ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION v1; | 401 | ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION v1; |
359 | }; | 402 | }; |
360 | 403 | ||
361 | static void atombios_set_ss(struct drm_crtc *crtc, int enable) | 404 | static void atombios_enable_ss(struct drm_crtc *crtc) |
362 | { | 405 | { |
363 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 406 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
364 | struct drm_device *dev = crtc->dev; | 407 | struct drm_device *dev = crtc->dev; |
@@ -387,9 +430,9 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable) | |||
387 | step = dig->ss->step; | 430 | step = dig->ss->step; |
388 | delay = dig->ss->delay; | 431 | delay = dig->ss->delay; |
389 | range = dig->ss->range; | 432 | range = dig->ss->range; |
390 | } else if (enable) | 433 | } else |
391 | return; | 434 | return; |
392 | } else if (enable) | 435 | } else |
393 | return; | 436 | return; |
394 | break; | 437 | break; |
395 | } | 438 | } |
@@ -406,13 +449,13 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable) | |||
406 | args.v1.ucSpreadSpectrumDelay = delay; | 449 | args.v1.ucSpreadSpectrumDelay = delay; |
407 | args.v1.ucSpreadSpectrumRange = range; | 450 | args.v1.ucSpreadSpectrumRange = range; |
408 | args.v1.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | 451 | args.v1.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; |
409 | args.v1.ucEnable = enable; | 452 | args.v1.ucEnable = ATOM_ENABLE; |
410 | } else { | 453 | } else { |
411 | args.legacy.usSpreadSpectrumPercentage = cpu_to_le16(percentage); | 454 | args.legacy.usSpreadSpectrumPercentage = cpu_to_le16(percentage); |
412 | args.legacy.ucSpreadSpectrumType = type; | 455 | args.legacy.ucSpreadSpectrumType = type; |
413 | args.legacy.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2; | 456 | args.legacy.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2; |
414 | args.legacy.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4; | 457 | args.legacy.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4; |
415 | args.legacy.ucEnable = enable; | 458 | args.legacy.ucEnable = ATOM_ENABLE; |
416 | } | 459 | } |
417 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 460 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
418 | } | 461 | } |
@@ -478,11 +521,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
478 | /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ | 521 | /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ |
479 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) | 522 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) |
480 | adjusted_clock = mode->clock * 2; | 523 | adjusted_clock = mode->clock * 2; |
481 | /* LVDS PLL quirks */ | ||
482 | if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { | ||
483 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
484 | pll->algo = dig->pll_algo; | ||
485 | } | ||
486 | } else { | 524 | } else { |
487 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) | 525 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) |
488 | pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; | 526 | pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; |
@@ -503,8 +541,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
503 | int index; | 541 | int index; |
504 | 542 | ||
505 | index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll); | 543 | index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll); |
506 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, | 544 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, |
507 | &crev); | 545 | &crev)) |
546 | return adjusted_clock; | ||
508 | 547 | ||
509 | memset(&args, 0, sizeof(args)); | 548 | memset(&args, 0, sizeof(args)); |
510 | 549 | ||
@@ -542,11 +581,16 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
542 | } | 581 | } |
543 | } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | 582 | } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { |
544 | /* may want to enable SS on DP/eDP eventually */ | 583 | /* may want to enable SS on DP/eDP eventually */ |
545 | args.v3.sInput.ucDispPllConfig |= | 584 | /*args.v3.sInput.ucDispPllConfig |= |
546 | DISPPLL_CONFIG_SS_ENABLE; | 585 | DISPPLL_CONFIG_SS_ENABLE;*/ |
547 | if (mode->clock > 165000) | 586 | if (encoder_mode == ATOM_ENCODER_MODE_DP) |
548 | args.v3.sInput.ucDispPllConfig |= | 587 | args.v3.sInput.ucDispPllConfig |= |
549 | DISPPLL_CONFIG_DUAL_LINK; | 588 | DISPPLL_CONFIG_COHERENT_MODE; |
589 | else { | ||
590 | if (mode->clock > 165000) | ||
591 | args.v3.sInput.ucDispPllConfig |= | ||
592 | DISPPLL_CONFIG_DUAL_LINK; | ||
593 | } | ||
550 | } | 594 | } |
551 | atom_execute_table(rdev->mode_info.atom_context, | 595 | atom_execute_table(rdev->mode_info.atom_context, |
552 | index, (uint32_t *)&args); | 596 | index, (uint32_t *)&args); |
@@ -592,8 +636,9 @@ static void atombios_crtc_set_dcpll(struct drm_crtc *crtc) | |||
592 | memset(&args, 0, sizeof(args)); | 636 | memset(&args, 0, sizeof(args)); |
593 | 637 | ||
594 | index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); | 638 | index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); |
595 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, | 639 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, |
596 | &crev); | 640 | &crev)) |
641 | return; | ||
597 | 642 | ||
598 | switch (frev) { | 643 | switch (frev) { |
599 | case 1: | 644 | case 1: |
@@ -667,8 +712,9 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode | |||
667 | &ref_div, &post_div); | 712 | &ref_div, &post_div); |
668 | 713 | ||
669 | index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); | 714 | index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); |
670 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, | 715 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, |
671 | &crev); | 716 | &crev)) |
717 | return; | ||
672 | 718 | ||
673 | switch (frev) { | 719 | switch (frev) { |
674 | case 1: | 720 | case 1: |
@@ -1083,15 +1129,12 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, | |||
1083 | 1129 | ||
1084 | /* TODO color tiling */ | 1130 | /* TODO color tiling */ |
1085 | 1131 | ||
1086 | /* pick pll */ | 1132 | atombios_disable_ss(crtc); |
1087 | radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); | ||
1088 | |||
1089 | atombios_set_ss(crtc, 0); | ||
1090 | /* always set DCPLL */ | 1133 | /* always set DCPLL */ |
1091 | if (ASIC_IS_DCE4(rdev)) | 1134 | if (ASIC_IS_DCE4(rdev)) |
1092 | atombios_crtc_set_dcpll(crtc); | 1135 | atombios_crtc_set_dcpll(crtc); |
1093 | atombios_crtc_set_pll(crtc, adjusted_mode); | 1136 | atombios_crtc_set_pll(crtc, adjusted_mode); |
1094 | atombios_set_ss(crtc, 1); | 1137 | atombios_enable_ss(crtc); |
1095 | 1138 | ||
1096 | if (ASIC_IS_DCE4(rdev)) | 1139 | if (ASIC_IS_DCE4(rdev)) |
1097 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); | 1140 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); |
@@ -1120,6 +1163,11 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, | |||
1120 | 1163 | ||
1121 | static void atombios_crtc_prepare(struct drm_crtc *crtc) | 1164 | static void atombios_crtc_prepare(struct drm_crtc *crtc) |
1122 | { | 1165 | { |
1166 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
1167 | |||
1168 | /* pick pll */ | ||
1169 | radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); | ||
1170 | |||
1123 | atombios_lock_crtc(crtc, ATOM_ENABLE); | 1171 | atombios_lock_crtc(crtc, ATOM_ENABLE); |
1124 | atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); | 1172 | atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); |
1125 | } | 1173 | } |