xf86-video-ati: Branch 'randr-1.2' - 4 commits

Alex Deucher agd5f at kemper.freedesktop.org
Tue Aug 14 20:45:25 PDT 2007


 src/radeon_display.c |   11 -
 src/radeon_output.c  |  488 ++++++++++++++++++++++++++++++++++++++++++++++++---
 src/radeon_reg.h     |   40 +++-
 3 files changed, 504 insertions(+), 35 deletions(-)

New commits:
diff-tree 6f398cd07ea734dd66a8eac71b629e59123d75b8 (from 366a1d4c240ac93622caff97b652696db99bf2e6)
Author: Alex Deucher <alex at t41p.hsd1.va.comcast.net>
Date:   Tue Aug 14 23:42:32 2007 -0400

    RADEON: Implement improved tv load detection for r300
    
    The previous implementation resulted in false positives
    on occasion.  This method works much more reliably.
    Based on beos code by Thomas Kurschel

diff --git a/src/radeon_output.c b/src/radeon_output.c
index fdf85a9..7f8f406 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -1325,6 +1325,76 @@ radeon_detect_tv_dac(ScrnInfoPtr pScrn, 
 }
 
 static RADEONMonitorType
+r300_detect_tv(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 tmp, dac_cntl2, crtc2_gen_cntl, dac_ext_cntl, tv_dac_cntl;
+    CARD32 gpiopad_a;
+    RADEONMonitorType found = MT_NONE;
+
+    /* save the regs we need */
+    gpiopad_a = INREG(RADEON_GPIOPAD_A);
+    dac_cntl2 = INREG(RADEON_DAC_CNTL2);
+    crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
+    dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL);
+    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
+
+    OUTREGP(RADEON_GPIOPAD_A, 0, ~1 );
+
+    OUTREG(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL );
+
+    OUTREG(RADEON_CRTC2_GEN_CNTL,
+	   RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT );
+
+    OUTREG(RADEON_DAC_EXT_CNTL,
+	   RADEON_DAC2_FORCE_BLANK_OFF_EN |
+	   RADEON_DAC2_FORCE_DATA_EN |
+	   RADEON_DAC_FORCE_DATA_SEL_RGB |
+	   (0xec << RADEON_DAC_FORCE_DATA_SHIFT ));
+
+    OUTREG(RADEON_TV_DAC_CNTL,
+	   RADEON_TV_DAC_STD_NTSC |
+	   (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
+	   (6 << RADEON_TV_DAC_DACADJ_SHIFT ));
+
+    INREG(RADEON_TV_DAC_CNTL);
+
+    usleep(4000);
+
+    OUTREG(RADEON_TV_DAC_CNTL,
+	   RADEON_TV_DAC_NBLANK |
+	   RADEON_TV_DAC_NHOLD |
+	   RADEON_TV_MONITOR_DETECT_EN |
+	   RADEON_TV_DAC_STD_NTSC |
+	   (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
+	   (6 << RADEON_TV_DAC_DACADJ_SHIFT ));
+
+    INREG(RADEON_TV_DAC_CNTL);
+
+    usleep(6000);
+
+    tmp = INREG(RADEON_TV_DAC_CNTL);
+    if ( (tmp & RADEON_TV_DAC_GDACDET) != 0 ) {
+	found = MT_STV;
+	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+		    "S-Video TV connection detected\n");
+    } else if ( (tmp & RADEON_TV_DAC_BDACDET) != 0 ) {
+	found = MT_CTV;
+	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+		    "Composite TV connection detected\n" );
+    }
+
+    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl );
+    OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
+    OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+    OUTREG(RADEON_DAC_CNTL2, dac_cntl2);
+    OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1);
+
+    return found;
+}
+
+static RADEONMonitorType
 radeon_detect_tv(ScrnInfoPtr pScrn)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
@@ -1333,6 +1403,9 @@ radeon_detect_tv(ScrnInfoPtr pScrn)
     CARD32 tv_dac_cntl, tv_pre_dac_mux_cntl, config_cntl;
     RADEONMonitorType found = MT_NONE;
 
+    if (IS_R300_VARIANT)
+	return r300_detect_tv(pScrn);
+
     /* save the regs we need */
     dac_cntl2 = INREG(RADEON_DAC_CNTL2);
     crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL);
diff-tree 366a1d4c240ac93622caff97b652696db99bf2e6 (from 5b4a04c23e3f1ec2490418b111f417c16463c709)
Author: Alex Deucher <alex at t41p.hsd1.va.comcast.net>
Date:   Tue Aug 14 23:25:37 2007 -0400

    RADEON: Turn off tv encoder in disableoutputs()

diff --git a/src/radeon_display.c b/src/radeon_display.c
index da2b82f..4334016 100644
--- a/src/radeon_display.c
+++ b/src/radeon_display.c
@@ -276,6 +276,13 @@ void RADEONDisableDisplays(ScrnInfoPtr p
     }
     RADEONDacPowerSet(pScrn, FALSE, FALSE);
 
+    /* turn off tv-out */
+    if (info->InternalTVOut) {
+	tmp = INREG(RADEON_TV_MASTER_CNTL);
+	tmp &= ~RADEON_TV_ON;
+	OUTREG(RADEON_TV_MASTER_CNTL, tmp);
+    }
+
     /* FP 1 */
     tmp = INREG(RADEON_FP_GEN_CNTL);
     tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
@@ -333,7 +340,7 @@ void RADEONEnableDisplay(xf86OutputPtr o
                     save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
                 } else {
                     tmp = INREG(RADEON_CRTC2_GEN_CNTL);
-                    tmp |= RADEON_CRTC2_CRT2_ON;  
+                    tmp |= RADEON_CRTC2_CRT2_ON;
                     OUTREG(RADEON_CRTC2_GEN_CNTL, tmp);
                     save->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
                 }
@@ -368,7 +375,7 @@ void RADEONEnableDisplay(xf86OutputPtr o
         if (radeon_output->MonType == MT_CRT) {
             if (radeon_output->DACType == DAC_PRIMARY) {
                 tmp = INREG(RADEON_CRTC_EXT_CNTL);
-                tmp &= ~RADEON_CRTC_CRT_ON;       
+                tmp &= ~RADEON_CRTC_CRT_ON;
                 OUTREG(RADEON_CRTC_EXT_CNTL, tmp);
                 save->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON;
             } else if (radeon_output->DACType == DAC_TVDAC) {
diff-tree 5b4a04c23e3f1ec2490418b111f417c16463c709 (from db2a828b2f21b92cd654b309d137204334975b89)
Author: Alex Deucher <alex at t41p.hsd1.va.comcast.net>
Date:   Tue Aug 14 23:11:52 2007 -0400

    RADEON: Make sure RMX is always programmed for crtc1
    
    If the RMX registers are left as programmed by the bios
    this can lead to a blank screen when crtc1 is feeding a
    DAC.  Fix found and reported by Lisa Wu <liswu at ati.com>
    Fixes bug 11985

diff --git a/src/radeon_output.c b/src/radeon_output.c
index c2598dc..fdf85a9 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -825,6 +825,15 @@ static void RADEONInitRMXRegisters(xf86O
     int    yres = mode->VDisplay;
     float  Hratio, Vratio;
 
+    save->fp_vert_stretch = info->SavedReg.fp_vert_stretch &
+	                    RADEON_VERT_STRETCH_RESERVED;
+    save->fp_horz_stretch = info->SavedReg.fp_horz_stretch &
+	                    (RADEON_HORZ_FP_LOOP_STRETCH |
+	                     RADEON_HORZ_AUTO_RATIO_INC);
+
+    if (radeon_output->MonType != MT_LCD && radeon_output->MonType != MT_DFP)
+	return;
+
     if (radeon_output->PanelXRes == 0 || radeon_output->PanelYRes == 0) {
 	Hratio = 1.0;
 	Vratio = 1.0;
@@ -836,12 +845,6 @@ static void RADEONInitRMXRegisters(xf86O
 	Vratio = (float)yres/(float)radeon_output->PanelYRes;
     }
 
-	save->fp_vert_stretch = info->SavedReg.fp_vert_stretch &
-				  RADEON_VERT_STRETCH_RESERVED;
-	save->fp_horz_stretch = info->SavedReg.fp_horz_stretch &
-				  (RADEON_HORZ_FP_LOOP_STRETCH |
-				  RADEON_HORZ_AUTO_RATIO_INC);
-
     if (Hratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) {
 	save->fp_horz_stretch |= ((xres/8-1)<<16);
     } else {
@@ -978,6 +981,9 @@ RADEONInitOutputRegisters(ScrnInfoPtr pS
     Bool IsPrimary = crtc_num == 0 ? TRUE : FALSE;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
 
+    if (crtc_num == 0)
+	RADEONInitRMXRegisters(output, save, mode);
+
     if (radeon_output->MonType == MT_CRT) {
 	if (radeon_output->DACType == DAC_PRIMARY) {
 	    RADEONInitDACRegisters(output, save, mode, IsPrimary);
@@ -985,12 +991,8 @@ RADEONInitOutputRegisters(ScrnInfoPtr pS
 	    RADEONInitDAC2Registers(output, save, mode, IsPrimary);
 	}
     } else if (radeon_output->MonType == MT_LCD) {
-	if (crtc_num == 0)
-	    RADEONInitRMXRegisters(output, save, mode);
 	RADEONInitLVDSRegisters(output, save, mode, IsPrimary);
     } else if (radeon_output->MonType == MT_DFP) {
-	if (crtc_num == 0)
-	    RADEONInitRMXRegisters(output, save, mode);
 	if (radeon_output->TMDSType == TMDS_INT) {
 	    RADEONInitFPRegisters(output, save, mode, IsPrimary);
 	} else {
@@ -1014,16 +1016,15 @@ radeon_mode_set(xf86OutputPtr output, Di
 
     RADEONInitOutputRegisters(pScrn, &info->ModeReg, adjusted_mode, output, radeon_crtc->crtc_id);
 
+    if (radeon_crtc->crtc_id == 0)
+	RADEONRestoreRMXRegisters(pScrn, &info->ModeReg);
+
     switch(radeon_output->MonType) {
     case MT_LCD:
 	ErrorF("restore LVDS\n");
-	if (radeon_crtc->crtc_id == 0)
-	    RADEONRestoreRMXRegisters(pScrn, &info->ModeReg);
 	RADEONRestoreLVDSRegisters(pScrn, &info->ModeReg);
 	break;
     case MT_DFP:
-	if (radeon_crtc->crtc_id == 0)
-	    RADEONRestoreRMXRegisters(pScrn, &info->ModeReg);
 	if (radeon_output->TMDSType == TMDS_INT) {
 	    ErrorF("restore FP\n");
 	    RADEONRestoreFPRegisters(pScrn, &info->ModeReg);
diff-tree db2a828b2f21b92cd654b309d137204334975b89 (from 6fc3ddbbb6fbbee1f6076c776e5b46c0c772b6d4)
Author: Alex Deucher <alex at t41p.hsd1.va.comcast.net>
Date:   Tue Aug 14 22:47:29 2007 -0400

    RADEON: Add load detection
    
    Based on the beos driver by Thomas Kurschel and the
    existing load detection code in this driver.

diff --git a/src/radeon_output.c b/src/radeon_output.c
index d86fbbd..c2598dc 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -149,6 +149,10 @@ static const RADEONTMDSPll default_tmds_
 
 static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, xf86OutputPtr output);
 static void RADEONUpdatePanelSize(xf86OutputPtr output);
+static RADEONMonitorType radeon_detect_tv(ScrnInfoPtr pScrn);
+static RADEONMonitorType radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color);
+static RADEONMonitorType radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color);
+static RADEONMonitorType radeon_detect_ext_dac(ScrnInfoPtr pScrn);
 
 void RADEONPrintPortMap(ScrnInfoPtr pScrn)
 {
@@ -275,6 +279,7 @@ RADEONDisplayDDCConnected(ScrnInfoPtr pS
     return MonType;
 }
 
+#if 0
 static RADEONMonitorType
 RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac)
 {
@@ -519,6 +524,7 @@ RADEONCrtIsPhysicallyConnected(ScrnInfoP
 
     return(bConnected ? MT_CRT : MT_NONE);
 }
+#endif
 
 /* Primary Head (DVI or Laptop Int. panel)*/
 /* A ddc capable display connected on DVI port */
@@ -527,12 +533,28 @@ void RADEONConnectorFindMonitor(ScrnInfo
 {
     RADEONInfoPtr info       = RADEONPTR(pScrn);
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
-    
+
     if (radeon_output->MonType == MT_UNKNOWN) {
-	if ((radeon_output->MonType = RADEONDisplayDDCConnected(pScrn, output)));
-	else if((radeon_output->MonType = RADEONPortCheckNonDDC(pScrn, output)));
-	else if (radeon_output->DACType == DAC_PRIMARY) 
-	    radeon_output->MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(radeon_output->DACType));
+	if (radeon_output->type == OUTPUT_STV || radeon_output->type == OUTPUT_CTV) {
+	    if (info->InternalTVOut)
+		radeon_output->MonType = radeon_detect_tv(pScrn);
+	} else {
+	    radeon_output->MonType = RADEONDisplayDDCConnected(pScrn, output);
+	    if (!radeon_output->MonType) {
+		if (radeon_output->type == OUTPUT_LVDS || radeon_output->type == OUTPUT_DVI)
+		    radeon_output->MonType = RADEONPortCheckNonDDC(pScrn, output);
+		if (!radeon_output->MonType) {
+		    if (radeon_output->DACType == DAC_PRIMARY)
+			radeon_output->MonType = radeon_detect_primary_dac(pScrn, TRUE);
+		    else if (radeon_output->DACType == DAC_TVDAC) {
+			if (info->ChipFamily == CHIP_FAMILY_R200)
+			    radeon_output->MonType = radeon_detect_ext_dac(pScrn);
+			else
+			    radeon_output->MonType = radeon_detect_tv_dac(pScrn, TRUE);
+		    }
+		}
+	    }
+	}
     }
 
     /* update panel info for RMX */
@@ -1029,6 +1051,349 @@ radeon_mode_commit(xf86OutputPtr output)
     RADEONEnableDisplay(output, TRUE);
 }
 
+/* the following functions are based on the load detection code
+ * in the beos radeon driver by Thomas Kurschel and the existing
+ * load detection code in this driver.
+ */
+static RADEONMonitorType
+radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 vclk_ecp_cntl, crtc_ext_cntl;
+    CARD32 dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp;
+    RADEONMonitorType found = MT_NONE;
+
+    /* save the regs we need */
+    vclk_ecp_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
+    crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL);
+    dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL);
+    dac_cntl = INREG(RADEON_DAC_CNTL);
+    dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL);
+
+    tmp = vclk_ecp_cntl &
+	~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb);
+    OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp);
+
+    tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
+    OUTREG(RADEON_CRTC_EXT_CNTL, tmp);
+
+    tmp = RADEON_DAC_FORCE_BLANK_OFF_EN |
+	RADEON_DAC_FORCE_DATA_EN;
+
+    if (color)
+	tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
+    else
+	tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
+
+    if (IS_R300_VARIANT)
+	tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
+    else
+	tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
+
+    OUTREG(RADEON_DAC_EXT_CNTL, tmp);
+
+    tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN);
+    tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
+    OUTREG(RADEON_DAC_CNTL, tmp);
+
+    tmp &= ~(RADEON_DAC_PDWN_R |
+	     RADEON_DAC_PDWN_G |
+	     RADEON_DAC_PDWN_B);
+
+    OUTREG(RADEON_DAC_MACRO_CNTL, tmp);
+
+    usleep(2000);
+
+    if (INREG(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT) {
+	found = MT_CRT;
+	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+		    "Found %s CRT connected to primary DAC\n",
+		    color ? "color" : "bw");
+    }
+
+    /* restore the regs we used */
+    OUTREG(RADEON_DAC_CNTL, dac_cntl);
+    OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
+    OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
+    OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
+    OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl);
+
+    return found;
+}
+
+static RADEONMonitorType
+radeon_detect_ext_dac(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl;
+    CARD32 disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c;
+    CARD32 disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f;
+    CARD32 tmp, crtc2_h_total_disp, crtc2_v_total_disp;
+    CARD32 crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid;
+    RADEONMonitorType found = MT_NONE;
+    int connected = 0;
+    int i = 0;
+
+    /* save the regs we need */
+    gpio_monid = INREG(RADEON_GPIO_MONID);
+    fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL);
+    disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL);
+    crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
+    disp_lin_trans_grph_a = INREG(RADEON_DISP_LIN_TRANS_GRPH_A);
+    disp_lin_trans_grph_b = INREG(RADEON_DISP_LIN_TRANS_GRPH_B);
+    disp_lin_trans_grph_c = INREG(RADEON_DISP_LIN_TRANS_GRPH_C);
+    disp_lin_trans_grph_d = INREG(RADEON_DISP_LIN_TRANS_GRPH_D);
+    disp_lin_trans_grph_e = INREG(RADEON_DISP_LIN_TRANS_GRPH_E);
+    disp_lin_trans_grph_f = INREG(RADEON_DISP_LIN_TRANS_GRPH_F);
+    crtc2_h_total_disp = INREG(RADEON_CRTC2_H_TOTAL_DISP);
+    crtc2_v_total_disp = INREG(RADEON_CRTC2_V_TOTAL_DISP);
+    crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID);
+    crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID);
+
+    tmp = INREG(RADEON_GPIO_MONID);
+    tmp &= ~RADEON_GPIO_A_0;
+    OUTREG(RADEON_GPIO_MONID, tmp);
+
+    OUTREG(RADEON_FP2_GEN_CNTL,
+	   RADEON_FP2_ON |
+	   RADEON_FP2_PANEL_FORMAT |
+	   R200_FP2_SOURCE_SEL_TRANS_UNIT |
+	   RADEON_FP2_DVO_EN |
+	   R200_FP2_DVO_RATE_SEL_SDR);
+
+    OUTREG(RADEON_DISP_OUTPUT_CNTL,
+	   RADEON_DISP_DAC_SOURCE_RMX |
+	   RADEON_DISP_TRANS_MATRIX_GRAPHICS);
+
+    OUTREG(RADEON_CRTC2_GEN_CNTL,
+	   RADEON_CRTC2_EN |
+	   RADEON_CRTC2_DISP_REQ_EN_B);
+
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
+
+    OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
+    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
+    OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
+    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
+
+    for (i = 0; i < 200; i++) {
+	tmp = INREG(RADEON_GPIO_MONID);
+	if (tmp & RADEON_GPIO_Y_0)
+	    connected = 1;
+	else
+	    connected = 0;
+
+	if (!connected)
+	    break;
+
+	usleep(1000);
+    }
+
+    if (connected)
+	found = MT_CRT;
+
+    /* restore the regs we used */
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e);
+    OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f);
+    OUTREG(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp);
+    OUTREG(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp);
+    OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid);
+    OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid);
+    OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+    OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+    OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+    OUTREG(RADEON_GPIO_MONID, gpio_monid);
+
+    return found;
+}
+
+static RADEONMonitorType
+radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
+    CARD32 disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
+    RADEONMonitorType found = MT_NONE;
+
+    /* save the regs we need */
+    pixclks_cntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
+    if (IS_R300_VARIANT) {
+	gpiopad_a = INREG(RADEON_GPIOPAD_A);
+	disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL);
+    } else {
+	disp_hw_debug = INREG(RADEON_DISP_HW_DEBUG);
+    }
+    crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
+    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
+    dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL);
+    dac_cntl2 = INREG(RADEON_DAC_CNTL2);
+
+    tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb
+			   | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
+    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
+
+    if (IS_R300_VARIANT) {
+	OUTREGP(RADEON_GPIOPAD_A, 1, ~1 );
+    }
+
+    tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
+    tmp |= RADEON_CRTC2_CRT2_ON |
+	(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
+
+    OUTREG(RADEON_CRTC2_GEN_CNTL, tmp);
+
+    if (IS_R300_VARIANT) {
+	tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
+	tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
+	OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp);
+    } else {
+	tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
+	OUTREG(RADEON_DISP_HW_DEBUG, tmp);
+    }
+
+    tmp = RADEON_TV_DAC_NBLANK |
+	RADEON_TV_DAC_NHOLD |
+	RADEON_TV_MONITOR_DETECT_EN |
+	RADEON_TV_DAC_STD_PS2;
+
+    OUTREG(RADEON_TV_DAC_CNTL, tmp);
+
+    tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN |
+	RADEON_DAC2_FORCE_DATA_EN;
+
+    if (color)
+	tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB;
+    else
+	tmp |= RADEON_DAC_FORCE_DATA_SEL_G;
+
+    if (IS_R300_VARIANT)
+	tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
+    else
+	tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
+
+    OUTREG(RADEON_DAC_EXT_CNTL, tmp);
+
+    tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN;
+    OUTREG(RADEON_DAC_CNTL2, tmp);
+
+    usleep(10000);
+
+    if (IS_R300_VARIANT) {
+	if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B) {
+	    found = MT_CRT;
+	    xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+			"Found %s CRT connected to TV DAC\n",
+			color ? "color" : "bw");
+	}
+    } else {
+	if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT) {
+	    found = MT_CRT;
+	    xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+			"Found %s CRT connected to TV DAC\n",
+			color ? "color" : "bw");
+	}
+    }
+
+    /* restore regs we used */
+    OUTREG(RADEON_DAC_CNTL2, dac_cntl2);
+    OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
+    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl);
+    OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+
+    if (IS_R300_VARIANT) {
+	OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+	OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1 );
+    } else {
+	OUTREG(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+    }
+    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, pixclks_cntl);
+
+    return found;
+}
+
+static RADEONMonitorType
+radeon_detect_tv(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 tmp, dac_cntl2, crtc_ext_cntl, crtc2_gen_cntl, tv_master_cntl;
+    CARD32 tv_dac_cntl, tv_pre_dac_mux_cntl, config_cntl;
+    RADEONMonitorType found = MT_NONE;
+
+    /* save the regs we need */
+    dac_cntl2 = INREG(RADEON_DAC_CNTL2);
+    crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL);
+    tv_master_cntl = INREG(RADEON_TV_MASTER_CNTL);
+    tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
+    config_cntl = INREG(RADEON_CONFIG_CNTL);
+    tv_pre_dac_mux_cntl = INREG(RADEON_TV_PRE_DAC_MUX_CNTL);
+
+    tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL;
+    OUTREG(RADEON_DAC_CNTL2, tmp);
+
+    tmp = tv_master_cntl | RADEON_TV_ON;
+    tmp &= ~(RADEON_TV_ASYNC_RST |
+	     RADEON_RESTART_PHASE_FIX |
+	     RADEON_CRT_FIFO_CE_EN |
+	     RADEON_TV_FIFO_CE_EN |
+	     RADEON_RE_SYNC_NOW_SEL_MASK);
+    tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST;
+
+    OUTREG(RADEON_TV_MASTER_CNTL, tmp);
+
+    tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD |
+	RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC |
+	(8 << RADEON_TV_DAC_BGADJ_SHIFT);
+
+    if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK)
+	tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT);
+    else
+	tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT);
+
+    OUTREG(RADEON_TV_DAC_CNTL, tmp);
+
+    tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN |
+	RADEON_RED_MX_FORCE_DAC_DATA |
+	RADEON_GRN_MX_FORCE_DAC_DATA |
+	RADEON_BLU_MX_FORCE_DAC_DATA |
+	(0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT);
+
+    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tmp);
+
+    usleep(3000);
+
+    tmp = INREG(RADEON_TV_DAC_CNTL);
+    if (tmp & RADEON_TV_DAC_GDACDET) {
+	found = MT_STV;
+	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+		    "S-Video TV connection detected\n");
+    } else if (tmp & RADEON_TV_DAC_BDACDET) {
+	found = MT_CTV;
+	xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+		    "Composite TV connection detected\n" );
+    }
+
+    OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl);
+    OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl);
+    OUTREG(RADEON_TV_MASTER_CNTL, tv_master_cntl);
+    OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
+    OUTREG(RADEON_DAC_CNTL2, dac_cntl2);
+
+    return found;
+}
+
 static xf86OutputStatus
 radeon_detect(xf86OutputPtr output)
 {
@@ -1037,15 +1402,8 @@ radeon_detect(xf86OutputPtr output)
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
     Bool connected = TRUE;
 
-    /* assume tv is disconnected for now */
-    if (radeon_output->type == OUTPUT_STV) {
-	radeon_output->MonType = MT_NONE;
-    } else if (radeon_output->type == OUTPUT_CTV) {
-	radeon_output->MonType = MT_NONE;
-    } else {
-	radeon_output->MonType = MT_UNKNOWN;
-	RADEONConnectorFindMonitor(pScrn, output);
-    }
+    radeon_output->MonType = MT_UNKNOWN;
+    RADEONConnectorFindMonitor(pScrn, output);
 
     /* force montype based on output property */
     if (radeon_output->type == OUTPUT_DVI) {
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index db2057a..4e4d874 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -325,6 +325,8 @@
 #       define RADEON_CRTC2_HSYNC_TRISTAT   (1 <<  5)
 #       define RADEON_CRTC2_VSYNC_TRISTAT   (1 <<  6)
 #       define RADEON_CRTC2_CRT2_ON         (1 <<  7)
+#       define RADEON_CRTC2_PIX_WIDTH_SHIFT 8
+#       define RADEON_CRTC2_PIX_WIDTH_MASK  (0xf << 8)
 #       define RADEON_CRTC2_ICON_EN         (1 << 15)
 #       define RADEON_CRTC2_CUR_EN          (1 << 16)
 #       define RADEON_CRTC2_CUR_MODE_MASK   (7 << 20)
@@ -335,8 +337,8 @@
 #       define RADEON_CRTC2_HSYNC_DIS       (1 << 28)
 #       define RADEON_CRTC2_VSYNC_DIS       (1 << 29)
 #define RADEON_CRTC_MORE_CNTL               0x27c
-#       define RADEON_CRTC_H_CUTOFF_ACTIVE_EN (1<<4)   
-#       define RADEON_CRTC_V_CUTOFF_ACTIVE_EN (1<<5)   
+#       define RADEON_CRTC_H_CUTOFF_ACTIVE_EN (1<<4)
+#       define RADEON_CRTC_V_CUTOFF_ACTIVE_EN (1<<5)
 #define RADEON_CRTC_GUI_TRIG_VLINE          0x0218
 #define RADEON_CRTC_H_SYNC_STRT_WID         0x0204
 #       define RADEON_CRTC_H_SYNC_STRT_PIX        (0x07  <<  0)
@@ -457,6 +459,7 @@
 
 #define RADEON_DAC_CNTL                     0x0058
 #       define RADEON_DAC_RANGE_CNTL        (3 <<  0)
+#       define RADEON_DAC_RANGE_CNTL_PS2    (2 <<  0)
 #       define RADEON_DAC_RANGE_CNTL_MASK   0x03
 #       define RADEON_DAC_BLANKING          (1 <<  2)
 #       define RADEON_DAC_CMP_EN            (1 <<  3)
@@ -471,10 +474,21 @@
 #       define RADEON_DAC2_DAC_CLK_SEL      (1 <<  0)
 #       define RADEON_DAC2_DAC2_CLK_SEL     (1 <<  1)
 #       define RADEON_DAC2_PALETTE_ACC_CTL  (1 <<  5)
+#       define RADEON_DAC2_CMP_EN           (1 <<  7)
+#       define RADEON_DAC2_CMP_OUT_R        (1 <<  8)
+#       define RADEON_DAC2_CMP_OUT_G        (1 <<  9)
+#       define RADEON_DAC2_CMP_OUT_B        (1 << 10)
+#       define RADEON_DAC2_CMP_OUTPUT       (1 << 11)
 #define RADEON_DAC_EXT_CNTL                 0x0280
-#       define RADEON_DAC_FORCE_BLANK_OFF_EN (1 << 4)
-#       define RADEON_DAC_FORCE_DATA_EN      (1 << 5)
+#       define RADEON_DAC2_FORCE_BLANK_OFF_EN (1 << 0)
+#       define RADEON_DAC2_FORCE_DATA_EN      (1 << 1)
+#       define RADEON_DAC_FORCE_BLANK_OFF_EN  (1 << 4)
+#       define RADEON_DAC_FORCE_DATA_EN       (1 << 5)
 #       define RADEON_DAC_FORCE_DATA_SEL_MASK (3 << 6)
+#       define RADEON_DAC_FORCE_DATA_SEL_R    (0 << 6)
+#       define RADEON_DAC_FORCE_DATA_SEL_G    (1 << 6)
+#       define RADEON_DAC_FORCE_DATA_SEL_B    (2 << 6)
+#       define RADEON_DAC_FORCE_DATA_SEL_RGB  (3 << 6)
 #       define RADEON_DAC_FORCE_DATA_MASK   0x0003ff00
 #       define RADEON_DAC_FORCE_DATA_SHIFT  8
 #define RADEON_DAC_MACRO_CNTL               0x0d04
@@ -494,10 +508,15 @@
 #       define RADEON_TV_DAC_STD_RS343      (3 <<  8)
 #       define RADEON_TV_DAC_BGSLEEP        (1 <<  6)
 #       define RADEON_TV_DAC_BGADJ_MASK     (0xf <<  16)
+#       define RADEON_TV_DAC_BGADJ_SHIFT    16
 #       define RADEON_TV_DAC_DACADJ_MASK    (0xf <<  20)
+#       define RADEON_TV_DAC_DACADJ_SHIFT   20
 #       define RADEON_TV_DAC_RDACPD         (1 <<  24)
 #       define RADEON_TV_DAC_GDACPD         (1 <<  25)
 #       define RADEON_TV_DAC_BDACPD         (1 <<  26)
+#       define RADEON_TV_DAC_RDACDET        (1 << 29)
+#       define RADEON_TV_DAC_GDACDET        (1 << 30)
+#       define RADEON_TV_DAC_BDACDET        (1 << 31)
 #       define R420_TV_DAC_DACADJ_MASK      (0x1f <<  20)
 #       define R420_TV_DAC_RDACPD           (1 <<  25)
 #       define R420_TV_DAC_GDACPD           (1 <<  26)
@@ -509,10 +528,18 @@
 #       define RADEON_DISP_DAC_SOURCE_MASK  0x03
 #       define RADEON_DISP_DAC2_SOURCE_MASK  0x0c
 #       define RADEON_DISP_DAC_SOURCE_CRTC2 0x01
+#       define RADEON_DISP_DAC_SOURCE_RMX   0x02
+#       define RADEON_DISP_DAC_SOURCE_LTU   0x03
 #       define RADEON_DISP_DAC2_SOURCE_CRTC2 0x04
 #       define RADEON_DISP_TVDAC_SOURCE_MASK  (0x03 << 2)
 #       define RADEON_DISP_TVDAC_SOURCE_CRTC  0x0
 #       define RADEON_DISP_TVDAC_SOURCE_CRTC2 (0x01 << 2)
+#       define RADEON_DISP_TVDAC_SOURCE_RMX   (0x02 << 2)
+#       define RADEON_DISP_TVDAC_SOURCE_LTU   (0x03 << 2)
+#       define RADEON_DISP_TRANS_MATRIX_MASK  (0x03 << 4)
+#       define RADEON_DISP_TRANS_MATRIX_ALPHA_MSB (0x00 << 4)
+#       define RADEON_DISP_TRANS_MATRIX_GRAPHICS  (0x01 << 4)
+#       define RADEON_DISP_TRANS_MATRIX_VIDEO     (0x02 << 4)
 #       define RADEON_DISP_TV_SOURCE_CRTC   (1 << 16) /* crtc1 or crtc2 */
 #       define RADEON_DISP_TV_SOURCE_LTU    (0 << 16) /* linear transform unit */
 #define RADEON_DISP_TV_OUT_CNTL             0x0d6c
@@ -756,6 +783,7 @@
 #       define R200_FP2_SOURCE_SEL_CRTC1       (0 <<  10)
 #       define R200_FP2_SOURCE_SEL_CRTC2       (1 << 10)
 #       define R200_FP2_SOURCE_SEL_RMX         (2 << 10)
+#       define R200_FP2_SOURCE_SEL_TRANS_UNIT  (3 << 10)
 #       define RADEON_FP2_SRC_SEL_MASK         (3 << 13)
 #       define RADEON_FP2_SRC_SEL_CRTC2        (1 << 13)
 #       define RADEON_FP2_FP_POL               (1 << 16)
@@ -767,6 +795,7 @@
 #       define RADEON_FP2_CRC_READ_EN          (1 << 24)
 #       define RADEON_FP2_DVO_EN               (1 << 25)
 #       define RADEON_FP2_DVO_RATE_SEL_SDR     (1 << 26)
+#       define R200_FP2_DVO_RATE_SEL_SDR       (1 << 27)
 #define RADEON_FP_H_SYNC_STRT_WID           0x02c4
 #define RADEON_FP_H2_SYNC_STRT_WID          0x03c4
 #define RADEON_FP_HORZ_STRETCH              0x028c
@@ -923,6 +952,7 @@
 #define RADEON_MDGPIO_A_REG                 0x01ac
 #define RADEON_MDGPIO_EN_REG                0x01b0
 #define RADEON_MDGPIO_MASK                  0x0198
+#define RADEON_GPIOPAD_A		    0x019c
 #define RADEON_MDGPIO_Y_REG                 0x01b4
 #define RADEON_MEM_ADDR_CONFIG              0x0148
 #define RADEON_MEM_BASE                     0x0f10 /* PCI */
@@ -3091,6 +3121,7 @@
 #	define RADEON_DVS_ASYNC_RST		 (1 <<  7)
 #       define RADEON_CRT_FIFO_CE_EN             (1 <<  9)
 #       define RADEON_TV_FIFO_CE_EN              (1 << 10)
+#       define RADEON_RE_SYNC_NOW_SEL_MASK       (3 << 14)
 #       define RADEON_TVCLK_ALWAYS_ONb           (1 << 30)
 #	define RADEON_TV_ON			 (1 << 31)
 #define RADEON_TV_PRE_DAC_MUX_CNTL               0x0888
@@ -3215,7 +3246,6 @@
 #       define RADEON_TVPDC_MASK                 (3 << 14)
 #       define RADEON_TVPLL_TEST_DIS             (1 << 31)
 #       define RADEON_TVCLK_SRC_SEL_TVPLL        (1 << 30)
-#define RADEON_GPIOPAD_A			     0x019c
 
 #define RADEON_RS480_UNK_e30			0xe30
 #define RADEON_RS480_UNK_e34			0xe34


More information about the xorg-commit mailing list