From: <mad...@ke...> - 2007-11-11 18:33:15
|
src/nv_crtc.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++--------- src/nv_driver.c | 4 - src/nv_output.c | 9 ---- src/nv_proto.h | 2 src/nv_type.h | 1 src/nvreg.h | 2 6 files changed, 107 insertions(+), 29 deletions(-) New commits: commit 27cbf73bc572f435870decc2017cbf1c4f38264d Author: Maarten Maathuis <mad...@gm...> Date: Sun Nov 11 19:32:26 2007 +0100 randr12: Overhaul vpll set code + misc fixes. - Hopefully the problematic G70's work again. diff --git a/src/nv_crtc.c b/src/nv_crtc.c index 8f0c4a8..2df071e 100644 --- a/src/nv_crtc.c +++ b/src/nv_crtc.c @@ -64,7 +64,7 @@ static void nv_crtc_load_state_ext(xf86CrtcPtr crtc, RIVA_HW_STATE *state); static void nv_crtc_save_state_ext(xf86CrtcPtr crtc, RIVA_HW_STATE *state); static void nv_crtc_save_state_vga(xf86CrtcPtr crtc, RIVA_HW_STATE *state); -static CARD8 NVReadPVIO(xf86CrtcPtr crtc, CARD8 address) +static CARD8 NVReadPVIO(xf86CrtcPtr crtc, CARD32 address) { ScrnInfoPtr pScrn = crtc->scrn; NVCrtcPrivatePtr nv_crtc = crtc->driver_private; @@ -77,7 +77,7 @@ static CARD8 NVReadPVIO(xf86CrtcPtr crtc, CARD8 address) } } -static void NVWritePVIO(xf86CrtcPtr crtc, CARD8 address, CARD8 value) +static void NVWritePVIO(xf86CrtcPtr crtc, CARD32 address, CARD8 value) { ScrnInfoPtr pScrn = crtc->scrn; NVCrtcPrivatePtr nv_crtc = crtc->driver_private; @@ -335,6 +335,8 @@ NVGetOutputFromCRTC(xf86CrtcPtr crtc) return output; } } + + return NULL; } xf86CrtcPtr @@ -508,34 +510,103 @@ static void nv_crtc_save_state_pll(NVPtr pNv, RIVA_HW_STATE *state) state->vpll2B = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL2_B); } state->pllsel = nvReadRAMDAC0(pNv, NV_RAMDAC_PLL_SELECT); + state->sel_clk = nvReadRAMDAC0(pNv, NV_RAMDAC_SEL_CLK); /* This seems to be strictly NV40 */ if (pNv->Architecture == NV_ARCH_40) { - //nvWriteMC(pNv, 0xc040, pNv->misc_info.reg_c040 & ~(0x3 << 16)); state->reg580 = nvReadRAMDAC0(pNv, NV_RAMDAC_580); - //nvWriteMC(pNv, 0xc040, pNv->misc_info.reg_c040); } } static void nv_crtc_load_state_pll(NVPtr pNv, RIVA_HW_STATE *state) { - nvWriteRAMDAC0(pNv, NV_RAMDAC_PLL_SELECT, state->pllsel); + CARD32 fp_debug_0[2]; + fp_debug_0[0] = nvReadRAMDAC(pNv, 0, NV_RAMDAC_FP_DEBUG_0); + fp_debug_0[1] = nvReadRAMDAC(pNv, 1, NV_RAMDAC_FP_DEBUG_0); + + if (state->vpll2) { + if (pNv->Architecture == NV_ARCH_40) { + nvWriteRAMDAC(pNv, 1, NV_RAMDAC_FP_DEBUG_0, + fp_debug_0[1] | NV_RAMDAC_FP_DEBUG_0_PWRDOWN_TMDS_PLL); + + /* Wait for the situation to stabilise */ + usleep(5000); + + CARD32 reg_c040 = pNv->misc_info.reg_c040; + /* for vpll2 change bits 18 and 19 are disabled */ + reg_c040 &= ~(0x3 << 18); + nvWriteMC(pNv, 0xc040, reg_c040); + } + + if(pNv->twoHeads) { + ErrorF("writing vpll2 %08X\n", state->vpll2); + nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL2, state->vpll2); + } + if(pNv->twoStagePLL) { + ErrorF("writing vpll2B %08X\n", state->vpll2B); + nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL2_B, state->vpll2B); + } + + ErrorF("writing pllsel %08X\n", state->pllsel); + /* Let's keep the primary vpll off */ + nvWriteRAMDAC0(pNv, NV_RAMDAC_PLL_SELECT, state->pllsel & ~NV_RAMDAC_PLL_SELECT_PLL_SOURCE_ALL); + + if (pNv->Architecture == NV_ARCH_40) { + uint32_t reg580 = state->reg580; + /* Let's keep vpll1 off for the moment */ + if (!(pNv->misc_info.ramdac_0_reg_580 & NV_RAMDAC_580_VPLL1_ACTIVE)) + reg580 &= ~NV_RAMDAC_580_VPLL1_ACTIVE; + ErrorF("writing reg580 %08X\n", reg580); + nvWriteRAMDAC0(pNv, NV_RAMDAC_580, reg580); + /* We need to wait a while */ + usleep(5000); + nvWriteMC(pNv, 0xc040, pNv->misc_info.reg_c040); + + nvWriteRAMDAC(pNv, 1, NV_RAMDAC_FP_DEBUG_0, fp_debug_0[1]); + + /* Wait for the situation to stabilise */ + usleep(5000); + } + } + if (pNv->Architecture == NV_ARCH_40) { - nvWriteRAMDAC0(pNv, NV_RAMDAC_580, state->reg580); + nvWriteRAMDAC(pNv, 0, NV_RAMDAC_FP_DEBUG_0, + fp_debug_0[0] | NV_RAMDAC_FP_DEBUG_0_PWRDOWN_TMDS_PLL); + + /* Wait for the situation to stabilise */ + usleep(5000); + + CARD32 reg_c040 = pNv->misc_info.reg_c040; + /* for vpll1 change bits 16 and 17 are disabled */ + reg_c040 &= ~(0x3 << 16); + nvWriteMC(pNv, 0xc040, reg_c040); } ErrorF("writing vpll %08X\n", state->vpll); nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL, state->vpll); - if(pNv->twoHeads) { - ErrorF("writing vpll2 %08X\n", state->vpll2); - nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL2, state->vpll2); - } if(pNv->twoStagePLL) { ErrorF("writing vpllB %08X\n", state->vpllB); - ErrorF("writing vpll2B %08X\n", state->vpll2B); nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL_B, state->vpllB); - nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL2_B, state->vpll2B); - } + } + + ErrorF("writing pllsel %08X\n", state->pllsel); + nvWriteRAMDAC0(pNv, NV_RAMDAC_PLL_SELECT, state->pllsel); + + if (pNv->Architecture == NV_ARCH_40) { + ErrorF("writing reg580 %08X\n", state->reg580); + nvWriteRAMDAC0(pNv, NV_RAMDAC_580, state->reg580); + /* We need to wait a while */ + usleep(5000); + nvWriteMC(pNv, 0xc040, pNv->misc_info.reg_c040); + + /* This register is only written after the last clock is set */ + nvWriteRAMDAC0(pNv, NV_RAMDAC_SEL_CLK, state->sel_clk); + + nvWriteRAMDAC(pNv, 0, NV_RAMDAC_FP_DEBUG_0, fp_debug_0[0]); + + /* Wait for the situation to stabilise */ + usleep(5000); + } } /* @@ -645,11 +716,20 @@ void nv_crtc_calc_state_ext( ErrorF("There are %d CRTC's enabled\n", num_crtc_enabled); - /* Something is wrong with this, so until it's proven to be needed, let's leave it alone */ if (pNv->Architecture == NV_ARCH_40) { + /* This register is only used on the primary ramdac */ + /* This seems to be needed to select the proper clocks, otherwise bad things happen */ + /* Assumption CRTC1 will overwrte the CRTC0 value */ + if (nv_crtc->head == 1) { + state->sel_clk = pNv->misc_info.sel_clk | (1 << 18); + } else { + state->sel_clk = pNv->misc_info.sel_clk | (1 << 16); + } + /* Do not remove any present VPLL related bits, that can cause problems */ /* The meaning of this register is debatable */ - state->reg580 = pNv->misc_info.ramdac_0_reg_580; + if (!state->reg580) + state->reg580 = pNv->misc_info.ramdac_0_reg_580; Bool vpll1_ok = TRUE; Bool vpll2_ok = TRUE; @@ -693,13 +773,13 @@ void nv_crtc_calc_state_ext( } else { state->pllsel &= ~NV_RAMDAC_PLL_SELECT_VCLK2_RATIO_DB2; } - state->pllsel |= NV_RAMDAC_PLL_SELECT_PLL_SOURCE_CRTC1; + state->pllsel |= NV_RAMDAC_PLL_SELECT_PLL_SOURCE_VPLL2; } else { state->vpll = state->pll; state->vpllB = state->pllB; if (nv_output->type == OUTPUT_LVDS) state->pllsel |= NV_RAMDAC_PLL_SELECT_PLL_SOURCE_ALL; - else + else state->pllsel |= NV_RAMDAC_PLL_SELECT_PLL_SOURCE_VPLL; if (pNv->misc_info.ramdac_0_pllsel & NV_RAMDAC_PLL_SELECT_VCLK_RATIO_DB2) { state->pllsel |= NV_RAMDAC_PLL_SELECT_VCLK_RATIO_DB2; @@ -708,6 +788,10 @@ void nv_crtc_calc_state_ext( } } + /* The purpose is unknown */ + if (pNv->Architecture == NV_ARCH_40) + state->pllsel |= (1 << 2); + regp->CRTC[NV_VGA_CRTCX_FIFO0] = state->arbitration0; regp->CRTC[NV_VGA_CRTCX_FIFO_LWM] = state->arbitration1 & 0xff; if (pNv->Architecture >= NV_ARCH_30) { diff --git a/src/nv_driver.c b/src/nv_driver.c index f7c3bce..23e85d2 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -772,11 +772,11 @@ NVEnterVT(int scrnIndex, int flags) uint8_t tmds_reg4; /* Disable any crosswired tmds, to avoid picking up a signal on a disabled output */ - /* Example: TMDS1 crosswired to CRTC0 (by bios) reassigned to CRTC1 in xorg, disabled. + /* Example: TMDS1 crosswired to CRTC0 (by bios) reassigned to CRTC1 in xorg, disabled. */ /* But the bios reinits it to CRTC0 when going back to VT. */ /* Because it's disabled, it doesn't get a mode set, still it picks up the signal from CRTC0 (which is another output) */ /* A legitimately crosswired output will get set properly during mode set */ - if (tmds_reg4 = NVReadTMDS(pNv, nv_output->ramdac, 0x4) & (1 << 3)) { + if ((tmds_reg4 = NVReadTMDS(pNv, nv_output->ramdac, 0x4)) & (1 << 3)) { NVWriteTMDS(pNv, nv_output->ramdac, 0x4, tmds_reg4 & ~(1 << 3)); } } diff --git a/src/nv_output.c b/src/nv_output.c index 52382ef..7218936 100644 --- a/src/nv_output.c +++ b/src/nv_output.c @@ -309,7 +309,6 @@ void nv_output_save_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state, Bool o regp->debug_0 = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_0); regp->debug_1 = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_1); regp->debug_2 = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_2); - regp->sel_clk = NVOutputReadRAMDAC(output, NV_RAMDAC_SEL_CLK); state->config = nvReadFB(pNv, NV_PFB_CFG0); regp->unk_a20 = NVOutputReadRAMDAC(output, NV_RAMDAC_A20); @@ -370,7 +369,6 @@ void nv_output_load_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state, Bool o NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_0, regp->debug_0); NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_1, regp->debug_1); NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_2, regp->debug_2); - NVOutputWriteRAMDAC(output, NV_RAMDAC_SEL_CLK, regp->sel_clk); NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, regp->output); NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_CONTROL, regp->fp_control); @@ -616,13 +614,6 @@ nv_output_mode_set_regs(xf86OutputPtr output, DisplayModePtr mode, DisplayModePt ErrorF("REG_DISP_VALID_END: 0x%X\n", regp->fp_vert_regs[REG_DISP_VALID_END]); } - /* This register is only used on the primary ramdac */ - /* The value 0x40000 is not acceptable in text mode, but seems to do no harm in X mode */ - /* The blob does this often, the exact purpose is not exactly known */ - if (nv_output->ramdac == 0) { - regp->sel_clk = pNv->misc_info.sel_clk | (1 << 18); - } - /* This seems to be a common mode * bit0: positive vsync * bit4: positive hsync diff --git a/src/nv_proto.h b/src/nv_proto.h index 0802bfc..4269853 100644 --- a/src/nv_proto.h +++ b/src/nv_proto.h @@ -138,6 +138,8 @@ xf86CrtcPtr nv_find_crtc_by_index(ScrnInfoPtr pScrn, int index); void NvSetupOutputs(ScrnInfoPtr pScrn); void NVOutputWriteRAMDAC(xf86OutputPtr output, CARD32 ramdac_reg, CARD32 val); CARD32 NVOutputReadRAMDAC(xf86OutputPtr output, CARD32 ramdac_reg); +void NVWriteTMDS(NVPtr pNv, int ramdac, CARD32 tmds_reg, CARD32 val); +CARD8 NVReadTMDS(NVPtr pNv, int ramdac, CARD32 tmds_reg); #endif /* ENABLE_RANDR12 */ diff --git a/src/nv_type.h b/src/nv_type.h index 7f1ea03..97c3e13 100644 --- a/src/nv_type.h +++ b/src/nv_type.h @@ -166,6 +166,7 @@ typedef struct _riva_hw_state CARD32 vpll2B; CARD32 pllsel; CARD32 reg580; + CARD32 sel_clk; CARD32 general; CARD32 crtcOwner; CARD32 head; diff --git a/src/nvreg.h b/src/nvreg.h index 471fda2..92776fd 100644 --- a/src/nvreg.h +++ b/src/nvreg.h @@ -162,7 +162,7 @@ #define NV_RAMDAC_PLL_SELECT_PLL_SOURCE_NVPLL (4<<8) #define NV_RAMDAC_PLL_SELECT_PLL_SOURCE_ALL (7<<8) /* Does this name make sense? */ -#define NV_RAMDAC_PLL_SELECT_PLL_SOURCE_CRTC1 (1<<11) +#define NV_RAMDAC_PLL_SELECT_PLL_SOURCE_VPLL2 (1<<11) #define NV_RAMDAC_PLL_SELECT_MPLL_BYPASS_FALSE (0<<12) #define NV_RAMDAC_PLL_SELECT_MPLL_BYPASS_TRUE (1<<12) #define NV_RAMDAC_PLL_SELECT_VS_PCLK_TV_NONE (0<<16) |