diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2009-03-09 20:48:39 -0400 |
---|---|---|
committer | Alex Deucher <alexdeucher@gmail.com> | 2009-03-09 20:49:49 -0400 |
commit | 60dac878cc8626b0821c4c7a6a6dfa12a5597cfa (patch) | |
tree | 7a7ee13a226ebe131cc3a94df6afa54822d55327 /src | |
parent | 758fcc33c232c32e7b66261fca51de161d1a4800 (diff) |
R4xx: add R4xxATOM option
If set, enables the use of atombios for modesetting
on r4xx cards.
Diffstat (limited to 'src')
-rw-r--r-- | src/atombios_crtc.c | 172 | ||||
-rw-r--r-- | src/atombios_output.c | 28 | ||||
-rw-r--r-- | src/legacy_crtc.c | 4 | ||||
-rw-r--r-- | src/radeon.h | 5 | ||||
-rw-r--r-- | src/radeon_crtc.c | 4 | ||||
-rw-r--r-- | src/radeon_driver.c | 8 | ||||
-rw-r--r-- | src/radeon_output.c | 8 |
7 files changed, 197 insertions, 32 deletions
diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c index c0047191..50db5781 100644 --- a/src/atombios_crtc.c +++ b/src/atombios_crtc.c @@ -50,6 +50,23 @@ extern int atombios_get_encoder_mode(xf86OutputPtr output); +extern void +RADEONInitCrtcBase(xf86CrtcPtr crtc, RADEONSavePtr save, + int x, int y); +extern void +RADEONInitCrtc2Base(xf86CrtcPtr crtc, RADEONSavePtr save, + int x, int y); +extern void +RADEONRestoreCrtcBase(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void +RADEONRestoreCrtc2Base(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void +RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info); +extern void +RADEONInitSurfaceCntl(xf86CrtcPtr crtc, RADEONSavePtr save); + AtomBiosResult atombios_lock_crtc(atomBiosHandlePtr atomBIOS, int crtc, int lock) { @@ -202,6 +219,37 @@ atombios_set_crtc_timing(atomBiosHandlePtr atomBIOS, SET_CRTC_TIMING_PARAMETERS_ return ATOM_NOT_IMPLEMENTED; } +static AtomBiosResult +atombios_set_crtc_dtd_timing(atomBiosHandlePtr atomBIOS, SET_CRTC_USING_DTD_TIMING_PARAMETERS *crtc_param) +{ + AtomBiosArgRec data; + unsigned char *space; + SET_CRTC_USING_DTD_TIMING_PARAMETERS conv_param; + + conv_param.usH_Size = cpu_to_le16(crtc_param->usH_Size); + conv_param.usH_Blanking_Time= cpu_to_le16(crtc_param->usH_Blanking_Time); + conv_param.usV_Size = cpu_to_le16(crtc_param->usV_Size); + conv_param.usV_Blanking_Time= cpu_to_le16(crtc_param->usV_Blanking_Time); + conv_param.usH_SyncOffset= cpu_to_le16(crtc_param->usH_SyncOffset); + conv_param.usH_SyncWidth= cpu_to_le16(crtc_param->usH_SyncWidth); + conv_param.usV_SyncOffset= cpu_to_le16(crtc_param->usV_SyncOffset); + conv_param.usV_SyncWidth= cpu_to_le16(crtc_param->usV_SyncWidth); + conv_param.susModeMiscInfo.usAccess = cpu_to_le16(crtc_param->susModeMiscInfo.usAccess); + conv_param.ucCRTC= crtc_param->ucCRTC; + + data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming); + data.exec.dataSpace = (void *)&space; + data.exec.pspace = &conv_param; + + if (RHDAtomBiosFunc(atomBIOS->scrnIndex, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { + ErrorF("Set DTD CRTC Timing success\n"); + return ATOM_SUCCESS ; + } + + ErrorF("Set DTD CRTC Timing failed\n"); + return ATOM_NOT_IMPLEMENTED; +} + void atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode) { @@ -220,25 +268,19 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode) RADEONOutputPrivatePtr radeon_output = NULL; radeon_encoder_ptr radeon_encoder = NULL; int pll_flags = 0; + uint32_t temp; void *ptr; AtomBiosArgRec data; unsigned char *space; - RADEONSavePtr save = info->ModeReg; memset(&spc_param, 0, sizeof(spc_param)); if (IS_AVIVO_VARIANT) { - uint32_t temp; - if (IS_DCE3_VARIANT && mode->Clock > 200000) /* range limits??? */ pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; else pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; - - RADEONComputePLL(&info->pll, mode->Clock, &temp, &fb_div, &ref_div, &post_div, pll_flags); - sclock = temp; - /* disable spread spectrum clocking for now -- thanks Hedy Lamarr */ if (radeon_crtc->crtc_id == 0) { temp = INREG(AVIVO_P1PLL_INT_SS_CNTL); @@ -248,12 +290,30 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode) OUTREG(AVIVO_P2PLL_INT_SS_CNTL, temp & ~1); } } else { - sclock = save->dot_clock_freq; - fb_div = save->feedback_div; - post_div = save->post_div; - ref_div = save->ppll_ref_div; + pll_flags |= RADEON_PLL_LEGACY; + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (output->crtc == crtc) { + if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT | + ATOM_DEVICE_DFP_SUPPORT)) + pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; + if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) + pll_flags |= (RADEON_PLL_USE_BIOS_DIVS | RADEON_PLL_USE_REF_DIV); + } + } + + if (mode->Clock > 200000) /* range limits??? */ + pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; + else + pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; } + RADEONComputePLL(&info->pll, mode->Clock, &temp, &fb_div, &ref_div, &post_div, pll_flags); + sclock = temp; + xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO, "crtc(%d) Clock: mode %d, PLL %lu\n", radeon_crtc->crtc_id, mode->Clock, (long unsigned int)sclock * 10); @@ -350,8 +410,10 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc, int need_tv_timings = 0; int i, ret; SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing; + SET_CRTC_USING_DTD_TIMING_PARAMETERS crtc_dtd_timing; Bool tilingChanged = FALSE; memset(&crtc_timing, 0, sizeof(crtc_timing)); + memset(&crtc_dtd_timing, 0, sizeof(crtc_dtd_timing)); if (info->allowColorTiling) { radeon_crtc->can_tile = (adjusted_mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; @@ -410,6 +472,36 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc, if (adjusted_mode->Flags & V_DBLSCAN) crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE; + if (!IS_AVIVO_VARIANT && (radeon_crtc->crtc_id == 0)) { + crtc_dtd_timing.ucCRTC = radeon_crtc->crtc_id; + crtc_dtd_timing.usH_Size = adjusted_mode->CrtcHDisplay; + crtc_dtd_timing.usV_Size = adjusted_mode->CrtcVDisplay; + crtc_dtd_timing.usH_Blanking_Time = adjusted_mode->CrtcHBlankEnd - adjusted_mode->CrtcHDisplay; + crtc_dtd_timing.usV_Blanking_Time = adjusted_mode->CrtcVBlankEnd - adjusted_mode->CrtcVDisplay; + crtc_dtd_timing.usH_SyncOffset = adjusted_mode->CrtcHSyncStart - adjusted_mode->CrtcHDisplay; + crtc_dtd_timing.usV_SyncOffset = adjusted_mode->CrtcVSyncStart - adjusted_mode->CrtcVDisplay; + crtc_dtd_timing.usH_SyncWidth = adjusted_mode->CrtcHSyncEnd - adjusted_mode->CrtcHSyncStart; + crtc_dtd_timing.usV_SyncWidth = adjusted_mode->CrtcVSyncEnd - adjusted_mode->CrtcVSyncStart; + ErrorF("%d %d %d %d %d %d %d %d\n", crtc_dtd_timing.usH_Size, crtc_dtd_timing.usH_SyncOffset, + crtc_dtd_timing.usH_SyncWidth, crtc_dtd_timing.usH_Blanking_Time, + crtc_dtd_timing.usV_Size, crtc_dtd_timing.usV_SyncOffset, + crtc_dtd_timing.usV_SyncWidth, crtc_dtd_timing.usV_Blanking_Time); + + if (adjusted_mode->Flags & V_NVSYNC) + crtc_dtd_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY; + + if (adjusted_mode->Flags & V_NHSYNC) + crtc_dtd_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY; + + if (adjusted_mode->Flags & V_CSYNC) + crtc_dtd_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC; + + if (adjusted_mode->Flags & V_INTERLACE) + crtc_dtd_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE; + + if (adjusted_mode->Flags & V_DBLSCAN) + crtc_dtd_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE; + } } ErrorF("Mode %dx%d - %d %d %d\n", adjusted_mode->CrtcHDisplay, adjusted_mode->CrtcVDisplay, @@ -418,6 +510,11 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc, RADEONInitMemMapRegisters(pScrn, info->ModeReg, info); RADEONRestoreMemMapRegisters(pScrn, info->ModeReg); + atombios_crtc_set_pll(crtc, adjusted_mode); + atombios_set_crtc_timing(info->atomBIOS, &crtc_timing); + if (!IS_AVIVO_VARIANT && (radeon_crtc->crtc_id == 0)) + atombios_set_crtc_dtd_timing(info->atomBIOS, &crtc_dtd_timing); + if (IS_AVIVO_VARIANT) { uint32_t fb_format; @@ -481,11 +578,56 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc, else OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0); - } - - atombios_crtc_set_pll(crtc, adjusted_mode); + } else { + int format = 0; + uint32_t crtc_gen_cntl, crtc2_gen_cntl, crtc_pitch; + + + RADEONInitCommonRegisters(info->ModeReg, info); + RADEONInitSurfaceCntl(crtc, info->ModeReg); + ErrorF("restore common\n"); + RADEONRestoreCommonRegisters(pScrn, info->ModeReg); + + switch (info->CurrentLayout.pixel_code) { + case 4: format = 1; break; + case 8: format = 2; break; + case 15: format = 3; break; /* 555 */ + case 16: format = 4; break; /* 565 */ + case 24: format = 5; break; /* RGB */ + case 32: format = 6; break; /* xRGB */ + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unsupported pixel depth (%d)\n", + info->CurrentLayout.bitsPerPixel); + } - atombios_set_crtc_timing(info->atomBIOS, &crtc_timing); + crtc_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + + ((pScrn->bitsPerPixel * 8) -1)) / + (pScrn->bitsPerPixel * 8)); + crtc_pitch |= crtc_pitch << 16; + + switch (radeon_crtc->crtc_id) { + case 0: + ErrorF("init crtc1\n"); + crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL) & 0xfffff0ff; + crtc_gen_cntl |= (format << 8); + OUTREG(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); + OUTREG(RADEON_CRTC_PITCH, crtc_pitch); + RADEONInitCrtcBase(crtc, info->ModeReg, x, y); + RADEONRestoreCrtcBase(pScrn, info->ModeReg); + break; + case 1: + crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL) & 0xfffff0ff; + crtc2_gen_cntl |= (format << 8); + OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + OUTREG(RADEON_CRTC2_PITCH, crtc_pitch); + RADEONInitCrtc2Base(crtc, info->ModeReg, x, y); + RADEONRestoreCrtc2Base(pScrn, info->ModeReg); + OUTREG(RADEON_FP_H2_SYNC_STRT_WID, INREG(RADEON_CRTC2_H_SYNC_STRT_WID)); + OUTREG(RADEON_FP_V2_SYNC_STRT_WID, INREG(RADEON_CRTC2_V_SYNC_STRT_WID)); + break; + } + } if (info->DispPriority) RADEONInitDispBandwidth(pScrn); diff --git a/src/atombios_output.c b/src/atombios_output.c index 613f729c..4f62b67d 100644 --- a/src/atombios_output.c +++ b/src/atombios_output.c @@ -1063,6 +1063,9 @@ atombios_output_scaler_setup(xf86OutputPtr output, DisplayModePtr mode) AtomBiosArgRec data; unsigned char *space; + if (!IS_AVIVO_VARIANT && radeon_crtc->crtc_id) + return ATOM_SUCCESS; + memset(&disp_data, 0, sizeof(disp_data)); disp_data.ucScaler = radeon_crtc->crtc_id; @@ -1113,7 +1116,10 @@ atombios_output_scaler_setup(xf86OutputPtr output, DisplayModePtr mode) disp_data.ucEnable = ATOM_SCALER_EXPANSION; } else { ErrorF("Not using RMX\n"); - disp_data.ucEnable = ATOM_SCALER_DISABLE; + if (IS_AVIVO_VARIANT) + disp_data.ucEnable = ATOM_SCALER_DISABLE; + else + disp_data.ucEnable = ATOM_SCALER_CENTER; } data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableScaler); @@ -1326,7 +1332,10 @@ atombios_set_output_crtc_source(xf86OutputPtr output) case 0: case 1: default: - crtc_src_param.ucCRTC = radeon_crtc->crtc_id; + if (IS_AVIVO_VARIANT) + crtc_src_param.ucCRTC = radeon_crtc->crtc_id; + else + crtc_src_param.ucCRTC = radeon_crtc->crtc_id << 2; switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_TMDS1: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: @@ -1468,7 +1477,7 @@ atombios_apply_output_quirks(xf86OutputPtr output, DisplayModePtr mode) } /* set scaler clears this on some chips */ - if (mode->Flags & V_INTERLACE) + if (IS_AVIVO_VARIANT && (mode->Flags & V_INTERLACE)) OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, AVIVO_D1MODE_INTERLEAVE_EN); } @@ -1479,17 +1488,20 @@ atombios_output_mode_set(xf86OutputPtr output, { RADEONOutputPrivatePtr radeon_output = output->driver_private; radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); - + RADEONInfoPtr info = RADEONPTR(output->scrn); if (radeon_encoder == NULL) return; atombios_output_overscan_setup(output, mode, adjusted_mode); atombios_output_scaler_setup(output, adjusted_mode); atombios_set_output_crtc_source(output); - if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) - atombios_output_yuv_setup(output, TRUE); - else - atombios_output_yuv_setup(output, FALSE); + + if (IS_AVIVO_VARIANT) { + if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) + atombios_output_yuv_setup(output, TRUE); + else + atombios_output_yuv_setup(output, FALSE); + } switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_TMDS1: diff --git a/src/legacy_crtc.c b/src/legacy_crtc.c index b8c53806..829b453e 100644 --- a/src/legacy_crtc.c +++ b/src/legacy_crtc.c @@ -714,7 +714,7 @@ legacy_crtc_dpms(xf86CrtcPtr crtc, int mode) /* Define common registers for requested video mode */ -static void +void RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info) { save->ovr_clr = 0; @@ -745,7 +745,7 @@ RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info) save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN; } -static void +void RADEONInitSurfaceCntl(xf86CrtcPtr crtc, RADEONSavePtr save) { save->surface_cntl = 0; diff --git a/src/radeon.h b/src/radeon.h index 355a9494..4c966ec0 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -206,7 +206,8 @@ typedef enum { OPTION_DEFAULT_TVDAC_ADJ, OPTION_INT10, OPTION_EXA_VSYNC, - OPTION_ATOM_TVOUT + OPTION_ATOM_TVOUT, + OPTION_R4XX_ATOM } RADEONOpts; @@ -884,6 +885,8 @@ typedef struct { int virtualX; int virtualY; + Bool r4xx_atom; + } RADEONInfoRec, *RADEONInfoPtr; #define RADEONWaitForFifo(pScrn, entries) \ diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c index 3a9432fc..e360d4e8 100644 --- a/src/radeon_crtc.c +++ b/src/radeon_crtc.c @@ -77,7 +77,7 @@ radeon_crtc_dpms(xf86CrtcPtr crtc, int mode) if ((mode == DPMSModeOn) && radeon_crtc->enabled) return; - if (IS_AVIVO_VARIANT) { + if (IS_AVIVO_VARIANT || info->r4xx_atom) { atombios_crtc_dpms(crtc, mode); } else { @@ -271,7 +271,7 @@ radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, ScrnInfoPtr pScrn = crtc->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); - if (IS_AVIVO_VARIANT) { + if (IS_AVIVO_VARIANT || info->r4xx_atom) { atombios_crtc_mode_set(crtc, mode, adjusted_mode, x, y); } else { legacy_crtc_mode_set(crtc, mode, adjusted_mode, x, y); diff --git a/src/radeon_driver.c b/src/radeon_driver.c index e8d28f01..b665033b 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -193,6 +193,7 @@ static const OptionInfoRec RADEONOptions[] = { { OPTION_INT10, "Int10", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_EXA_VSYNC, "EXAVSync", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_ATOM_TVOUT, "ATOMTVOut", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_R4XX_ATOM, "R4xxATOM", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -1915,6 +1916,13 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) info->Chipset != PCI_CHIP_RN50_5969); #endif + info->r4xx_atom = FALSE; + if (((info->ChipFamily == CHIP_FAMILY_R420) || (info->ChipFamily == CHIP_FAMILY_RV410)) && + xf86ReturnOptValBool(info->Options, OPTION_R4XX_ATOM, FALSE)) { + info->r4xx_atom = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using ATOMBIOS for R4xx chip\n"); + } + return TRUE; } diff --git a/src/radeon_output.c b/src/radeon_output.c index fcf22efd..baa9592a 100644 --- a/src/radeon_output.c +++ b/src/radeon_output.c @@ -346,7 +346,7 @@ radeon_dpms(xf86OutputPtr output, int mode) if ((mode == DPMSModeOn) && radeon_output->enabled) return; - if (IS_AVIVO_VARIANT) { + if (IS_AVIVO_VARIANT || info->r4xx_atom) { atombios_output_dpms(output, mode); } else { legacy_output_dpms(output, mode); @@ -523,7 +523,7 @@ radeon_mode_prepare(xf86OutputPtr output) if (other_crtc->enabled) { if (other_radeon_crtc->initialized) { radeon_crtc_dpms(other_crtc, DPMSModeOff); - if (IS_AVIVO_VARIANT) + if (IS_AVIVO_VARIANT || info->r4xx_atom) atombios_lock_crtc(info->atomBIOS, other_radeon_crtc->crtc_id, 1); radeon_dpms(loop_output, DPMSModeOff); } @@ -543,7 +543,7 @@ radeon_mode_set(xf86OutputPtr output, DisplayModePtr mode, { RADEONInfoPtr info = RADEONPTR(output->scrn); - if (IS_AVIVO_VARIANT) + if (IS_AVIVO_VARIANT || info->r4xx_atom) atombios_output_mode_set(output, mode, adjusted_mode); else legacy_output_mode_set(output, mode, adjusted_mode); @@ -568,7 +568,7 @@ radeon_mode_commit(xf86OutputPtr output) if (other_crtc->enabled) { if (other_radeon_crtc->initialized) { radeon_crtc_dpms(other_crtc, DPMSModeOn); - if (IS_AVIVO_VARIANT) + if (IS_AVIVO_VARIANT || info->r4xx_atom) atombios_lock_crtc(info->atomBIOS, other_radeon_crtc->crtc_id, 0); radeon_dpms(loop_output, DPMSModeOn); } |