aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/atombios_crtc.c
diff options
context:
space:
mode:
authorJerome Glisse <jglisse@redhat.com>2009-07-13 15:04:08 -0400
committerDave Airlie <airlied@redhat.com>2009-07-29 01:45:09 -0400
commitc93bb85b5cba3e3a06f2cad8e9bc5c23d3d10aac (patch)
tree3168bee69e08dcb1f0f509b03ea1693a688d34ef /drivers/gpu/drm/radeon/atombios_crtc.c
parente024e11070a0a0dc7163ce1ec2da354a638bdbed (diff)
drm/radeon/kms: fix bandwidth computation on avivo hardware
Fix bandwidth computation and crtc priority in memory controller so that crtc memory request are fullfill in time to avoid display artifact. Signed-off-by: Jerome Glisse <jglisse@redhat.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.c276
1 files changed, 131 insertions, 145 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index eac26cdb5dae..74d034f77c6b 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -31,6 +31,132 @@
31#include "atom.h" 31#include "atom.h"
32#include "atom-bits.h" 32#include "atom-bits.h"
33 33
34static void atombios_overscan_setup(struct drm_crtc *crtc,
35 struct drm_display_mode *mode,
36 struct drm_display_mode *adjusted_mode)
37{
38 struct drm_device *dev = crtc->dev;
39 struct radeon_device *rdev = dev->dev_private;
40 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
41 SET_CRTC_OVERSCAN_PS_ALLOCATION args;
42 int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
43 int a1, a2;
44
45 memset(&args, 0, sizeof(args));
46
47 args.usOverscanRight = 0;
48 args.usOverscanLeft = 0;
49 args.usOverscanBottom = 0;
50 args.usOverscanTop = 0;
51 args.ucCRTC = radeon_crtc->crtc_id;
52
53 switch (radeon_crtc->rmx_type) {
54 case RMX_CENTER:
55 args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
56 args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
57 args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
58 args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
59 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
60 break;
61 case RMX_ASPECT:
62 a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay;
63 a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay;
64
65 if (a1 > a2) {
66 args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
67 args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
68 } else if (a2 > a1) {
69 args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
70 args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
71 }
72 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
73 break;
74 case RMX_FULL:
75 default:
76 args.usOverscanRight = 0;
77 args.usOverscanLeft = 0;
78 args.usOverscanBottom = 0;
79 args.usOverscanTop = 0;
80 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
81 break;
82 }
83}
84
85static void atombios_scaler_setup(struct drm_crtc *crtc)
86{
87 struct drm_device *dev = crtc->dev;
88 struct radeon_device *rdev = dev->dev_private;
89 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
90 ENABLE_SCALER_PS_ALLOCATION args;
91 int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
92 /* fixme - fill in enc_priv for atom dac */
93 enum radeon_tv_std tv_std = TV_STD_NTSC;
94
95 if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id)
96 return;
97
98 memset(&args, 0, sizeof(args));
99
100 args.ucScaler = radeon_crtc->crtc_id;
101
102 if (radeon_crtc->devices & (ATOM_DEVICE_TV_SUPPORT)) {
103 switch (tv_std) {
104 case TV_STD_NTSC:
105 default:
106 args.ucTVStandard = ATOM_TV_NTSC;
107 break;
108 case TV_STD_PAL:
109 args.ucTVStandard = ATOM_TV_PAL;
110 break;
111 case TV_STD_PAL_M:
112 args.ucTVStandard = ATOM_TV_PALM;
113 break;
114 case TV_STD_PAL_60:
115 args.ucTVStandard = ATOM_TV_PAL60;
116 break;
117 case TV_STD_NTSC_J:
118 args.ucTVStandard = ATOM_TV_NTSCJ;
119 break;
120 case TV_STD_SCART_PAL:
121 args.ucTVStandard = ATOM_TV_PAL; /* ??? */
122 break;
123 case TV_STD_SECAM:
124 args.ucTVStandard = ATOM_TV_SECAM;
125 break;
126 case TV_STD_PAL_CN:
127 args.ucTVStandard = ATOM_TV_PALCN;
128 break;
129 }
130 args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
131 } else if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT)) {
132 args.ucTVStandard = ATOM_TV_CV;
133 args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
134 } else {
135 switch (radeon_crtc->rmx_type) {
136 case RMX_FULL:
137 args.ucEnable = ATOM_SCALER_EXPANSION;
138 break;
139 case RMX_CENTER:
140 args.ucEnable = ATOM_SCALER_CENTER;
141 break;
142 case RMX_ASPECT:
143 args.ucEnable = ATOM_SCALER_EXPANSION;
144 break;
145 default:
146 if (ASIC_IS_AVIVO(rdev))
147 args.ucEnable = ATOM_SCALER_DISABLE;
148 else
149 args.ucEnable = ATOM_SCALER_CENTER;
150 break;
151 }
152 }
153 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
154 if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)
155 && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_RV570) {
156 atom_rv515_force_tv_scaler(rdev);
157 }
158}
159
34static void atombios_lock_crtc(struct drm_crtc *crtc, int lock) 160static void atombios_lock_crtc(struct drm_crtc *crtc, int lock)
35{ 161{
36 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 162 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
@@ -522,6 +648,9 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
522 radeon_crtc_set_base(crtc, x, y, old_fb); 648 radeon_crtc_set_base(crtc, x, y, old_fb);
523 radeon_legacy_atom_set_surface(crtc); 649 radeon_legacy_atom_set_surface(crtc);
524 } 650 }
651 atombios_overscan_setup(crtc, mode, adjusted_mode);
652 atombios_scaler_setup(crtc);
653 radeon_bandwidth_update(rdev);
525 return 0; 654 return 0;
526} 655}
527 656
@@ -529,6 +658,8 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
529 struct drm_display_mode *mode, 658 struct drm_display_mode *mode,
530 struct drm_display_mode *adjusted_mode) 659 struct drm_display_mode *adjusted_mode)
531{ 660{
661 if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
662 return false;
532 return true; 663 return true;
533} 664}
534 665
@@ -561,148 +692,3 @@ void radeon_atombios_init_crtc(struct drm_device *dev,
561 AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL; 692 AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
562 drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); 693 drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
563} 694}
564
565void radeon_init_disp_bw_avivo(struct drm_device *dev,
566 struct drm_display_mode *mode1,
567 uint32_t pixel_bytes1,
568 struct drm_display_mode *mode2,
569 uint32_t pixel_bytes2)
570{
571 struct radeon_device *rdev = dev->dev_private;
572 fixed20_12 min_mem_eff;
573 fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff;
574 fixed20_12 sclk_ff, mclk_ff;
575 uint32_t dc_lb_memory_split, temp;
576
577 min_mem_eff.full = rfixed_const_8(0);
578 if (rdev->disp_priority == 2) {
579 uint32_t mc_init_misc_lat_timer = 0;
580 if (rdev->family == CHIP_RV515)
581 mc_init_misc_lat_timer =
582 RREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER);
583 else if (rdev->family == CHIP_RS690)
584 mc_init_misc_lat_timer =
585 RREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER);
586
587 mc_init_misc_lat_timer &=
588 ~(R300_MC_DISP1R_INIT_LAT_MASK <<
589 R300_MC_DISP1R_INIT_LAT_SHIFT);
590 mc_init_misc_lat_timer &=
591 ~(R300_MC_DISP0R_INIT_LAT_MASK <<
592 R300_MC_DISP0R_INIT_LAT_SHIFT);
593
594 if (mode2)
595 mc_init_misc_lat_timer |=
596 (1 << R300_MC_DISP1R_INIT_LAT_SHIFT);
597 if (mode1)
598 mc_init_misc_lat_timer |=
599 (1 << R300_MC_DISP0R_INIT_LAT_SHIFT);
600
601 if (rdev->family == CHIP_RV515)
602 WREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER,
603 mc_init_misc_lat_timer);
604 else if (rdev->family == CHIP_RS690)
605 WREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER,
606 mc_init_misc_lat_timer);
607 }
608
609 /*
610 * determine is there is enough bw for current mode
611 */
612 temp_ff.full = rfixed_const(100);
613 mclk_ff.full = rfixed_const(rdev->clock.default_mclk);
614 mclk_ff.full = rfixed_div(mclk_ff, temp_ff);
615 sclk_ff.full = rfixed_const(rdev->clock.default_sclk);
616 sclk_ff.full = rfixed_div(sclk_ff, temp_ff);
617
618 temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1);
619 temp_ff.full = rfixed_const(temp);
620 mem_bw.full = rfixed_mul(mclk_ff, temp_ff);
621 mem_bw.full = rfixed_mul(mem_bw, min_mem_eff);
622
623 pix_clk.full = 0;
624 pix_clk2.full = 0;
625 peak_disp_bw.full = 0;
626 if (mode1) {
627 temp_ff.full = rfixed_const(1000);
628 pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */
629 pix_clk.full = rfixed_div(pix_clk, temp_ff);
630 temp_ff.full = rfixed_const(pixel_bytes1);
631 peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff);
632 }
633 if (mode2) {
634 temp_ff.full = rfixed_const(1000);
635 pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */
636 pix_clk2.full = rfixed_div(pix_clk2, temp_ff);
637 temp_ff.full = rfixed_const(pixel_bytes2);
638 peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff);
639 }
640
641 if (peak_disp_bw.full >= mem_bw.full) {
642 DRM_ERROR
643 ("You may not have enough display bandwidth for current mode\n"
644 "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
645 printk("peak disp bw %d, mem_bw %d\n",
646 rfixed_trunc(peak_disp_bw), rfixed_trunc(mem_bw));
647 }
648
649 /*
650 * Line Buffer Setup
651 * There is a single line buffer shared by both display controllers.
652 * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between the display
653 * controllers. The paritioning can either be done manually or via one of four
654 * preset allocations specified in bits 1:0:
655 * 0 - line buffer is divided in half and shared between each display controller
656 * 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4
657 * 2 - D1 gets the whole buffer
658 * 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4
659 * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual allocation mode.
660 * In manual allocation mode, D1 always starts at 0, D1 end/2 is specified in bits
661 * 14:4; D2 allocation follows D1.
662 */
663
664 /* is auto or manual better ? */
665 dc_lb_memory_split =
666 RREG32(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK;
667 dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
668#if 1
669 /* auto */
670 if (mode1 && mode2) {
671 if (mode1->hdisplay > mode2->hdisplay) {
672 if (mode1->hdisplay > 2560)
673 dc_lb_memory_split |=
674 AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;
675 else
676 dc_lb_memory_split |=
677 AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
678 } else if (mode2->hdisplay > mode1->hdisplay) {
679 if (mode2->hdisplay > 2560)
680 dc_lb_memory_split |=
681 AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
682 else
683 dc_lb_memory_split |=
684 AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
685 } else
686 dc_lb_memory_split |=
687 AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
688 } else if (mode1) {
689 dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY;
690 } else if (mode2) {
691 dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
692 }
693#else
694 /* manual */
695 dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
696 dc_lb_memory_split &=
697 ~(AVIVO_DC_LB_DISP1_END_ADR_MASK <<
698 AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
699 if (mode1) {
700 dc_lb_memory_split |=
701 ((((mode1->hdisplay / 2) + 64) & AVIVO_DC_LB_DISP1_END_ADR_MASK)
702 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
703 } else if (mode2) {
704 dc_lb_memory_split |= (0 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
705 }
706#endif
707 WREG32(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split);
708}