diff --git a/headers/private/graphics/nvidia/nv_macros.h b/headers/private/graphics/nvidia/nv_macros.h index b14e3f3263..45232d45ca 100644 --- a/headers/private/graphics/nvidia/nv_macros.h +++ b/headers/private/graphics/nvidia/nv_macros.h @@ -480,12 +480,15 @@ #define NVDAC_OUTPUT 0x0068052c #define NVDAC_PIXPLLC2 0x00680578 /* NV31, NV36 only */ #define NVDAC_GENCTRL 0x00680600 +#define NVDAC_TSTCTRL 0x00680608 +#define NVDAC_TSTDATA 0x00680610 /* secondary head */ #define NVDAC2_CURPOS 0x00682300 #define NVDAC2_PIXPLLC 0x00680520 #define NVDAC2_OUTPUT 0x0068252c #define NVDAC2_PIXPLLC2 0x0068057c /* NV31, NV36 only */ #define NVDAC2_GENCTRL 0x00682600 +#define NVDAC2_TSTCTRL 0x00682608 /* Nvidia CRTC indexed registers */ /* VGA standard registers: */ diff --git a/src/add-ons/accelerants/nvidia/SetDisplayMode.c b/src/add-ons/accelerants/nvidia/SetDisplayMode.c index 556f7f5f38..6e0a984b61 100644 --- a/src/add-ons/accelerants/nvidia/SetDisplayMode.c +++ b/src/add-ons/accelerants/nvidia/SetDisplayMode.c @@ -184,6 +184,10 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) /*work out where the "right" screen starts*/ startadd_right = startadd + (target.timing.h_display * (colour_depth1 >> 3)); + /* fixme: test... */ + nv_dac_crt_connected(); + nv_dac2_crt_connected(); + /* set the outputs if possible */ if (si->ps.secondary_head) { diff --git a/src/add-ons/accelerants/nvidia/engine/nv_dac.c b/src/add-ons/accelerants/nvidia/engine/nv_dac.c index ffdc380917..7417835fbc 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_dac.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_dac.c @@ -12,6 +12,56 @@ static status_t nv4_nv10_nv20_dac_pix_pll_find( static status_t g100_g400max_dac_sys_pll_find( float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result); +/* see if an analog VGA monitor is connected to DAC */ +bool nv_dac_crt_connected(void) +{ + uint32 output, dac; + bool present; + + /* save output connector setting */ + output = DACR(OUTPUT); + /* save DAC state */ + dac = DACR(TSTCTRL); + + /* shut-off DAC */ + DACW(TSTCTRL, (DACR(TSTCTRL) | 0x00010000)); + /* select primary head and turn off CRT (and DVI?) outputs */ + DACW(OUTPUT, (output & 0x0000feee)); + /* wait for signal lines to stabilize */ + snooze(1000); + /* re-enable CRT output */ + DACW(OUTPUT, (DACR(OUTPUT) | 0x00000001)); + + /* setup RGB test signal levels to approx 30% of DAC range and enable them */ + DACW(TSTDATA, ((0x2 << 30) | (0x140 << 20) | (0x140 << 10) | (0x140 << 0))); + /* route test signals to output */ + DACW(TSTCTRL, (DACR(TSTCTRL) | 0x00001000)); + /* wait for signal lines to stabilize */ + snooze(1000); + + /* do actual detection: all signals paths high == CRT connected */ + if DACR(TSTCTRL & 0x10000000) + { + present = true; + LOG(4,("DAC: CRT detected\n")); + } + else + { + present = false; + LOG(4,("DAC: no CRT detected\n")); + } + + /* kill test signal routing */ + DACW(TSTCTRL, (DACR(TSTCTRL) & 0xffffefff)); + + /* restore output connector setting */ + DACW(OUTPUT, output); + /* restore DAC state */ + DACW(TSTCTRL, dac); + + return present; +} + /*set the mode, brightness is a value from 0->2 (where 1 is equivalent to direct)*/ status_t nv_dac_mode(int mode,float brightness) { diff --git a/src/add-ons/accelerants/nvidia/engine/nv_dac2.c b/src/add-ons/accelerants/nvidia/engine/nv_dac2.c index 81ee411dc7..d5038c6301 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_dac2.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_dac2.c @@ -10,6 +10,59 @@ static status_t nv10_nv20_dac2_pix_pll_find( display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test); +/* see if an analog VGA monitor is connected to DAC */ +bool nv_dac2_crt_connected() +{ + uint32 output, dac; + bool present; + + /* save output connector setting */ + output = DAC2R(OUTPUT); + /* save DAC state */ + dac = DAC2R(TSTCTRL); + + /* shut-off DAC */ + DAC2W(TSTCTRL, (DAC2R(TSTCTRL) | 0x00010000)); + /* select primary head and turn off CRT (and DVI?) outputs */ + DAC2W(OUTPUT, (output & 0x0000feee)); + /* wait for signal lines to stabilize */ + snooze(1000); + /* re-enable CRT output */ + DAC2W(OUTPUT, (DACR(OUTPUT) | 0x00000001)); + + /* setup RGB test signal levels to approx 30% of DAC range and enable them + * (NOTE: testsignal function block resides in DAC1 only (!)) */ + DACW(TSTDATA, ((0x2 << 30) | (0x140 << 20) | (0x140 << 10) | (0x140 << 0))); + /* route test signals to output + * (NOTE: testsignal function block resides in DAC1 only (!)) */ + DACW(TSTCTRL, (DACR(TSTCTRL) | 0x00001000)); + /* wait for signal lines to stabilize */ + snooze(1000); + + /* do actual detection: all signals paths high == CRT connected */ + if DAC2R(TSTCTRL & 0x10000000) + { + present = true; + LOG(4,("DAC2: CRT detected\n")); + } + else + { + present = false; + LOG(4,("DAC2: no CRT detected\n")); + } + + /* kill test signal routing + * (NOTE: testsignal function block resides in DAC1 only (!)) */ + DACW(TSTCTRL, (DACR(TSTCTRL) & 0xffffefff)); + + /* restore output connector setting */ + DAC2W(OUTPUT, output); + /* restore DAC state */ + DAC2W(TSTCTRL, dac); + + return present; +} + /*set the mode, brightness is a value from 0->2 (where 1 is equivalent to direct)*/ status_t nv_dac2_mode(int mode,float brightness) { diff --git a/src/add-ons/accelerants/nvidia/engine/nv_general.c b/src/add-ons/accelerants/nvidia/engine/nv_general.c index 87cce1ee48..01df4e8697 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_general.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_general.c @@ -802,8 +802,9 @@ status_t nv_general_output_select(bool cross) LOG(4,("INIT: switching outputs to be cross-connected\n")); /* enable head 2 on connector 1 */ - /* (b8 = select head for output, - * b0 = enable sync signals on output (if generated)) */ + /* (b8 = select CRTC (head) for output, + * b4 = enable DVI???, + * b0 = enable CRT) */ DACW(OUTPUT, 0x00000101); /* enable head 1 on connector 2 */ DAC2W(OUTPUT, 0x00000001); @@ -830,78 +831,6 @@ status_t nv_general_output_select(bool cross) } } -/*connect CRTC1 to the specified DAC*/ -status_t nv_general_dac_select(int dac) -{ - if (!si->ps.secondary_head) - return B_ERROR; - - /*MISCCTRL, clock src,...*/ - switch(dac) - { - /* G400 */ - case DS_CRTC1DAC_CRTC2MAVEN: - /* connect CRTC1 to pixPLL */ -// DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1); - /* connect CRTC2 to vidPLL, connect CRTC1 to internal DAC and - * enable CRTC2 external video timing reset signal. - * (Setting for MAVEN 'master mode' TVout signal generation.) */ -// CR2W(CTL,(CR2R(CTL)&0xffe00779)|0xD0000002); - /* disable CRTC1 external video timing reset signal */ -// VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)&0x77)); - /* select CRTC2 RGB24 MAFC mode: connects CRTC2 to MAVEN DAC */ -// DXIW(MISCCTRL,(DXIR(MISCCTRL)&0x19)|0x82); - break; - case DS_CRTC1MAVEN_CRTC2DAC: - /* connect CRTC1 to vidPLL */ -// DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x2); - /* connect CRTC2 to pixPLL and internal DAC and - * disable CRTC2 external video timing reset signal */ -// CR2W(CTL,(CR2R(CTL)&0x2fe00779)|0x4|(0x1<<20)); - /* enable CRTC1 external video timing reset signal. - * note: this is nolonger used as G450/G550 cannot do TVout on CRTC1 */ -// VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)|0x88)); - /* select CRTC1 RGB24 MAFC mode: connects CRTC1 to MAVEN DAC */ -// DXIW(MISCCTRL,(DXIR(MISCCTRL)&0x19)|0x02); - break; - /* G450/G550 */ - case DS_CRTC1CON1_CRTC2CON2: - /* connect CRTC1 to pixPLL */ -// DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1); - /* connect CRTC2 to vidPLL, connect CRTC1 to DAC1, disable CRTC2 - * external video timing reset signal, set CRTC2 progressive scan mode - * and disable TVout mode (b12). - * (Setting for MAVEN 'slave mode' TVout signal generation.) */ - //fixme: enable timing resets if TVout is used in master mode! - //otherwise keep it disabled. -// CR2W(CTL,(CR2R(CTL)&0x2de00779)|0x6|(0x0<<20)); - /* connect DAC1 to CON1, CRTC2/'DAC2' to CON2 (monitor mode) */ -// DXIW(OUTPUTCONN,0x09); - /* Select 1.5 Volt MAVEN DAC ref. for monitor mode */ -// DXIW(GENIOCTRL, DXIR(GENIOCTRL) & ~0x40); -// DXIW(GENIODATA, 0x00); - break; - //fixme: toggle PLL's below if possible: - // otherwise toggle PLL's for G400 2nd case? - case DS_CRTC1CON2_CRTC2CON1: - /* connect CRTC1 to pixPLL */ -// DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1); - /* connect CRTC2 to vidPLL and DAC1, disable CRTC2 external - * video timing reset signal, and set CRTC2 progressive scan mode and - * disable TVout mode (b12). */ -// CR2W(CTL,(CR2R(CTL)&0x2de00779)|0x6|(0x1<<20)); - /* connect DAC1 to CON2 (monitor mode), CRTC2/'DAC2' to CON1 */ -// DXIW(OUTPUTCONN,0x05); - /* Select 1.5 Volt MAVEN DAC ref. for monitor mode */ -// DXIW(GENIOCTRL, DXIR(GENIOCTRL) & ~0x40); -// DXIW(GENIODATA, 0x00); - break; - default: - return B_ERROR; - } - return B_OK; -} - /* basic change of card state from VGA to enhanced mode: * Should work from VGA BIOS POST init state. */ static @@ -1014,6 +943,14 @@ status_t nv_general_bios_to_powergraphics() DACW(PLLSEL, 0x10000700); if (si->ps.secondary_head) DACW(PLLSEL, (DACR(PLLSEL) | 0x20000800)); + /* turn on DAC and make sure detection testsignal routing is disabled + * (b16 = disable DAC, + * b12 = enable testsignal output */ + DACW(TSTCTRL, (DACR(TSTCTRL) & 0xfffeefff)); + /* turn on DAC2 if it exists + * (NOTE: testsignal function block resides in DAC1 only (!)) */ + if (si->ps.secondary_head) DAC2W(TSTCTRL, (DAC2R(TSTCTRL) & 0xfffeefff)); + /* turn screen one on */ nv_crtc_dpms(true, true, true); diff --git a/src/add-ons/accelerants/nvidia/engine/nv_proto.h b/src/add-ons/accelerants/nvidia/engine/nv_proto.h index dd3fb8e5d2..8735ead282 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_proto.h +++ b/src/add-ons/accelerants/nvidia/engine/nv_proto.h @@ -2,7 +2,6 @@ status_t nv_general_powerup(void); status_t nv_set_cas_latency(void); status_t nv_general_output_select(bool cross); -status_t nv_general_dac_select(int); status_t nv_general_wait_retrace(void); status_t nv_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row, bool *acc_mode); @@ -32,6 +31,8 @@ void fake_pins(void); void dump_pins(void); /* DAC functions */ +/* see if an analog VGA monitor is connected to DAC */ +bool nv_dac_crt_connected(void); status_t nv_dac_mode(int,float); status_t nv_dac_palette(uint8*,uint8*,uint8*); status_t nv_dac_pix_pll_find(display_mode target,float * result,uint8 *,uint8 *,uint8 *, uint8); @@ -39,6 +40,7 @@ status_t nv_dac_set_pix_pll(display_mode target); status_t g400_dac_set_sys_pll(void); /* DAC2 functions */ +bool nv_dac2_crt_connected(void); status_t nv_dac2_mode(int,float); status_t nv_dac2_palette(uint8*,uint8*,uint8*); status_t nv_dac2_pix_pll_find(display_mode target,float * result,uint8 *,uint8 *,uint8 *, uint8);