diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2012-09-13 10:56:16 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2012-09-20 13:10:44 -0400 |
commit | 19eca43e5a52a8e47fdd40e940912b2417c7c055 (patch) | |
tree | 9ca6f599f97728f13be6f4abe81829973d1c302a /drivers | |
parent | 2f454cf1261ba913e2f660b7555864b340502c60 (diff) |
drm/radeon: rework crtc pll setup to better support PPLL sharing
We need the calculate the pixel clock before allocating a PPLL
in order to insure the clocks really match.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_crtc.c | 221 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_mode.h | 32 |
2 files changed, 150 insertions, 103 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 2f7cc9e3b175..cf8ac5a5d8ca 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -533,11 +533,9 @@ union adjust_pixel_clock { | |||
533 | }; | 533 | }; |
534 | 534 | ||
535 | static u32 atombios_adjust_pll(struct drm_crtc *crtc, | 535 | static u32 atombios_adjust_pll(struct drm_crtc *crtc, |
536 | struct drm_display_mode *mode, | 536 | struct drm_display_mode *mode) |
537 | struct radeon_pll *pll, | ||
538 | bool ss_enabled, | ||
539 | struct radeon_atom_ss *ss) | ||
540 | { | 537 | { |
538 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
541 | struct drm_device *dev = crtc->dev; | 539 | struct drm_device *dev = crtc->dev; |
542 | struct radeon_device *rdev = dev->dev_private; | 540 | struct radeon_device *rdev = dev->dev_private; |
543 | struct drm_encoder *encoder = NULL; | 541 | struct drm_encoder *encoder = NULL; |
@@ -550,32 +548,32 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
550 | bool is_duallink = false; | 548 | bool is_duallink = false; |
551 | 549 | ||
552 | /* reset the pll flags */ | 550 | /* reset the pll flags */ |
553 | pll->flags = 0; | 551 | radeon_crtc->pll_flags = 0; |
554 | 552 | ||
555 | if (ASIC_IS_AVIVO(rdev)) { | 553 | if (ASIC_IS_AVIVO(rdev)) { |
556 | if ((rdev->family == CHIP_RS600) || | 554 | if ((rdev->family == CHIP_RS600) || |
557 | (rdev->family == CHIP_RS690) || | 555 | (rdev->family == CHIP_RS690) || |
558 | (rdev->family == CHIP_RS740)) | 556 | (rdev->family == CHIP_RS740)) |
559 | pll->flags |= (/*RADEON_PLL_USE_FRAC_FB_DIV |*/ | 557 | radeon_crtc->pll_flags |= (/*RADEON_PLL_USE_FRAC_FB_DIV |*/ |
560 | RADEON_PLL_PREFER_CLOSEST_LOWER); | 558 | RADEON_PLL_PREFER_CLOSEST_LOWER); |
561 | 559 | ||
562 | if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */ | 560 | if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */ |
563 | pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; | 561 | radeon_crtc->pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; |
564 | else | 562 | else |
565 | pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; | 563 | radeon_crtc->pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; |
566 | 564 | ||
567 | if (rdev->family < CHIP_RV770) | 565 | if (rdev->family < CHIP_RV770) |
568 | pll->flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP; | 566 | radeon_crtc->pll_flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP; |
569 | /* use frac fb div on APUs */ | 567 | /* use frac fb div on APUs */ |
570 | if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) | 568 | if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) |
571 | pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV; | 569 | radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV; |
572 | } else { | 570 | } else { |
573 | pll->flags |= RADEON_PLL_LEGACY; | 571 | radeon_crtc->pll_flags |= RADEON_PLL_LEGACY; |
574 | 572 | ||
575 | if (mode->clock > 200000) /* range limits??? */ | 573 | if (mode->clock > 200000) /* range limits??? */ |
576 | pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; | 574 | radeon_crtc->pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; |
577 | else | 575 | else |
578 | pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; | 576 | radeon_crtc->pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; |
579 | } | 577 | } |
580 | 578 | ||
581 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 579 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
@@ -598,12 +596,12 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
598 | 596 | ||
599 | /* use recommended ref_div for ss */ | 597 | /* use recommended ref_div for ss */ |
600 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | 598 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { |
601 | if (ss_enabled) { | 599 | if (radeon_crtc->ss_enabled) { |
602 | if (ss->refdiv) { | 600 | if (radeon_crtc->ss.refdiv) { |
603 | pll->flags |= RADEON_PLL_USE_REF_DIV; | 601 | radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV; |
604 | pll->reference_div = ss->refdiv; | 602 | radeon_crtc->pll_reference_div = radeon_crtc->ss.refdiv; |
605 | if (ASIC_IS_AVIVO(rdev)) | 603 | if (ASIC_IS_AVIVO(rdev)) |
606 | pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV; | 604 | radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV; |
607 | } | 605 | } |
608 | } | 606 | } |
609 | } | 607 | } |
@@ -613,14 +611,14 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
613 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) | 611 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) |
614 | adjusted_clock = mode->clock * 2; | 612 | adjusted_clock = mode->clock * 2; |
615 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) | 613 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) |
616 | pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; | 614 | radeon_crtc->pll_flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; |
617 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) | 615 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) |
618 | pll->flags |= RADEON_PLL_IS_LCD; | 616 | radeon_crtc->pll_flags |= RADEON_PLL_IS_LCD; |
619 | } else { | 617 | } else { |
620 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) | 618 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) |
621 | pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; | 619 | radeon_crtc->pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; |
622 | if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) | 620 | if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) |
623 | pll->flags |= RADEON_PLL_USE_REF_DIV; | 621 | radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV; |
624 | } | 622 | } |
625 | break; | 623 | break; |
626 | } | 624 | } |
@@ -650,7 +648,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
650 | args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); | 648 | args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); |
651 | args.v1.ucTransmitterID = radeon_encoder->encoder_id; | 649 | args.v1.ucTransmitterID = radeon_encoder->encoder_id; |
652 | args.v1.ucEncodeMode = encoder_mode; | 650 | args.v1.ucEncodeMode = encoder_mode; |
653 | if (ss_enabled && ss->percentage) | 651 | if (radeon_crtc->ss_enabled && radeon_crtc->ss.percentage) |
654 | args.v1.ucConfig |= | 652 | args.v1.ucConfig |= |
655 | ADJUST_DISPLAY_CONFIG_SS_ENABLE; | 653 | ADJUST_DISPLAY_CONFIG_SS_ENABLE; |
656 | 654 | ||
@@ -663,7 +661,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
663 | args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id; | 661 | args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id; |
664 | args.v3.sInput.ucEncodeMode = encoder_mode; | 662 | args.v3.sInput.ucEncodeMode = encoder_mode; |
665 | args.v3.sInput.ucDispPllConfig = 0; | 663 | args.v3.sInput.ucDispPllConfig = 0; |
666 | if (ss_enabled && ss->percentage) | 664 | if (radeon_crtc->ss_enabled && radeon_crtc->ss.percentage) |
667 | args.v3.sInput.ucDispPllConfig |= | 665 | args.v3.sInput.ucDispPllConfig |= |
668 | DISPPLL_CONFIG_SS_ENABLE; | 666 | DISPPLL_CONFIG_SS_ENABLE; |
669 | if (ENCODER_MODE_IS_DP(encoder_mode)) { | 667 | if (ENCODER_MODE_IS_DP(encoder_mode)) { |
@@ -695,14 +693,14 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
695 | index, (uint32_t *)&args); | 693 | index, (uint32_t *)&args); |
696 | adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10; | 694 | adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10; |
697 | if (args.v3.sOutput.ucRefDiv) { | 695 | if (args.v3.sOutput.ucRefDiv) { |
698 | pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV; | 696 | radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV; |
699 | pll->flags |= RADEON_PLL_USE_REF_DIV; | 697 | radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV; |
700 | pll->reference_div = args.v3.sOutput.ucRefDiv; | 698 | radeon_crtc->pll_reference_div = args.v3.sOutput.ucRefDiv; |
701 | } | 699 | } |
702 | if (args.v3.sOutput.ucPostDiv) { | 700 | if (args.v3.sOutput.ucPostDiv) { |
703 | pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV; | 701 | radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV; |
704 | pll->flags |= RADEON_PLL_USE_POST_DIV; | 702 | radeon_crtc->pll_flags |= RADEON_PLL_USE_POST_DIV; |
705 | pll->post_div = args.v3.sOutput.ucPostDiv; | 703 | radeon_crtc->pll_post_div = args.v3.sOutput.ucPostDiv; |
706 | } | 704 | } |
707 | break; | 705 | break; |
708 | default: | 706 | default: |
@@ -910,21 +908,17 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc, | |||
910 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 908 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
911 | } | 909 | } |
912 | 910 | ||
913 | static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | 911 | static bool atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) |
914 | { | 912 | { |
915 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 913 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
916 | struct drm_device *dev = crtc->dev; | 914 | struct drm_device *dev = crtc->dev; |
917 | struct radeon_device *rdev = dev->dev_private; | 915 | struct radeon_device *rdev = dev->dev_private; |
918 | struct drm_encoder *encoder = NULL; | 916 | struct drm_encoder *encoder = NULL; |
919 | struct radeon_encoder *radeon_encoder = NULL; | 917 | struct radeon_encoder *radeon_encoder = NULL; |
920 | u32 pll_clock = mode->clock; | ||
921 | u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; | ||
922 | struct radeon_pll *pll; | ||
923 | u32 adjusted_clock; | ||
924 | int encoder_mode = 0; | 918 | int encoder_mode = 0; |
925 | struct radeon_atom_ss ss; | 919 | |
926 | bool ss_enabled = false; | 920 | radeon_crtc->bpc = 8; |
927 | int bpc = 8; | 921 | radeon_crtc->ss_enabled = false; |
928 | 922 | ||
929 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 923 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
930 | if (encoder->crtc == crtc) { | 924 | if (encoder->crtc == crtc) { |
@@ -935,21 +929,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode | |||
935 | } | 929 | } |
936 | 930 | ||
937 | if (!radeon_encoder) | 931 | if (!radeon_encoder) |
938 | return; | 932 | return false; |
939 | |||
940 | switch (radeon_crtc->pll_id) { | ||
941 | case ATOM_PPLL1: | ||
942 | pll = &rdev->clock.p1pll; | ||
943 | break; | ||
944 | case ATOM_PPLL2: | ||
945 | pll = &rdev->clock.p2pll; | ||
946 | break; | ||
947 | case ATOM_DCPLL: | ||
948 | case ATOM_PPLL_INVALID: | ||
949 | default: | ||
950 | pll = &rdev->clock.dcpll; | ||
951 | break; | ||
952 | } | ||
953 | 933 | ||
954 | if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || | 934 | if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || |
955 | (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) { | 935 | (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) { |
@@ -961,7 +941,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode | |||
961 | struct radeon_connector_atom_dig *dig_connector = | 941 | struct radeon_connector_atom_dig *dig_connector = |
962 | radeon_connector->con_priv; | 942 | radeon_connector->con_priv; |
963 | int dp_clock; | 943 | int dp_clock; |
964 | bpc = radeon_get_monitor_bpc(connector); | 944 | radeon_crtc->bpc = radeon_get_monitor_bpc(connector); |
965 | 945 | ||
966 | switch (encoder_mode) { | 946 | switch (encoder_mode) { |
967 | case ATOM_ENCODER_MODE_DP_MST: | 947 | case ATOM_ENCODER_MODE_DP_MST: |
@@ -969,45 +949,54 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode | |||
969 | /* DP/eDP */ | 949 | /* DP/eDP */ |
970 | dp_clock = dig_connector->dp_clock / 10; | 950 | dp_clock = dig_connector->dp_clock / 10; |
971 | if (ASIC_IS_DCE4(rdev)) | 951 | if (ASIC_IS_DCE4(rdev)) |
972 | ss_enabled = | 952 | radeon_crtc->ss_enabled = |
973 | radeon_atombios_get_asic_ss_info(rdev, &ss, | 953 | radeon_atombios_get_asic_ss_info(rdev, &radeon_crtc->ss, |
974 | ASIC_INTERNAL_SS_ON_DP, | 954 | ASIC_INTERNAL_SS_ON_DP, |
975 | dp_clock); | 955 | dp_clock); |
976 | else { | 956 | else { |
977 | if (dp_clock == 16200) { | 957 | if (dp_clock == 16200) { |
978 | ss_enabled = | 958 | radeon_crtc->ss_enabled = |
979 | radeon_atombios_get_ppll_ss_info(rdev, &ss, | 959 | radeon_atombios_get_ppll_ss_info(rdev, |
960 | &radeon_crtc->ss, | ||
980 | ATOM_DP_SS_ID2); | 961 | ATOM_DP_SS_ID2); |
981 | if (!ss_enabled) | 962 | if (!radeon_crtc->ss_enabled) |
982 | ss_enabled = | 963 | radeon_crtc->ss_enabled = |
983 | radeon_atombios_get_ppll_ss_info(rdev, &ss, | 964 | radeon_atombios_get_ppll_ss_info(rdev, |
965 | &radeon_crtc->ss, | ||
984 | ATOM_DP_SS_ID1); | 966 | ATOM_DP_SS_ID1); |
985 | } else | 967 | } else |
986 | ss_enabled = | 968 | radeon_crtc->ss_enabled = |
987 | radeon_atombios_get_ppll_ss_info(rdev, &ss, | 969 | radeon_atombios_get_ppll_ss_info(rdev, |
970 | &radeon_crtc->ss, | ||
988 | ATOM_DP_SS_ID1); | 971 | ATOM_DP_SS_ID1); |
989 | } | 972 | } |
990 | break; | 973 | break; |
991 | case ATOM_ENCODER_MODE_LVDS: | 974 | case ATOM_ENCODER_MODE_LVDS: |
992 | if (ASIC_IS_DCE4(rdev)) | 975 | if (ASIC_IS_DCE4(rdev)) |
993 | ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss, | 976 | radeon_crtc->ss_enabled = |
994 | dig->lcd_ss_id, | 977 | radeon_atombios_get_asic_ss_info(rdev, |
995 | mode->clock / 10); | 978 | &radeon_crtc->ss, |
979 | dig->lcd_ss_id, | ||
980 | mode->clock / 10); | ||
996 | else | 981 | else |
997 | ss_enabled = radeon_atombios_get_ppll_ss_info(rdev, &ss, | 982 | radeon_crtc->ss_enabled = |
998 | dig->lcd_ss_id); | 983 | radeon_atombios_get_ppll_ss_info(rdev, |
984 | &radeon_crtc->ss, | ||
985 | dig->lcd_ss_id); | ||
999 | break; | 986 | break; |
1000 | case ATOM_ENCODER_MODE_DVI: | 987 | case ATOM_ENCODER_MODE_DVI: |
1001 | if (ASIC_IS_DCE4(rdev)) | 988 | if (ASIC_IS_DCE4(rdev)) |
1002 | ss_enabled = | 989 | radeon_crtc->ss_enabled = |
1003 | radeon_atombios_get_asic_ss_info(rdev, &ss, | 990 | radeon_atombios_get_asic_ss_info(rdev, |
991 | &radeon_crtc->ss, | ||
1004 | ASIC_INTERNAL_SS_ON_TMDS, | 992 | ASIC_INTERNAL_SS_ON_TMDS, |
1005 | mode->clock / 10); | 993 | mode->clock / 10); |
1006 | break; | 994 | break; |
1007 | case ATOM_ENCODER_MODE_HDMI: | 995 | case ATOM_ENCODER_MODE_HDMI: |
1008 | if (ASIC_IS_DCE4(rdev)) | 996 | if (ASIC_IS_DCE4(rdev)) |
1009 | ss_enabled = | 997 | radeon_crtc->ss_enabled = |
1010 | radeon_atombios_get_asic_ss_info(rdev, &ss, | 998 | radeon_atombios_get_asic_ss_info(rdev, |
999 | &radeon_crtc->ss, | ||
1011 | ASIC_INTERNAL_SS_ON_HDMI, | 1000 | ASIC_INTERNAL_SS_ON_HDMI, |
1012 | mode->clock / 10); | 1001 | mode->clock / 10); |
1013 | break; | 1002 | break; |
@@ -1017,43 +1006,91 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode | |||
1017 | } | 1006 | } |
1018 | 1007 | ||
1019 | /* adjust pixel clock as needed */ | 1008 | /* adjust pixel clock as needed */ |
1020 | adjusted_clock = atombios_adjust_pll(crtc, mode, pll, ss_enabled, &ss); | 1009 | radeon_crtc->adjusted_clock = atombios_adjust_pll(crtc, mode); |
1010 | |||
1011 | return true; | ||
1012 | } | ||
1013 | |||
1014 | static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | ||
1015 | { | ||
1016 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
1017 | struct drm_device *dev = crtc->dev; | ||
1018 | struct radeon_device *rdev = dev->dev_private; | ||
1019 | struct drm_encoder *encoder = NULL; | ||
1020 | struct radeon_encoder *radeon_encoder = NULL; | ||
1021 | u32 pll_clock = mode->clock; | ||
1022 | u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; | ||
1023 | struct radeon_pll *pll; | ||
1024 | int encoder_mode = 0; | ||
1025 | |||
1026 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
1027 | if (encoder->crtc == crtc) { | ||
1028 | radeon_encoder = to_radeon_encoder(encoder); | ||
1029 | encoder_mode = atombios_get_encoder_mode(encoder); | ||
1030 | break; | ||
1031 | } | ||
1032 | } | ||
1033 | |||
1034 | if (!radeon_encoder) | ||
1035 | return; | ||
1036 | |||
1037 | switch (radeon_crtc->pll_id) { | ||
1038 | case ATOM_PPLL1: | ||
1039 | pll = &rdev->clock.p1pll; | ||
1040 | break; | ||
1041 | case ATOM_PPLL2: | ||
1042 | pll = &rdev->clock.p2pll; | ||
1043 | break; | ||
1044 | case ATOM_DCPLL: | ||
1045 | case ATOM_PPLL_INVALID: | ||
1046 | default: | ||
1047 | pll = &rdev->clock.dcpll; | ||
1048 | break; | ||
1049 | } | ||
1050 | |||
1051 | /* update pll params */ | ||
1052 | pll->flags = radeon_crtc->pll_flags; | ||
1053 | pll->reference_div = radeon_crtc->pll_reference_div; | ||
1054 | pll->post_div = radeon_crtc->pll_post_div; | ||
1021 | 1055 | ||
1022 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) | 1056 | if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) |
1023 | /* TV seems to prefer the legacy algo on some boards */ | 1057 | /* TV seems to prefer the legacy algo on some boards */ |
1024 | radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, | 1058 | radeon_compute_pll_legacy(pll, radeon_crtc->adjusted_clock, &pll_clock, |
1025 | &ref_div, &post_div); | 1059 | &fb_div, &frac_fb_div, &ref_div, &post_div); |
1026 | else if (ASIC_IS_AVIVO(rdev)) | 1060 | else if (ASIC_IS_AVIVO(rdev)) |
1027 | radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, | 1061 | radeon_compute_pll_avivo(pll, radeon_crtc->adjusted_clock, &pll_clock, |
1028 | &ref_div, &post_div); | 1062 | &fb_div, &frac_fb_div, &ref_div, &post_div); |
1029 | else | 1063 | else |
1030 | radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, | 1064 | radeon_compute_pll_legacy(pll, radeon_crtc->adjusted_clock, &pll_clock, |
1031 | &ref_div, &post_div); | 1065 | &fb_div, &frac_fb_div, &ref_div, &post_div); |
1032 | 1066 | ||
1033 | atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss); | 1067 | atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, |
1068 | radeon_crtc->crtc_id, &radeon_crtc->ss); | ||
1034 | 1069 | ||
1035 | atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, | 1070 | atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, |
1036 | encoder_mode, radeon_encoder->encoder_id, mode->clock, | 1071 | encoder_mode, radeon_encoder->encoder_id, mode->clock, |
1037 | ref_div, fb_div, frac_fb_div, post_div, bpc, ss_enabled, &ss); | 1072 | ref_div, fb_div, frac_fb_div, post_div, |
1073 | radeon_crtc->bpc, radeon_crtc->ss_enabled, &radeon_crtc->ss); | ||
1038 | 1074 | ||
1039 | if (ss_enabled) { | 1075 | if (radeon_crtc->ss_enabled) { |
1040 | /* calculate ss amount and step size */ | 1076 | /* calculate ss amount and step size */ |
1041 | if (ASIC_IS_DCE4(rdev)) { | 1077 | if (ASIC_IS_DCE4(rdev)) { |
1042 | u32 step_size; | 1078 | u32 step_size; |
1043 | u32 amount = (((fb_div * 10) + frac_fb_div) * ss.percentage) / 10000; | 1079 | u32 amount = (((fb_div * 10) + frac_fb_div) * radeon_crtc->ss.percentage) / 10000; |
1044 | ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK; | 1080 | radeon_crtc->ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK; |
1045 | ss.amount |= ((amount - (amount / 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) & | 1081 | radeon_crtc->ss.amount |= ((amount - (amount / 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) & |
1046 | ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK; | 1082 | ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK; |
1047 | if (ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD) | 1083 | if (radeon_crtc->ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD) |
1048 | step_size = (4 * amount * ref_div * (ss.rate * 2048)) / | 1084 | step_size = (4 * amount * ref_div * (radeon_crtc->ss.rate * 2048)) / |
1049 | (125 * 25 * pll->reference_freq / 100); | 1085 | (125 * 25 * pll->reference_freq / 100); |
1050 | else | 1086 | else |
1051 | step_size = (2 * amount * ref_div * (ss.rate * 2048)) / | 1087 | step_size = (2 * amount * ref_div * (radeon_crtc->ss.rate * 2048)) / |
1052 | (125 * 25 * pll->reference_freq / 100); | 1088 | (125 * 25 * pll->reference_freq / 100); |
1053 | ss.step = step_size; | 1089 | radeon_crtc->ss.step = step_size; |
1054 | } | 1090 | } |
1055 | 1091 | ||
1056 | atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss); | 1092 | atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, |
1093 | radeon_crtc->crtc_id, &radeon_crtc->ss); | ||
1057 | } | 1094 | } |
1058 | } | 1095 | } |
1059 | 1096 | ||
@@ -1809,6 +1846,8 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, | |||
1809 | { | 1846 | { |
1810 | if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) | 1847 | if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) |
1811 | return false; | 1848 | return false; |
1849 | if (!atombios_crtc_prepare_pll(crtc, adjusted_mode)) | ||
1850 | return false; | ||
1812 | return true; | 1851 | return true; |
1813 | } | 1852 | } |
1814 | 1853 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 5005057974b1..9f45e4bf06e9 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -282,6 +282,18 @@ struct radeon_tv_regs { | |||
282 | uint16_t v_code_timing[MAX_V_CODE_TIMING_LEN]; | 282 | uint16_t v_code_timing[MAX_V_CODE_TIMING_LEN]; |
283 | }; | 283 | }; |
284 | 284 | ||
285 | struct radeon_atom_ss { | ||
286 | uint16_t percentage; | ||
287 | uint8_t type; | ||
288 | uint16_t step; | ||
289 | uint8_t delay; | ||
290 | uint8_t range; | ||
291 | uint8_t refdiv; | ||
292 | /* asic_ss */ | ||
293 | uint16_t rate; | ||
294 | uint16_t amount; | ||
295 | }; | ||
296 | |||
285 | struct radeon_crtc { | 297 | struct radeon_crtc { |
286 | struct drm_crtc base; | 298 | struct drm_crtc base; |
287 | int crtc_id; | 299 | int crtc_id; |
@@ -306,6 +318,14 @@ struct radeon_crtc { | |||
306 | /* page flipping */ | 318 | /* page flipping */ |
307 | struct radeon_unpin_work *unpin_work; | 319 | struct radeon_unpin_work *unpin_work; |
308 | int deferred_flip_completion; | 320 | int deferred_flip_completion; |
321 | /* pll sharing */ | ||
322 | struct radeon_atom_ss ss; | ||
323 | bool ss_enabled; | ||
324 | u32 adjusted_clock; | ||
325 | int bpc; | ||
326 | u32 pll_reference_div; | ||
327 | u32 pll_post_div; | ||
328 | u32 pll_flags; | ||
309 | }; | 329 | }; |
310 | 330 | ||
311 | struct radeon_encoder_primary_dac { | 331 | struct radeon_encoder_primary_dac { |
@@ -359,18 +379,6 @@ struct radeon_encoder_ext_tmds { | |||
359 | }; | 379 | }; |
360 | 380 | ||
361 | /* spread spectrum */ | 381 | /* spread spectrum */ |
362 | struct radeon_atom_ss { | ||
363 | uint16_t percentage; | ||
364 | uint8_t type; | ||
365 | uint16_t step; | ||
366 | uint8_t delay; | ||
367 | uint8_t range; | ||
368 | uint8_t refdiv; | ||
369 | /* asic_ss */ | ||
370 | uint16_t rate; | ||
371 | uint16_t amount; | ||
372 | }; | ||
373 | |||
374 | struct radeon_encoder_atom_dig { | 382 | struct radeon_encoder_atom_dig { |
375 | bool linkb; | 383 | bool linkb; |
376 | /* atom dig */ | 384 | /* atom dig */ |