summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2008-07-21 23:47:45 -0400
committerAlex Deucher <alexdeucher@gmail.com>2008-07-21 23:47:45 -0400
commit1c5858484da4fb1c9bc3ac3b4d7a97863ab99730 (patch)
treec24aaa9ca5188bae1fb9f85aa838579040933d00 /src
parentb0378bb145c8a915c943bef7d17f2cdecfccc891 (diff)
First pass at InitDispBandwidth() for AVIVO chips
- support for LB allocation - MC priority bumps for display1/2 on RV515 variants and RS690 If you are having display underflow problems (flickering on sides of screen in high res modes, etc.) on RV515 or RS690 boards, try setting: Option "DisplayPriority" "HIGH" in your config. - still no support for full display watermark programming yet Something similar might be useful in rhd as well.
Diffstat (limited to 'src')
-rw-r--r--src/atombios_crtc.c126
-rw-r--r--src/radeon_crtc.c9
-rw-r--r--src/radeon_driver.c2
-rw-r--r--src/radeon_probe.h1
-rw-r--r--src/radeon_reg.h13
5 files changed, 150 insertions, 1 deletions
diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 406e7864..70650e12 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -514,6 +514,9 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc,
atombios_set_crtc_timing(info->atomBIOS, &crtc_timing);
+ if (info->DispPriority)
+ RADEONInitDispBandwidth(pScrn);
+
if (tilingChanged) {
/* need to redraw front buffer, I guess this can be considered a hack ? */
/* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
@@ -527,3 +530,126 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc,
}
+/* Calculate display buffer watermark to prevent buffer underflow */
+void
+RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn,
+ DisplayModePtr mode1, int pixel_bytes1,
+ DisplayModePtr mode2, int pixel_bytes2)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ uint32_t dc_lb_memory_split;
+ float mem_bw, peak_disp_bw;
+ float min_mem_eff = 0.8; /* XXX: taken from legacy method */
+ float pix_clk, pix_clk2; /* in MHz */
+
+ /*
+ * Set display0/1 priority up in the memory controller for
+ * modes if the user specifies HIGH for displaypriority
+ * option.
+ */
+ if (info->DispPriority == 2) {
+ uint32_t mc_init_misc_lat_timer = 0;
+ if (info->ChipFamily == CHIP_FAMILY_RV515)
+ mc_init_misc_lat_timer = INMC(pScrn, RV515_MC_INIT_MISC_LAT_TIMER);
+ else if (info->ChipFamily == CHIP_FAMILY_RS690)
+ mc_init_misc_lat_timer = INMC(pScrn, RS690_MC_INIT_MISC_LAT_TIMER);
+
+ mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT);
+ mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT);
+
+ if (pRADEONEnt->pCrtc[1]->enabled)
+ mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); /* display 1 */
+ if (pRADEONEnt->pCrtc[0]->enabled)
+ mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); /* display 0 */
+
+ if (info->ChipFamily == CHIP_FAMILY_RV515)
+ OUTMC(pScrn, RV515_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
+ else if (info->ChipFamily == CHIP_FAMILY_RS690)
+ OUTMC(pScrn, RS690_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
+ }
+
+ /* XXX: fix me for AVIVO
+ * Determine if there is enough bandwidth for current display mode
+ */
+ mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1);
+
+ pix_clk = 0;
+ pix_clk2 = 0;
+ peak_disp_bw = 0;
+ if (mode1) {
+ pix_clk = mode1->Clock/1000.0;
+ peak_disp_bw += (pix_clk * pixel_bytes1);
+ }
+ if (mode2) {
+ pix_clk2 = mode2->Clock/1000.0;
+ peak_disp_bw += (pix_clk2 * pixel_bytes2);
+ }
+
+ if (peak_disp_bw >= mem_bw * min_mem_eff) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "You may not have enough display bandwidth for current mode\n"
+ "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
+ }
+
+ /*
+ * Line Buffer Setup
+ * There is a single line buffer shared by both display controllers.
+ * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between the display
+ * controllers. The paritioning can either be done manually or via one of four
+ * preset allocations specified in bits 1:0:
+ * 0 - line buffer is divided in half and shared between each display controller
+ * 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4
+ * 2 - D1 gets the whole buffer
+ * 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4
+ * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual allocation mode.
+ * In manual allocation mode, D1 always starts at 0, D1 end/2 is specified in bits
+ * 14:4; D2 allocation follows D1.
+ */
+
+ /* is auto or manual better ? */
+ dc_lb_memory_split = INREG(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK;
+ dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
+#if 1
+ /* auto */
+ if (mode1 && mode2) {
+ if (mode1->HDisplay > mode2->HDisplay) {
+ if (mode1->HDisplay > 2560)
+ dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;
+ else
+ dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
+ } else if (mode2->HDisplay > mode1->HDisplay) {
+ if (mode2->HDisplay > 2560)
+ dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
+ else
+ dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
+ } else
+ dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
+ } else if (mode1) {
+ dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY;
+ } else if (mode2) {
+ dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
+ }
+#else
+ /* manual */
+ dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
+ dc_lb_memory_split &= ~(AVIVO_DC_LB_DISP1_END_ADR_MASK << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
+ if (mode1) {
+ dc_lb_memory_split |= ((((mode1->HDisplay / 2) + 64 /*???*/) & AVIVO_DC_LB_DISP1_END_ADR_MASK)
+ << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
+ } else if (mode2) {
+ dc_lb_memory_split |= (0 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
+ }
+ OUTREG(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split);
+#endif
+
+ /*
+ * Watermark setup
+ * TODO...
+ * Unforunately, I haven't been able to dig up the avivo watermark programming
+ * guide yet. -AGD
+ */
+
+}
diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c
index 9e5f672b..13166698 100644
--- a/src/radeon_crtc.c
+++ b/src/radeon_crtc.c
@@ -62,6 +62,10 @@ extern void
RADEONInitDispBandwidthLegacy(ScrnInfoPtr pScrn,
DisplayModePtr mode1, int pixel_bytes1,
DisplayModePtr mode2, int pixel_bytes2);
+extern void
+RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn,
+ DisplayModePtr mode1, int pixel_bytes1,
+ DisplayModePtr mode2, int pixel_bytes2);
void
radeon_crtc_dpms(xf86CrtcPtr crtc, int mode)
@@ -602,7 +606,10 @@ RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
return;
}
- RADEONInitDispBandwidthLegacy(pScrn, mode1, pixel_bytes1, mode2, pixel_bytes2);
+ if (IS_AVIVO_VARIANT)
+ RADEONInitDispBandwidthAVIVO(pScrn, mode1, pixel_bytes1, mode2, pixel_bytes2);
+ else
+ RADEONInitDispBandwidthLegacy(pScrn, mode1, pixel_bytes1, mode2, pixel_bytes2);
}
Bool RADEONAllocateControllers(ScrnInfoPtr pScrn, int mask)
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 4de7bae2..d55b9064 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -4188,6 +4188,7 @@ avivo_save(ScrnInfoPtr pScrn, RADEONSavePtr save)
state->crtc_master_en = INREG(AVIVO_DC_CRTC_MASTER_EN);
state->crtc_tv_control = INREG(AVIVO_DC_CRTC_TV_CONTROL);
+ state->dc_lb_memory_split = INREG(AVIVO_DC_LB_MEMORY_SPLIT);
state->pll1.ref_div_src = INREG(AVIVO_EXT1_PPLL_REF_DIV_SRC);
state->pll1.ref_div = INREG(AVIVO_EXT1_PPLL_REF_DIV);
@@ -4818,6 +4819,7 @@ avivo_restore(ScrnInfoPtr pScrn, RADEONSavePtr restore)
/* Where should that go ? */
OUTREG(AVIVO_DC_CRTC_TV_CONTROL, state->crtc_tv_control);
+ OUTREG(AVIVO_DC_LB_MEMORY_SPLIT, state->dc_lb_memory_split);
/* Need fixing too ? */
OUTREG(AVIVO_D1CRTC_BLANK_CONTROL, state->crtc1.blank_control);
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index 35d622dd..944ab9fa 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -328,6 +328,7 @@ struct avivo_state
uint32_t crtc_master_en;
uint32_t crtc_tv_control;
+ uint32_t dc_lb_memory_split;
struct avivo_pll_state pll1;
struct avivo_pll_state pll2;
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index b7503032..60f12fc4 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -3422,6 +3422,7 @@
#define RS690_MC_AGP_LOCATION 0x101
#define RS690_MC_AGP_BASE 0x102
#define RS690_MC_AGP_BASE_2 0x103
+#define RS690_MC_INIT_MISC_LAT_TIMER 0x104
#define RS690_MC_STATUS 0x90
#define RS690_MC_STATUS_IDLE (1 << 0)
@@ -3440,6 +3441,7 @@
# define R520_MC_STATUS_IDLE (1 << 1)
#define RV515_MC_STATUS 0x08
# define RV515_MC_STATUS_IDLE (1 << 4)
+#define RV515_MC_INIT_MISC_LAT_TIMER 0x09
#define AVIVO_MC_DATA 0x0074
#define RV515_MC_FB_LOCATION 0x1
@@ -3602,6 +3604,17 @@
#define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN 0x64d4
#define AVIVO_DC_LUTA_WHITE_OFFSET_RED 0x64d8
+#define AVIVO_DC_LB_MEMORY_SPLIT 0x6520
+# define AVIVO_DC_LB_MEMORY_SPLIT_MASK 0x3
+# define AVIVO_DC_LB_MEMORY_SPLIT_SHIFT 0
+# define AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF 0
+# define AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q 1
+# define AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY 2
+# define AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q 3
+# define AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE (1 << 2)
+# define AVIVO_DC_LB_DISP1_END_ADR_SHIFT 4
+# define AVIVO_DC_LB_DISP1_END_ADR_MASK 0x7ff
+
#define AVIVO_D1MODE_DATA_FORMAT 0x6528
# define AVIVO_D1MODE_INTERLEAVE_EN (1 << 0)
#define AVIVO_D1MODE_DESKTOP_HEIGHT 0x652c