aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/atombios_crtc.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-09-02 02:17:56 -0400
committerIngo Molnar <mingo@elte.hu>2009-09-02 02:17:56 -0400
commit936e894a976dd3b0f07f1f6f43c17b77b7e6146d (patch)
tree5ed5c1f6735dcd26550594df23c8f7fe2aa21a15 /drivers/gpu/drm/radeon/atombios_crtc.c
parent69575d388603365f2afbf4166df93152df59b165 (diff)
parent326ba5010a5429a5a528b268b36a5900d4ab0eba (diff)
Merge commit 'v2.6.31-rc8' into x86/txt
Conflicts: arch/x86/kernel/reboot.c security/Kconfig Merge reason: resolve the conflicts, bump up from rc3 to rc8. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c')
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c293
1 files changed, 146 insertions, 147 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index c0080cc9bf8d..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);
@@ -203,6 +329,12 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
203 if (ASIC_IS_AVIVO(rdev)) { 329 if (ASIC_IS_AVIVO(rdev)) {
204 uint32_t ss_cntl; 330 uint32_t ss_cntl;
205 331
332 if ((rdev->family == CHIP_RS600) ||
333 (rdev->family == CHIP_RS690) ||
334 (rdev->family == CHIP_RS740))
335 pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
336 RADEON_PLL_PREFER_CLOSEST_LOWER);
337
206 if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */ 338 if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */
207 pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; 339 pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
208 else 340 else
@@ -321,7 +453,7 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
321 struct drm_gem_object *obj; 453 struct drm_gem_object *obj;
322 struct drm_radeon_gem_object *obj_priv; 454 struct drm_radeon_gem_object *obj_priv;
323 uint64_t fb_location; 455 uint64_t fb_location;
324 uint32_t fb_format, fb_pitch_pixels; 456 uint32_t fb_format, fb_pitch_pixels, tiling_flags;
325 457
326 if (!crtc->fb) 458 if (!crtc->fb)
327 return -EINVAL; 459 return -EINVAL;
@@ -358,7 +490,14 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
358 return -EINVAL; 490 return -EINVAL;
359 } 491 }
360 492
361 /* TODO tiling */ 493 radeon_object_get_tiling_flags(obj->driver_private,
494 &tiling_flags, NULL);
495 if (tiling_flags & RADEON_TILING_MACRO)
496 fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE;
497
498 if (tiling_flags & RADEON_TILING_MICRO)
499 fb_format |= AVIVO_D1GRPH_TILED;
500
362 if (radeon_crtc->crtc_id == 0) 501 if (radeon_crtc->crtc_id == 0)
363 WREG32(AVIVO_D1VGA_CONTROL, 0); 502 WREG32(AVIVO_D1VGA_CONTROL, 0);
364 else 503 else
@@ -509,6 +648,9 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
509 radeon_crtc_set_base(crtc, x, y, old_fb); 648 radeon_crtc_set_base(crtc, x, y, old_fb);
510 radeon_legacy_atom_set_surface(crtc); 649 radeon_legacy_atom_set_surface(crtc);
511 } 650 }
651 atombios_overscan_setup(crtc, mode, adjusted_mode);
652 atombios_scaler_setup(crtc);
653 radeon_bandwidth_update(rdev);
512 return 0; 654 return 0;
513} 655}
514 656
@@ -516,6 +658,8 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
516 struct drm_display_mode *mode, 658 struct drm_display_mode *mode,
517 struct drm_display_mode *adjusted_mode) 659 struct drm_display_mode *adjusted_mode)
518{ 660{
661 if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
662 return false;
519 return true; 663 return true;
520} 664}
521 665
@@ -548,148 +692,3 @@ void radeon_atombios_init_crtc(struct drm_device *dev,
548 AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL; 692 AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
549 drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); 693 drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
550} 694}
551
552void radeon_init_disp_bw_avivo(struct drm_device *dev,
553 struct drm_display_mode *mode1,
554 uint32_t pixel_bytes1,
555 struct drm_display_mode *mode2,
556 uint32_t pixel_bytes2)
557{
558 struct radeon_device *rdev = dev->dev_private;
559 fixed20_12 min_mem_eff;
560 fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff;
561 fixed20_12 sclk_ff, mclk_ff;
562 uint32_t dc_lb_memory_split, temp;
563
564 min_mem_eff.full = rfixed_const_8(0);
565 if (rdev->disp_priority == 2) {
566 uint32_t mc_init_misc_lat_timer = 0;
567 if (rdev->family == CHIP_RV515)
568 mc_init_misc_lat_timer =
569 RREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER);
570 else if (rdev->family == CHIP_RS690)
571 mc_init_misc_lat_timer =
572 RREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER);
573
574 mc_init_misc_lat_timer &=
575 ~(R300_MC_DISP1R_INIT_LAT_MASK <<
576 R300_MC_DISP1R_INIT_LAT_SHIFT);
577 mc_init_misc_lat_timer &=
578 ~(R300_MC_DISP0R_INIT_LAT_MASK <<
579 R300_MC_DISP0R_INIT_LAT_SHIFT);
580
581 if (mode2)
582 mc_init_misc_lat_timer |=
583 (1 << R300_MC_DISP1R_INIT_LAT_SHIFT);
584 if (mode1)
585 mc_init_misc_lat_timer |=
586 (1 << R300_MC_DISP0R_INIT_LAT_SHIFT);
587
588 if (rdev->family == CHIP_RV515)
589 WREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER,
590 mc_init_misc_lat_timer);
591 else if (rdev->family == CHIP_RS690)
592 WREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER,
593 mc_init_misc_lat_timer);
594 }
595
596 /*
597 * determine is there is enough bw for current mode
598 */
599 temp_ff.full = rfixed_const(100);
600 mclk_ff.full = rfixed_const(rdev->clock.default_mclk);
601 mclk_ff.full = rfixed_div(mclk_ff, temp_ff);
602 sclk_ff.full = rfixed_const(rdev->clock.default_sclk);
603 sclk_ff.full = rfixed_div(sclk_ff, temp_ff);
604
605 temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1);
606 temp_ff.full = rfixed_const(temp);
607 mem_bw.full = rfixed_mul(mclk_ff, temp_ff);
608 mem_bw.full = rfixed_mul(mem_bw, min_mem_eff);
609
610 pix_clk.full = 0;
611 pix_clk2.full = 0;
612 peak_disp_bw.full = 0;
613 if (mode1) {
614 temp_ff.full = rfixed_const(1000);
615 pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */
616 pix_clk.full = rfixed_div(pix_clk, temp_ff);
617 temp_ff.full = rfixed_const(pixel_bytes1);
618 peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff);
619 }
620 if (mode2) {
621 temp_ff.full = rfixed_const(1000);
622 pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */
623 pix_clk2.full = rfixed_div(pix_clk2, temp_ff);
624 temp_ff.full = rfixed_const(pixel_bytes2);
625 peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff);
626 }
627
628 if (peak_disp_bw.full >= mem_bw.full) {
629 DRM_ERROR
630 ("You may not have enough display bandwidth for current mode\n"
631 "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
632 printk("peak disp bw %d, mem_bw %d\n",
633 rfixed_trunc(peak_disp_bw), rfixed_trunc(mem_bw));
634 }
635
636 /*
637 * Line Buffer Setup
638 * There is a single line buffer shared by both display controllers.
639 * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between the display
640 * controllers. The paritioning can either be done manually or via one of four
641 * preset allocations specified in bits 1:0:
642 * 0 - line buffer is divided in half and shared between each display controller
643 * 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4
644 * 2 - D1 gets the whole buffer
645 * 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4
646 * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual allocation mode.
647 * In manual allocation mode, D1 always starts at 0, D1 end/2 is specified in bits
648 * 14:4; D2 allocation follows D1.
649 */
650
651 /* is auto or manual better ? */
652 dc_lb_memory_split =
653 RREG32(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK;
654 dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
655#if 1
656 /* auto */
657 if (mode1 && mode2) {
658 if (mode1->hdisplay > mode2->hdisplay) {
659 if (mode1->hdisplay > 2560)
660 dc_lb_memory_split |=
661 AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;
662 else
663 dc_lb_memory_split |=
664 AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
665 } else if (mode2->hdisplay > mode1->hdisplay) {
666 if (mode2->hdisplay > 2560)
667 dc_lb_memory_split |=
668 AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
669 else
670 dc_lb_memory_split |=
671 AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
672 } else
673 dc_lb_memory_split |=
674 AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
675 } else if (mode1) {
676 dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY;
677 } else if (mode2) {
678 dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
679 }
680#else
681 /* manual */
682 dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
683 dc_lb_memory_split &=
684 ~(AVIVO_DC_LB_DISP1_END_ADR_MASK <<
685 AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
686 if (mode1) {
687 dc_lb_memory_split |=
688 ((((mode1->hdisplay / 2) + 64) & AVIVO_DC_LB_DISP1_END_ADR_MASK)
689 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
690 } else if (mode2) {
691 dc_lb_memory_split |= (0 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
692 }
693#endif
694 WREG32(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split);
695}