xf86-video-ati: Branch 'master' - 6 commits

Dave Airlie airlied at kemper.freedesktop.org
Mon Aug 9 20:27:14 PDT 2010


 src/atombios_crtc.c   |  426 +++++++++++++++++++++++++-------------------------
 src/atombios_output.c |  331 ++++++++++++++++----------------------
 src/radeon.h          |    2 
 src/radeon_atombios.c |    7 
 src/radeon_atombios.h |    2 
 src/radeon_output.c   |    3 
 6 files changed, 369 insertions(+), 402 deletions(-)

New commits:
commit 94bc1b7156cd0866566dc44a823c7e051bb45175
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Aug 10 13:24:52 2010 +1000

    atombios: fixup set crtc source like KMS
    
    This removes a bunch of strict aliasing warnings and fixes the
    codepaths up like the latest KMS code, including a workaround for a bug
    on evergreen.

diff --git a/src/atombios_output.c b/src/atombios_output.c
index 2feacde..8d640be 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -67,8 +67,6 @@ const char *device_name[12] = {
 
 static void do_displayport_link_train(xf86OutputPtr output);
 
-static void atombios_set_output_crtc_source(xf86OutputPtr output);
-
 static int
 atombios_output_dac_setup(xf86OutputPtr output, int action)
 {
@@ -1409,7 +1407,12 @@ atombios_output_dpms(xf86OutputPtr output, int mode)
     }
 }
 
-static void
+union crtc_source_param {
+    SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
+    SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
+};
+
+void
 atombios_set_output_crtc_source(xf86OutputPtr output)
 {
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
@@ -1418,16 +1421,15 @@ atombios_set_output_crtc_source(xf86OutputPtr output)
     radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
     AtomBiosArgRec data;
     unsigned char *space;
-    SELECT_CRTC_SOURCE_PS_ALLOCATION crtc_src_param;
-    SELECT_CRTC_SOURCE_PARAMETERS_V2 crtc_src_param2;
+    union crtc_source_param args;
     int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
     int major, minor;
 
     if (radeon_encoder == NULL)
 	return;
 
-    memset(&crtc_src_param, 0, sizeof(crtc_src_param));
-    memset(&crtc_src_param2, 0, sizeof(crtc_src_param2));
+    memset(&args, 0, sizeof(args));
+
     atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
 
     /*ErrorF("select crtc source table is %d %d\n", major, minor);*/
@@ -1439,55 +1441,54 @@ atombios_set_output_crtc_source(xf86OutputPtr output)
 	case 1:
 	default:
 	    if (IS_AVIVO_VARIANT)
-		crtc_src_param.ucCRTC = radeon_crtc->crtc_id;
+		args.v1.ucCRTC = radeon_crtc->crtc_id;
 	    else {
 		if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1)
-		    crtc_src_param.ucCRTC = radeon_crtc->crtc_id;
+		    args.v1.ucCRTC = radeon_crtc->crtc_id;
 		else
-		    crtc_src_param.ucCRTC = radeon_crtc->crtc_id << 2;
+		    args.v1.ucCRTC = radeon_crtc->crtc_id << 2;
 	    }
 	    switch (radeon_encoder->encoder_id) {
 	    case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
 	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
-		crtc_src_param.ucDevice = ATOM_DEVICE_DFP1_INDEX;
+		args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX;
 		break;
 	    case ENCODER_OBJECT_ID_INTERNAL_LVDS:
 	    case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
 		if (radeon_output->active_device & ATOM_DEVICE_LCD1_SUPPORT)
-		    crtc_src_param.ucDevice = ATOM_DEVICE_LCD1_INDEX;
+		    args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX;
 		else
-		    crtc_src_param.ucDevice = ATOM_DEVICE_DFP3_INDEX;
+		    args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX;
 		break;
 	    case ENCODER_OBJECT_ID_INTERNAL_DVO1:
 	    case ENCODER_OBJECT_ID_INTERNAL_DDI:
 	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-		crtc_src_param.ucDevice = ATOM_DEVICE_DFP2_INDEX;
+		args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX;
 		break;
 	    case ENCODER_OBJECT_ID_INTERNAL_DAC1:
 	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
 		if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
-		    crtc_src_param.ucDevice = ATOM_DEVICE_TV1_INDEX;
+		    args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
 		else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
-		    crtc_src_param.ucDevice = ATOM_DEVICE_CV_INDEX;
+		    args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
 		else
-		    crtc_src_param.ucDevice = ATOM_DEVICE_CRT1_INDEX;
+		    args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
 		break;
 	    case ENCODER_OBJECT_ID_INTERNAL_DAC2:
 	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
 		if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
-		    crtc_src_param.ucDevice = ATOM_DEVICE_TV1_INDEX;
+		    args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
 		else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
-		    crtc_src_param.ucDevice = ATOM_DEVICE_CV_INDEX;
+		    args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
 		else
-		    crtc_src_param.ucDevice = ATOM_DEVICE_CRT2_INDEX;
+		    args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
 		break;
 	    }
-	    data.exec.pspace = &crtc_src_param;
-	    /*ErrorF("device sourced: 0x%x\n", crtc_src_param.ucDevice);*/
+	    /*ErrorF("device sourced: 0x%x\n", args.v1.ucDevice);*/
 	    break;
 	case 2:
-	    crtc_src_param2.ucCRTC = radeon_crtc->crtc_id;
-	    crtc_src_param2.ucEncodeMode = atombios_get_encoder_mode(output);
+	    args.v2.ucCRTC = radeon_crtc->crtc_id;
+	    args.v2.ucEncodeMode = atombios_get_encoder_mode(output);
 	    switch (radeon_encoder->encoder_id) {
 	    case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
 	    case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
@@ -1495,44 +1496,46 @@ atombios_set_output_crtc_source(xf86OutputPtr output)
 	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
  		switch (radeon_output->dig_encoder) {
  		case 0:
- 		    crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
+ 		    args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
  		    break;
  		case 1:
- 		    crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
+ 		    args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
  		    break;
  		case 2:
- 		    crtc_src_param2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
+ 		    args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
  		    break;
  		case 3:
- 		    crtc_src_param2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
+ 		    args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
  		    break;
  		case 4:
- 		    crtc_src_param2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
+ 		    args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
  		    break;
  		case 5:
- 		    crtc_src_param2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
+ 		    args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
  		    break;
  		}
 		break;
+	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+		args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
+		break;
 	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
 		if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
-		    crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+		    args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
 		else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
-		    crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+		    args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
 		else
-		    crtc_src_param2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
+		    args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
 		break;
 	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
 		if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
-		    crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+		    args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
 		else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT))
-		    crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
+		    args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
 		else
-		    crtc_src_param2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
+		    args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
 		break;
 	    }
-	    data.exec.pspace = &crtc_src_param2;
-	    /*ErrorF("device sourced: 0x%x\n", crtc_src_param2.ucEncoderID);*/
+	    /*ErrorF("device sourced: 0x%x\n", args.v2.ucEncoderID);*/
 	    break;
 	}
 	break;
@@ -1541,6 +1544,7 @@ atombios_set_output_crtc_source(xf86OutputPtr output)
 	exit(-1);
     }
 
+    data.exec.pspace = &args;
     data.exec.index = index;
     data.exec.dataSpace = (void *)&space;
 
diff --git a/src/radeon_atombios.h b/src/radeon_atombios.h
index 67f65ca..866c4bf 100644
--- a/src/radeon_atombios.h
+++ b/src/radeon_atombios.h
@@ -288,4 +288,5 @@ radeon_add_encoder(ScrnInfoPtr pScrn, uint32_t encoder_id, uint32_t device_suppo
 extern uint32_t
 radeon_get_encoder_id_from_supported_device(ScrnInfoPtr pScrn, uint32_t supported_device, int dac);
 
+void atombios_set_output_crtc_source(xf86OutputPtr output);
 #endif /*  RHD_ATOMBIOS_H_ */
diff --git a/src/radeon_output.c b/src/radeon_output.c
index 172b871..42aa3ca 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -734,6 +734,9 @@ radeon_mode_prepare(xf86OutputPtr output)
     radeon_dpms(output, DPMSModeOff);
     radeon_crtc_dpms(output->crtc, DPMSModeOff);
 
+    if (IS_AVIVO_VARIANT || info->r4xx_atom)
+        atombios_set_output_crtc_source(output);
+
 }
 
 static void
commit 9bc716eb62d4e0eed2902b92437a42634eef6ba1
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Aug 10 13:23:21 2010 +1000

    atombios: move adjust pixel clock around to follow KMS code flow
    
    This reworks the pixel clock adjusting code to follow the KMS style,
    also fixes warnings in this code.

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 6f083b4..d0ffa07 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -347,6 +347,164 @@ atombios_pick_pll(xf86CrtcPtr crtc)
     }
 }
 
+union adjust_pixel_clock {
+	ADJUST_DISPLAY_PLL_PS_ALLOCATION v1;
+	ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 v3;
+};
+
+static uint32_t atombios_adjust_pll(xf86CrtcPtr crtc, DisplayModePtr mode, int *pll_flags_p)
+{
+    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
+    ScrnInfoPtr pScrn = crtc->scrn;
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+    uint32_t adjusted_clock = mode->Clock;
+    RADEONOutputPrivatePtr radeon_output = NULL;
+    radeon_encoder_ptr radeon_encoder = NULL;
+    xf86OutputPtr output;
+    int pll_flags = 0;
+    int i;
+
+    if (IS_AVIVO_VARIANT) {
+	if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, TRUE))
+	    radeon_crtc->pll_algo = RADEON_PLL_NEW;
+	else
+	    radeon_crtc->pll_algo = RADEON_PLL_OLD;
+    } else {
+	if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, FALSE))
+	    radeon_crtc->pll_algo = RADEON_PLL_NEW;
+	else
+	    radeon_crtc->pll_algo = RADEON_PLL_OLD;
+    }
+
+    if (IS_AVIVO_VARIANT) {
+	if ((info->ChipFamily == CHIP_FAMILY_RS600) ||
+	    (info->ChipFamily == CHIP_FAMILY_RS690) ||
+	    (info->ChipFamily == CHIP_FAMILY_RS740))
+	    pll_flags |= /*RADEON_PLL_USE_FRAC_FB_DIV |*/
+		RADEON_PLL_PREFER_CLOSEST_LOWER;
+	if (IS_DCE32_VARIANT && mode->Clock > 200000) /* range limits??? */
+	    pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+	else
+	    pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+    } else {
+	pll_flags |= RADEON_PLL_LEGACY;
+
+	if (mode->Clock > 200000) /* range limits??? */
+	    pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+	else
+	    pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+    }
+    
+    for (i = 0; i < xf86_config->num_output; i++) {
+	output = xf86_config->output[i];
+	if (output->crtc == crtc) {
+	    radeon_output = output->driver_private;
+	    radeon_encoder = radeon_get_encoder(output);
+	    if (IS_AVIVO_VARIANT) {
+		/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
+		if (radeon_encoder &&
+		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) &&
+		    !IS_DCE3_VARIANT)
+		    adjusted_clock *= 2;
+		if (radeon_output->active_device &
+		    (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) {
+		    pll_flags |= RADEON_PLL_PREFER_CLOSEST_LOWER;
+		    radeon_crtc->pll_algo = RADEON_PLL_OLD;
+		}
+	    } else {
+		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 (IS_DCE3_VARIANT)
+		break;
+	}
+    }
+    
+    if (IS_DCE3_VARIANT) {
+	union adjust_pixel_clock args;
+	int major, minor, index;
+	AtomBiosArgRec data;
+	unsigned char *space;
+
+	memset(&args, 0, sizeof(args));
+
+	index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
+
+	atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
+
+	data.exec.index = index;
+	data.exec.dataSpace = (void *)&space;
+	data.exec.pspace = &args;
+
+	switch(major) {
+	case 1:
+	    switch(minor) {
+	    case 1:
+	    case 2:
+		args.v1.usPixelClock = cpu_to_le16(adjusted_clock / 10);
+		args.v1.ucTransmitterID = radeon_encoder->encoder_id;
+		args.v1.ucEncodeMode = atombios_get_encoder_mode(output);
+
+		ErrorF("before %d\n", args.v1.usPixelClock);
+		if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
+		    adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10;
+		}
+		ErrorF("after %d\n", args.v1.usPixelClock);
+		break;
+	    case 3:
+		args.v3.sInput.usPixelClock = cpu_to_le16(adjusted_clock / 10);
+		args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id;
+		args.v3.sInput.ucEncodeMode = atombios_get_encoder_mode(output);
+		args.v3.sInput.ucDispPllConfig = 0;
+		if (radeon_output->coherent_mode || (args.v3.sInput.ucEncodeMode == ATOM_ENCODER_MODE_DP))
+		    args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_COHERENT_MODE;
+		if (adjusted_clock > 165000)
+		    args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK;
+		// if SS
+		//    args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE;
+
+		ErrorF("before %d 0x%x\n", args.v3.sInput.usPixelClock, args.v3.sInput.ucDispPllConfig);
+		if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
+		    adjusted_clock = args.v3.sOutput.ulDispPllFreq * 10;
+		    if (args.v3.sOutput.ucRefDiv) {
+			pll_flags |= RADEON_PLL_USE_REF_DIV;
+			info->pll.reference_div = args.v3.sOutput.ucRefDiv;
+		    }
+		    if (args.v3.sOutput.ucPostDiv) {
+			pll_flags |= RADEON_PLL_USE_POST_DIV;
+			info->pll.post_div = args.v3.sOutput.ucPostDiv;
+		    }
+		    ErrorF("after %d %d %d\n", args.v3.sOutput.ulDispPllFreq,
+			   args.v3.sOutput.ucRefDiv, args.v3.sOutput.ucPostDiv);
+		}
+		break;
+	    default:
+		ErrorF("%s: Unknown table version %d %d\n", __func__, major, minor);
+		goto out;
+	    }
+	    break;
+	default:
+	    ErrorF("%s: Unknown table version %d %d\n", __func__, major, minor);
+	    goto out;
+	}
+    }
+out:
+    *pll_flags_p = pll_flags;
+    return adjusted_clock;
+}
+				    
+union set_pixel_clock {
+	SET_PIXEL_CLOCK_PS_ALLOCATION base;
+	PIXEL_CLOCK_PARAMETERS v1;
+	PIXEL_CLOCK_PARAMETERS_V2 v2;
+	PIXEL_CLOCK_PARAMETERS_V3 v3;
+	PIXEL_CLOCK_PARAMETERS_V5 v5;
+};
+
 static void
 atombios_crtc_set_dcpll(xf86CrtcPtr crtc)
 {
@@ -357,7 +515,7 @@ atombios_crtc_set_dcpll(xf86CrtcPtr crtc)
     radeon_encoder_ptr radeon_encoder = NULL;
     int index;
     int major, minor, i;
-    PIXEL_CLOCK_PARAMETERS_V5 args;
+    union set_pixel_clock args;
     AtomBiosArgRec data;
     unsigned char *space;
 
@@ -390,25 +548,10 @@ atombios_crtc_set_dcpll(xf86CrtcPtr crtc)
     case 1:
 	switch(minor) {
 	case 5:
-	    args.ucCRTC = ATOM_CRTC_INVALID;
+	    args.v5.ucCRTC = ATOM_CRTC_INVALID;
 	    /* XXX: get this from the firmwareinfo table */
-	    args.usPixelClock = 60000; // 600 Mhz
-	    args.ucPostDiv = info->pll.pll_out_max / 60000;
-	    if (info->pll.reference_freq == 10000) {
-		// 100 Mhz ref clock
-		args.ucRefDiv = 7;
-		args.usFbDiv = cpu_to_le16(84);
-		args.ulFbDivDecFrac = cpu_to_le32(0);
-	    } else {
-		// 27 Mhz ref clock
-		args.ucRefDiv = 2;
-		args.usFbDiv = cpu_to_le16(88);
-		args.ulFbDivDecFrac = cpu_to_le32(888889);
-	    }
-	    args.ucPpll = ATOM_DCPLL;
-	    args.ucMiscInfo = 0; //HDMI depth
-	    args.ucTransmitterID = radeon_encoder->encoder_id;
-	    args.ucEncoderMode = atombios_get_encoder_mode(output);
+	    args.v5.usPixelClock = info->default_dispclk;
+	    args.v5.ucPpll = ATOM_DCPLL;
 	    break;
 	default:
 	    ErrorF("Unknown table version\n");
@@ -439,200 +582,66 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
     ScrnInfoPtr pScrn = crtc->scrn;
     RADEONInfoPtr  info = RADEONPTR(pScrn);
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
     unsigned char *RADEONMMIO = info->MMIO;
     int index;
-    uint32_t sclock = mode->Clock;
+    uint32_t sclock;
     uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
-    int major, minor, i;
-    SET_PIXEL_CLOCK_PS_ALLOCATION spc_param;
-    PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr;
-    PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr;
-    PIXEL_CLOCK_PARAMETERS_V5 *spc5_ptr;
+    int major, minor;
+    union set_pixel_clock args;
     xf86OutputPtr output = NULL;
-    RADEONOutputPrivatePtr radeon_output = NULL;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
     radeon_encoder_ptr radeon_encoder = NULL;
     int pll_flags = 0;
     uint32_t temp;
     AtomBiosArgRec data;
     unsigned char *space;
+    int i;
 
-    memset(&spc_param, 0, sizeof(spc_param));
-
-    if (IS_AVIVO_VARIANT) {
-	if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, TRUE))
-	    radeon_crtc->pll_algo = RADEON_PLL_NEW;
-	else
-	    radeon_crtc->pll_algo = RADEON_PLL_OLD;
-    } else {
-	if (xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, FALSE))
-	    radeon_crtc->pll_algo = RADEON_PLL_NEW;
-	else
-	    radeon_crtc->pll_algo = RADEON_PLL_OLD;
-    }
-
-    if (IS_AVIVO_VARIANT) {
-	if ((info->ChipFamily == CHIP_FAMILY_RS600) ||
-	    (info->ChipFamily == CHIP_FAMILY_RS690) ||
-	    (info->ChipFamily == CHIP_FAMILY_RS740))
-	    pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV | RADEON_PLL_PREFER_CLOSEST_LOWER;
-	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;
-
-	for (i = 0; i < xf86_config->num_output; i++) {
-	    xf86OutputPtr output = xf86_config->output[i];
-	    if (output->crtc == crtc) {
-		radeon_output = output->driver_private;
-		radeon_encoder = radeon_get_encoder(output);
-		/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
-		/* AdjustDisplayPll handles this on DCE3.x */
-		if (radeon_encoder &&
-		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) &&
-		    !IS_DCE3_VARIANT)
-		    sclock *= 2;
-		if (radeon_output->active_device &
-		    (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) {
-		    pll_flags |= RADEON_PLL_PREFER_CLOSEST_LOWER;
-		    radeon_crtc->pll_algo = RADEON_PLL_OLD;
-		}
-	    }
-	}
+    memset(&args, 0, sizeof(args));
 
-	/* disable spread spectrum clocking for now -- thanks Hedy Lamarr */
-	if (IS_DCE4_VARIANT) {
-	    /* XXX 6 crtcs, but only 2 plls */
-	    switch (radeon_crtc->pll_id) {
-	    case ATOM_PPLL1:
-		temp = INREG(EVERGREEN_P1PLL_SS_CNTL);
-		OUTREG(EVERGREEN_P1PLL_SS_CNTL, temp & ~EVERGREEN_PxPLL_SS_EN);
-		break;
-	    case ATOM_PPLL2:
-		temp = INREG(EVERGREEN_P2PLL_SS_CNTL);
-		OUTREG(EVERGREEN_P2PLL_SS_CNTL, temp & ~EVERGREEN_PxPLL_SS_EN);
-		break;
-	    }
-	} else {
-	    if (radeon_crtc->crtc_id == 0) {
-		temp = INREG(AVIVO_P1PLL_INT_SS_CNTL);
-		OUTREG(AVIVO_P1PLL_INT_SS_CNTL, temp & ~1);
-	    } else {
-		temp = INREG(AVIVO_P2PLL_INT_SS_CNTL);
-		OUTREG(AVIVO_P2PLL_INT_SS_CNTL, temp & ~1);
-	    }
+    if (IS_DCE4_VARIANT) {
+	/* XXX 6 crtcs, but only 2 plls */
+	switch (radeon_crtc->pll_id) {
+	case ATOM_PPLL1:
+	    temp = INREG(EVERGREEN_P1PLL_SS_CNTL);
+	    OUTREG(EVERGREEN_P1PLL_SS_CNTL, temp & ~EVERGREEN_PxPLL_SS_EN);
+	    break;
+	case ATOM_PPLL2:
+	    temp = INREG(EVERGREEN_P2PLL_SS_CNTL);
+	    OUTREG(EVERGREEN_P2PLL_SS_CNTL, temp & ~EVERGREEN_PxPLL_SS_EN);
+	    break;
 	}
     } else {
-	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 (radeon_crtc->crtc_id == 0) {
+	    temp = INREG(AVIVO_P1PLL_INT_SS_CNTL);
+	    OUTREG(AVIVO_P1PLL_INT_SS_CNTL, temp & ~1);
+	} else {
+	    temp = INREG(AVIVO_P2PLL_INT_SS_CNTL);
+	    OUTREG(AVIVO_P2PLL_INT_SS_CNTL, temp & ~1);
 	}
-
-	if (mode->Clock > 200000) /* range limits??? */
-	    pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
-	else
-	    pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
     }
 
     if (IS_DCE3_VARIANT) {
-	ADJUST_DISPLAY_PLL_PS_ALLOCATION adjust_pll_param;
-	ADJUST_DISPLAY_PLL_PS_ALLOCATION *adp_ptr;
-	ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 *adp3_ptr;
-
-	/* Can't really do cloning easily on DCE3 cards */
 	for (i = 0; i < xf86_config->num_output; i++) {
 	    output = xf86_config->output[i];
 	    if (output->crtc == crtc) {
-		radeon_output = output->driver_private;
 		radeon_encoder = radeon_get_encoder(output);
 		break;
 	    }
 	}
 
-	if (radeon_output == NULL) {
+	if (output->driver_private == NULL) {
 	    xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "No output assigned to crtc!\n");
 	    return;
 	}
-
 	if (radeon_encoder == NULL) {
 	    xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "No encoder assigned to output!\n");
 	    return;
 	}
-
-	memset(&adjust_pll_param, 0, sizeof(adjust_pll_param));
-
-	index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
-	atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
-
-	data.exec.index = index;
-	data.exec.dataSpace = (void *)&space;
-	data.exec.pspace = &adjust_pll_param;
-
-	switch(major) {
-	case 1:
-	    switch(minor) {
-	    case 1:
-	    case 2:
-		adp_ptr = (ADJUST_DISPLAY_PLL_PS_ALLOCATION*)&adjust_pll_param.usPixelClock;
-		adp_ptr->usPixelClock = cpu_to_le16(sclock / 10);
-		adp_ptr->ucTransmitterID = radeon_encoder->encoder_id;
-		adp_ptr->ucEncodeMode = atombios_get_encoder_mode(output);
-
-		ErrorF("before %d\n", adp_ptr->usPixelClock);
-		if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
-		    sclock = le16_to_cpu(adp_ptr->usPixelClock) * 10;
-		}
-		ErrorF("after %d\n", adp_ptr->usPixelClock);
-		break;
-	    case 3:
-		adp3_ptr = (ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3*)&adjust_pll_param.usPixelClock;
-		adp3_ptr->sInput.usPixelClock = cpu_to_le16(sclock / 10);
-		adp3_ptr->sInput.ucTransmitterID = radeon_encoder->encoder_id;
-		adp3_ptr->sInput.ucEncodeMode = atombios_get_encoder_mode(output);
-		adp3_ptr->sInput.ucDispPllConfig = 0;
-		if (radeon_output->coherent_mode || (adp3_ptr->sInput.ucEncodeMode == ATOM_ENCODER_MODE_DP))
-		    adp3_ptr->sInput.ucDispPllConfig |= DISPPLL_CONFIG_COHERENT_MODE;
-		if (sclock > 165000)
-		    adp3_ptr->sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK;
-		// if SS
-		//    adp3_ptr->sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE;
-
-		ErrorF("before %d 0x%x\n", adp3_ptr->sInput.usPixelClock, adp3_ptr->sInput.ucDispPllConfig);
-		if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
-		    sclock = adp3_ptr->sOutput.ulDispPllFreq * 10;
-		    if (adp3_ptr->sOutput.ucRefDiv) {
-			pll_flags |= RADEON_PLL_USE_REF_DIV;
-			info->pll.reference_div = adp3_ptr->sOutput.ucRefDiv;
-		    }
-		    if (adp3_ptr->sOutput.ucPostDiv) {
-			pll_flags |= RADEON_PLL_USE_POST_DIV;
-			info->pll.post_div = adp3_ptr->sOutput.ucPostDiv;
-		    }
-		    ErrorF("after %d %d %d\n", adp3_ptr->sOutput.ulDispPllFreq,
-			   adp3_ptr->sOutput.ucRefDiv, adp3_ptr->sOutput.ucPostDiv);
-		}
-		break;
-	    default:
-		ErrorF("Unknown table version\n");
-		exit(-1);
-	    }
-	    break;
-	default:
-	    ErrorF("Unknown table version\n");
-	    exit(-1);
-	}
     }
 
+    sclock = atombios_adjust_pll(crtc, mode, &pll_flags);
+
     RADEONComputePLL(crtc, &info->pll, sclock, &temp,
 		     &fb_div, &frac_fb_div, &ref_div, &post_div, pll_flags);
     sclock = temp; /* 10 khz */
@@ -654,40 +663,37 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 	switch(minor) {
 	case 1:
 	case 2:
-	    spc2_ptr = (PIXEL_CLOCK_PARAMETERS_V2*)&spc_param.sPCLKInput;
-	    spc2_ptr->usPixelClock = cpu_to_le16(mode->Clock / 10);
-	    spc2_ptr->usRefDiv = cpu_to_le16(ref_div);
-	    spc2_ptr->usFbDiv = cpu_to_le16(fb_div);
-	    spc2_ptr->ucFracFbDiv = frac_fb_div;
-	    spc2_ptr->ucPostDiv = post_div;
-	    spc2_ptr->ucPpll = radeon_crtc->pll_id;
-	    spc2_ptr->ucCRTC = radeon_crtc->crtc_id;
-	    spc2_ptr->ucRefDivSrc = 1;
+	    args.v2.usPixelClock = cpu_to_le16(mode->Clock / 10);
+	    args.v2.usRefDiv = cpu_to_le16(ref_div);
+	    args.v2.usFbDiv = cpu_to_le16(fb_div);
+	    args.v2.ucFracFbDiv = frac_fb_div;
+	    args.v2.ucPostDiv = post_div;
+	    args.v2.ucPpll = radeon_crtc->pll_id;
+	    args.v2.ucCRTC = radeon_crtc->crtc_id;
+	    args.v2.ucRefDivSrc = 1;
 	    break;
 	case 3:
-	    spc3_ptr = (PIXEL_CLOCK_PARAMETERS_V3*)&spc_param.sPCLKInput;
-	    spc3_ptr->usPixelClock = cpu_to_le16(mode->Clock / 10);
-	    spc3_ptr->usRefDiv = cpu_to_le16(ref_div);
-	    spc3_ptr->usFbDiv = cpu_to_le16(fb_div);
-	    spc3_ptr->ucFracFbDiv = frac_fb_div;
-	    spc3_ptr->ucPostDiv = post_div;
-	    spc3_ptr->ucPpll = radeon_crtc->pll_id;
-	    spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2);
-	    spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id;
-	    spc3_ptr->ucEncoderMode = atombios_get_encoder_mode(output);
+	    args.v3.usPixelClock = cpu_to_le16(mode->Clock / 10);
+	    args.v3.usRefDiv = cpu_to_le16(ref_div);
+	    args.v3.usFbDiv = cpu_to_le16(fb_div);
+	    args.v3.ucFracFbDiv = frac_fb_div;
+	    args.v3.ucPostDiv = post_div;
+	    args.v3.ucPpll = radeon_crtc->pll_id;
+	    args.v3.ucMiscInfo = (radeon_crtc->crtc_id << 2);
+	    args.v3.ucTransmitterId = radeon_encoder->encoder_id;
+	    args.v3.ucEncoderMode = atombios_get_encoder_mode(output);
 	    break;
 	case 5:
-	    spc5_ptr = (PIXEL_CLOCK_PARAMETERS_V5*)&spc_param.sPCLKInput;
-	    spc5_ptr->ucCRTC = radeon_crtc->crtc_id;
-	    spc5_ptr->usPixelClock = cpu_to_le16(mode->Clock / 10);
-	    spc5_ptr->ucRefDiv = ref_div;
-	    spc5_ptr->usFbDiv = cpu_to_le16(fb_div);
-	    spc5_ptr->ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000);
-	    spc5_ptr->ucPostDiv = post_div;
-	    spc5_ptr->ucPpll = radeon_crtc->pll_id;
-	    spc5_ptr->ucMiscInfo = 0; //HDMI depth
-	    spc5_ptr->ucTransmitterID = radeon_encoder->encoder_id;
-	    spc5_ptr->ucEncoderMode = atombios_get_encoder_mode(output);
+	    args.v5.ucCRTC = radeon_crtc->crtc_id;
+	    args.v5.usPixelClock = cpu_to_le16(mode->Clock / 10);
+	    args.v5.ucRefDiv = ref_div;
+	    args.v5.usFbDiv = cpu_to_le16(fb_div);
+	    args.v5.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000);
+	    args.v5.ucPostDiv = post_div;
+	    args.v5.ucPpll = radeon_crtc->pll_id;
+	    args.v5.ucMiscInfo = 0; //HDMI depth
+	    args.v5.ucTransmitterID = radeon_encoder->encoder_id;
+	    args.v5.ucEncoderMode = atombios_get_encoder_mode(output);
 	    break;
 	default:
 	    ErrorF("Unknown table version\n");
@@ -701,7 +707,7 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 
     data.exec.index = index;
     data.exec.dataSpace = (void *)&space;
-    data.exec.pspace = &spc_param;
+    data.exec.pspace = &args;
 
     if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
 	ErrorF("Set CRTC %d PLL success\n", radeon_crtc->crtc_id);
commit 31de43bf9d9eb93cc2b2150474ea7404beabe49d
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Aug 10 13:21:39 2010 +1000

    displayport: retry on timeout
    
    this is ported from KMS

diff --git a/src/atombios_output.c b/src/atombios_output.c
index ee024a6..2feacde 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -2002,6 +2002,7 @@ RADEONProcessAuxCH(xf86OutputPtr output, uint8_t *req_bytes, uint8_t num_bytes,
     AtomBiosArgRec data;
     unsigned char *space;
     unsigned char *base;
+    int retry_count = 0;
 
     memset(&args, 0, sizeof(args));
     if (info->atomBIOS->fbBase)
@@ -2011,6 +2012,7 @@ RADEONProcessAuxCH(xf86OutputPtr output, uint8_t *req_bytes, uint8_t num_bytes,
     else
 	return FALSE;
 
+retry:
     memcpy(base, req_bytes, num_bytes);
 
     args.v1.lpAuxRequest = 0;
@@ -2026,9 +2028,11 @@ RADEONProcessAuxCH(xf86OutputPtr output, uint8_t *req_bytes, uint8_t num_bytes,
     data.exec.pspace = &args;
 
     RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data);
-    if (args.v1.ucReplyStatus) {
-	ErrorF("failed to get auxch %02x%02x %02x %02x %02x\n",
-	       req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3], args.v1.ucReplyStatus);
+    if (args.v1.ucReplyStatus && !args.v1.ucDataOutLen) {
+	if (args.v1.ucReplyStatus == 0x20 && retry_count++ < 10)
+		goto retry;
+	ErrorF("failed to get auxch %02x%02x %02x %02x %02x after %d retries\n",
+	       req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3], args.v1.ucReplyStatus, retry_count);
 	return FALSE;
     }
     if (args.v1.ucDataOutLen && read_byte && read_buf_len) {
@@ -2066,7 +2070,7 @@ RADEONDPEncoderService(xf86OutputPtr output, int action, uint8_t ucconfig, uint8
 
     RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data);
 
-    ErrorF("%s: %d\n", __func__, args.ucStatus);
+    ErrorF("%s: %d %d\n", __func__, action, args.ucStatus);
     return args.ucStatus;
 }
 
commit 9ef67335583d36080d227e8bce1966afe08e0486
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Aug 10 13:21:01 2010 +1000

    evergreen: don't call YUV table on evergreen

diff --git a/src/atombios_output.c b/src/atombios_output.c
index 5ccf50d..ee024a6 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -1693,7 +1693,7 @@ atombios_output_mode_set(xf86OutputPtr output,
     atombios_output_scaler_setup(output);
     atombios_set_output_crtc_source(output);
 
-    if (IS_AVIVO_VARIANT) {
+    if (IS_AVIVO_VARIANT && !IS_DCE4_VARIANT) {
 	if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
 	    atombios_output_yuv_setup(output, TRUE);
 	else
commit 1cce55e8ba43e7958cb67147aeaeb068826ab99f
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Aug 10 13:20:13 2010 +1000

    evergreen: add support to parse firmware info for ext dp clk

diff --git a/src/atombios_output.c b/src/atombios_output.c
index 003b8f8..5ccf50d 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -729,7 +729,7 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t
 	}
 
 	// select the PLL for the UNIPHY
-	if (radeon_output->MonType == MT_DP)
+	if (radeon_output->MonType == MT_DP && info->dp_extclk)
 	    disp_data.v3.acConfig.ucRefClkSource = 2; /* ext clk */
 	else
 	    disp_data.v3.acConfig.ucRefClkSource = radeon_output->pll_id;
diff --git a/src/radeon.h b/src/radeon.h
index d66cdd9..134a4cf 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -872,6 +872,8 @@ typedef struct {
     Bool              ddc2;
 
     RADEONPLLRec      pll;
+    int               default_dispclk;
+    int               dp_extclk;
 
     int               RamWidth;
     float	      sclk;		/* in MHz */
diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index 996e6ee..61b5372 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -2307,6 +2307,13 @@ RADEONGetATOMClockInfo(ScrnInfoPtr pScrn)
 	    pll->pll_out_min = 64800;
     }
 
+    if (IS_DCE4_VARIANT) {
+	info->default_dispclk =
+	    le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_2_1->ulDefaultDispEngineClkFreq);
+	if (info->default_dispclk == 0)
+	    info->default_dispclk = 60000;
+	info->dp_extclk = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_2_1->usUniphyDPModeExtClkFreq);
+    }
     return TRUE;
 }
 
diff --git a/src/radeon_atombios.h b/src/radeon_atombios.h
index 1f21c46..67f65ca 100644
--- a/src/radeon_atombios.h
+++ b/src/radeon_atombios.h
@@ -194,6 +194,7 @@ typedef struct _atomDataTables
         ATOM_FIRMWARE_INFO_V1_2         *FirmwareInfo_V_1_2;
         ATOM_FIRMWARE_INFO_V1_3         *FirmwareInfo_V_1_3;
         ATOM_FIRMWARE_INFO_V1_4         *FirmwareInfo_V_1_4;
+        ATOM_FIRMWARE_INFO_V2_1         *FirmwareInfo_V_2_1;
     } FirmwareInfo;
     ATOM_DAC_INFO                       *DAC_Info;
     union {
commit bbffd67d3296344e8735b007cdee83146d38369c
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Aug 10 13:14:54 2010 +1000

    atombios: realign digital transmitter/encoder setup with kms

diff --git a/src/atombios_output.c b/src/atombios_output.c
index 3e2d301..003b8f8 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -559,19 +559,40 @@ dp_link_clock_for_mode_clock(RADEONOutputPrivatePtr radeon_output,
  * - 2 DIG encoder blocks.
  * DIG1/2 can drive UNIPHY0/1/2 link A or link B
  *
+ * DCE 4.0
+ * - 3 DIG transmitter blocks UNPHY0/1/2 (links A and B).
+ * Supports up to 6 digital outputs
+ * - 6 DIG encoder blocks.
+ * - DIG to PHY mapping is hardcoded
+ * DIG1 drives UNIPHY0 link A, A+B
+ * DIG2 drives UNIPHY0 link B
+ * DIG3 drives UNIPHY1 link A, A+B
+ * DIG4 drives UNIPHY1 link B
+ * DIG5 drives UNIPHY2 link A, A+B
+ * DIG6 drives UNIPHY2 link B
+ *
  * Routing
  * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
  * Examples:
  * crtc0 -> dig2 -> LVTMA links A+B
  * crtc1 -> dig1 -> UNIPHY0 link B
+ * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
+ * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
  */
+
+union dig_encoder_control {
+	DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
+	DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
+	DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
+};
+
 static int
 atombios_output_dig_encoder_setup(xf86OutputPtr output, int action)
 {
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
     RADEONInfoPtr info       = RADEONPTR(output->scrn);
     radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
-    DIG_ENCODER_CONTROL_PS_ALLOCATION disp_data;
+    union dig_encoder_control disp_data;
     AtomBiosArgRec data;
     unsigned char *space;
     int index = 0, major, minor;
@@ -582,55 +603,49 @@ atombios_output_dig_encoder_setup(xf86OutputPtr output, int action)
 
     memset(&disp_data,0, sizeof(disp_data));
 
-    if (radeon_output->dig_encoder)
+    if (IS_DCE4_VARIANT)
+	index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
+    else if (radeon_output->dig_encoder)
         index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
     else
         index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
 
     atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
 
-    disp_data.ucAction = action;
-    disp_data.usPixelClock = cpu_to_le16(clock / 10);
+    disp_data.v1.ucAction = action;
+    disp_data.v1.usPixelClock = cpu_to_le16(clock / 10);
+    disp_data.v1.ucEncoderMode = atombios_get_encoder_mode(output);
 
-    if (IS_DCE32_VARIANT) {
+    if (disp_data.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
+	if (dp_link_clock_for_mode_clock(radeon_output, clock) == 27000)
+	    disp_data.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
+	disp_data.v1.ucLaneNum = dp_lanes_for_mode_clock(radeon_output, clock);
+    } else if (clock > 165000)
+	disp_data.v1.ucLaneNum = 8;
+    else
+	disp_data.v1.ucLaneNum = 4;
+
+    if (IS_DCE4_VARIANT) {
+	disp_data.v3.acConfig.ucDigSel = radeon_output->dig_encoder;
+	disp_data.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
+    } else {
 	switch (radeon_encoder->encoder_id) {
 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	    disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
+	    disp_data.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
 	    break;
 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-	    disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
+	    disp_data.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
 	    break;
 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-	    disp_data.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
-	    break;
-	}
-    } else {
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	    disp_data.ucConfig = ATOM_ENCODER_CONFIG_UNIPHY;
-	    break;
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-	    disp_data.ucConfig = ATOM_ENCODER_CONFIG_LVTMA;
+	    disp_data.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
 	    break;
 	}
+	if (radeon_output->linkb)
+	    disp_data.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
+	else
+	    disp_data.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
     }
 
-    disp_data.ucEncoderMode = atombios_get_encoder_mode(output);
-
-    if (disp_data.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
-	if (dp_link_clock_for_mode_clock(radeon_output, clock) == 27000)
-	    disp_data.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
-	disp_data.ucLaneNum = dp_lanes_for_mode_clock(radeon_output, clock);
-    } else if (clock > 165000)
-	disp_data.ucLaneNum = 8;
-    else
-	disp_data.ucLaneNum = 4;
-
-    if (radeon_output->linkb)
-	disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
-    else
-	disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
-
     data.exec.index = index;
     data.exec.dataSpace = (void *)&space;
     data.exec.pspace = &disp_data;
@@ -645,54 +660,6 @@ atombios_output_dig_encoder_setup(xf86OutputPtr output, int action)
 
 }
 
-static int
-atombios_dce4_output_dig_encoder_setup(xf86OutputPtr output, int action)
-{
-    RADEONOutputPrivatePtr radeon_output = output->driver_private;
-    RADEONInfoPtr info       = RADEONPTR(output->scrn);
-    radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
-    DIG_ENCODER_CONTROL_PARAMETERS_V3 disp_data;
-    AtomBiosArgRec data;
-    unsigned char *space;
-    int index;
-    int clock = radeon_output->pixel_clock;
-
-    if (radeon_encoder == NULL)
-	return ATOM_NOT_IMPLEMENTED;
-
-    memset(&disp_data,0, sizeof(disp_data));
-
-    index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
-
-    disp_data.ucAction = action;
-    disp_data.usPixelClock = cpu_to_le16(clock / 10);
-    disp_data.ucEncoderMode = atombios_get_encoder_mode(output);
-    disp_data.acConfig.ucDigSel = radeon_output->dig_encoder;
-
-    if (disp_data.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
-	if (dp_link_clock_for_mode_clock(radeon_output, clock) == 27000)
-	    disp_data.acConfig.ucDPLinkRate = 1;
-	disp_data.ucLaneNum = dp_lanes_for_mode_clock(radeon_output, clock);
-    } else if (clock > 165000)
-	disp_data.ucLaneNum = 8;
-    else
-	disp_data.ucLaneNum = 4;
-
-    disp_data.ucBitPerColor = PANEL_8BIT_PER_COLOR;
-
-    data.exec.index = index;
-    data.exec.dataSpace = (void *)&space;
-    data.exec.pspace = &disp_data;
-
-    if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
-	ErrorF("Output DIG%d encoder setup success\n", radeon_output->dig_encoder);
-	return ATOM_SUCCESS;
-    }
-
-    ErrorF("Output DIG%d setup failed\n", radeon_output->dig_encoder);
-    return ATOM_NOT_IMPLEMENTED;
-}
-
 union dig_transmitter_control {
     DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
     DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
@@ -733,25 +700,22 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t
     atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
 
     disp_data.v1.ucAction = action;
+    if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+        disp_data.v1.usInitInfo = radeon_output->connector_object_id;
+    } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+	disp_data.v1.asMode.ucLaneSel = lane_num;
+	disp_data.v1.asMode.ucLaneSet = lane_set;
+    } else {
+	if (radeon_output->MonType == MT_DP) 
+	    disp_data.v1.usPixelClock =
+		cpu_to_le16(dp_link_clock_for_mode_clock(radeon_output, clock));
+	else if (clock > 165000)
+	    disp_data.v1.usPixelClock = cpu_to_le16((clock / 2) / 10);
+	else
+	    disp_data.v1.usPixelClock = cpu_to_le16(clock / 10);
+    }
 
     if (IS_DCE4_VARIANT) {
-	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
-	    disp_data.v3.usInitInfo = radeon_output->connector_object_id;
-	} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
-	    disp_data.v3.asMode.ucLaneSel = lane_num;
-	    disp_data.v3.asMode.ucLaneSet = lane_set;
-	} else {
-	    if (radeon_output->MonType == MT_DP) {
-		disp_data.v3.usPixelClock =
-		    cpu_to_le16(dp_link_clock_for_mode_clock(radeon_output, clock));
-	    } else if (clock > 165000) {
-		disp_data.v3.usPixelClock = cpu_to_le16((clock / 2) / 10);
-		disp_data.v3.acConfig.fDualLinkConnector = 1;
-	    } else {
-		disp_data.v3.usPixelClock = cpu_to_le16(clock / 10);
-	    }
-	}
-
 	if (radeon_output->MonType == MT_DP)
 	    disp_data.v3.ucLaneNum = dp_lanes_for_mode_clock(radeon_output, clock);
 	else if (clock > 165000)
@@ -790,25 +754,10 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t
 	else if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) {
 	    if (radeon_output->coherent_mode)
 		disp_data.v3.acConfig.fCoherentMode = 1;
+	    if (clock > 165000)
+		disp_data.v3.acConfig.fDualLinkConnector = 1;
 	}
     } else if (IS_DCE32_VARIANT) {
-	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
-	    disp_data.v2.usInitInfo = radeon_output->connector_object_id;
-	} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
-	    disp_data.v2.asMode.ucLaneSel = lane_num;
-	    disp_data.v2.asMode.ucLaneSet = lane_set;
-	} else {
-	    if (radeon_output->MonType == MT_DP) {
-		disp_data.v2.usPixelClock =
-		    cpu_to_le16(dp_link_clock_for_mode_clock(radeon_output, clock));
-		disp_data.v2.acConfig.fDPConnector = 1;
-	    } else if (clock > 165000) {
-		disp_data.v2.usPixelClock = cpu_to_le16((clock / 2) / 10);
-		disp_data.v2.acConfig.fDualLinkConnector = 1;
-	    } else {
-		disp_data.v2.usPixelClock = cpu_to_le16(clock / 10);
-	    }
-	}
 	if (radeon_output->dig_encoder)
 	    disp_data.v2.acConfig.ucEncoderSel = 1;
 
@@ -839,21 +788,6 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t
     } else {
 	disp_data.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
 
-	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
-	    disp_data.v1.usInitInfo = radeon_output->connector_object_id;
-	} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
-	    disp_data.v1.asMode.ucLaneSel = lane_num;
-	    disp_data.v1.asMode.ucLaneSet = lane_set;
-	} else {
-	    if (radeon_output->MonType == MT_DP)
-		disp_data.v1.usPixelClock =
-		    cpu_to_le16(dp_link_clock_for_mode_clock(radeon_output, clock));
-	    else if (clock > 165000)
-		disp_data.v1.usPixelClock = cpu_to_le16((clock / 2) / 10);
-	    else
-		disp_data.v1.usPixelClock = cpu_to_le16(clock / 10);
-	}
-
 	if (radeon_output->dig_encoder)
 	    disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
 	else
@@ -880,8 +814,6 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t
 	    }
 	    break;
 	}
-	if (clock > 165000)
-	    disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
 	if (radeon_output->linkb)
 	    disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
 	else
@@ -892,6 +824,8 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t
 	else if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) {
 	    if (radeon_output->coherent_mode)
 		disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
+	    if (clock > 165000)
+		disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
 	}
     }
 
@@ -1415,13 +1349,14 @@ atombios_output_dpms(xf86OutputPtr output, int mode)
     case DPMSModeOn:
 	radeon_encoder->devices |= radeon_output->active_device;
 	if (is_dig) {
-	    atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
+	    if (!IS_DCE4_VARIANT)
+		atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
 	    if (((radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) ||
 		 (radeon_output->ConnectorType == CONNECTOR_EDP)) &&
 		(radeon_output->MonType == MT_DP)) {
 		do_displayport_link_train(output);
 		if (IS_DCE4_VARIANT)
-		    atombios_dce4_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_VIDEO_ON);
+		    atombios_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_VIDEO_ON);
 	    }
 	}
 	else {
@@ -1447,13 +1382,14 @@ atombios_output_dpms(xf86OutputPtr output, int mode)
 	radeon_encoder->devices &= ~(radeon_output->active_device);
 	if (!radeon_encoder->devices) {
 	    if (is_dig) {
+		if (!IS_DCE4_VARIANT)
+		    atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
 		if (((radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) ||
 		     (radeon_output->ConnectorType == CONNECTOR_EDP)) &&
 		    (radeon_output->MonType == MT_DP)) {
 		    if (IS_DCE4_VARIANT)
-			atombios_dce4_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_VIDEO_OFF);
+			atombios_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_VIDEO_OFF);
 		}
-		atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
 	    } else {
 		disp_data.ucAction = ATOM_DISABLE;
 		data.exec.index = index;
@@ -1777,17 +1713,20 @@ atombios_output_mode_set(xf86OutputPtr output,
     case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
 	/* disable encoder and transmitter */
 	/* setup and enable the encoder and transmitter */
-	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-	if (IS_DCE4_VARIANT)
-	    atombios_dce4_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_SETUP);
-	else {
+	if (IS_DCE4_VARIANT) {
+	    atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+	    atombios_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_SETUP);
+	    atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
+	    atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+	} else {
+	    atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
 	    atombios_output_dig_encoder_setup(output, ATOM_DISABLE);
 	    atombios_output_dig_encoder_setup(output, ATOM_ENABLE);
+
+	    atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
+	    atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
+	    atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
 	}
-	atombios_output_dig_encoder_setup(output, ATOM_ENABLE);
-	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
-	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
-	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
 	break;
     case ENCODER_OBJECT_ID_INTERNAL_DDI:
 	atombios_output_ddia_setup(output, ATOM_ENABLE);
@@ -2683,8 +2622,8 @@ static void do_displayport_link_train(xf86OutputPtr output)
 
     /* start local training start */
     if (IS_DCE4_VARIANT) {
-	atombios_dce4_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_LINK_TRAINING_START);
-	atombios_dce4_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1);
+	atombios_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_LINK_TRAINING_START);
+	atombios_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1);
     } else {
 	RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_START, enc_id, 0);
 	RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, enc_id, 0);
@@ -2744,7 +2683,7 @@ static void do_displayport_link_train(xf86OutputPtr output)
     channel_eq = FALSE;
     dp_set_training(output, DP_TRAINING_PATTERN_2);
     if (IS_DCE4_VARIANT)
-	atombios_dce4_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2);
+	atombios_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2);
     else
 	RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, enc_id, 1);
 
@@ -2778,7 +2717,7 @@ static void do_displayport_link_train(xf86OutputPtr output)
 
     dp_set_training(output, DP_TRAINING_PATTERN_DISABLE);
     if (IS_DCE4_VARIANT)
-	atombios_dce4_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE);
+	atombios_output_dig_encoder_setup(output, ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE);
     else
 	RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_COMPLETE, enc_id, 0);
 


More information about the xorg-commit mailing list