aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/atombios_crtc.c
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2011-05-20 04:34:16 -0400
committerDave Airlie <airlied@redhat.com>2011-05-20 06:02:21 -0400
commit8e8e523d865490e95ed7c9d2e173c02648d6be90 (patch)
treecfab46ff01a706afd4b21558ee879e433b071cbf /drivers/gpu/drm/radeon/atombios_crtc.c
parentdf271bec805b42527d864777ed035fcbb42e76c0 (diff)
drm/radeon/kms: spread spectrum fixes
- properly mask the ss type - don't enable ss if type is external or percentage is 0 - if ss enabled and type is external, set ref_div_src to ext clock - prefer ASIC_INTERNAL_SS_ON_DP to LCD_Info SS_Id for eDP - fix ss amount calculation 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.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 608b1c20a768..ff0d1cad1012 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -420,7 +420,7 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc,
420 420
421 if (ASIC_IS_DCE5(rdev)) { 421 if (ASIC_IS_DCE5(rdev)) {
422 args.v3.usSpreadSpectrumAmountFrac = cpu_to_le16(0); 422 args.v3.usSpreadSpectrumAmountFrac = cpu_to_le16(0);
423 args.v3.ucSpreadSpectrumType = ss->type; 423 args.v3.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;
424 switch (pll_id) { 424 switch (pll_id) {
425 case ATOM_PPLL1: 425 case ATOM_PPLL1:
426 args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P1PLL; 426 args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P1PLL;
@@ -441,9 +441,11 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc,
441 return; 441 return;
442 } 442 }
443 args.v2.ucEnable = enable; 443 args.v2.ucEnable = enable;
444 if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK))
445 args.v3.ucEnable = ATOM_DISABLE;
444 } else if (ASIC_IS_DCE4(rdev)) { 446 } else if (ASIC_IS_DCE4(rdev)) {
445 args.v2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); 447 args.v2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
446 args.v2.ucSpreadSpectrumType = ss->type; 448 args.v2.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;
447 switch (pll_id) { 449 switch (pll_id) {
448 case ATOM_PPLL1: 450 case ATOM_PPLL1:
449 args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P1PLL; 451 args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P1PLL;
@@ -464,32 +466,36 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc,
464 return; 466 return;
465 } 467 }
466 args.v2.ucEnable = enable; 468 args.v2.ucEnable = enable;
469 if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK))
470 args.v2.ucEnable = ATOM_DISABLE;
467 } else if (ASIC_IS_DCE3(rdev)) { 471 } else if (ASIC_IS_DCE3(rdev)) {
468 args.v1.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); 472 args.v1.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
469 args.v1.ucSpreadSpectrumType = ss->type; 473 args.v1.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;
470 args.v1.ucSpreadSpectrumStep = ss->step; 474 args.v1.ucSpreadSpectrumStep = ss->step;
471 args.v1.ucSpreadSpectrumDelay = ss->delay; 475 args.v1.ucSpreadSpectrumDelay = ss->delay;
472 args.v1.ucSpreadSpectrumRange = ss->range; 476 args.v1.ucSpreadSpectrumRange = ss->range;
473 args.v1.ucPpll = pll_id; 477 args.v1.ucPpll = pll_id;
474 args.v1.ucEnable = enable; 478 args.v1.ucEnable = enable;
475 } else if (ASIC_IS_AVIVO(rdev)) { 479 } else if (ASIC_IS_AVIVO(rdev)) {
476 if (enable == ATOM_DISABLE) { 480 if ((enable == ATOM_DISABLE) || (ss->percentage == 0) ||
481 (ss->type & ATOM_EXTERNAL_SS_MASK)) {
477 atombios_disable_ss(crtc); 482 atombios_disable_ss(crtc);
478 return; 483 return;
479 } 484 }
480 args.lvds_ss_2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); 485 args.lvds_ss_2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
481 args.lvds_ss_2.ucSpreadSpectrumType = ss->type; 486 args.lvds_ss_2.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;
482 args.lvds_ss_2.ucSpreadSpectrumStep = ss->step; 487 args.lvds_ss_2.ucSpreadSpectrumStep = ss->step;
483 args.lvds_ss_2.ucSpreadSpectrumDelay = ss->delay; 488 args.lvds_ss_2.ucSpreadSpectrumDelay = ss->delay;
484 args.lvds_ss_2.ucSpreadSpectrumRange = ss->range; 489 args.lvds_ss_2.ucSpreadSpectrumRange = ss->range;
485 args.lvds_ss_2.ucEnable = enable; 490 args.lvds_ss_2.ucEnable = enable;
486 } else { 491 } else {
487 if (enable == ATOM_DISABLE) { 492 if ((enable == ATOM_DISABLE) || (ss->percentage == 0) ||
493 (ss->type & ATOM_EXTERNAL_SS_MASK)) {
488 atombios_disable_ss(crtc); 494 atombios_disable_ss(crtc);
489 return; 495 return;
490 } 496 }
491 args.lvds_ss.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); 497 args.lvds_ss.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
492 args.lvds_ss.ucSpreadSpectrumType = ss->type; 498 args.lvds_ss.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;
493 args.lvds_ss.ucSpreadSpectrumStepSize_Delay = (ss->step & 3) << 2; 499 args.lvds_ss.ucSpreadSpectrumStepSize_Delay = (ss->step & 3) << 2;
494 args.lvds_ss.ucSpreadSpectrumStepSize_Delay |= (ss->delay & 7) << 4; 500 args.lvds_ss.ucSpreadSpectrumStepSize_Delay |= (ss->delay & 7) << 4;
495 args.lvds_ss.ucEnable = enable; 501 args.lvds_ss.ucEnable = enable;
@@ -615,7 +621,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
615 args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); 621 args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
616 args.v1.ucTransmitterID = radeon_encoder->encoder_id; 622 args.v1.ucTransmitterID = radeon_encoder->encoder_id;
617 args.v1.ucEncodeMode = encoder_mode; 623 args.v1.ucEncodeMode = encoder_mode;
618 if (ss_enabled) 624 if (ss_enabled && ss->percentage)
619 args.v1.ucConfig |= 625 args.v1.ucConfig |=
620 ADJUST_DISPLAY_CONFIG_SS_ENABLE; 626 ADJUST_DISPLAY_CONFIG_SS_ENABLE;
621 627
@@ -628,7 +634,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
628 args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id; 634 args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id;
629 args.v3.sInput.ucEncodeMode = encoder_mode; 635 args.v3.sInput.ucEncodeMode = encoder_mode;
630 args.v3.sInput.ucDispPllConfig = 0; 636 args.v3.sInput.ucDispPllConfig = 0;
631 if (ss_enabled) 637 if (ss_enabled && ss->percentage)
632 args.v3.sInput.ucDispPllConfig |= 638 args.v3.sInput.ucDispPllConfig |=
633 DISPPLL_CONFIG_SS_ENABLE; 639 DISPPLL_CONFIG_SS_ENABLE;
634 if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { 640 if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
@@ -758,7 +764,9 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc,
758 u32 fb_div, 764 u32 fb_div,
759 u32 frac_fb_div, 765 u32 frac_fb_div,
760 u32 post_div, 766 u32 post_div,
761 int bpc) 767 int bpc,
768 bool ss_enabled,
769 struct radeon_atom_ss *ss)
762{ 770{
763 struct drm_device *dev = crtc->dev; 771 struct drm_device *dev = crtc->dev;
764 struct radeon_device *rdev = dev->dev_private; 772 struct radeon_device *rdev = dev->dev_private;
@@ -816,6 +824,8 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc,
816 args.v5.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000); 824 args.v5.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000);
817 args.v5.ucPostDiv = post_div; 825 args.v5.ucPostDiv = post_div;
818 args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */ 826 args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */
827 if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))
828 args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_REF_DIV_SRC;
819 switch (bpc) { 829 switch (bpc) {
820 case 8: 830 case 8:
821 default: 831 default:
@@ -837,6 +847,8 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc,
837 args.v6.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000); 847 args.v6.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000);
838 args.v6.ucPostDiv = post_div; 848 args.v6.ucPostDiv = post_div;
839 args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */ 849 args.v6.ucMiscInfo = 0; /* HDMI depth, etc. */
850 if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))
851 args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
840 switch (bpc) { 852 switch (bpc) {
841 case 8: 853 case 8:
842 default: 854 default:
@@ -927,12 +939,18 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
927 /* DP/eDP */ 939 /* DP/eDP */
928 dp_clock = dig_connector->dp_clock / 10; 940 dp_clock = dig_connector->dp_clock / 10;
929 if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) { 941 if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
930 if (ASIC_IS_DCE4(rdev)) 942 if (ASIC_IS_DCE4(rdev)) {
943 /* first try ASIC_INTERNAL_SS_ON_DP */
931 ss_enabled = 944 ss_enabled =
932 radeon_atombios_get_asic_ss_info(rdev, &ss, 945 radeon_atombios_get_asic_ss_info(rdev, &ss,
933 dig->lcd_ss_id, 946 ASIC_INTERNAL_SS_ON_DP,
934 dp_clock); 947 dp_clock);
935 else 948 if (!ss_enabled)
949 ss_enabled =
950 radeon_atombios_get_asic_ss_info(rdev, &ss,
951 dig->lcd_ss_id,
952 dp_clock);
953 } else
936 ss_enabled = 954 ss_enabled =
937 radeon_atombios_get_ppll_ss_info(rdev, &ss, 955 radeon_atombios_get_ppll_ss_info(rdev, &ss,
938 dig->lcd_ss_id); 956 dig->lcd_ss_id);
@@ -1004,7 +1022,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
1004 1022
1005 atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, 1023 atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,
1006 encoder_mode, radeon_encoder->encoder_id, mode->clock, 1024 encoder_mode, radeon_encoder->encoder_id, mode->clock,
1007 ref_div, fb_div, frac_fb_div, post_div, bpc); 1025 ref_div, fb_div, frac_fb_div, post_div, bpc, ss_enabled, &ss);
1008 1026
1009 if (ss_enabled) { 1027 if (ss_enabled) {
1010 /* calculate ss amount and step size */ 1028 /* calculate ss amount and step size */
@@ -1012,7 +1030,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
1012 u32 step_size; 1030 u32 step_size;
1013 u32 amount = (((fb_div * 10) + frac_fb_div) * ss.percentage) / 10000; 1031 u32 amount = (((fb_div * 10) + frac_fb_div) * ss.percentage) / 10000;
1014 ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK; 1032 ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK;
1015 ss.amount |= ((amount - (ss.amount * 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) & 1033 ss.amount |= ((amount - (amount / 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
1016 ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK; 1034 ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK;
1017 if (ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD) 1035 if (ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD)
1018 step_size = (4 * amount * ref_div * (ss.rate * 2048)) / 1036 step_size = (4 * amount * ref_div * (ss.rate * 2048)) /
@@ -1545,6 +1563,8 @@ static void atombios_crtc_commit(struct drm_crtc *crtc)
1545static void atombios_crtc_disable(struct drm_crtc *crtc) 1563static void atombios_crtc_disable(struct drm_crtc *crtc)
1546{ 1564{
1547 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 1565 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1566 struct radeon_atom_ss ss;
1567
1548 atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 1568 atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
1549 1569
1550 switch (radeon_crtc->pll_id) { 1570 switch (radeon_crtc->pll_id) {
@@ -1552,7 +1572,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
1552 case ATOM_PPLL2: 1572 case ATOM_PPLL2:
1553 /* disable the ppll */ 1573 /* disable the ppll */
1554 atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, 1574 atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,
1555 0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0); 1575 0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss);
1556 break; 1576 break;
1557 default: 1577 default:
1558 break; 1578 break;