aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2010-06-11 17:58:38 -0400
committerDave Airlie <airlied@redhat.com>2010-07-20 21:27:21 -0400
commit37f9003bd355d9109769fff66f7f228aab42155b (patch)
treef25cfac28c99937596a5a6fcdcaebe076a589c71 /drivers/gpu
parent90c1efdd121c84ee73e9960667229a662f2315a3 (diff)
drm/radeon/kms/atom: add crtc disable function
Disables the crts as per dpms and also disables the ppll associated with the crtc. This should save additional power. Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c152
1 files changed, 96 insertions, 56 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 8c2d6478a221..a22d5a3bca4e 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -669,56 +669,25 @@ static void atombios_crtc_set_dcpll(struct drm_crtc *crtc)
669 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 669 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
670} 670}
671 671
672static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) 672static void atombios_crtc_program_pll(struct drm_crtc *crtc,
673 int crtc_id,
674 int pll_id,
675 u32 encoder_mode,
676 u32 encoder_id,
677 u32 clock,
678 u32 ref_div,
679 u32 fb_div,
680 u32 frac_fb_div,
681 u32 post_div)
673{ 682{
674 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
675 struct drm_device *dev = crtc->dev; 683 struct drm_device *dev = crtc->dev;
676 struct radeon_device *rdev = dev->dev_private; 684 struct radeon_device *rdev = dev->dev_private;
677 struct drm_encoder *encoder = NULL;
678 struct radeon_encoder *radeon_encoder = NULL;
679 u8 frev, crev; 685 u8 frev, crev;
680 int index; 686 int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
681 union set_pixel_clock args; 687 union set_pixel_clock args;
682 u32 pll_clock = mode->clock;
683 u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
684 struct radeon_pll *pll;
685 u32 adjusted_clock;
686 int encoder_mode = 0;
687 688
688 memset(&args, 0, sizeof(args)); 689 memset(&args, 0, sizeof(args));
689 690
690 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
691 if (encoder->crtc == crtc) {
692 radeon_encoder = to_radeon_encoder(encoder);
693 encoder_mode = atombios_get_encoder_mode(encoder);
694 break;
695 }
696 }
697
698 if (!radeon_encoder)
699 return;
700
701 switch (radeon_crtc->pll_id) {
702 case ATOM_PPLL1:
703 pll = &rdev->clock.p1pll;
704 break;
705 case ATOM_PPLL2:
706 pll = &rdev->clock.p2pll;
707 break;
708 case ATOM_DCPLL:
709 case ATOM_PPLL_INVALID:
710 default:
711 pll = &rdev->clock.dcpll;
712 break;
713 }
714
715 /* adjust pixel clock as needed */
716 adjusted_clock = atombios_adjust_pll(crtc, mode, pll);
717
718 radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
719 &ref_div, &post_div);
720
721 index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
722 if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, 691 if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
723 &crev)) 692 &crev))
724 return; 693 return;
@@ -727,47 +696,49 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
727 case 1: 696 case 1:
728 switch (crev) { 697 switch (crev) {
729 case 1: 698 case 1:
730 args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); 699 if (clock == ATOM_DISABLE)
700 return;
701 args.v1.usPixelClock = cpu_to_le16(clock / 10);
731 args.v1.usRefDiv = cpu_to_le16(ref_div); 702 args.v1.usRefDiv = cpu_to_le16(ref_div);
732 args.v1.usFbDiv = cpu_to_le16(fb_div); 703 args.v1.usFbDiv = cpu_to_le16(fb_div);
733 args.v1.ucFracFbDiv = frac_fb_div; 704 args.v1.ucFracFbDiv = frac_fb_div;
734 args.v1.ucPostDiv = post_div; 705 args.v1.ucPostDiv = post_div;
735 args.v1.ucPpll = radeon_crtc->pll_id; 706 args.v1.ucPpll = pll_id;
736 args.v1.ucCRTC = radeon_crtc->crtc_id; 707 args.v1.ucCRTC = crtc_id;
737 args.v1.ucRefDivSrc = 1; 708 args.v1.ucRefDivSrc = 1;
738 break; 709 break;
739 case 2: 710 case 2:
740 args.v2.usPixelClock = cpu_to_le16(mode->clock / 10); 711 args.v2.usPixelClock = cpu_to_le16(clock / 10);
741 args.v2.usRefDiv = cpu_to_le16(ref_div); 712 args.v2.usRefDiv = cpu_to_le16(ref_div);
742 args.v2.usFbDiv = cpu_to_le16(fb_div); 713 args.v2.usFbDiv = cpu_to_le16(fb_div);
743 args.v2.ucFracFbDiv = frac_fb_div; 714 args.v2.ucFracFbDiv = frac_fb_div;
744 args.v2.ucPostDiv = post_div; 715 args.v2.ucPostDiv = post_div;
745 args.v2.ucPpll = radeon_crtc->pll_id; 716 args.v2.ucPpll = pll_id;
746 args.v2.ucCRTC = radeon_crtc->crtc_id; 717 args.v2.ucCRTC = crtc_id;
747 args.v2.ucRefDivSrc = 1; 718 args.v2.ucRefDivSrc = 1;
748 break; 719 break;
749 case 3: 720 case 3:
750 args.v3.usPixelClock = cpu_to_le16(mode->clock / 10); 721 args.v3.usPixelClock = cpu_to_le16(clock / 10);
751 args.v3.usRefDiv = cpu_to_le16(ref_div); 722 args.v3.usRefDiv = cpu_to_le16(ref_div);
752 args.v3.usFbDiv = cpu_to_le16(fb_div); 723 args.v3.usFbDiv = cpu_to_le16(fb_div);
753 args.v3.ucFracFbDiv = frac_fb_div; 724 args.v3.ucFracFbDiv = frac_fb_div;
754 args.v3.ucPostDiv = post_div; 725 args.v3.ucPostDiv = post_div;
755 args.v3.ucPpll = radeon_crtc->pll_id; 726 args.v3.ucPpll = pll_id;
756 args.v3.ucMiscInfo = (radeon_crtc->pll_id << 2); 727 args.v3.ucMiscInfo = (pll_id << 2);
757 args.v3.ucTransmitterId = radeon_encoder->encoder_id; 728 args.v3.ucTransmitterId = encoder_id;
758 args.v3.ucEncoderMode = encoder_mode; 729 args.v3.ucEncoderMode = encoder_mode;
759 break; 730 break;
760 case 5: 731 case 5:
761 args.v5.ucCRTC = radeon_crtc->crtc_id; 732 args.v5.ucCRTC = crtc_id;
762 args.v5.usPixelClock = cpu_to_le16(mode->clock / 10); 733 args.v5.usPixelClock = cpu_to_le16(clock / 10);
763 args.v5.ucRefDiv = ref_div; 734 args.v5.ucRefDiv = ref_div;
764 args.v5.usFbDiv = cpu_to_le16(fb_div); 735 args.v5.usFbDiv = cpu_to_le16(fb_div);
765 args.v5.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000); 736 args.v5.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000);
766 args.v5.ucPostDiv = post_div; 737 args.v5.ucPostDiv = post_div;
767 args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */ 738 args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */
768 args.v5.ucTransmitterID = radeon_encoder->encoder_id; 739 args.v5.ucTransmitterID = encoder_id;
769 args.v5.ucEncoderMode = encoder_mode; 740 args.v5.ucEncoderMode = encoder_mode;
770 args.v5.ucPpll = radeon_crtc->pll_id; 741 args.v5.ucPpll = pll_id;
771 break; 742 break;
772 default: 743 default:
773 DRM_ERROR("Unknown table version %d %d\n", frev, crev); 744 DRM_ERROR("Unknown table version %d %d\n", frev, crev);
@@ -782,6 +753,56 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
782 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 753 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
783} 754}
784 755
756static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
757{
758 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
759 struct drm_device *dev = crtc->dev;
760 struct radeon_device *rdev = dev->dev_private;
761 struct drm_encoder *encoder = NULL;
762 struct radeon_encoder *radeon_encoder = NULL;
763 u32 pll_clock = mode->clock;
764 u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
765 struct radeon_pll *pll;
766 u32 adjusted_clock;
767 int encoder_mode = 0;
768
769 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
770 if (encoder->crtc == crtc) {
771 radeon_encoder = to_radeon_encoder(encoder);
772 encoder_mode = atombios_get_encoder_mode(encoder);
773 break;
774 }
775 }
776
777 if (!radeon_encoder)
778 return;
779
780 switch (radeon_crtc->pll_id) {
781 case ATOM_PPLL1:
782 pll = &rdev->clock.p1pll;
783 break;
784 case ATOM_PPLL2:
785 pll = &rdev->clock.p2pll;
786 break;
787 case ATOM_DCPLL:
788 case ATOM_PPLL_INVALID:
789 default:
790 pll = &rdev->clock.dcpll;
791 break;
792 }
793
794 /* adjust pixel clock as needed */
795 adjusted_clock = atombios_adjust_pll(crtc, mode, pll);
796
797 radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
798 &ref_div, &post_div);
799
800 atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,
801 encoder_mode, radeon_encoder->encoder_id, mode->clock,
802 ref_div, fb_div, frac_fb_div, post_div);
803
804}
805
785static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y, 806static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y,
786 struct drm_framebuffer *old_fb) 807 struct drm_framebuffer *old_fb)
787{ 808{
@@ -1191,6 +1212,24 @@ static void atombios_crtc_commit(struct drm_crtc *crtc)
1191 atombios_lock_crtc(crtc, ATOM_DISABLE); 1212 atombios_lock_crtc(crtc, ATOM_DISABLE);
1192} 1213}
1193 1214
1215static void atombios_crtc_disable(struct drm_crtc *crtc)
1216{
1217 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1218 atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
1219
1220 switch (radeon_crtc->pll_id) {
1221 case ATOM_PPLL1:
1222 case ATOM_PPLL2:
1223 /* disable the ppll */
1224 atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,
1225 0, 0, ATOM_DISABLE, 0, 0, 0, 0);
1226 break;
1227 default:
1228 break;
1229 }
1230 radeon_crtc->pll_id = -1;
1231}
1232
1194static const struct drm_crtc_helper_funcs atombios_helper_funcs = { 1233static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
1195 .dpms = atombios_crtc_dpms, 1234 .dpms = atombios_crtc_dpms,
1196 .mode_fixup = atombios_crtc_mode_fixup, 1235 .mode_fixup = atombios_crtc_mode_fixup,
@@ -1199,6 +1238,7 @@ static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
1199 .prepare = atombios_crtc_prepare, 1238 .prepare = atombios_crtc_prepare,
1200 .commit = atombios_crtc_commit, 1239 .commit = atombios_crtc_commit,
1201 .load_lut = radeon_crtc_load_lut, 1240 .load_lut = radeon_crtc_load_lut,
1241 .disable = atombios_crtc_disable,
1202}; 1242};
1203 1243
1204void radeon_atombios_init_crtc(struct drm_device *dev, 1244void radeon_atombios_init_crtc(struct drm_device *dev,