diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2008-07-21 23:47:45 -0400 |
---|---|---|
committer | Alex Deucher <alexdeucher@gmail.com> | 2008-07-21 23:47:45 -0400 |
commit | 1c5858484da4fb1c9bc3ac3b4d7a97863ab99730 (patch) | |
tree | c24aaa9ca5188bae1fb9f85aa838579040933d00 /src | |
parent | b0378bb145c8a915c943bef7d17f2cdecfccc891 (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.c | 126 | ||||
-rw-r--r-- | src/radeon_crtc.c | 9 | ||||
-rw-r--r-- | src/radeon_driver.c | 2 | ||||
-rw-r--r-- | src/radeon_probe.h | 1 | ||||
-rw-r--r-- | src/radeon_reg.h | 13 |
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 |