xf86-video-ati: Branch 'displayport' - 225 commits

Dave Airlie airlied at kemper.freedesktop.org
Wed Nov 25 15:38:19 PST 2009


Rebased ref, commits from common ancestor:
commit 256de862a3c017dcb4ed0d8689294a552eda0d18
Author: Dave Airlie <airlied at redhat.com>
Date:   Thu Nov 26 06:35:39 2009 +1000

    displayport: cleanup call dp from dpms on instead.

diff --git a/src/atombios_output.c b/src/atombios_output.c
index 9c2cb92..b608a17 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -65,7 +65,7 @@ const char *device_name[12] = {
     "DFP5",
 };
 
-static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode);
+static void do_displayport_dance(xf86OutputPtr output);
 
 static void atombios_set_output_crtc_source(xf86OutputPtr output);
 
@@ -1337,8 +1337,12 @@ atombios_output_dpms(xf86OutputPtr output, int mode)
     switch (mode) {
     case DPMSModeOn:
 	radeon_encoder->devices |= radeon_output->active_device;
-	if (is_dig)
+	if (is_dig) {
 	    atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
+	    if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT && radeon_output->MonType == MT_DP) {
+	      do_displayport_dance(output);
+	    }
+	}
 	else {
 	    disp_data.ucAction = ATOM_ENABLE;
 	    data.exec.index = index;
@@ -1599,9 +1603,6 @@ atombios_output_mode_set(xf86OutputPtr output,
 	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);
-	if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT && radeon_output->MonType == MT_DP) {
-	    do_displayport_dance(output, mode, adjusted_mode);
-	}
 	break;
     case ENCODER_OBJECT_ID_INTERNAL_DDI:
 	atombios_output_ddia_setup(output, ATOM_ENABLE);
@@ -2433,7 +2434,7 @@ static int radeon_dp_link_required(int pixel_clock)
     return pixel_clock * 3;
 }
 
-static Bool radeon_dp_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+Bool radeon_dp_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
 {
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
     int lane_count, clock;
@@ -2461,7 +2462,7 @@ static Bool radeon_dp_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, Disp
     return FALSE;
 }
 
-static void radeon_dp_mode_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+static void radeon_dp_mode_set(xf86OutputPtr output)
 {
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
     memset(radeon_output->dp_link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
@@ -2483,41 +2484,43 @@ static void dp_update_dpvs_emph(xf86OutputPtr output, uint8_t train_set[4])
     atom_dp_aux_native_write(output, DP_TRAINING_LANE0_SET, radeon_output->dp_lane_count, train_set);
 }
 
-static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+static void do_displayport_dance(xf86OutputPtr output)
 {
     ScrnInfoPtr pScrn = output->scrn;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
-    int num_lane = dp_lanes_for_mode_clock(radeon_output, mode->Clock);
-    int dp_clock = dp_link_clock_for_mode_clock(radeon_output, mode->Clock);
+    int num_lane = radeon_output->dp_lane_count;
     int enc_id = atom_dp_get_encoder_id(output);
     Bool clock_recovery;
     uint8_t link_status[DP_LINK_STATUS_SIZE];
     uint8_t tries, voltage, ss_cntl;
     uint8_t train_set[4];
-    Bool ret;
     int i;
     Bool channel_eq;
 
+
     /* see if the link is trained */
+#if 0
     if (atom_dp_get_link_status(output, link_status)) {
 	ErrorF("XXXXXXXXXXXXXXXXXX\n");
 	if (dp_channel_eq_ok(link_status, radeon_output->dp_lane_count))
 	    return;
     }
+#endif
 
-    ErrorF("Doing displayport DANCE lanes:%d %d\n", num_lane, dp_clock);
+    ErrorF("Doing displayport DANCE lanes:%d\n", num_lane);
 
+#if 0
     ret = radeon_dp_mode_fixup(output, mode, adjusted_mode);
     if (ret == FALSE) {
 	ErrorF("Doing displayport DANCE failed to fixup\n");
 	return;
     }
-
+#endif
     memset(train_set, 0, 4);
 
     ErrorF("radeon_dp_mode_set\n");
     /* set up link configuration */
-    radeon_dp_mode_set(output, mode, adjusted_mode);
+    radeon_dp_mode_set(output);
 
     ErrorF("dp_set_power\n");
     /* power up to D0 */
diff --git a/src/radeon.h b/src/radeon.h
index 231ffda..69a0416 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -1250,6 +1250,7 @@ extern void RADEONSetOutputType(ScrnInfoPtr pScrn,
 extern Bool RADEONSetupConnectors(ScrnInfoPtr pScrn);
 extern Bool RADEONI2CDoLock(xf86OutputPtr output, I2CBusPtr b, Bool lock_state);
 
+extern Bool radeon_dp_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode);
 
 /* radeon_tv.c */
 extern void RADEONSaveTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save);
diff --git a/src/radeon_output.c b/src/radeon_output.c
index 9ed266f..82f1409 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -669,6 +669,9 @@ radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 	}
     }
 
+    if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT && radeon_output->MonType == MT_DP) {
+      radeon_dp_mode_fixup(output, mode, adjusted_mode);
+    }
     return TRUE;
 }
 
commit 543338842ba7fe7da4902947d386ea1cabd1cdf0
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Fri Nov 20 16:38:43 2009 -0500

    dp fix timing
    
    aux channel atom command table delay is 10 usec units
    this gets the link training working, but alas, no image.

diff --git a/src/atombios_output.c b/src/atombios_output.c
index 726b647..9c2cb92 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -1890,7 +1890,7 @@ RADEONProcessAuxCH(xf86OutputPtr output, uint8_t *req_bytes, uint8_t num_bytes,
     args.lpDataOut = 16;
     args.ucDataOutLen = 0;
     args.ucChannelID = radeon_output->ucI2cId;
-    args.ucDelay = delay;
+    args.ucDelay = delay / 10; /* 10 usec */
 
     data.exec.index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction);
     data.exec.dataSpace = (void *)&space;
@@ -2498,6 +2498,13 @@ static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, Disp
     int i;
     Bool channel_eq;
 
+    /* see if the link is trained */
+    if (atom_dp_get_link_status(output, link_status)) {
+	ErrorF("XXXXXXXXXXXXXXXXXX\n");
+	if (dp_channel_eq_ok(link_status, radeon_output->dp_lane_count))
+	    return;
+    }
+
     ErrorF("Doing displayport DANCE lanes:%d %d\n", num_lane, dp_clock);
 
     ret = radeon_dp_mode_fixup(output, mode, adjusted_mode);
@@ -2551,7 +2558,7 @@ static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, Disp
     for (;;) {
       	usleep(100);
 	ErrorF("atom_dp_get_link_status\n");
-	if (atom_dp_get_link_status(output, link_status))
+	if (!atom_dp_get_link_status(output, link_status))
 	    break;
 
 	ErrorF("dp_clock_recovery_ok\n");
commit df35d40d4ec260cdab57a9b36e4e96b2a6c2a827
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Nov 19 20:01:42 2009 -0500

    DP: hack that makes DP work.
    
    Something's wrong with the status check.

diff --git a/src/atombios_output.c b/src/atombios_output.c
index 0c705e8..726b647 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -2551,7 +2551,7 @@ static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, Disp
     for (;;) {
       	usleep(100);
 	ErrorF("atom_dp_get_link_status\n");
-	if (!atom_dp_get_link_status(output, link_status))
+	if (atom_dp_get_link_status(output, link_status))
 	    break;
 
 	ErrorF("dp_clock_recovery_ok\n");
commit f42412ec4dbd21f562a7fe4239c0a1f17ef1b8f2
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Nov 19 19:40:54 2009 -0500

    wip

diff --git a/src/atombios_output.c b/src/atombios_output.c
index a4dd4af..0c705e8 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -2010,7 +2010,7 @@ void RADEON_DP_GetDPCP(xf86OutputPtr output)
 		ErrorF("%02x ", radeon_output->dpcp8[i]);
 	    ErrorF("\n");
 	}
-	ret = atom_dp_aux_native_read(output, 0x100, 0, 2, msg);
+	ret = atom_dp_aux_native_read(output, DP_LINK_BW_SET, 0, 2, msg);
 	if (ret) {
 	    ErrorF("0x200: %02x %02x\n", msg[0], msg[1]);
 	}
@@ -2492,7 +2492,7 @@ static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, Disp
     int enc_id = atom_dp_get_encoder_id(output);
     Bool clock_recovery;
     uint8_t link_status[DP_LINK_STATUS_SIZE];
-    uint8_t tries, voltage;
+    uint8_t tries, voltage, ss_cntl;
     uint8_t train_set[4];
     Bool ret;
     int i;
@@ -2522,9 +2522,14 @@ static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, Disp
 
     ErrorF("atom_dp_aux_native_write - link rate / num /framing\n");
     /* write link rate / num / eh framing */
-    atom_dp_aux_native_write(output, 0x100, 2,
+    atom_dp_aux_native_write(output, DP_LINK_BW_SET, 2,
 			     radeon_output->dp_link_configuration);
 
+    /* write ss cntl */
+    ss_cntl = 0;
+    atom_dp_aux_native_write(output, DP_DOWNSPREAD_CTRL, 1,
+			     &ss_cntl);
+
     ErrorF("RADEONDPEncoderService - ATOM_DP_ACTION_TRAINING_START\n");
     /* start local training start */
     RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_START, enc_id, 0);
commit 54c09778d79de1516ee511d6d7d5b54dd4bf9130
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Nov 19 13:32:30 2009 -0500

    DP wip
    
    - use coherent
    - fix up lane/clock numbers

diff --git a/src/atombios_output.c b/src/atombios_output.c
index 213e18a..a4dd4af 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -468,37 +468,76 @@ atombios_get_encoder_mode(xf86OutputPtr output)
 }
 
 static const int dp_clocks[] = {
-    54000,
-    81000,
-    108000,
-    162000,
-    0,
-    0,
-    100000,
-    324000,
+    5400,  // 1 lane, 1.62 Ghz
+    9000,  // 1 lane, 2.70 Ghz
+    10800, // 2 lane, 1.62 Ghz
+    18000, // 2 lane, 2.70 Ghz
+    21600, // 4 lane, 1.62 Ghz
+    36000, // 4 lane, 2.70 Ghz
 };
 static const int num_dp_clocks = sizeof(dp_clocks) / sizeof(int);
 
+# define DP_LINK_BW_1_62                    0x06
+# define DP_LINK_BW_2_7                     0x0a
+
 static int
-dp_lanes_for_mode_clock(int mode_clock)
+dp_lanes_for_mode_clock(RADEONOutputPrivatePtr radeon_output,
+			int mode_clock)
 {
     int i;
+    int max_link_bw = radeon_output->dpcp8[1];
 
-    for (i = 0; i < num_dp_clocks; i++)
-	if (dp_clocks[i] > (mode_clock / 10))
-	    return (i / 2) + 1;
+    switch (max_link_bw) {
+    case DP_LINK_BW_1_62:
+    default:
+	for (i = 0; i < num_dp_clocks; i++) {
+	    if (i % 2)
+		continue;
+	    if (dp_clocks[i] > (mode_clock / 10)) {
+		if (i < 2)
+		    return 1;
+		else if (i < 4)
+		    return 2;
+		else
+		    return 4;
+	    }
+	}
+	break;
+    case DP_LINK_BW_2_7:
+	for (i = 0; i < num_dp_clocks; i++) {
+	    if (dp_clocks[i] > (mode_clock / 10)) {
+		if (i < 2)
+		    return 1;
+		else if (i < 4)
+		    return 2;
+		else
+		    return 4;
+	    }
+	}
+        break;
+    }
 
     return 0;
 }
 
 static int
-dp_link_clock_for_mode_clock(int mode_clock)
+dp_link_clock_for_mode_clock(RADEONOutputPrivatePtr radeon_output,
+			     int mode_clock)
 {
     int i;
+    int max_link_bw = radeon_output->dpcp8[1];
 
-    for (i = 0; i < num_dp_clocks; i++)
-	if (dp_clocks[i] > (mode_clock / 10))
-	    return (i % 2) ? 27000 : 16200;
+    switch (max_link_bw) {
+    case DP_LINK_BW_1_62:
+    default:
+	return 16200;
+	break;
+    case DP_LINK_BW_2_7:
+	for (i = 0; i < num_dp_clocks; i++)
+	    if (dp_clocks[i] > (mode_clock / 10))
+		return (i % 2) ? 27000 : 16200;
+        break;
+    }
 
     return 0;
 }
@@ -600,9 +639,9 @@ atombios_output_dig_encoder_setup(xf86OutputPtr output, int action)
     disp_data.ucEncoderMode = atombios_get_encoder_mode(output);
 
     if (disp_data.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
-	if (dp_link_clock_for_mode_clock(clock) == 27000)
+	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(clock);
+	disp_data.ucLaneNum = dp_lanes_for_mode_clock(radeon_output, clock);
     } else if (clock > 165000)
 	disp_data.ucLaneNum = 8;
     else
@@ -677,7 +716,7 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t
 	} else {
 	    if (radeon_output->MonType == MT_DP) {
 		disp_data.v2.usPixelClock =
-		    cpu_to_le16(dp_link_clock_for_mode_clock(clock));
+		    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);
@@ -708,7 +747,7 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t
 	}
 
 	if (radeon_output->MonType == MT_DP)
-	    disp_data.v2.acConfig.fCoherentMode = 0;
+	    disp_data.v2.acConfig.fCoherentMode = 1; /* DP requires coherent */
 	else if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) {
 	    if (radeon_output->coherent_mode) {
 		disp_data.v2.acConfig.fCoherentMode = 1;
@@ -727,7 +766,7 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t
 	} else {
 	    if (radeon_output->MonType == MT_DP)
 		disp_data.v1.usPixelClock =
-		    cpu_to_le16(dp_link_clock_for_mode_clock(clock));
+		    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
@@ -773,9 +812,10 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t
 	else
 	    disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
 
-	if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) {
-	    if (radeon_output->coherent_mode &&
-		radeon_output->MonType != MT_DP) {
+	if (radeon_output->MonType == MT_DP)
+	    disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;  /* DP requires coherent */
+	else if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) {
+	    if (radeon_output->coherent_mode) {
 		disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
 		xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
 			"DIG%d transmitter: Coherent Mode enabled\n", num);
@@ -1716,8 +1756,8 @@ atombios_dac_detect(xf86OutputPtr output)
 
 /* from intel i830_dp.h */
 #define DP_LINK_BW_SET          0x100
-# define DP_LINK_BW_1_62                    0x06
-# define DP_LINK_BW_2_7                     0x0a
+//# define DP_LINK_BW_1_62                    0x06
+//# define DP_LINK_BW_2_7                     0x0a
 #define DP_LANE_COUNT_SET       0x101
 # define DP_LANE_COUNT_MASK                 0x0f
 # define DP_LANE_COUNT_ENHANCED_FRAME_EN    (1 << 7)
@@ -2447,8 +2487,8 @@ static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, Disp
 {
     ScrnInfoPtr pScrn = output->scrn;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
-    int num_lane = dp_lanes_for_mode_clock(mode->Clock);
-    int dp_clock = dp_link_clock_for_mode_clock(mode->Clock);
+    int num_lane = dp_lanes_for_mode_clock(radeon_output, mode->Clock);
+    int dp_clock = dp_link_clock_for_mode_clock(radeon_output, mode->Clock);
     int enc_id = atom_dp_get_encoder_id(output);
     Bool clock_recovery;
     uint8_t link_status[DP_LINK_STATUS_SIZE];
@@ -2468,37 +2508,48 @@ static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, Disp
 
     memset(train_set, 0, 4);
 
+    ErrorF("radeon_dp_mode_set\n");
     /* set up link configuration */
     radeon_dp_mode_set(output, mode, adjusted_mode);
 
+    ErrorF("dp_set_power\n");
     /* power up to D0 */
     dp_set_power(output, DP_SET_POWER_D0);
 
+    ErrorF("dp_set_training\n");
     /* disable training */
     dp_set_training(output, DP_TRAINING_PATTERN_DISABLE);
 
+    ErrorF("atom_dp_aux_native_write - link rate / num /framing\n");
     /* write link rate / num / eh framing */
     atom_dp_aux_native_write(output, 0x100, 2,
 			     radeon_output->dp_link_configuration);
 
+    ErrorF("RADEONDPEncoderService - ATOM_DP_ACTION_TRAINING_START\n");
     /* start local training start */
     RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_START, enc_id, 0);
 
+    ErrorF("RADEONDPEncoderService - ATOM_DP_ACTION_TRAINING_PATTERN_SEL\n");
     RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, enc_id, 0);
 
+    ErrorF("dp_update_dpvs_emph\n");
     dp_update_dpvs_emph(output, train_set);
     usleep(400);
+    ErrorF("dp_set_training - DP_TRAINING_PATTERN_1\n");
     dp_set_training(output, DP_TRAINING_PATTERN_1);
 
+    ErrorF("start loop 1\n");
     /* loop around doing configuration reads and DP encoder setups */
     clock_recovery = FALSE;
     tries = 0;
     voltage = 0xff;
     for (;;) {
       	usleep(100);
+	ErrorF("atom_dp_get_link_status\n");
 	if (!atom_dp_get_link_status(output, link_status))
 	    break;
 
+	ErrorF("dp_clock_recovery_ok\n");
 	if (dp_clock_recovery_ok(link_status, num_lane)) {
 	    clock_recovery = TRUE;
 	    break;
@@ -2526,11 +2577,13 @@ static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, Disp
 
 	voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
 
+	ErrorF("dp_get_adjust_train\n");
         dp_get_adjust_train(output, link_status, radeon_output->dp_lane_count, train_set);
+	ErrorF("dp_update_dpvs_emph\n");
 	dp_update_dpvs_emph(output, train_set);
 
     }
-
+    ErrorF("end loop 1\n");
     if (!clock_recovery)
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "clock recovery failed\n");
@@ -2544,15 +2597,20 @@ static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, Disp
     /* channel equalization */
     tries = 0;
     channel_eq = FALSE;
+    ErrorF("dp_set_training - DP_TRAINING_PATTERN_2\n");
     dp_set_training(output, DP_TRAINING_PATTERN_2);
+    ErrorF("RADEONDPEncoderService - ATOM_DP_ACTION_TRAINING_PATTERN_SEL\n");
     RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, enc_id, 1);
 
+    ErrorF("start loop 2\n");
     for (;;) {
 
 	usleep(400);
+	ErrorF("atom_dp_get_link_status\n");
 	if (!atom_dp_get_link_status(output, link_status))
 	    break;
 
+	ErrorF("dp_channel_eq_ok\n");
 	if (dp_channel_eq_ok(link_status, radeon_output->dp_lane_count)) {
 	    channel_eq = TRUE;
 	    break;
@@ -2566,12 +2624,14 @@ static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, Disp
 	}
 
 	/* Compute new train_set as requested by target */
+	ErrorF("dp_get_adjust_train\n");
         dp_get_adjust_train(output, link_status, radeon_output->dp_lane_count, train_set);
+	ErrorF("dp_update_dpvs_emph\n");
 	dp_update_dpvs_emph(output, train_set);
 
 	++tries;
     }
-
+    ErrorF("end loop 2\n");
     if (!channel_eq)
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "channel eq failed\n");
@@ -2582,8 +2642,9 @@ static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, Disp
 		   (train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK)
 		   >> DP_TRAIN_PRE_EMPHASIS_SHIFT);
 
-
+    ErrorF("dp_set_training - DP_TRAINING_PATTERN_DISABLE\n");
     dp_set_training(output, DP_TRAINING_PATTERN_DISABLE);
+    ErrorF("RADEONDPEncoderService - ATOM_DP_ACTION_TRAINING_COMPLETE\n");
     RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_COMPLETE, enc_id, 0);
 
 }
commit 605c869076985b69350c893cf2bbcc90de8dc6bf
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Nov 18 01:51:12 2009 -0500

    more dp cleanup
    
    - clean up handling of linkb, etc.
    - add support for ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH
    to existing transmitter control function
    - fix lots of warnings

diff --git a/src/atombios_output.c b/src/atombios_output.c
index 7b2742d..213e18a 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -503,6 +503,28 @@ dp_link_clock_for_mode_clock(int mode_clock)
     return 0;
 }
 
+/*
+ * DIG Encoder/Transmitter Setup
+ *
+ * DCE 3.0/3.1
+ * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
+ * Supports up to 3 digital outputs
+ * - 2 DIG encoder blocks.
+ * DIG1 can drive UNIPHY link A or link B
+ * DIG2 can drive UNIPHY link B or LVTMA
+ *
+ * DCE 3.2
+ * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
+ * Supports up to 5 digital outputs
+ * - 2 DIG encoder blocks.
+ * DIG1/2 can drive UNIPHY0/1/2 link A or link B
+ *
+ * Routing
+ * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
+ * Examples:
+ * crtc0 -> dig2 -> LVTMA links A+B
+ * crtc1 -> dig1 -> UNIPHY0 link B
+ */
 static int
 atombios_output_dig_encoder_setup(xf86OutputPtr output, int action)
 {
@@ -530,6 +552,9 @@ atombios_output_dig_encoder_setup(xf86OutputPtr output, int action)
     } else {
 	switch (radeon_encoder->encoder_id) {
 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	    /* doesn't really matter which dig encoder we pick as long as it's
+	     * not already in use
+	     */
 	    if (radeon_output->linkb)
 		index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
 	    else
@@ -537,6 +562,7 @@ atombios_output_dig_encoder_setup(xf86OutputPtr output, int action)
 	    num = 1;
 	    break;
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+	    /* Only dig2 encoder can drive LVTMA */
 	    index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
 	    num = 2;
 	    break;
@@ -574,26 +600,18 @@ atombios_output_dig_encoder_setup(xf86OutputPtr output, int action)
     disp_data.ucEncoderMode = atombios_get_encoder_mode(output);
 
     if (disp_data.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
-	if (radeon_output->linkb)
-	    disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
-	else
-	    disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
-
 	if (dp_link_clock_for_mode_clock(clock) == 27000)
 	    disp_data.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
-
 	disp_data.ucLaneNum = dp_lanes_for_mode_clock(clock);
-    } else if (clock > 165000) {
-	disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA_B;
+    } else if (clock > 165000)
 	disp_data.ucLaneNum = 8;
-    } else {
-	if (radeon_output->linkb)
-	    disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
-	else
-	    disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
-
+    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;
@@ -615,7 +633,7 @@ union dig_transmitter_control {
 };
 
 static int
-atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action)
+atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t lane_num, uint8_t lane_set)
 {
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
     RADEONInfoPtr info       = RADEONPTR(output->scrn);
@@ -653,6 +671,9 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action)
     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 =
@@ -668,6 +689,9 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action)
 	if (dig_block)
 	    disp_data.v2.acConfig.ucEncoderSel = 1;
 
+	if (radeon_output->linkb)
+	    disp_data.v2.acConfig.ucLinkSel = 1;
+
 	switch (radeon_encoder->encoder_id) {
 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
 	    disp_data.v2.acConfig.ucTransmitterSel = 0;
@@ -697,6 +721,9 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int 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.v2.asMode.ucLaneSel = lane_num;
+	    disp_data.v2.asMode.ucLaneSet = lane_set;
 	} else {
 	    if (radeon_output->MonType == MT_DP)
 		disp_data.v1.usPixelClock =
@@ -709,21 +736,20 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action)
 
 	switch (radeon_encoder->encoder_id) {
 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	    /* doesn't really matter which dig encoder we pick as long as it's
+	     * not already in use
+	     */
 	    if (radeon_output->linkb)
 		disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
 	    else
 		disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
 	    if (info->IsIGP) {
 		if (clock > 165000) {
-		    disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
-					      ATOM_TRANSMITTER_CONFIG_LINKA_B);
-
 		    if (radeon_output->igp_lane_info & 0x3)
 			disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
 		    else if (radeon_output->igp_lane_info & 0xc)
 			disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
 		} else {
-		    disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
 		    if (radeon_output->igp_lane_info & 0x1)
 			disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
 		    else if (radeon_output->igp_lane_info & 0x2)
@@ -733,35 +759,19 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action)
 		    else if (radeon_output->igp_lane_info & 0x8)
 			disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
 		}
-	    } else {
-		if (clock > 165000)
-		    disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
-					      ATOM_TRANSMITTER_CONFIG_LINKA_B |
-					      ATOM_TRANSMITTER_CONFIG_LANE_0_7);
-		else {
-		    /* XXX */
-		    if (radeon_output->linkb)
-			disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
-		    else
-			disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
-		}
 	    }
 	    break;
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+	    /* Only dig2 encoder can drive LVTMA */
 	    disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
-	    if (clock > 165000)
-		disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
-					  ATOM_TRANSMITTER_CONFIG_LINKA_B |
-					  ATOM_TRANSMITTER_CONFIG_LANE_0_7);
-	    else {
-		/* XXX */
-		if (radeon_output->linkb)
-		    disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
-		else
-		    disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
-	    }
 	    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
+	    disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
 
 	if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) {
 	    if (radeon_output->coherent_mode &&
@@ -1288,7 +1298,7 @@ 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);
+	    atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
 	else {
 	    disp_data.ucAction = ATOM_ENABLE;
 	    data.exec.index = index;
@@ -1312,7 +1322,7 @@ atombios_output_dpms(xf86OutputPtr output, int mode)
 	radeon_encoder->devices &= ~(radeon_output->active_device);
 	if (!radeon_encoder->devices) {
 	    if (is_dig)
-		atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT);
+		atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
 	    else {
 		disp_data.ucAction = ATOM_DISABLE;
 		data.exec.index = index;
@@ -1420,10 +1430,18 @@ atombios_set_output_crtc_source(xf86OutputPtr output)
 			crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
 		    else
 			crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
-		} else
-		    crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
+		} else {
+		    /* doesn't really matter which dig encoder we pick as long as it's
+		     * not already in use
+		     */
+		    if (radeon_output->linkb)
+			crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
+		    else
+			crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
+		}
 		break;
 	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		/* Only dig2 encoder can drive LVTMA */
 		crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
 		break;
 	    case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
@@ -1533,14 +1551,14 @@ atombios_output_mode_set(xf86OutputPtr output,
     case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
     case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
 	/* disable encoder and transmitter */
-	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE);
+	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
 	atombios_output_dig_encoder_setup(output, ATOM_DISABLE);
 
 	/* setup and enable the encoder and transmitter */
 	atombios_output_dig_encoder_setup(output, ATOM_ENABLE);
-	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_INIT);
-	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP);
-	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_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);
 	if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT && radeon_output->MonType == MT_DP) {
 	    do_displayport_dance(output, mode, adjusted_mode);
 	}
@@ -1788,21 +1806,27 @@ static inline int atom_dp_get_encoder_id(xf86OutputPtr output)
 {
     RADEONInfoPtr info       = RADEONPTR(output->scrn);
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    int ret = 0;
     if (IS_DCE32_VARIANT) {
 	if (radeon_output->dig_block)
-	    return ATOM_DP_CONFIG_DIG2_ENCODER;
+	    ret |= ATOM_DP_CONFIG_DIG2_ENCODER;
 	else
-	    return ATOM_DP_CONFIG_DIG1_ENCODER;
+	    ret |= ATOM_DP_CONFIG_DIG1_ENCODER;
+	if (radeon_output->linkb)
+	    ret |= ATOM_DP_CONFIG_LINK_B;
+	else
+	    ret |= ATOM_DP_CONFIG_LINK_A;
     } else {
 	if (radeon_output->linkb)
-	    return ATOM_DP_CONFIG_DIG2_ENCODER;
+	    ret |= ATOM_DP_CONFIG_DIG2_ENCODER | ATOM_DP_CONFIG_LINK_B;
 	else
-	    return ATOM_DP_CONFIG_DIG1_ENCODER;
+	    ret |= ATOM_DP_CONFIG_DIG1_ENCODER | ATOM_DP_CONFIG_LINK_A;
     }
+    return ret;
 }
 
 Bool
-RADEONProcessAuxCH(xf86OutputPtr output, char *req_bytes, int num_bytes,
+RADEONProcessAuxCH(xf86OutputPtr output, uint8_t *req_bytes, uint8_t num_bytes,
 		   uint8_t *read_byte, uint8_t read_buf_len, uint8_t delay)
 {
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
@@ -1854,8 +1878,7 @@ RADEONProcessAuxCH(xf86OutputPtr output, char *req_bytes, int num_bytes,
 static int
 RADEONDPEncoderService(xf86OutputPtr output, int action, uint8_t ucconfig, uint8_t lane_num)
 {
-    RADEONOutputPrivatePtr radeon_output = output->driver_private;
-    RADEONInfoPtr info       = RADEONPTR(output->scrn);
+    RADEONInfoPtr info = RADEONPTR(output->scrn);
     DP_ENCODER_SERVICE_PARAMETERS args;
     AtomBiosArgRec data;
     unsigned char *space;
@@ -1885,100 +1908,6 @@ int RADEON_DP_GetSinkType(xf86OutputPtr output)
     return RADEONDPEncoderService(output, ATOM_DP_ACTION_GET_SINK_TYPE, radeon_output->ucI2cId, 0);
 }
 
-static int
-RADEON_DP_DigTransmitterSetup_VSEMPH(xf86OutputPtr output, uint8_t lane_num, uint8_t lane_set)
-{
-    RADEONOutputPrivatePtr radeon_output = output->driver_private;
-    RADEONInfoPtr info       = RADEONPTR(output->scrn);
-    radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
-    union dig_transmitter_control disp_data;
-    AtomBiosArgRec data;
-    unsigned char *space;
-    int clock = radeon_output->pixel_clock;
-    int dig_block = radeon_output->dig_block;
-    int num = 0;
-    int index = 0;
-    int major, minor;
-
-    if (radeon_encoder == NULL)
-        return ATOM_NOT_IMPLEMENTED;
-
-    memset(&disp_data, 0, sizeof(disp_data));
-
-    if (IS_DCE32_VARIANT)
-	index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
-    else {
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	    if (radeon_output->linkb)
-		index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl);
-	    else
-		index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl);
-	    break;
-	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-	    index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl);
-	    break;
-	}
-    }
-
-    atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
-
-    disp_data.v1.ucAction = ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH;
-
-    disp_data.v1.asMode.ucLaneSel = lane_num;
-    disp_data.v1.asMode.ucLaneSet = lane_set;
-
-    if (IS_DCE32_VARIANT) {
-	disp_data.v2.acConfig.fDPConnector = 1;
-
-	if (dig_block)
-	    disp_data.v2.acConfig.ucEncoderSel = 1;
-
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	    disp_data.v2.acConfig.ucTransmitterSel = 0;
-	    num = 0;
-	    break;
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-	    disp_data.v2.acConfig.ucTransmitterSel = 1;
-	    num = 1;
-	    break;
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-	    disp_data.v2.acConfig.ucTransmitterSel = 2;
-	    num = 2;
-	    break;
-	}
-    } else {
-	switch (radeon_encoder->encoder_id) {
-	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	    if (radeon_output->linkb)
-		disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
-	    else
-		disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
-	    break;
-	    if (info->IsIGP) {
-	    } else {
-
-	    }
-	}
-    }
-    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) {
-	if (IS_DCE32_VARIANT)
-	    ErrorF("Output UNIPHY%d transmitter VSEMPH setup success\n", num);
-	else
-	   ErrorF("Output DIG%d transmitter VSEMPH setup success\n", num);
-	return ATOM_SUCCESS;
-    }
-
-    ErrorF("Output DIG%d transmitter VSEMPH setup failed\n", num);
-    return ATOM_NOT_IMPLEMENTED;
-
-}
-
 static Bool atom_dp_aux_native_write(xf86OutputPtr output, uint16_t address,
 				     uint8_t send_bytes, uint8_t *send)
 {
@@ -2019,7 +1948,7 @@ static Bool atom_dp_aux_native_read(xf86OutputPtr output, uint16_t address,
     msg[3] = (dp_msg_len) << 4;
     msg[3] |= expected_bytes - 1;
 
-    ErrorF("reading %02x %02x %02x, %d\n", msg[0], msg[1], msg[3], expected_bytes, dp_msg_len);
+    ErrorF("reading %02x %02x %02x, %d, %d\n", msg[0], msg[1], msg[3], expected_bytes, dp_msg_len);
     ret = RADEONProcessAuxCH(output, msg, msg_len, read_p, expected_bytes, delay);
     return ret;
 }
@@ -2113,7 +2042,6 @@ atom_dp_i2c_address(I2CDevPtr dev, I2CSlaveAddr addr)
     I2CBusPtr bus = dev->pI2CBus;
     xf86OutputPtr output = bus->DriverPrivate.ptr;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
-    ScrnInfoPtr scrn = output->scrn;
     int ret;
 
     radeon_output->dp_i2c_addr = addr;
@@ -2125,10 +2053,11 @@ atom_dp_i2c_address(I2CDevPtr dev, I2CSlaveAddr addr)
 
     return ret;
 }
-static void
-atom_dp_i2c_start(I2CDevPtr dev)
+static Bool
+atom_dp_i2c_start(I2CBusPtr bus, int timeout)
 {
     ErrorF("%s\n", __func__);
+    return TRUE;
 }
 
 static void
@@ -2137,7 +2066,7 @@ atom_dp_i2c_stop(I2CDevPtr dev)
     I2CBusPtr bus = dev->pI2CBus;
     xf86OutputPtr output = bus->DriverPrivate.ptr;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
-    ScrnInfoPtr scrn = output->scrn;
+
     if (radeon_output->dp_i2c_running)
 	atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr,
 				    dp_aux_i2c_stop, 0, NULL);
@@ -2151,7 +2080,6 @@ atom_dp_i2c_put_byte(I2CDevPtr dev, I2CByte byte)
     I2CBusPtr bus = dev->pI2CBus;
     xf86OutputPtr output = bus->DriverPrivate.ptr;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
-    ScrnInfoPtr scrn = output->scrn;
     Bool ret;
 
     ret = (atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr,
@@ -2165,7 +2093,6 @@ atom_dp_i2c_get_byte(I2CDevPtr dev, I2CByte *byte_ret, Bool last)
     I2CBusPtr bus = dev->pI2CBus;
     xf86OutputPtr output = bus->DriverPrivate.ptr;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
-    ScrnInfoPtr scrn = output->scrn;
     Bool ret;
 
     ret = (atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr,
@@ -2268,7 +2195,6 @@ static Bool
 atom_dp_get_link_status(xf86OutputPtr output,
 			  uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
-    RADEONOutputPrivatePtr radeon_output = output->driver_private;
     ScrnInfoPtr pScrn = output->scrn;
     int ret;
     ret = atom_dp_aux_native_read(output, DP_LANE0_1_STATUS, 100,
@@ -2350,9 +2276,9 @@ static void dp_set_training(xf86OutputPtr output, uint8_t training)
 static Bool
 atom_dp_set_link_train(xf86OutputPtr output, uint8_t dp_train_pat, uint8_t train_set[4])
 {
-    int ret;
-    int enc_id = atom_dp_get_encoder_id(output);
-    int i;
+    //int ret;
+    //int enc_id = atom_dp_get_encoder_id(output);
+    //int i;
     /* set DP encoder training start */
 
     xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
@@ -2368,7 +2294,7 @@ atom_dp_set_link_train(xf86OutputPtr output, uint8_t dp_train_pat, uint8_t train
 
 static void dp_set_power(xf86OutputPtr output, uint8_t power_state)
 {
-    uint8_t pstate;
+    //uint8_t pstate;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
 
     if (radeon_output->dpcp8[0] >= 0x11) {
@@ -2383,7 +2309,6 @@ dp_get_adjust_train(xf86OutputPtr output,
 		      uint8_t train_set[4])
 {
     ScrnInfoPtr pScrn = output->scrn;
-    RADEONInfoPtr info       = RADEONPTR(output->scrn);
     uint8_t v = 0;
     uint8_t p = 0;
     int lane;
@@ -2470,8 +2395,6 @@ static int radeon_dp_link_required(int pixel_clock)
 
 static Bool radeon_dp_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
 {
-    ScrnInfoPtr pScrn = output->scrn;
-    RADEONInfoPtr info       = RADEONPTR(output->scrn);
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
     int lane_count, clock;
     int max_lane_count = radeon_dp_max_lane_count(output);
@@ -2515,7 +2438,7 @@ static void dp_update_dpvs_emph(xf86OutputPtr output, uint8_t train_set[4])
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
     int i;
     for (i = 0; i < radeon_output->dp_lane_count; i++)
-	RADEON_DP_DigTransmitterSetup_VSEMPH(output, i, train_set[i]);
+	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH, i, train_set[i]);
 
     atom_dp_aux_native_write(output, DP_TRAINING_LANE0_SET, radeon_output->dp_lane_count, train_set);
 }
@@ -2523,7 +2446,6 @@ static void dp_update_dpvs_emph(xf86OutputPtr output, uint8_t train_set[4])
 static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
 {
     ScrnInfoPtr pScrn = output->scrn;
-    RADEONInfoPtr info       = RADEONPTR(output->scrn);
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
     int num_lane = dp_lanes_for_mode_clock(mode->Clock);
     int dp_clock = dp_link_clock_for_mode_clock(mode->Clock);
commit bce1911f66f446b793125ac8cd5463bf6292629e
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Nov 18 00:04:33 2009 -0500

    radeon: pull previous displayport work into master

diff --git a/src/atombios_output.c b/src/atombios_output.c
index d85c3f6..7b2742d 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -65,6 +65,8 @@ const char *device_name[12] = {
     "DFP5",
 };
 
+static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode);
+
 static void atombios_set_output_crtc_source(xf86OutputPtr output);
 
 static int
@@ -466,14 +468,14 @@ atombios_get_encoder_mode(xf86OutputPtr output)
 }
 
 static const int dp_clocks[] = {
-    16200,
-    27000,
-    32400,
     54000,
+    81000,
+    108000,
+    162000,
     0,
     0,
-    64800,
-    108000,
+    100000,
+    324000,
 };
 static const int num_dp_clocks = sizeof(dp_clocks) / sizeof(int);
 
@@ -481,7 +483,7 @@ static int
 dp_lanes_for_mode_clock(int mode_clock)
 {
     int i;
-    
+
     for (i = 0; i < num_dp_clocks; i++)
 	if (dp_clocks[i] > (mode_clock / 10))
 	    return (i / 2) + 1;
@@ -496,7 +498,7 @@ dp_link_clock_for_mode_clock(int mode_clock)
 
     for (i = 0; i < num_dp_clocks; i++)
 	if (dp_clocks[i] > (mode_clock / 10))
-	    return (dp_clocks[i % 2]);
+	    return (i % 2) ? 27000 : 16200;
 
     return 0;
 }
@@ -528,7 +530,10 @@ atombios_output_dig_encoder_setup(xf86OutputPtr output, int action)
     } else {
 	switch (radeon_encoder->encoder_id) {
 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	    index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
+	    if (radeon_output->linkb)
+		index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
+	    else
+		index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
 	    num = 1;
 	    break;
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
@@ -678,7 +683,9 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action)
 	    break;
 	}
 
-	if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) {
+	if (radeon_output->MonType == MT_DP)
+	    disp_data.v2.acConfig.fCoherentMode = 0;
+	else if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) {
 	    if (radeon_output->coherent_mode) {
 		disp_data.v2.acConfig.fCoherentMode = 1;
 		xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "UNIPHY%d transmitter: Coherent Mode enabled\n",disp_data.v2.acConfig.ucTransmitterSel);
@@ -702,7 +709,10 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action)
 
 	switch (radeon_encoder->encoder_id) {
 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-	    disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
+	    if (radeon_output->linkb)
+		disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
+	    else
+		disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
 	    if (info->IsIGP) {
 		if (clock > 165000) {
 		    disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
@@ -1531,6 +1541,9 @@ atombios_output_mode_set(xf86OutputPtr output,
 	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_INIT);
 	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP);
 	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE);
+	if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT && radeon_output->MonType == MT_DP) {
+	    do_displayport_dance(output, mode, adjusted_mode);
+	}
 	break;
     case ENCODER_OBJECT_ID_INTERNAL_DDI:
 	atombios_output_ddia_setup(output, ATOM_ENABLE);
@@ -1666,3 +1679,990 @@ atombios_dac_detect(xf86OutputPtr output)
     return MonType;
 }
 
+#define AUX_NATIVE_WRITE 0x8
+#define AUX_NATIVE_READ 0x9
+
+#define AUX_I2C_WRITE 0x0
+#define AUX_I2C_READ 0x1
+#define AUX_I2C_STATUS 0x2
+#define AUX_I2C_MOT 0x4
+
+#define DP_DPCP_REV 0x0
+#define DP_MAX_LINK_RATE 0x1
+#define DP_MAX_LANE_COUNT 0x2
+#define DP_MAX_DOWNSPREAD 0x3
+#define DP_NORP 0x4
+#define DP_DOWNSTREAMPORT_PRESENT 0x5
+#define DP_MAIN_LINK_CHANNEL_CONFIG 0x6
+#define DP_DP11_DOWNSTREAM_PORT_COUNT 0x7
+
+/* from intel i830_dp.h */
+#define DP_LINK_BW_SET          0x100
+# define DP_LINK_BW_1_62                    0x06
+# define DP_LINK_BW_2_7                     0x0a
+#define DP_LANE_COUNT_SET       0x101
+# define DP_LANE_COUNT_MASK                 0x0f
+# define DP_LANE_COUNT_ENHANCED_FRAME_EN    (1 << 7)
+
+#define DP_TRAINING_PATTERN_SET 0x102
+
+# define DP_TRAINING_PATTERN_DISABLE        0
+# define DP_TRAINING_PATTERN_1              1
+# define DP_TRAINING_PATTERN_2              2
+# define DP_TRAINING_PATTERN_MASK           0x3
+
+# define DP_LINK_QUAL_PATTERN_DISABLE       (0 << 2)
+# define DP_LINK_QUAL_PATTERN_D10_2         (1 << 2)
+# define DP_LINK_QUAL_PATTERN_ERROR_RATE    (2 << 2)
+# define DP_LINK_QUAL_PATTERN_PRBS7         (3 << 2)
+# define DP_LINK_QUAL_PATTERN_MASK          (3 << 2)
+# define DP_RECOVERED_CLOCK_OUT_EN          (1 << 4)
+# define DP_LINK_SCRAMBLING_DISABLE         (1 << 5)
+
+# define DP_SYMBOL_ERROR_COUNT_BOTH         (0 << 6)
+# define DP_SYMBOL_ERROR_COUNT_DISPARITY    (1 << 6)
+# define DP_SYMBOL_ERROR_COUNT_SYMBOL       (2 << 6)
+# define DP_SYMBOL_ERROR_COUNT_MASK         (3 << 6)
+
+#define DP_TRAINING_LANE0_SET               0x103
+#define DP_TRAINING_LANE1_SET               0x104
+#define DP_TRAINING_LANE2_SET               0x105
+#define DP_TRAINING_LANE3_SET               0x106
+# define DP_TRAIN_VOLTAGE_SWING_MASK        0x3
+# define DP_TRAIN_VOLTAGE_SWING_SHIFT       0
+# define DP_TRAIN_MAX_SWING_REACHED         (1 << 2)
+# define DP_TRAIN_VOLTAGE_SWING_400         (0 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_600         (1 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_800         (2 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_1200        (3 << 0)
+
+# define DP_TRAIN_PRE_EMPHASIS_MASK         (3 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_0            (0 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_3_5          (1 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_6            (2 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_9_5          (3 << 3)
+
+# define DP_TRAIN_PRE_EMPHASIS_SHIFT        3
+# define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED  (1 << 5)
+#define DP_DOWNSPREAD_CTRL                  0x107
+# define DP_SPREAD_AMP_0_5                  (1 << 4)
+
+#define DP_MAIN_LINK_CHANNEL_CODING_SET     0x108
+# define DP_SET_ANSI_8B10B                  (1 << 0)
+
+#define DP_LANE0_1_STATUS                   0x202
+#define DP_LANE2_3_STATUS                   0x203
+
+# define DP_LANE_CR_DONE                    (1 << 0)
+# define DP_LANE_CHANNEL_EQ_DONE            (1 << 1)
+# define DP_LANE_SYMBOL_LOCKED              (1 << 2)
+
+#define DP_LANE_ALIGN_STATUS_UPDATED        0x204
+#define DP_INTERLANE_ALIGN_DONE             (1 << 0)
+#define DP_DOWNSTREAM_PORT_STATUS_CHANGED   (1 << 6)
+#define DP_LINK_STATUS_UPDATED              (1 << 7)
+
+#define DP_SINK_STATUS                      0x205
+
+#define DP_RECEIVE_PORT_0_STATUS            (1 << 0)
+#define DP_RECEIVE_PORT_1_STATUS            (1 << 1)
+
+#define DP_ADJUST_REQUEST_LANE0_1           0x206
+#define DP_ADJUST_REQUEST_LANE2_3           0x207
+
+#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK  0x03
+#define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0
+#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK   0x0c
+#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT  2
+#define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK  0x30
+#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4
+#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK   0xc0
+#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT  6
+
+#define DP_LINK_STATUS_SIZE 6
+
+#define DP_SET_POWER_D0  0x1
+#define DP_SET_POWER_D3  0x2
+
+static inline int atom_dp_get_encoder_id(xf86OutputPtr output)
+{
+    RADEONInfoPtr info       = RADEONPTR(output->scrn);
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    if (IS_DCE32_VARIANT) {
+	if (radeon_output->dig_block)
+	    return ATOM_DP_CONFIG_DIG2_ENCODER;
+	else
+	    return ATOM_DP_CONFIG_DIG1_ENCODER;
+    } else {
+	if (radeon_output->linkb)
+	    return ATOM_DP_CONFIG_DIG2_ENCODER;
+	else
+	    return ATOM_DP_CONFIG_DIG1_ENCODER;
+    }
+}
+
+Bool
+RADEONProcessAuxCH(xf86OutputPtr output, char *req_bytes, int num_bytes,
+		   uint8_t *read_byte, uint8_t read_buf_len, uint8_t delay)
+{
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    RADEONInfoPtr info       = RADEONPTR(output->scrn);
+    PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION args;
+    AtomBiosArgRec data;
+    unsigned char *space;
+    unsigned char *base;
+
+    memset(&args, 0, sizeof(args));
+    if (info->atomBIOS->fbBase)
+	base = info->FB + info->atomBIOS->fbBase;
+    else if (info->atomBIOS->scratchBase)
+	base = (unsigned char *)info->atomBIOS->scratchBase;
+    else
+	return FALSE;
+
+    memcpy(base, req_bytes, num_bytes);
+
+    args.lpAuxRequest = 0;
+    args.lpDataOut = 16;
+    args.ucDataOutLen = 0;
+    args.ucChannelID = radeon_output->ucI2cId;
+    args.ucDelay = delay;
+
+    data.exec.index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction);
+    data.exec.dataSpace = (void *)&space;
+    data.exec.pspace = &args;
+
+    RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data);
+    if (args.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.ucReplyStatus);
+	return FALSE;
+    }
+    if (args.ucDataOutLen && read_byte && read_buf_len) {
+	if (read_buf_len < args.ucDataOutLen) {
+	    ErrorF("%s: Buffer too small for return answer %d %d\n", __func__, read_buf_len, args.ucDataOutLen);
+	    return FALSE;
+	}
+	{
+	    int len = read_buf_len < args.ucDataOutLen ? read_buf_len : args.ucDataOutLen;
+	    memcpy(read_byte, base+16, len);
+	}
+    }
+    return TRUE;
+}
+
+static int
+RADEONDPEncoderService(xf86OutputPtr output, int action, uint8_t ucconfig, uint8_t lane_num)
+{
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    RADEONInfoPtr info       = RADEONPTR(output->scrn);
+    DP_ENCODER_SERVICE_PARAMETERS args;
+    AtomBiosArgRec data;
+    unsigned char *space;
+
+    memset(&args, 0, sizeof(args));
+
+    args.ucLinkClock = 0;
+    args.ucConfig = ucconfig;
+    args.ucAction = action;
+    args.ucLaneNum = lane_num;
+    args.ucStatus = 0;
+
+    data.exec.index = GetIndexIntoMasterTable(COMMAND, DPEncoderService);
+    data.exec.dataSpace = (void *)&space;
+    data.exec.pspace = &args;
+
+    RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data);
+
+    ErrorF("%s: %d\n", __func__, args.ucStatus);
+    return args.ucStatus;
+}
+
+int RADEON_DP_GetSinkType(xf86OutputPtr output)
+{
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+
+    return RADEONDPEncoderService(output, ATOM_DP_ACTION_GET_SINK_TYPE, radeon_output->ucI2cId, 0);
+}
+
+static int
+RADEON_DP_DigTransmitterSetup_VSEMPH(xf86OutputPtr output, uint8_t lane_num, uint8_t lane_set)
+{
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    RADEONInfoPtr info       = RADEONPTR(output->scrn);
+    radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
+    union dig_transmitter_control disp_data;
+    AtomBiosArgRec data;
+    unsigned char *space;
+    int clock = radeon_output->pixel_clock;
+    int dig_block = radeon_output->dig_block;
+    int num = 0;
+    int index = 0;
+    int major, minor;
+
+    if (radeon_encoder == NULL)
+        return ATOM_NOT_IMPLEMENTED;
+
+    memset(&disp_data, 0, sizeof(disp_data));
+
+    if (IS_DCE32_VARIANT)
+	index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
+    else {
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	    if (radeon_output->linkb)
+		index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl);
+	    else
+		index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl);
+	    break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+	    index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl);
+	    break;
+	}
+    }
+
+    atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
+
+    disp_data.v1.ucAction = ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH;
+
+    disp_data.v1.asMode.ucLaneSel = lane_num;
+    disp_data.v1.asMode.ucLaneSet = lane_set;
+
+    if (IS_DCE32_VARIANT) {
+	disp_data.v2.acConfig.fDPConnector = 1;
+
+	if (dig_block)
+	    disp_data.v2.acConfig.ucEncoderSel = 1;
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	    disp_data.v2.acConfig.ucTransmitterSel = 0;
+	    num = 0;
+	    break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	    disp_data.v2.acConfig.ucTransmitterSel = 1;
+	    num = 1;
+	    break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+	    disp_data.v2.acConfig.ucTransmitterSel = 2;
+	    num = 2;
+	    break;
+	}
+    } else {
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	    if (radeon_output->linkb)
+		disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
+	    else
+		disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
+	    break;
+	    if (info->IsIGP) {
+	    } else {
+
+	    }
+	}
+    }
+    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) {
+	if (IS_DCE32_VARIANT)
+	    ErrorF("Output UNIPHY%d transmitter VSEMPH setup success\n", num);
+	else
+	   ErrorF("Output DIG%d transmitter VSEMPH setup success\n", num);
+	return ATOM_SUCCESS;
+    }
+
+    ErrorF("Output DIG%d transmitter VSEMPH setup failed\n", num);
+    return ATOM_NOT_IMPLEMENTED;
+
+}
+
+static Bool atom_dp_aux_native_write(xf86OutputPtr output, uint16_t address,
+				     uint8_t send_bytes, uint8_t *send)
+{
+    uint8_t msg[20];
+    uint8_t msg_len, dp_msg_len;
+    int ret;
+
+    dp_msg_len = 4;
+    msg[0] = address;
+    msg[1] = address >> 8;
+    msg[2] = AUX_NATIVE_WRITE << 4;
+    dp_msg_len += send_bytes;
+    msg[3] = (dp_msg_len << 4)| (send_bytes - 1);
+
+    ErrorF("writing %02x %02x %02x, %d, %d\n", msg[0], msg[1], msg[3], send_bytes, dp_msg_len);
+    if (send_bytes > 16)
+	return FALSE;
+
+    memcpy(&msg[4], send, send_bytes);
+    msg_len = 4 + send_bytes;
+    ret = RADEONProcessAuxCH(output, msg, msg_len, NULL, 0, 0);
+    return ret;
+}
+
+static Bool atom_dp_aux_native_read(xf86OutputPtr output, uint16_t address,
+				    uint8_t delay,
+				    uint8_t expected_bytes, uint8_t *read_p)
+{
+    uint8_t msg[20];
+    uint8_t msg_len, dp_msg_len;
+    int ret;
+
+    msg_len = 4;
+    dp_msg_len = 4;
+    msg[0] = address;
+    msg[1] = address >> 8;
+    msg[2] = AUX_NATIVE_READ << 4;
+    msg[3] = (dp_msg_len) << 4;
+    msg[3] |= expected_bytes - 1;
+
+    ErrorF("reading %02x %02x %02x, %d\n", msg[0], msg[1], msg[3], expected_bytes, dp_msg_len);
+    ret = RADEONProcessAuxCH(output, msg, msg_len, read_p, expected_bytes, delay);
+    return ret;
+}
+
+/* fill out the DPCP structure */
+void RADEON_DP_GetDPCP(xf86OutputPtr output)
+{
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    uint8_t msg[25];
+    int ret;
+
+    ret = atom_dp_aux_native_read(output, DP_DPCP_REV, 0, 8, msg);
+    if (ret) {
+	memcpy(radeon_output->dpcp8, msg, 8);
+	{
+	    int i;
+	    ErrorF("DPCP: ");
+	    for (i = 0; i < 8; i++)
+		ErrorF("%02x ", radeon_output->dpcp8[i]);
+	    ErrorF("\n");
+	}
+	ret = atom_dp_aux_native_read(output, 0x100, 0, 2, msg);
+	if (ret) {
+	    ErrorF("0x200: %02x %02x\n", msg[0], msg[1]);
+	}
+	return;
+    }
+    radeon_output->dpcp8[0] = 0;
+
+
+    return;
+}
+
+
+enum dp_aux_i2c_mode {
+    dp_aux_i2c_start,
+    dp_aux_i2c_write,
+    dp_aux_i2c_read,
+    dp_aux_i2c_stop,
+};
+
+
+static Bool atom_dp_aux_i2c_transaction(xf86OutputPtr output, uint16_t address,
+				       enum dp_aux_i2c_mode mode,
+				       uint8_t write_byte, uint8_t *read_byte)
+{
+    uint8_t msg[8], msg_len, dp_msg_len;
+    int ret;
+    int auxch_cmd = 0;
+
+    memset(msg, 0, 8);
+
+    if (mode != dp_aux_i2c_stop)
+	auxch_cmd = AUX_I2C_MOT;
+
+    if (address & 1)
+	auxch_cmd |= AUX_I2C_READ;
+    else
+    	auxch_cmd |= AUX_I2C_WRITE;
+
+    msg[2] = auxch_cmd << 4;
+
+    msg[4] = 0;
+    msg[0] = (address >> 1);
+    msg[1] = (address >> 9);
+
+    msg_len = 4;
+    dp_msg_len = 3;
+    switch (mode) {
+    case dp_aux_i2c_read:
+	/* bottom bits is byte count - 1 so for 1 byte == 0 */
+	dp_msg_len += 1;
+	break;
+    case dp_aux_i2c_write:
+	dp_msg_len += 2;
+	msg[4] = write_byte;
+	msg_len++;
+	break;
+    default:
+	break;
+    }
+    msg[3] = dp_msg_len << 4;
+
+    ret = RADEONProcessAuxCH(output, msg, msg_len, read_byte, 1, 0);
+    return ret;
+}
+
+static Bool
+atom_dp_i2c_address(I2CDevPtr dev, I2CSlaveAddr addr)
+{
+    I2CBusPtr bus = dev->pI2CBus;
+    xf86OutputPtr output = bus->DriverPrivate.ptr;
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    ScrnInfoPtr scrn = output->scrn;
+    int ret;
+
+    radeon_output->dp_i2c_addr = addr;
+    radeon_output->dp_i2c_running = TRUE;
+
+    /* call i2c start */
+    ret = atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr,
+				      dp_aux_i2c_start, 0, NULL);
+
+    return ret;
+}
+static void
+atom_dp_i2c_start(I2CDevPtr dev)
+{
+    ErrorF("%s\n", __func__);
+}
+
+static void
+atom_dp_i2c_stop(I2CDevPtr dev)
+{
+    I2CBusPtr bus = dev->pI2CBus;
+    xf86OutputPtr output = bus->DriverPrivate.ptr;
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    ScrnInfoPtr scrn = output->scrn;
+    if (radeon_output->dp_i2c_running)
+	atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr,
+				    dp_aux_i2c_stop, 0, NULL);
+    radeon_output->dp_i2c_running = FALSE;
+}
+
+
+static Bool
+atom_dp_i2c_put_byte(I2CDevPtr dev, I2CByte byte)
+{
+    I2CBusPtr bus = dev->pI2CBus;
+    xf86OutputPtr output = bus->DriverPrivate.ptr;
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    ScrnInfoPtr scrn = output->scrn;
+    Bool ret;
+
+    ret = (atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr,
+				       dp_aux_i2c_write, byte, NULL));
+    return ret;
+}
+
+static Bool
+atom_dp_i2c_get_byte(I2CDevPtr dev, I2CByte *byte_ret, Bool last)
+{
+    I2CBusPtr bus = dev->pI2CBus;
+    xf86OutputPtr output = bus->DriverPrivate.ptr;
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    ScrnInfoPtr scrn = output->scrn;
+    Bool ret;
+
+    ret = (atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr,
+				       dp_aux_i2c_read, 0, byte_ret));
+    return ret;
+}
+
+Bool
+RADEON_DP_I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, char *name, xf86OutputPtr output)
+{
+    I2CBusPtr pI2CBus;
+
+    pI2CBus = xf86CreateI2CBusRec();
+    if (!pI2CBus) return FALSE;
+
+    pI2CBus->BusName = name;
+    pI2CBus->scrnIndex = pScrn->scrnIndex;
+    pI2CBus->I2CGetByte = atom_dp_i2c_get_byte;
+    pI2CBus->I2CPutByte = atom_dp_i2c_put_byte;
+    pI2CBus->I2CAddress = atom_dp_i2c_address;
+    pI2CBus->I2CStart = atom_dp_i2c_start;
+    pI2CBus->I2CStop = atom_dp_i2c_stop;
+    pI2CBus->DriverPrivate.ptr = output;
+
+    /*
+     * These were set incorrectly in the server pre-1.3, Having
+     * duplicate settings is sub-optimal, but this lets the driver
+     * work with older servers
+     */
+    pI2CBus->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
+    pI2CBus->StartTimeout = 550;
+    pI2CBus->BitTimeout = 40;
+    pI2CBus->AcknTimeout = 40;
+    pI2CBus->RiseFallTime = 20;
+
+    if (!xf86I2CBusInit(pI2CBus))
+	return FALSE;
+
+    *bus_ptr = pI2CBus;
+    return TRUE;
+}
+
+
+static uint8_t dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE], int r)
+{
+    return link_status[r - DP_LANE0_1_STATUS];
+}
+
+static uint8_t dp_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane)
+{
+    int i = DP_LANE0_1_STATUS + (lane >> 1);
+    int s = (lane & 1) * 4;
+    uint8_t l = dp_link_status(link_status, i);
+    return (l >> s) & 0xf;
+}
+
+static Bool dp_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
+{
+    int lane;
+
+    uint8_t lane_status;
+
+    for (lane = 0; lane < lane_count; lane++) {
+	lane_status = dp_get_lane_status(link_status, lane);
+	if ((lane_status & DP_LANE_CR_DONE) == 0)
+	    return FALSE;
+    }
+    return TRUE;
+}
+
+
+/* Check to see if channel eq is done on all channels */
+#define CHANNEL_EQ_BITS (DP_LANE_CR_DONE|\
+			 DP_LANE_CHANNEL_EQ_DONE|\
+			 DP_LANE_SYMBOL_LOCKED)
+static Bool
+dp_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
+{
+    uint8_t lane_align;
+    uint8_t lane_status;
+    int lane;
+
+    lane_align = dp_link_status(link_status,
+				DP_LANE_ALIGN_STATUS_UPDATED);
+    if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
+	return FALSE;
+    for (lane = 0; lane < lane_count; lane++) {
+	lane_status = dp_get_lane_status(link_status, lane);
+	if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
+	    return FALSE;
+    }
+    return TRUE;
+}
+
+/*
+ * Fetch AUX CH registers 0x202 - 0x207 which contain
+ * link status information
+ */
+static Bool
+atom_dp_get_link_status(xf86OutputPtr output,
+			  uint8_t link_status[DP_LINK_STATUS_SIZE])
+{
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    ScrnInfoPtr pScrn = output->scrn;
+    int ret;
+    ret = atom_dp_aux_native_read(output, DP_LANE0_1_STATUS, 100,
+				  DP_LINK_STATUS_SIZE, link_status);
+    if (!ret) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "dp link status failed\n");
+	return FALSE;
+    }
+    ErrorF("link status %02x %02x %02x %02x %02x %02x\n", link_status[0], link_status[1],
+	   link_status[2], link_status[3], link_status[4], link_status[5]);
+
+    return TRUE;
+}
+
+static uint8_t
+dp_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE],
+			      int lane)
+
+{
+    int     i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
+    int     s = ((lane & 1) ?
+                 DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
+                 DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
+    uint8_t l = dp_link_status(link_status, i);
+
+    return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
+}
+
+static uint8_t
+dp_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE],
+				   int lane)
+{
+    int     i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
+    int     s = ((lane & 1) ?
+                 DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
+                 DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
+    uint8_t l = dp_link_status(link_status, i);
+
+    return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
+}
+
+static char     *voltage_names[] = {
+        "0.4V", "0.6V", "0.8V", "1.2V"
+};
+static char     *pre_emph_names[] = {
+        "0dB", "3.5dB", "6dB", "9.5dB"
+};
+static char     *link_train_names[] = {
+        "pattern 1", "pattern 2", "idle", "off"
+};
+
+/*
+ * These are source-specific values; current Intel hardware supports
+ * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
+ */
+#define DP_VOLTAGE_MAX         DP_TRAIN_VOLTAGE_SWING_1200
+
+static uint8_t
+dp_pre_emphasis_max(uint8_t voltage_swing)
+{
+    switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
+    case DP_TRAIN_VOLTAGE_SWING_400:
+        return DP_TRAIN_PRE_EMPHASIS_6;
+    case DP_TRAIN_VOLTAGE_SWING_600:
+        return DP_TRAIN_PRE_EMPHASIS_6;
+    case DP_TRAIN_VOLTAGE_SWING_800:
+        return DP_TRAIN_PRE_EMPHASIS_3_5;
+    case DP_TRAIN_VOLTAGE_SWING_1200:
+    default:
+        return DP_TRAIN_PRE_EMPHASIS_0;
+    }
+}
+
+static void dp_set_training(xf86OutputPtr output, uint8_t training)
+{
+    atom_dp_aux_native_write(output, DP_TRAINING_PATTERN_SET, 1, &training);
+}
+
+static Bool
+atom_dp_set_link_train(xf86OutputPtr output, uint8_t dp_train_pat, uint8_t train_set[4])
+{
+    int ret;
+    int enc_id = atom_dp_get_encoder_id(output);
+    int i;
+    /* set DP encoder training start */
+
+    xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
+	       "Training  trying link voltage %x pre-emphasis\n", train_set[0]);
+
+    usleep(400);
+
+    /* set DP encoder training start */
+    dp_set_training(output, dp_train_pat);
+
+    return TRUE;
+}
+
+static void dp_set_power(xf86OutputPtr output, uint8_t power_state)
+{
+    uint8_t pstate;
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+
+    if (radeon_output->dpcp8[0] >= 0x11) {
+	atom_dp_aux_native_write(output, 0x600, 1, &power_state);
+    }
+}
+
+static void
+dp_get_adjust_train(xf86OutputPtr output,
+		      uint8_t link_status[DP_LINK_STATUS_SIZE],
+		      int lane_count,
+		      uint8_t train_set[4])
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    RADEONInfoPtr info       = RADEONPTR(output->scrn);
+    uint8_t v = 0;
+    uint8_t p = 0;
+    int lane;
+
+    for (lane = 0; lane < lane_count; lane++) {
+	uint8_t this_v = dp_get_adjust_request_voltage(link_status, lane);
+	uint8_t this_p = dp_get_adjust_request_pre_emphasis(link_status, lane);
+
+	if  (1) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "requested signal parameters: lane %d voltage %s pre_emph %s\n",
+		       lane,
+		       voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT],
+		       pre_emph_names[this_p >> DP_TRAIN_PRE_EMPHASIS_SHIFT]);
+	}
+	if (this_v > v)
+	    v = this_v;
+	if (this_p > p)
+	    p = this_p;
+    }
+
+    if (v >= DP_VOLTAGE_MAX)
+	v = DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED;
+
+    if (p >= dp_pre_emphasis_max(v))
+	p = dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+    if (1) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "using signal parameters: voltage %s pre_emph %s\n",
+		   voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK) >> DP_TRAIN_VOLTAGE_SWING_SHIFT],
+		   pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT]);
+    }
+    for (lane = 0; lane < 4; lane++)
+	train_set[lane] = v | p;
+}
+
+static int radeon_dp_max_lane_count(xf86OutputPtr output)
+{
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    int max_lane_count = 4;
+
+    if (radeon_output->dpcp8[0] >= 0x11) {
+	max_lane_count = radeon_output->dpcp8[2] & 0x1f;
+	switch(max_lane_count) {
+	case 1: case 2: case 4:
+	    break;
+	default:
+	    max_lane_count = 4;
+	}
+    }
+    return max_lane_count;
+}
+
+static int radeon_dp_max_link_bw(xf86OutputPtr output)
+{
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    int max_link_bw = radeon_output->dpcp8[1];
+    switch(max_link_bw) {
+    case DP_LINK_BW_1_62:
+    case DP_LINK_BW_2_7:
+	break;
+    default:
+	max_link_bw = DP_LINK_BW_1_62;
+	break;
+    }
+    return max_link_bw;
+}
+
+static int radeon_dp_link_clock(uint8_t link_bw)
+{
+    if (link_bw == DP_LINK_BW_2_7)
+	return 270000;
+    else
+	return 162000;
+}
+
+
+/* I think this is a fiction */
+static int radeon_dp_link_required(int pixel_clock)
+{
+    return pixel_clock * 3;
+}
+
+static Bool radeon_dp_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    RADEONInfoPtr info       = RADEONPTR(output->scrn);
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    int lane_count, clock;
+    int max_lane_count = radeon_dp_max_lane_count(output);
+    int max_clock = radeon_dp_max_link_bw(output) == DP_LINK_BW_2_7 ? 1 : 0;
+    static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
+
+    for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
+	for (clock = 0; clock <= max_clock; clock++) {
+	    int link_avail = radeon_dp_link_clock(bws[clock]) * lane_count;
+
+	    if (radeon_dp_link_required(mode->Clock) <= link_avail) {
+		radeon_output->dp_link_bw = bws[clock];
+		radeon_output->dp_lane_count = lane_count;
+		radeon_output->dp_clock = radeon_dp_link_clock(radeon_output->dp_link_bw);
+		if (1)
+			xf86DrvMsg(0, X_INFO,
+				   "link_bw %d lane_count %d clock %d\n",
+				   radeon_output->dp_link_bw, radeon_output->dp_lane_count,
+				   radeon_output->dp_clock);
+		return TRUE;
+	    }
+	}
+    }
+    return FALSE;
+}
+
+static void radeon_dp_mode_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+{
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    memset(radeon_output->dp_link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
+    radeon_output->dp_link_configuration[0] = radeon_output->dp_link_bw;
+    radeon_output->dp_link_configuration[1] = radeon_output->dp_lane_count;
+
+    if (radeon_output->dpcp8[0] >= 0x11) {
+	radeon_output->dp_link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+    }
+}
+
+static void dp_update_dpvs_emph(xf86OutputPtr output, uint8_t train_set[4])
+{
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    int i;
+    for (i = 0; i < radeon_output->dp_lane_count; i++)
+	RADEON_DP_DigTransmitterSetup_VSEMPH(output, i, train_set[i]);
+
+    atom_dp_aux_native_write(output, DP_TRAINING_LANE0_SET, radeon_output->dp_lane_count, train_set);
+}
+
+static void do_displayport_dance(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    RADEONInfoPtr info       = RADEONPTR(output->scrn);
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    int num_lane = dp_lanes_for_mode_clock(mode->Clock);
+    int dp_clock = dp_link_clock_for_mode_clock(mode->Clock);
+    int enc_id = atom_dp_get_encoder_id(output);
+    Bool clock_recovery;
+    uint8_t link_status[DP_LINK_STATUS_SIZE];
+    uint8_t tries, voltage;
+    uint8_t train_set[4];
+    Bool ret;
+    int i;
+    Bool channel_eq;
+
+    ErrorF("Doing displayport DANCE lanes:%d %d\n", num_lane, dp_clock);
+
+    ret = radeon_dp_mode_fixup(output, mode, adjusted_mode);
+    if (ret == FALSE) {
+	ErrorF("Doing displayport DANCE failed to fixup\n");
+	return;
+    }
+
+    memset(train_set, 0, 4);
+
+    /* set up link configuration */
+    radeon_dp_mode_set(output, mode, adjusted_mode);
+
+    /* power up to D0 */
+    dp_set_power(output, DP_SET_POWER_D0);
+
+    /* disable training */
+    dp_set_training(output, DP_TRAINING_PATTERN_DISABLE);
+
+    /* write link rate / num / eh framing */
+    atom_dp_aux_native_write(output, 0x100, 2,
+			     radeon_output->dp_link_configuration);
+
+    /* start local training start */
+    RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_START, enc_id, 0);
+
+    RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, enc_id, 0);
+
+    dp_update_dpvs_emph(output, train_set);
+    usleep(400);
+    dp_set_training(output, DP_TRAINING_PATTERN_1);
+
+    /* loop around doing configuration reads and DP encoder setups */
+    clock_recovery = FALSE;
+    tries = 0;
+    voltage = 0xff;
+    for (;;) {
+      	usleep(100);
+	if (!atom_dp_get_link_status(output, link_status))
+	    break;
+
+	if (dp_clock_recovery_ok(link_status, num_lane)) {
+	    clock_recovery = TRUE;
+	    break;
+	}
+
+	for (i = 0; i < radeon_output->dp_lane_count; i++)
+	    if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
+		break;
+	if (i == radeon_output->dp_lane_count) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "clock recovery reached max voltage\n");
+	    break;
+	}
+
+	/* Check to see if we've tried the same voltage 5 times */
+	if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
+	    ++tries;
+	    if (tries == 5) {
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "clock recovery tried 5 times\n");
+		break;
+	    }
+	} else
+	    tries = 0;
+
+	voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+
+        dp_get_adjust_train(output, link_status, radeon_output->dp_lane_count, train_set);
+	dp_update_dpvs_emph(output, train_set);
+
+    }
+
+    if (!clock_recovery)
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "clock recovery failed\n");
+    else if (1)
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "clock recovery at voltage %d pre-emphasis %d\n",
+                   train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK,
+                   (train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >>
+                   DP_TRAIN_PRE_EMPHASIS_SHIFT);
+
+    /* channel equalization */
+    tries = 0;
+    channel_eq = FALSE;
+    dp_set_training(output, DP_TRAINING_PATTERN_2);
+    RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, enc_id, 1);
+
+    for (;;) {
+
+	usleep(400);
+	if (!atom_dp_get_link_status(output, link_status))
+	    break;
+
+	if (dp_channel_eq_ok(link_status, radeon_output->dp_lane_count)) {
+	    channel_eq = TRUE;
+	    break;
+	}
+
+	/* Try 5 times */
+	if (tries > 5) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "channel eq failed: 5 tries\n");
+	    break;
+	}
+
+	/* Compute new train_set as requested by target */
+        dp_get_adjust_train(output, link_status, radeon_output->dp_lane_count, train_set);
+	dp_update_dpvs_emph(output, train_set);
+
+	++tries;
+    }
+
+    if (!channel_eq)
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "channel eq failed\n");
+    else if (1) //pI830->debug_modes)
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "channel eq at voltage %d pre-emphasis %d\n",
+		   train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK,
+		   (train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK)
+		   >> DP_TRAIN_PRE_EMPHASIS_SHIFT);
+
+
+    dp_set_training(output, DP_TRAINING_PATTERN_DISABLE);
+    RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_COMPLETE, enc_id, 0);
+
+}
+
diff --git a/src/radeon.h b/src/radeon.h
index 7fd297e..231ffda 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -1190,6 +1190,10 @@ void RADEONFreeRec(ScrnInfoPtr pScrn);
 Bool RADEONPreInitVisual(ScrnInfoPtr pScrn);
 Bool RADEONPreInitWeight(ScrnInfoPtr pScrn);
 
+extern Bool RADEON_DP_I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr,
+			      char *name, xf86OutputPtr output);
+extern void RADEON_DP_GetDPCP(xf86OutputPtr output);
+extern int RADEON_DP_GetSinkType(xf86OutputPtr output);
 
 /* radeon_pm.c */
 extern void RADEONPMInit(ScrnInfoPtr pScrn);
diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index f3c88bc..ee99da2 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -1576,8 +1576,10 @@ rhdAtomParseI2CRecord(ScrnInfoPtr pScrn, atomBiosHandlePtr handle,
 		      ATOM_I2C_RECORD *Record, int i)
 {
     RADEONInfoPtr info = RADEONPTR (pScrn);
+    uint8_t *temp = &Record->sucI2cId;
 
     info->BiosConnector[i].i2c_line_mux = Record->sucI2cId.bfI2C_LineMux;
+    info->BiosConnector[i].ucI2cId = *temp;
     return RADEONLookupGPIOLineForDDC(pScrn, Record->sucI2cId.bfI2C_LineMux);
 }
 
diff --git a/src/radeon_output.c b/src/radeon_output.c
index 24e07db..9ed266f 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -301,10 +301,13 @@ radeon_ddc_connected(xf86OutputPtr output)
     RADEONMonitorType MonType = MT_NONE;
     xf86MonPtr MonInfo = NULL;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    int ret;
 
     if (radeon_output->custom_edid) {
 	MonInfo = xnfcalloc(sizeof(xf86Monitor), 1);
 	*MonInfo = *radeon_output->custom_mon;
+    } else if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) {
+	MonInfo = xf86OutputGetEDID(output, radeon_output->dp_pI2CBus);
     } else if (radeon_output->pI2CBus) {
 	if (info->get_hardcoded_edid_from_bios)
 	    MonInfo = RADEONGetHardCodedEDIDFromBIOS(output);
@@ -364,7 +367,13 @@ radeon_ddc_connected(xf86OutputPtr output)
 	     * XXX wrong. need to infer based on whether we got DDC from I2C
 	     * or AUXCH.
 	     */
-	    MonType = MT_DFP;
+	    ret = RADEON_DP_GetSinkType(output);
+
+	    if (ret == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
+		MonType = MT_DP;
+		RADEON_DP_GetDPCP(output);
+	    } else
+		MonType = MT_DFP;
 	    break;
 	case CONNECTOR_HDMI_TYPE_B:
 	case CONNECTOR_DVI_I:
@@ -2070,6 +2079,13 @@ void RADEONInitConnector(xf86OutputPtr output)
     if (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT))
 	radeon_output->coherent_mode = TRUE;
 
+    if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) {
+	strcpy(radeon_output->dp_bus_name, output->name);
+	strcat(radeon_output->dp_bus_name, "-DP");
+	RADEON_DP_I2CInit(pScrn, &radeon_output->dp_pI2CBus, radeon_output->dp_bus_name, output);
+	RADEON_DP_GetSinkType(output);
+    }
+
     if (radeon_output->ddc_i2c.valid)
 	RADEONI2CInit(pScrn, &radeon_output->pI2CBus, output->name, &radeon_output->ddc_i2c);
 
@@ -2909,6 +2925,7 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn)
 	    radeon_output->linkb = info->BiosConnector[i].linkb;
 	    radeon_output->connector_id = info->BiosConnector[i].connector_object;
 	    radeon_output->connector_object_id = info->BiosConnector[i].connector_object_id;
+	    radeon_output->ucI2cId = info->BiosConnector[i].ucI2cId;
 
 	    /* Technically HDMI-B is a glorfied DL DVI so the bios is correct,
 	     * but this can be confusing to users when it comes to output names,
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index 12e73ef..174bfe0 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -240,6 +240,7 @@ typedef struct {
     Bool linkb;
     uint16_t connector_object;
     uint16_t connector_object_id;
+    uint8_t ucI2cId;
 } RADEONBIOSConnector;
 
 typedef struct _RADEONOutputPrivateRec {
@@ -284,6 +285,18 @@ typedef struct _RADEONOutputPrivateRec {
     int dig_block;
 
     int pixel_clock;
+
+    // DP - special DP I2C bus
+    I2CBusPtr dp_pI2CBus;
+    char dp_bus_name[20];
+    uint32_t dp_i2c_addr, dp_i2c_running;
+    uint8_t dpcp8[8];
+    uint8_t ucI2cId;
+    int dp_lane_count;
+    int dp_link_bw;
+    int dp_clock;
+#define DP_LINK_CONFIGURATION_SIZE 9
+    uint8_t dp_link_configuration[DP_LINK_CONFIGURATION_SIZE];
 } RADEONOutputPrivateRec, *RADEONOutputPrivatePtr;
 
 struct avivo_pll_state {
commit 437113124bbd6fb166825169eabec4dfde900dd9
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Nov 17 14:16:22 2009 -0500

    radeon: deal with connectors sourced to the same encoder
    
    Some systems have multiple connectors connected to the
    same encoder; e.g., DVI and HDMI connected to the same
    encoder with the same ddc line.  Since we expose
    connectors as xrandr outputs, randr treats them separately
    which results in it trying to source the same encoder to
    different crtcs.  If we have an HDMI and DVI-D port on the
    same encoder, pick the one to be considered connected
    based on the edid (HDMI if edid indicates HDMI, DVI
    otherwise).  Also, don't turn off (dpms) encoders that are
    shared.
    
    Fixes fdo bug 21767.
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/radeon_output.c b/src/radeon_output.c
index 42d37fa..24e07db 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -322,10 +322,40 @@ radeon_ddc_connected(xf86OutputPtr output)
 	case CONNECTOR_DVI_D:
 	case CONNECTOR_HDMI_TYPE_A:
 	    if (radeon_output->shared_ddc) {
+		xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (output->scrn);
+		int i;
+
 		if (monitor_is_digital(MonInfo))
 		    MonType = MT_DFP;
 		else
 		    MonType = MT_NONE;
+
+		for (i = 0; i < config->num_output; i++) {
+		    if (output != config->output[i]) {
+			RADEONOutputPrivatePtr other_radeon_output =
+			    config->output[i]->driver_private;
+			if (radeon_output->devices & other_radeon_output->devices) {
+#ifndef EDID_COMPLETE_RAWDATA
+			    if (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) {
+				MonType = MT_NONE;
+				break;
+			    }
+#else
+			    if (xf86MonitorIsHDMI(MonInfo)) {
+				if (radeon_output->ConnectorType == CONNECTOR_DVI_D) {
+				    MonType = MT_NONE;
+				    break;
+				}
+			    } else {
+				if (radeon_output->ConnectorType == CONNECTOR_HDMI_TYPE_A) {
+				    MonType = MT_NONE;
+				    break;
+				}
+			    }
+#endif
+			}
+		    }
+		}
 	    } else
 		MonType = MT_DFP;
 	    break;
@@ -422,6 +452,22 @@ radeon_dpms(xf86OutputPtr output, int mode)
     if ((mode == DPMSModeOn) && radeon_output->enabled)
 	return;
 
+    if ((mode != DPMSModeOn) && radeon_output->shared_ddc) {
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (output->scrn);
+	int i;
+
+	for (i = 0; i < config->num_output; i++) {
+	    if (output != config->output[i]) {
+		RADEONOutputPrivatePtr other_radeon_output =
+		    config->output[i]->driver_private;
+		if (radeon_output->devices & other_radeon_output->devices) {
+		    if (output->status == XF86OutputStatusDisconnected)
+			return;
+		}
+	    }
+	}
+    }
+
     if (IS_AVIVO_VARIANT || info->r4xx_atom) {
 	atombios_output_dpms(output, mode);
     } else {
commit 9b8605d4e2bf7703c7848f3e2022a8c7328a3acd
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Nov 17 11:45:09 2009 -0500

    radeon: fix potential memory leak in ddc code
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/radeon_output.c b/src/radeon_output.c
index 9d9a16c..42d37fa 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -356,9 +356,11 @@ radeon_ddc_connected(xf86OutputPtr output)
 	    break;
 	}
 
-	if (MonType != MT_NONE)
+	if (MonType != MT_NONE) {
 	    if (!xf86ReturnOptValBool(info->Options, OPTION_IGNORE_EDID, FALSE))
 		xf86OutputSetEDID(output, MonInfo);
+	} else
+	    xfree(MonInfo);
     } else
 	MonType = MT_NONE;
 
commit ce8299962003de572122561a6f7f61eaccf633b2
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Nov 17 15:23:30 2009 +1000

    kms: check for 0 mask for cloned outputs.
    
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index d78a82a..29c3ff1 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -951,12 +951,17 @@ uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
 	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
 	int index_mask = 0;
 
+	if (drmmode_output->enc_clone_mask == 0)
+		return index_mask;
+
 	for (i = 0; i < xf86_config->num_output; i++) {
 		clone_output = xf86_config->output[i];
 		clone_drmout = clone_output->driver_private;
 		if (output == clone_output)
 			continue;
 		
+		if (clone_drmout->enc_mask == 0)
+			continue;
 		if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask)
 			index_mask |= (1 << i);
 	}
commit 06d68f7fa3870f9601e837e1834d33e8395008b1
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Nov 17 15:10:04 2009 +1000

    kms: add cloning support.
    
    We have to translate from the kernel encoder cloning to the randr
    connector cloning, we do this by constructing an encoder mask per output
    and an encoder cloning mask per output then comparing them.
    
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 86adfeb..d78a82a 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -618,8 +618,12 @@ drmmode_output_destroy(xf86OutputPtr output)
 	if (drmmode_output->edid_blob)
 		drmModeFreePropertyBlob(drmmode_output->edid_blob);
 	for (i = 0; i < drmmode_output->num_props; i++) {
-	    drmModeFreeProperty(drmmode_output->props[i].mode_prop);
-	    xfree(drmmode_output->props[i].atoms);
+		drmModeFreeProperty(drmmode_output->props[i].mode_prop);
+		xfree(drmmode_output->props[i].atoms);
+	}
+	for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) {
+		drmModeFreeEncoder(drmmode_output->mode_encoders[i]);
+		xfree(drmmode_output->mode_encoders);
 	}
 	xfree(drmmode_output->props);
 	drmModeFreeConnector(drmmode_output->mode_output);
@@ -847,7 +851,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
 {
 	xf86OutputPtr output;
 	drmModeConnectorPtr koutput;
-	drmModeEncoderPtr kencoder;
+	drmModeEncoderPtr *kencoders = NULL;
 	drmmode_output_private_ptr drmmode_output;
 	drmModePropertyPtr props;
 	char name[32];
@@ -857,10 +861,16 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
 	if (!koutput)
 		return;
 
-	kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]);
-	if (!kencoder) {
-		drmModeFreeConnector(koutput);
-		return;
+	kencoders = xcalloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
+	if (!kencoders) {
+		goto out_free_encoders;
+	}
+		
+	for (i = 0; i < koutput->count_encoders; i++) {
+		kencoders[i] = drmModeGetEncoder(drmmode->fd, koutput->encoders[i]);
+		if (!kencoders[i]) {
+			goto out_free_encoders;
+		}
 	}
 
 	/* need to do smart conversion here for compat with non-kms ATI driver */
@@ -884,31 +894,31 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
 
 	output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
 	if (!output) {
-		drmModeFreeEncoder(kencoder);
-		drmModeFreeConnector(koutput);
-		return;
+		goto out_free_encoders;
 	}
 
 	drmmode_output = xcalloc(sizeof(drmmode_output_private_rec), 1);
 	if (!drmmode_output) {
 		xf86OutputDestroy(output);
-		drmModeFreeConnector(koutput);
-		drmModeFreeEncoder(kencoder);
-		return;
+		goto out_free_encoders;
 	}
 
 	drmmode_output->output_id = drmmode->mode_res->connectors[num];
 	drmmode_output->mode_output = koutput;
-	drmmode_output->mode_encoder = kencoder;
+	drmmode_output->mode_encoders = kencoders;
 	drmmode_output->drmmode = drmmode;
 	output->mm_width = koutput->mmWidth;
 	output->mm_height = koutput->mmHeight;
 
 	output->subpixel_order = subpixel_conv_table[koutput->subpixel];
 	output->driver_private = drmmode_output;
-
-	output->possible_crtcs = kencoder->possible_crtcs;
-	output->possible_clones = kencoder->possible_clones;
+	
+	output->possible_crtcs = 0xf;
+	for (i = 0; i < koutput->count_encoders; i++) {
+		output->possible_crtcs &= kencoders[i]->possible_crtcs;
+	}
+	/* work out the possible clones later */
+	output->possible_clones = 0;
 
 	for (i = 0; i < koutput->count_props; i++) {
 		props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
@@ -923,6 +933,66 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
 	}
 
 	return;
+out_free_encoders:
+	if (kencoders){
+		for (i = 0; i < koutput->count_encoders; i++)
+			drmModeFreeEncoder(kencoders[i]);
+		xfree(kencoders);
+	}
+	drmModeFreeConnector(koutput);
+	
+}
+
+uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
+{
+	drmmode_output_private_ptr drmmode_output = output->driver_private, clone_drmout;
+	int i;
+	xf86OutputPtr clone_output;
+	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+	int index_mask = 0;
+
+	for (i = 0; i < xf86_config->num_output; i++) {
+		clone_output = xf86_config->output[i];
+		clone_drmout = clone_output->driver_private;
+		if (output == clone_output)
+			continue;
+		
+		if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask)
+			index_mask |= (1 << i);
+	}
+	return index_mask;
+}
+
+
+static void
+drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
+{
+	int i, j;
+	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+
+	for (i = 0; i < xf86_config->num_output; i++) {
+		xf86OutputPtr output = xf86_config->output[i];
+		drmmode_output_private_ptr drmmode_output;
+
+		drmmode_output = output->driver_private;
+		drmmode_output->enc_clone_mask = 0xff;
+		/* and all the possible encoder clones for this output together */
+		for (j = 0; j < drmmode_output->mode_output->count_encoders; j++)
+		{
+			int k;
+			for (k = 0; k < drmmode->mode_res->count_encoders; k++) {
+				if (drmmode->mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id)
+					drmmode_output->enc_mask |= (1 << k);
+			}
+
+			drmmode_output->enc_clone_mask &= drmmode_output->mode_encoders[j]->possible_clones;
+		}
+	}
+
+	for (i = 0; i < xf86_config->num_output; i++) {
+		xf86OutputPtr output = xf86_config->output[i];
+		output->possible_clones = find_clones(scrn, output);
+	}
 }
 
 static Bool
@@ -1081,6 +1151,9 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, char *busId, char
 		if (zaphod_mask & (1 << i))
 			drmmode_output_init(pScrn, drmmode, i);
 
+	/* workout clones */
+	drmmode_clones_init(pScrn, drmmode);
+
 	xf86InitialConfiguration(pScrn, TRUE);
 
 	return TRUE;
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 1410afe..371ad18 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -64,11 +64,13 @@ typedef struct {
     drmmode_ptr drmmode;
     int output_id;
     drmModeConnectorPtr mode_output;
-    drmModeEncoderPtr mode_encoder;
+    drmModeEncoderPtr *mode_encoders;
     drmModePropertyBlobPtr edid_blob;
     int dpms_enum_id;
     int num_props;
     drmmode_prop_ptr props;
+    int enc_mask;
+    int enc_clone_mask;
 } drmmode_output_private_rec, *drmmode_output_private_ptr;
 
 
commit 7587ce16ab0380337fe801f457c1d1d9b4141cc5
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Mon Nov 16 19:16:03 2009 -0500

    r600: remove un-needed format conversions
    
    we do the normalization and xforms in the vertex
    shader.
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 7d8cf46..ca1a1fa 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -1901,23 +1901,11 @@ static void R600Composite(PixmapPtr pDst,
     RADEONInfoPtr info = RADEONPTR(pScrn);
     struct radeon_accel_state *accel_state = info->accel_state;
     float *vb;
-    xPointFixed srcTopLeft, srcTopRight, srcBottomLeft, srcBottomRight;
 
     /* ErrorF("R600Composite (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n",
        srcX, srcY, maskX, maskY,dstX, dstY, w, h); */
 
-    srcTopLeft.x     = IntToxFixed(srcX);
-    srcTopLeft.y     = IntToxFixed(srcY);
-    srcTopRight.x    = IntToxFixed(srcX + w);
-    srcTopRight.y    = IntToxFixed(srcY);
-    srcBottomLeft.x  = IntToxFixed(srcX);
-    srcBottomLeft.y  = IntToxFixed(srcY + h);
-    srcBottomRight.x = IntToxFixed(srcX + w);
-    srcBottomRight.y = IntToxFixed(srcY + h);
-
     if (accel_state->msk_pic) {
-	xPointFixed maskTopLeft, maskTopRight, maskBottomLeft, maskBottomRight;
-
         if (((accel_state->vb_index + 3) * 24) > accel_state->vb_total) {
             R600DoneComposite(pDst);
 	    r600_cp_start(pScrn);
@@ -1925,35 +1913,26 @@ static void R600Composite(PixmapPtr pDst,
 
         vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*24);
 
-	maskTopLeft.x     = IntToxFixed(maskX);
-	maskTopLeft.y     = IntToxFixed(maskY);
-	maskTopRight.x    = IntToxFixed(maskX + w);
-	maskTopRight.y    = IntToxFixed(maskY);
-	maskBottomLeft.x  = IntToxFixed(maskX);
-	maskBottomLeft.y  = IntToxFixed(maskY + h);
-	maskBottomRight.x = IntToxFixed(maskX + w);
-	maskBottomRight.y = IntToxFixed(maskY + h);
-
 	vb[0] = (float)dstX;
 	vb[1] = (float)dstY;
-	vb[2] = xFixedToFloat(srcTopLeft.x);
-	vb[3] = xFixedToFloat(srcTopLeft.y);
-	vb[4] = xFixedToFloat(maskTopLeft.x);
-	vb[5] = xFixedToFloat(maskTopLeft.y);
+	vb[2] = (float)srcX;
+	vb[3] = (float)srcY;
+	vb[4] = (float)maskX;
+	vb[5] = (float)maskY;
 
 	vb[6] = (float)dstX;
 	vb[7] = (float)(dstY + h);
-	vb[8] = xFixedToFloat(srcBottomLeft.x);
-	vb[9] = xFixedToFloat(srcBottomLeft.y);
-	vb[10] = xFixedToFloat(maskBottomLeft.x);
-	vb[11] = xFixedToFloat(maskBottomLeft.y);
+	vb[8] = (float)srcX;
+	vb[9] = (float)(srcY + h);
+	vb[10] = (float)maskX;
+	vb[11] = (float)(maskY + h);
 
 	vb[12] = (float)(dstX + w);
 	vb[13] = (float)(dstY + h);
-	vb[14] = xFixedToFloat(srcBottomRight.x);
-	vb[15] = xFixedToFloat(srcBottomRight.y);
-	vb[16] = xFixedToFloat(maskBottomRight.x);
-	vb[17] = xFixedToFloat(maskBottomRight.y);
+	vb[14] = (float)(srcX + w);
+	vb[15] = (float)(srcY + h);
+	vb[16] = (float)(maskX + w);
+	vb[17] = (float)(maskY + h);
 
     } else {
         if (((accel_state->vb_index + 3) * 16) > accel_state->vb_total) {
@@ -1965,18 +1944,18 @@ static void R600Composite(PixmapPtr pDst,
 
 	vb[0] = (float)dstX;
 	vb[1] = (float)dstY;
-	vb[2] = xFixedToFloat(srcTopLeft.x);
-	vb[3] = xFixedToFloat(srcTopLeft.y);
+	vb[2] = (float)srcX;
+	vb[3] = (float)srcY;
 
 	vb[4] = (float)dstX;
 	vb[5] = (float)(dstY + h);
-	vb[6] = xFixedToFloat(srcBottomLeft.x);
-	vb[7] = xFixedToFloat(srcBottomLeft.y);
+	vb[6] = (float)srcX;
+	vb[7] = (float)(srcY + h);
 
 	vb[8] = (float)(dstX + w);
 	vb[9] = (float)(dstY + h);
-	vb[10] = xFixedToFloat(srcBottomRight.x);
-	vb[11] = xFixedToFloat(srcBottomRight.y);
+	vb[10] = (float)(srcX + w);
+	vb[11] = (float)(srcY + h);
     }
 
     accel_state->vb_index += 3;
commit ba605b5c9ff48765f2b66960aa4cc81b6235d012
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Mon Nov 16 19:00:52 2009 -0500

    r600: fix num format in vtx fetch
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/r600_shader.c b/src/r600_shader.c
index 584deb4..e78aa32 100644
--- a/src/r600_shader.c
+++ b/src/r600_shader.c
@@ -106,9 +106,9 @@ int R600_solid_vs(RADEONChipFamily ChipSet, uint32_t* shader)
 				 DST_SEL_Z(SQ_SEL_0),
 				 DST_SEL_W(SQ_SEL_1),
 				 USE_CONST_FIELDS(0),
-				 DATA_FORMAT(FMT_32_32_FLOAT), /* xxx */
-				 NUM_FORMAT_ALL(SQ_NUM_FORMAT_NORM), /* xxx */
-				 FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED), /* xxx */
+				 DATA_FORMAT(FMT_32_32_FLOAT),
+				 NUM_FORMAT_ALL(SQ_NUM_FORMAT_SCALED),
+				 FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED),
 				 SRF_MODE_ALL(SRF_MODE_ZERO_CLAMP_MINUS_ONE));
     shader[i++] = VTX_DWORD2(OFFSET(0),
 			     ENDIAN_SWAP(ENDIAN_NONE),
@@ -336,9 +336,9 @@ int R600_copy_vs(RADEONChipFamily ChipSet, uint32_t* shader)
 				 DST_SEL_Z(SQ_SEL_0),
 				 DST_SEL_W(SQ_SEL_1),
 				 USE_CONST_FIELDS(0),
-				 DATA_FORMAT(FMT_32_32_FLOAT), /* xxx */
-				 NUM_FORMAT_ALL(SQ_NUM_FORMAT_NORM), /* xxx */
-				 FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED), /* xxx */
+				 DATA_FORMAT(FMT_32_32_FLOAT),
+				 NUM_FORMAT_ALL(SQ_NUM_FORMAT_SCALED),
+				 FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED),
 				 SRF_MODE_ALL(SRF_MODE_ZERO_CLAMP_MINUS_ONE));
     shader[i++] = VTX_DWORD2(OFFSET(0),
 			     ENDIAN_SWAP(ENDIAN_NONE),
@@ -361,9 +361,9 @@ int R600_copy_vs(RADEONChipFamily ChipSet, uint32_t* shader)
 				 DST_SEL_Z(SQ_SEL_0),
 				 DST_SEL_W(SQ_SEL_1),
 				 USE_CONST_FIELDS(0),
-				 DATA_FORMAT(FMT_32_32_FLOAT), /* xxx */
-				 NUM_FORMAT_ALL(SQ_NUM_FORMAT_NORM), /* xxx */
-				 FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED), /* xxx */
+				 DATA_FORMAT(FMT_32_32_FLOAT),
+				 NUM_FORMAT_ALL(SQ_NUM_FORMAT_SCALED),
+				 FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED),
 				 SRF_MODE_ALL(SRF_MODE_ZERO_CLAMP_MINUS_ONE));
     shader[i++] = VTX_DWORD2(OFFSET(8),
 			     ENDIAN_SWAP(ENDIAN_NONE),
@@ -592,7 +592,7 @@ int R600_xv_vs(RADEONChipFamily ChipSet, uint32_t* shader)
                                  DST_SEL_W(SQ_SEL_1),
                                  USE_CONST_FIELDS(0),
                                  DATA_FORMAT(FMT_32_32_FLOAT),
-                                 NUM_FORMAT_ALL(SQ_NUM_FORMAT_NORM),
+                                 NUM_FORMAT_ALL(SQ_NUM_FORMAT_SCALED),
                                  FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED),
                                  SRF_MODE_ALL(SRF_MODE_ZERO_CLAMP_MINUS_ONE));
     shader[i++] = VTX_DWORD2(OFFSET(0),
@@ -617,7 +617,7 @@ int R600_xv_vs(RADEONChipFamily ChipSet, uint32_t* shader)
                                  DST_SEL_W(SQ_SEL_1),
                                  USE_CONST_FIELDS(0),
                                  DATA_FORMAT(FMT_32_32_FLOAT),
-                                 NUM_FORMAT_ALL(SQ_NUM_FORMAT_NORM),
+                                 NUM_FORMAT_ALL(SQ_NUM_FORMAT_SCALED),
                                  FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED),
                                  SRF_MODE_ALL(SRF_MODE_ZERO_CLAMP_MINUS_ONE));
     shader[i++] = VTX_DWORD2(OFFSET(8),
@@ -1817,9 +1817,9 @@ int R600_comp_vs(RADEONChipFamily ChipSet, uint32_t* shader)
 				 DST_SEL_Z(SQ_SEL_0),
 				 DST_SEL_W(SQ_SEL_1),
 				 USE_CONST_FIELDS(0),
-				 DATA_FORMAT(FMT_32_32_FLOAT), /* xxx */
-				 NUM_FORMAT_ALL(SQ_NUM_FORMAT_NORM), /* xxx */
-				 FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED), /* xxx */
+				 DATA_FORMAT(FMT_32_32_FLOAT),
+				 NUM_FORMAT_ALL(SQ_NUM_FORMAT_SCALED),
+				 FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED),
 				 SRF_MODE_ALL(SRF_MODE_ZERO_CLAMP_MINUS_ONE));
     shader[i++] = VTX_DWORD2(OFFSET(0),
 			     ENDIAN_SWAP(ENDIAN_NONE),
@@ -1842,9 +1842,9 @@ int R600_comp_vs(RADEONChipFamily ChipSet, uint32_t* shader)
 				 DST_SEL_Z(SQ_SEL_1),
 				 DST_SEL_W(SQ_SEL_0),
 				 USE_CONST_FIELDS(0),
-				 DATA_FORMAT(FMT_32_32_FLOAT), /* xxx */
-				 NUM_FORMAT_ALL(SQ_NUM_FORMAT_NORM), /* xxx */
-				 FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED), /* xxx */
+				 DATA_FORMAT(FMT_32_32_FLOAT),
+				 NUM_FORMAT_ALL(SQ_NUM_FORMAT_SCALED),
+				 FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED),
 				 SRF_MODE_ALL(SRF_MODE_ZERO_CLAMP_MINUS_ONE));
     shader[i++] = VTX_DWORD2(OFFSET(8),
 			     ENDIAN_SWAP(ENDIAN_NONE),
@@ -1867,9 +1867,9 @@ int R600_comp_vs(RADEONChipFamily ChipSet, uint32_t* shader)
 				 DST_SEL_Z(SQ_SEL_1),
 				 DST_SEL_W(SQ_SEL_0),
 				 USE_CONST_FIELDS(0),
-				 DATA_FORMAT(FMT_32_32_FLOAT), /* xxx */
-				 NUM_FORMAT_ALL(SQ_NUM_FORMAT_NORM), /* xxx */
-				 FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED), /* xxx */
+				 DATA_FORMAT(FMT_32_32_FLOAT),
+				 NUM_FORMAT_ALL(SQ_NUM_FORMAT_SCALED),
+				 FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED),
 				 SRF_MODE_ALL(SRF_MODE_ZERO_CLAMP_MINUS_ONE));
     shader[i++] = VTX_DWORD2(OFFSET(16),
 			     ENDIAN_SWAP(ENDIAN_NONE),
@@ -2117,9 +2117,9 @@ int R600_comp_vs(RADEONChipFamily ChipSet, uint32_t* shader)
 				 DST_SEL_Z(SQ_SEL_0),
 				 DST_SEL_W(SQ_SEL_1),
 				 USE_CONST_FIELDS(0),
-				 DATA_FORMAT(FMT_32_32_FLOAT), /* xxx */
-				 NUM_FORMAT_ALL(SQ_NUM_FORMAT_NORM), /* xxx */
-				 FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED), /* xxx */
+				 DATA_FORMAT(FMT_32_32_FLOAT),
+				 NUM_FORMAT_ALL(SQ_NUM_FORMAT_SCALED),
+				 FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED),
 				 SRF_MODE_ALL(SRF_MODE_ZERO_CLAMP_MINUS_ONE));
     shader[i++] = VTX_DWORD2(OFFSET(0),
 			     ENDIAN_SWAP(ENDIAN_NONE),
@@ -2142,9 +2142,9 @@ int R600_comp_vs(RADEONChipFamily ChipSet, uint32_t* shader)
 				 DST_SEL_Z(SQ_SEL_1),
 				 DST_SEL_W(SQ_SEL_0),
 				 USE_CONST_FIELDS(0),
-				 DATA_FORMAT(FMT_32_32_FLOAT), /* xxx */
-				 NUM_FORMAT_ALL(SQ_NUM_FORMAT_NORM), /* xxx */
-				 FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED), /* xxx */
+				 DATA_FORMAT(FMT_32_32_FLOAT),
+				 NUM_FORMAT_ALL(SQ_NUM_FORMAT_SCALED),
+				 FORMAT_COMP_ALL(SQ_FORMAT_COMP_SIGNED),
 				 SRF_MODE_ALL(SRF_MODE_ZERO_CLAMP_MINUS_ONE));
     shader[i++] = VTX_DWORD2(OFFSET(8),
 			     ENDIAN_SWAP(ENDIAN_NONE),
commit 0c4710c67a2fee2061fc3da43c9f908585693cfa
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Nov 12 11:11:17 2009 -0500

    radeon: man page updates

diff --git a/man/radeon.man b/man/radeon.man
index 28b1385..47fa9f5 100644
--- a/man/radeon.man
+++ b/man/radeon.man
@@ -40,14 +40,14 @@ R/RV/RS2xx and RS3xx);
 .TP
 \(bu
 Textured XVideo acceleration including anti-tearing support (Bicubic filtering
-only available on R/RV3xx, R/RV/RS4xx, R/RV5xx, and RS6xx);
+only available on R/RV3xx, R/RV/RS4xx, R/RV5xx, and RS6xx/RS740);
 .TP
 \(bu
 Overlay XVideo acceleration (only on R/RV/RS1xx, R/RV/RS2xx,
 R/RV/RS3xx, R/RV/RS4xx);
 .TP
 \(bu
-3D acceleration (not supported on R/RV6xx and R/RV/RS7xx);
+3D acceleration;
 .PD
 .SH SUPPORTED HARDWARE
 The
commit 2af2744c80f3307e6d84edba9479be5bd36e1d03
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Nov 11 13:12:24 2009 -0500

    radeon: fix support for external tmds on some legacy chips
    
    Should fix bug 11801.
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/radeon_bios.c b/src/radeon_bios.c
index f19d929..d066edc 100644
--- a/src/radeon_bios.c
+++ b/src/radeon_bios.c
@@ -533,6 +533,11 @@ static void RADEONApplyLegacyQuirks(ScrnInfoPtr pScrn, int index)
 	info->BiosConnector[index].ddc_i2c.get_data_reg = RADEON_LCD_GPIO_Y_REG;
     }
 
+    /* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */
+    if ((IS_R300_VARIANT) &&
+	info->BiosConnector[index].ddc_i2c.mask_clk_reg == RADEON_GPIO_CRT2_DDC)
+	info->BiosConnector[index].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+
     /* Certain IBM chipset RN50s have a BIOS reporting two VGAs,
        one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */
     if (info->Chipset == PCI_CHIP_RN50_515E &&
@@ -1301,7 +1306,6 @@ RADEONLookupI2CBlock(ScrnInfoPtr pScrn, int id)
 	for (i = 0; i < blocks; i++) {
 	    int i2c_id = RADEON_BIOS8(offset + 3 + (i * 5) + 0);
 	    if (id == i2c_id) {
-		int reg = RADEON_BIOS16(offset + 3 + (i * 5) + 1) * 4;
 		int clock_shift = RADEON_BIOS8(offset + 3 + (i * 5) + 3);
 		int data_shift = RADEON_BIOS8(offset + 3 + (i * 5) + 4);
 
@@ -1313,14 +1317,14 @@ RADEONLookupI2CBlock(ScrnInfoPtr pScrn, int id)
 		i2c.put_data_mask = (1 << data_shift);
 		i2c.get_clk_mask = (1 << clock_shift);
 		i2c.get_data_mask = (1 << data_shift);
-		i2c.mask_clk_reg = reg;
-		i2c.mask_data_reg = reg;
-		i2c.a_clk_reg = reg;
-		i2c.a_data_reg = reg;
-		i2c.put_clk_reg = reg;
-		i2c.put_data_reg = reg;
-		i2c.get_clk_reg = reg;
-		i2c.get_data_reg = reg;
+		i2c.mask_clk_reg = RADEON_GPIOPAD_MASK;
+		i2c.mask_data_reg = RADEON_GPIOPAD_MASK;
+		i2c.a_clk_reg = RADEON_GPIOPAD_A;
+		i2c.a_data_reg = RADEON_GPIOPAD_A;
+		i2c.put_clk_reg = RADEON_GPIOPAD_EN;
+		i2c.put_data_reg = RADEON_GPIOPAD_EN;
+		i2c.get_clk_reg = RADEON_LCD_GPIO_Y_REG;
+		i2c.get_data_reg = RADEON_LCD_GPIO_Y_REG;
 		i2c.valid = TRUE;
 		break;
 	    }
@@ -1384,6 +1388,10 @@ Bool RADEONGetExtTMDSInfoFromBIOS (ScrnInfoPtr pScrn, radeon_dvo_ptr dvo)
 		    }
 		}
 	    }
+	} else {
+	    dvo->dvo_i2c_slave_addr = 0x70;
+	    dvo->dvo_i2c = RADEONLookupI2CBlock(pScrn, 136);
+	    info->ext_tmds_chip = RADEON_SIL_164;
 	}
     } else {
 	offset = RADEON_BIOS16(info->ROMHeaderStart + 0x58);
@@ -1402,9 +1410,12 @@ Bool RADEONGetExtTMDSInfoFromBIOS (ScrnInfoPtr pScrn, radeon_dvo_ptr dvo)
 		dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
 	    else if (gpio_reg == 3)
 		dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
-	    else if (gpio_reg == 4)
-		dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
-	    else if (gpio_reg == 5) {
+	    else if (gpio_reg == 4) {
+		if (IS_R300_VARIANT)
+		    dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID);
+		else
+		    dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
+	    } else if (gpio_reg == 5) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			   "unsupported MM gpio_reg\n");
 		return FALSE;
commit f17657fdc83d8f4c0386d2c7dade98de5b94acbe
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Mon Nov 9 16:59:11 2009 -0500

    r600/r700: typo, fix mask of DB_ALPHA_TO_MASK
    
    noticed by glisse.

diff --git a/src/r600_reg_r6xx.h b/src/r600_reg_r6xx.h
index b4cc639..fec02ac 100644
--- a/src/r600_reg_r6xx.h
+++ b/src/r600_reg_r6xx.h
@@ -417,11 +417,11 @@ enum {
 	ALPHA_TO_MASK_ENABLE                              = 1 << 0,
 	ALPHA_TO_MASK_OFFSET0_mask                        = 0x03 << 8,
 	ALPHA_TO_MASK_OFFSET0_shift                       = 8,
-	ALPHA_TO_MASK_OFFSET1_mask                        = 0x03 << 8,
+	ALPHA_TO_MASK_OFFSET1_mask                        = 0x03 << 10,
 	ALPHA_TO_MASK_OFFSET1_shift                       = 10,
-	ALPHA_TO_MASK_OFFSET2_mask                        = 0x03 << 8,
+	ALPHA_TO_MASK_OFFSET2_mask                        = 0x03 << 12,
 	ALPHA_TO_MASK_OFFSET2_shift                       = 12,
-	ALPHA_TO_MASK_OFFSET3_mask                        = 0x03 << 8,
+	ALPHA_TO_MASK_OFFSET3_mask                        = 0x03 << 14,
 	ALPHA_TO_MASK_OFFSET3_shift                       = 14,
 
 //  SQ_VTX_CONSTANT_WORD2_0                               = 0x00038008,
commit 0ee7763fb33bf7fbc4ae1e8372cbc74578bfb720
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Mon Nov 9 15:09:34 2009 -0500

    IGP: some IGP chips report as AGP
    
    Set bus type appropriately.  fixes bug 25002
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 7cb4c03..5fddcce 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -2000,6 +2000,11 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn)
     if (info->cardType == CARD_PCIE && info->IsIGP)
 	info->cardType = CARD_PCI;
 
+    /* some rs4xx cards report as agp */
+    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
+	(info->ChipFamily == CHIP_FAMILY_RS480))
+	info->cardType = CARD_PCI;
+
     if ((info->ChipFamily >= CHIP_FAMILY_R600) && info->IsIGP)
 	info->cardType = CARD_PCIE;
 
@@ -2013,7 +2018,13 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn)
 	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into AGP mode\n");
 	} else if ((strcmp(s, "PCI") == 0) ||
 		   (strcmp(s, "PCIE") == 0)) {
-	    if (info->ChipFamily >= CHIP_FAMILY_RV380) {
+	    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
+		(info->ChipFamily == CHIP_FAMILY_RS480) ||
+		(info->ChipFamily == CHIP_FAMILY_RS690) ||
+		(info->ChipFamily == CHIP_FAMILY_RS740)) {
+		info->cardType = CARD_PCI;
+		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI mode\n");
+	    } else if (info->ChipFamily >= CHIP_FAMILY_RV380) {
 		info->cardType = CARD_PCIE;
 		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI Express mode\n");
 	    } else {
commit da1fcddaade58e371c7bee555ce32944c689f810
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Nov 5 14:13:49 2009 -0500

    radeon: properly fix unused label warnings

diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index d5a3103..61c7427 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -512,7 +512,9 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
         goto out;
     }
 
+#if X_BYTE_ORDER == X_BIG_ENDIAN
 copy:
+#endif
     r = radeon_bo_map(scratch, 0);
     if (r) {
         r = FALSE;
@@ -628,7 +630,9 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
                     RADEON_GEM_DOMAIN_GTT);
     FLUSH_RING();
 
+#if X_BYTE_ORDER == X_BIG_ENDIAN
 copy:
+#endif
     r = radeon_bo_map(scratch, 0);
     if (r) {
         r = FALSE;
commit 6e496f46fdc90d0a6cef41e9d45a6458aaed1eca
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Nov 5 14:11:55 2009 -0500

    Revert "Fix warning about unused defined labels in radeon_exa_funcs.c."
    
    This reverts commit b6ac42cce2156880ac18b32e15acbff40b2f53e9.
    
    This patch is very broken.

diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 1f463d1..d5a3103 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -454,18 +454,16 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
     RINFO_FROM_SCREEN(pScreen);
     struct radeon_exa_pixmap_priv *driver_priv;
     struct radeon_bo *scratch;
+    unsigned char *dst;
     unsigned size;
+    uint32_t datatype = 0;
     uint32_t dst_domain;
+    uint32_t dst_pitch_offset;
     unsigned bpp = pDst->drawable.bitsPerPixel;
     uint32_t scratch_pitch = (w * bpp / 8 + 63) & ~63;
+    uint32_t swap = RADEON_HOST_DATA_SWAP_NONE;
     Bool r;
-#if X_BYTE_ORDER == X_BIG_ENDIAN
-	unsigned char *dst;
-	uint32_t datatype = 0;
-	uint32_t dst_pitch_offset;
-	uint32_t swap = RADEON_HOST_DATA_SWAP_NONE;
     int i;
-#endif
 
     if (bpp < 8)
 	return FALSE;
@@ -514,7 +512,6 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
         goto out;
     }
 
-#if X_BYTE_ORDER == X_BIG_ENDIAN
 copy:
     r = radeon_bo_map(scratch, 0);
     if (r) {
@@ -541,7 +538,7 @@ copy:
 			dst_pitch_offset, 0, 0, x, y, w, h,
 			RADEON_GEM_DOMAIN_GTT, RADEON_GEM_DOMAIN_VRAM);
     }
-#endif
+
 out:
     if (scratch != driver_priv->bo)
 	radeon_bo_unref(scratch);
@@ -561,9 +558,7 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
     uint32_t src_pitch_offset;
     unsigned bpp = pSrc->drawable.bitsPerPixel;
     uint32_t scratch_pitch = (w * bpp / 8 + 63) & ~63;
-#if X_BYTE_ORDER == X_BIG_ENDIAN
     uint32_t swap = RADEON_HOST_DATA_SWAP_NONE;
-#endif
     Bool r;
 
     if (bpp < 8)
@@ -633,7 +628,6 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
                     RADEON_GEM_DOMAIN_GTT);
     FLUSH_RING();
 
-#if X_BYTE_ORDER == X_BIG_ENDIAN
 copy:
     r = radeon_bo_map(scratch, 0);
     if (r) {
@@ -652,7 +646,6 @@ copy:
         dst += dst_pitch;
     }
     radeon_bo_unmap(scratch);
-#endif
 out:
     if (scratch != driver_priv->bo)
 	radeon_bo_unref(scratch);
commit b6ac42cce2156880ac18b32e15acbff40b2f53e9
Author: Tomáš Chvátal <scarabeus at gentoo.org>
Date:   Sat Oct 31 23:07:07 2009 +0100

    Fix warning about unused defined labels in radeon_exa_funcs.c.
    
    Signed-off-by: Tomáš Chvátal <scarabeus at gentoo.org>

diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index d5a3103..1f463d1 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -454,16 +454,18 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
     RINFO_FROM_SCREEN(pScreen);
     struct radeon_exa_pixmap_priv *driver_priv;
     struct radeon_bo *scratch;
-    unsigned char *dst;
     unsigned size;
-    uint32_t datatype = 0;
     uint32_t dst_domain;
-    uint32_t dst_pitch_offset;
     unsigned bpp = pDst->drawable.bitsPerPixel;
     uint32_t scratch_pitch = (w * bpp / 8 + 63) & ~63;
-    uint32_t swap = RADEON_HOST_DATA_SWAP_NONE;
     Bool r;
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+	unsigned char *dst;
+	uint32_t datatype = 0;
+	uint32_t dst_pitch_offset;
+	uint32_t swap = RADEON_HOST_DATA_SWAP_NONE;
     int i;
+#endif
 
     if (bpp < 8)
 	return FALSE;
@@ -512,6 +514,7 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
         goto out;
     }
 
+#if X_BYTE_ORDER == X_BIG_ENDIAN
 copy:
     r = radeon_bo_map(scratch, 0);
     if (r) {
@@ -538,7 +541,7 @@ copy:
 			dst_pitch_offset, 0, 0, x, y, w, h,
 			RADEON_GEM_DOMAIN_GTT, RADEON_GEM_DOMAIN_VRAM);
     }
-
+#endif
 out:
     if (scratch != driver_priv->bo)
 	radeon_bo_unref(scratch);
@@ -558,7 +561,9 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
     uint32_t src_pitch_offset;
     unsigned bpp = pSrc->drawable.bitsPerPixel;
     uint32_t scratch_pitch = (w * bpp / 8 + 63) & ~63;
+#if X_BYTE_ORDER == X_BIG_ENDIAN
     uint32_t swap = RADEON_HOST_DATA_SWAP_NONE;
+#endif
     Bool r;
 
     if (bpp < 8)
@@ -628,6 +633,7 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
                     RADEON_GEM_DOMAIN_GTT);
     FLUSH_RING();
 
+#if X_BYTE_ORDER == X_BIG_ENDIAN
 copy:
     r = radeon_bo_map(scratch, 0);
     if (r) {
@@ -646,6 +652,7 @@ copy:
         dst += dst_pitch;
     }
     radeon_bo_unmap(scratch);
+#endif
 out:
     if (scratch != driver_priv->bo)
 	radeon_bo_unref(scratch);
commit 87d7235790866f9c19ef08972d5237f09d940cd9
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Nov 5 10:23:03 2009 -0500

    EXA: fallback if no pMaskPicture->pDrawable
    
    A solid or gradient mask could be used for blending
    the source picture onto the destination picture.
    
    Fixes fdo bug 24838
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/r600_exa.c b/src/r600_exa.c
index a2ce5c9..7d8cf46 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -1603,7 +1603,12 @@ static Bool R600CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP
     }
 
     if (pMaskPicture) {
-	PixmapPtr pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
+	PixmapPtr pMaskPixmap;
+
+	if (!pMaskPicture->pDrawable)
+	    RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
+
+	pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
 
 	if (pMaskPixmap->drawable.width >= max_tex_w ||
 	    pMaskPixmap->drawable.height >= max_tex_h) {
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 7ae0d1f..b745705 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -524,7 +524,12 @@ static Bool R100CheckComposite(int op, PicturePtr pSrcPicture,
     }
 
     if (pMaskPicture) {
-	PixmapPtr pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
+	PixmapPtr pMaskPixmap;
+
+	if (!pMaskPicture->pDrawable)
+	    RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
+
+	pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
 
 	if (pMaskPixmap->drawable.width > 2047 ||
 	    pMaskPixmap->drawable.height > 2047) {
@@ -900,7 +905,12 @@ static Bool R200CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP
     }
 
     if (pMaskPicture) {
-	PixmapPtr pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
+	PixmapPtr pMaskPixmap;
+
+	if (!pMaskPicture->pDrawable)
+	    RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
+
+	pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
 
 	if (pMaskPixmap->drawable.width > 2047 ||
 	    pMaskPixmap->drawable.height > 2047) {
@@ -1359,7 +1369,12 @@ static Bool R300CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP
     }
 
     if (pMaskPicture) {
-	PixmapPtr pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
+	PixmapPtr pMaskPixmap;
+
+	if (!pMaskPicture->pDrawable)
+	    RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
+
+	pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
 
 	if (pMaskPixmap->drawable.width > max_tex_w ||
 	    pMaskPixmap->drawable.height > max_tex_h) {
commit 873897c54429e230a23011a9dd2f1069f4eb7752
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Nov 5 00:51:11 2009 -0500

    DCE3+: call transmitter init on mode set
    
    Generally this is done at post, but might not always
    be done with softboot or for connectors on docking
    stations.
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/atombios_output.c b/src/atombios_output.c
index 4db5d0c..d85c3f6 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -646,15 +646,19 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action)
     disp_data.v1.ucAction = action;
 
     if (IS_DCE32_VARIANT) {
-	if (radeon_output->MonType == MT_DP) {
-	    disp_data.v2.usPixelClock =
-		cpu_to_le16(dp_link_clock_for_mode_clock(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;
+	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+	    disp_data.v2.usInitInfo = radeon_output->connector_object_id;
 	} else {
-	    disp_data.v2.usPixelClock = cpu_to_le16(clock / 10);
+	    if (radeon_output->MonType == MT_DP) {
+		disp_data.v2.usPixelClock =
+		    cpu_to_le16(dp_link_clock_for_mode_clock(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 (dig_block)
 	    disp_data.v2.acConfig.ucEncoderSel = 1;
@@ -684,13 +688,17 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action)
     } else {
 	disp_data.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
 
-	if (radeon_output->MonType == MT_DP)
-	    disp_data.v1.usPixelClock =
-		cpu_to_le16(dp_link_clock_for_mode_clock(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 (action == ATOM_TRANSMITTER_ACTION_INIT) {
+	    disp_data.v1.usInitInfo = radeon_output->connector_object_id;
+	} else {
+	    if (radeon_output->MonType == MT_DP)
+		disp_data.v1.usPixelClock =
+		    cpu_to_le16(dp_link_clock_for_mode_clock(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);
+	}
 
 	switch (radeon_encoder->encoder_id) {
 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
@@ -1488,7 +1496,7 @@ atombios_output_mode_set(xf86OutputPtr output,
     radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output);
     RADEONInfoPtr info       = RADEONPTR(output->scrn);
     if (radeon_encoder == NULL)
-        return;
+	return;
 
     radeon_output->pixel_clock = adjusted_mode->Clock;
     radeon_output->dig_block = radeon_crtc->crtc_id;
@@ -1520,6 +1528,7 @@ atombios_output_mode_set(xf86OutputPtr output,
 
 	/* setup and enable the encoder and transmitter */
 	atombios_output_dig_encoder_setup(output, ATOM_ENABLE);
+	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_INIT);
 	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP);
 	atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE);
 	break;
diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index 1f4b9dc..f3c88bc 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -1873,10 +1873,13 @@ RADEONGetATOMConnectorInfoFromBIOSObject (ScrnInfoPtr pScrn)
 
 		    ct = (slot_config  >> 16) & 0xff;
 		    info->BiosConnector[i].ConnectorType = object_connector_convert[ct];
+		    info->BiosConnector[i].connector_object_id = ct;
 		    info->BiosConnector[i].igp_lane_info = slot_config & 0xffff;
 		}
-	    } else
+	    } else {
 		info->BiosConnector[i].ConnectorType = object_connector_convert[con_obj_id];
+		info->BiosConnector[i].connector_object_id = con_obj_id;
+	    }
 
 	    if (info->BiosConnector[i].ConnectorType == CONNECTOR_NONE) {
 		info->BiosConnector[i].valid = FALSE;
diff --git a/src/radeon_output.c b/src/radeon_output.c
index 6e00ab8..9d9a16c 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -2860,6 +2860,7 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn)
 	    radeon_output->load_detection = info->BiosConnector[i].load_detection;
 	    radeon_output->linkb = info->BiosConnector[i].linkb;
 	    radeon_output->connector_id = info->BiosConnector[i].connector_object;
+	    radeon_output->connector_object_id = info->BiosConnector[i].connector_object_id;
 
 	    /* Technically HDMI-B is a glorfied DL DVI so the bios is correct,
 	     * but this can be confusing to users when it comes to output names,
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index 0ae3a87..12e73ef 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -239,6 +239,7 @@ typedef struct {
     Bool load_detection;
     Bool linkb;
     uint16_t connector_object;
+    uint16_t connector_object_id;
 } RADEONBIOSConnector;
 
 typedef struct _RADEONOutputPrivateRec {
@@ -254,6 +255,7 @@ typedef struct _RADEONOutputPrivateRec {
     Bool linkb;
 
     RADEONConnectorType ConnectorType;
+    uint16_t connector_object_id;
     RADEONDviType DVIType;
     RADEONMonitorType MonType;
 
commit 3028374488cc0f34942ac372c8d05cf15898a613
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Nov 4 18:48:03 2009 -0500

    ATOM/DCE3+: fix up usPixelClock calculation for Transmitter tables
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/atombios_output.c b/src/atombios_output.c
index bf26c1b..4db5d0c 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -651,10 +651,10 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action)
 		cpu_to_le16(dp_link_clock_for_mode_clock(clock));
 	    disp_data.v2.acConfig.fDPConnector = 1;
 	} else if (clock > 165000) {
-	    disp_data.v2.usPixelClock = cpu_to_le16((clock * 10 * 2) / 100);
+	    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 * 4) / 100);
+	    disp_data.v2.usPixelClock = cpu_to_le16(clock / 10);
 	}
 	if (dig_block)
 	    disp_data.v2.acConfig.ucEncoderSel = 1;
@@ -687,8 +687,10 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action)
 	if (radeon_output->MonType == MT_DP)
 	    disp_data.v1.usPixelClock =
 		cpu_to_le16(dp_link_clock_for_mode_clock(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);
+	    disp_data.v1.usPixelClock = cpu_to_le16(clock / 10);
 
 	switch (radeon_encoder->encoder_id) {
 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
commit 52973e8f2c4104de60d00c0e5c29a31f77bf3de7
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Sun Nov 1 13:58:03 2009 -0500

    radeon/atom: fix tv-out on r5xx
    
    fixes bug 24796
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 6c80ea6..f9698f3 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -489,7 +489,7 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc,
     Bool tilingChanged = FALSE;
 
     if (info->allowColorTiling) {
-        radeon_crtc->can_tile = (adjusted_mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE;
+	radeon_crtc->can_tile = (mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE;
 	tilingChanged = RADEONSetTiling(pScrn);
     }
 
@@ -584,7 +584,7 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc,
 	OUTREG(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
 	       (mode->HDisplay << 16) | mode->VDisplay);
 
-	if (adjusted_mode->Flags & V_INTERLACE)
+	if (mode->Flags & V_INTERLACE)
 	    OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
 		   AVIVO_D1MODE_INTERLEAVE_EN);
 	else
diff --git a/src/atombios_output.c b/src/atombios_output.c
index 57345b3..bf26c1b 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -1470,8 +1470,10 @@ atombios_apply_output_quirks(xf86OutputPtr output, DisplayModePtr mode)
     }
 
     /* set scaler clears this on some chips */
-    if (IS_AVIVO_VARIANT && (mode->Flags & V_INTERLACE))
-	OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, AVIVO_D1MODE_INTERLEAVE_EN);
+    if (!(radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))) {
+	if (IS_AVIVO_VARIANT && (mode->Flags & V_INTERLACE))
+	    OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, AVIVO_D1MODE_INTERLEAVE_EN);
+    }
 }
 
 void
commit 19b4f5f9b647cd470616b8ec1d34f1e4afa357ad
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Oct 27 11:55:20 2009 -0400

    ATOM: fix up DVO for DCE 3.x
    
    AdjustDisplayPll takes care of this for us.

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index fb7728f..6c80ea6 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -328,8 +328,11 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 	    xf86OutputPtr output = xf86_config->output[i];
 	    if (output->crtc == crtc) {
 		radeon_encoder = radeon_get_encoder(output);
-		/* DVO seems to want 2x pixel clock */
-		if (radeon_encoder && (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1))
+		/* 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;
 	    }
 	}
commit 5a0019126a57138ee506d9a66738c9e8b75cbb96
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Oct 27 11:39:06 2009 -0400

    radeon: fix DVO on AVIVO chips
    
    DVO generally requires 2x ppll on AVIVO cards due to the
    way the tmds chip is wired up.  Because of this, disable
    cloning of DVO outputs.
    
    fixes fdo bug 21857.
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index d513c13..fb7728f 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -324,6 +324,16 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 	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_encoder = radeon_get_encoder(output);
+		/* DVO seems to want 2x pixel clock */
+		if (radeon_encoder && (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1))
+		    sclock *= 2;
+	    }
+	}
+
 	/* disable spread spectrum clocking for now -- thanks Hedy Lamarr */
 	if (radeon_crtc->crtc_id == 0) {
 	    temp = INREG(AVIVO_P1PLL_INT_SS_CNTL);
diff --git a/src/radeon_output.c b/src/radeon_output.c
index a252363..6e00ab8 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -2634,16 +2634,21 @@ radeon_output_clones (ScrnInfoPtr pScrn, xf86OutputPtr output)
     int			index_mask = 0;
 
     /* DIG routing gets problematic */
-    if (IS_DCE32_VARIANT)
+    if (info->ChipFamily >= CHIP_FAMILY_R600)
 	return index_mask;
 
     /* LVDS is too wacky */
     if (radeon_output->devices & (ATOM_DEVICE_LCD_SUPPORT))
 	return index_mask;
 
+    /* TV requires very specific timing */
     if (radeon_output->devices & (ATOM_DEVICE_TV_SUPPORT))
 	return index_mask;
 
+    /* DVO requires 2x ppll clocks depending on the tmds chip */
+    if (radeon_output->devices & (ATOM_DEVICE_DFP2_SUPPORT))
+	return index_mask;
+
     for (o = 0; o < config->num_output; o++) {
 	xf86OutputPtr clone = config->output[o];
 	RADEONOutputPrivatePtr radeon_clone = clone->driver_private;
commit 2a6eeec72d6bb04a32225883f431c1d2e8cff123
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Oct 27 11:18:44 2009 -0400

    atom: loosen pll min output limits
    
    Limiting the pll output range is a good thing generally as
    it limits the number of possible pll combinations for a given
    frequency presumably to the ones that work best on each card.
    That's why the limits are in the bios tables. However, certain
    duallink DVI monitors seem to like pll combinations that would
    be limited by this at least on pre-DCE 3.0 r6xx hardware.  This
    might need to be adjusted per family or per clock range in the
    future.
    
    Fixes fdo bug 24727.
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index a8eded6..1f4b9dc 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -2171,6 +2171,15 @@ RADEONGetATOMClockInfo(ScrnInfoPtr pScrn)
     if (pll->pll_out_min == 0)
 	pll->pll_out_min = 64800;
 
+    /* limiting the range is a good thing in most cases
+     * as it limits the number of matching pll combinations,
+     * however, some duallink DVI monitors seem to prefer combinations that
+     * would be limited by this.  This may need to be revisited
+     * per chip family.
+     */
+    if (pll->pll_out_min > 64800)
+	pll->pll_out_min = 64800;
+
     return TRUE;
 }
 
commit f0d9d80fee4176eaba9435a9539f29d0eefe2a87
Author: Luca Tettamanti <kronos.it at gmail.com>
Date:   Sat Oct 24 16:45:23 2009 -0400

    Disable color tiling on r600/r700
    
    Not supported yet.

diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index b3fe20c..8e46a8a 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -411,6 +411,10 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
 
     info->allowColorTiling = xf86ReturnOptValBool(info->Options,
                                         OPTION_COLOR_TILING, FALSE);
+    if (info->ChipFamily >= CHIP_FAMILY_R600) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Color tiling is not yet supported on R600/R700\n");
+	    info->allowColorTiling = FALSE;
+    }
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	 "KMS Color Tiling: %sabled\n", info->allowColorTiling ? "en" : "dis");
 
commit ac499c3c0ea92f83ebd8127bb8cb5de625de6c94
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Fri Oct 23 10:48:55 2009 -0400

    radeon: clamp the internal FB map to the aperture size v2
    
    We don't use the invisible memory yet and on cards with
    large amounts of vram this can cause the top of GART
    calculation to overflow.
    
    Fixes bug fdo bug 24301:
    http://bugs.freedesktop.org/show_bug.cgi?id=24301
    
    v2: only clamp cards with more than 512 MB.  This seems
    to cause problems on some older cards due to the way the
    drm and ddx set up the internal memory map.

diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index d039920..7cb4c03 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -1403,6 +1403,18 @@ static void RADEONInitMemoryMap(ScrnInfoPtr pScrn)
     if (aper_size > mem_size)
 	mem_size = aper_size;
 
+    /* don't map the whole FB in the internal address space.
+     * we don't currently use fb space larger than the aperture
+     * size and on cards with more than 512 MB of vram, this can overflow
+     * the internal top of gart calculation on some systems.
+     * Limit it to cards with more than 512 MB as this causes problems
+     * on some other cards due to the way the ddx and drm set up the
+     * internal memory map.
+     * See fdo bug 24301.
+     */
+    if (mem_size > 0x20000000)
+	mem_size = aper_size;
+
 #ifdef XF86DRI
     /* Apply memory map limitation if using an old DRI */
     if (info->directRenderingEnabled && !info->dri->newMemoryMap) {
commit e57b54daf318ff59315a1c9ed21934f288c5c782
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Oct 22 16:07:58 2009 -0400

    R7xx: program additional CUR/GRPH regs for 40 bit addresses
    
    The *_HIGH regs are reversed. The secondary ones are in the
    primary block and vice versa.

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 62402a7..d513c13 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -536,6 +536,15 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc,
 	    fb_location = fb_location + (char *)crtc->rotatedData - (char *)info->FB;
 	}
 
+	if (info->ChipFamily >= CHIP_FAMILY_RV770) {
+	    if (radeon_crtc->crtc_id) {
+		OUTREG(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0);
+		OUTREG(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0);
+	    } else {
+		OUTREG(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0);
+		OUTREG(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0);
+	    }
+	}
 	OUTREG(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, fb_location);
 	OUTREG(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, fb_location);
 	OUTREG(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
diff --git a/src/radeon_cursor.c b/src/radeon_cursor.c
index 5ecdfad..cf5e9a0 100644
--- a/src/radeon_cursor.c
+++ b/src/radeon_cursor.c
@@ -106,6 +106,12 @@ avivo_setup_cursor(xf86CrtcPtr crtc, Bool enable)
     OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
 
     if (enable) {
+	if (info->ChipFamily >= CHIP_FAMILY_RV770) {
+	    if (radeon_crtc->crtc_id)
+		OUTREG(R700_D2CUR_SURFACE_ADDRESS_HIGH, 0);
+	    else
+		OUTREG(R700_D1CUR_SURFACE_ADDRESS_HIGH, 0);
+	}
 	OUTREG(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
 	       info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset);
 	OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset,
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index 5467286..e656f5f 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -3669,8 +3669,16 @@
 #       define R600_D1GRPH_SWAP_ENDIAN_32BIT                   (2 << 0)
 #       define R600_D1GRPH_SWAP_ENDIAN_64BIT                   (3 << 0)
 
+/* the *_HIGH surface regs are backwards; the D1 regs are in the D2
+ * block and vice versa.  This applies to GRPH, CUR, etc.
+ */
+
 #define AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS                    0x6110
+#define R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH                0x6914
+#define R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH                0x6114
 #define AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS                  0x6118
+#define R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH              0x691c
+#define R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH              0x611c
 #define AVIVO_D1GRPH_PITCH                                      0x6120
 #define AVIVO_D1GRPH_SURFACE_OFFSET_X                           0x6124
 #define AVIVO_D1GRPH_SURFACE_OFFSET_Y                           0x6128
@@ -3690,6 +3698,8 @@
 #       define AVIVO_D1CURSOR_MODE_MASK   (0x3<<8)
 #       define AVIVO_D1CURSOR_MODE_24BPP  (0x2)
 #define AVIVO_D1CUR_SURFACE_ADDRESS             0x6408
+#define R700_D1CUR_SURFACE_ADDRESS_HIGH         0x6c0c
+#define R700_D2CUR_SURFACE_ADDRESS_HIGH         0x640c
 #define AVIVO_D1CUR_SIZE                        0x6410
 #define AVIVO_D1CUR_POSITION                    0x6414
 #define AVIVO_D1CUR_HOT_SPOT                    0x6418
commit 4cf06dfba617529291ce4b4c306c4fc1bba110ee
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Oct 22 02:08:45 2009 -0400

    ATOM: use indirect addressing for regs >= 0x10000

diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index 6db821f..a8eded6 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -30,6 +30,7 @@
 #include "xf86_OSproc.h"
 
 #include "radeon.h"
+#include "radeon_reg.h"
 #include "radeon_atombios.h"
 #include "radeon_atomwrapper.h"
 #include "radeon_probe.h"
@@ -2646,9 +2647,16 @@ CailReadATIRegister(VOID* CAIL, UINT32 idx)
     RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
     unsigned char *RADEONMMIO = pRADEONEnt->MMIO;
     UINT32 ret;
+    UINT32 mm_reg = idx << 2;
     CAILFUNC(CAIL);
 
-    ret  =  INREG(idx << 2);
+    if (mm_reg < 0x10000)
+	ret = INREG(mm_reg);
+    else {
+	OUTREG(RADEON_MM_INDEX, mm_reg);
+	ret = INREG(RADEON_MM_DATA);
+    }
+
     /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx << 2,ret));*/
     return ret;
 }
@@ -2659,9 +2667,16 @@ CailWriteATIRegister(VOID *CAIL, UINT32 idx, UINT32 data)
     ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex];
     RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
     unsigned char *RADEONMMIO = pRADEONEnt->MMIO;
+    UINT32 mm_reg = idx << 2;
     CAILFUNC(CAIL);
 
-    OUTREG(idx << 2,data);
+    if (mm_reg < 0x10000)
+	OUTREG(mm_reg, data);
+    else {
+	OUTREG(RADEON_MM_INDEX, mm_reg);
+	OUTREG(RADEON_MM_DATA, data);
+    }
+
     /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,idx << 2,data));*/
 }
 
commit 66b194a78c470cb3978f310828dd96c3f3e96944
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Oct 21 15:58:18 2009 -0400

    ATOM: fix up get clock info
    
    Newer revisions of the atom firmware table have
    changed.  This helps select better pll dividers
    in some cases.  Noticed by Mathias Froehlich.

diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index 13ef1ef..6db821f 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -2127,6 +2127,53 @@ RADEONGetATOMTVInfo(xf86OutputPtr output)
 }
 
 Bool
+RADEONGetATOMClockInfo(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr info = RADEONPTR (pScrn);
+    RADEONPLLPtr pll = &info->pll;
+    atomDataTablesPtr atomDataPtr;
+    uint8_t crev, frev;
+
+    atomDataPtr = info->atomBIOS->atomDataPtr;
+    if (!rhdAtomGetTableRevisionAndSize(
+	    (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->FirmwareInfo.base),
+	    &crev,&frev,NULL)) {
+	return FALSE;
+    }
+
+    switch(crev) {
+    case 1:
+	info->sclk = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->ulDefaultEngineClock) / 100.0;
+	info->mclk = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->ulDefaultMemoryClock) / 100.0;
+	pll->xclk = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usMaxPixelClock);
+	pll->pll_in_min = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usMinPixelClockPLL_Input);
+	pll->pll_in_max = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usMaxPixelClockPLL_Input);
+	pll->pll_out_min = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usMinPixelClockPLL_Output);
+	pll->pll_out_max = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->ulMaxPixelClockPLL_Output);
+	pll->reference_freq = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usReferenceClock);
+	break;
+    case 2:
+    case 3:
+    case 4:
+    default:
+	info->sclk = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->ulDefaultEngineClock) / 100.0;
+	info->mclk = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->ulDefaultMemoryClock) / 100.0;
+	pll->xclk = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->usMaxPixelClock);
+	pll->pll_in_min = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->usMinPixelClockPLL_Input);
+	pll->pll_in_max = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->usMaxPixelClockPLL_Input);
+	pll->pll_out_min = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->ulMinPixelClockPLL_Output);
+	pll->pll_out_max = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->ulMaxPixelClockPLL_Output);
+	pll->reference_freq = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->usReferenceClock);
+	break;
+    }
+    pll->reference_div = 0;
+    if (pll->pll_out_min == 0)
+	pll->pll_out_min = 64800;
+
+    return TRUE;
+}
+
+Bool
 RADEONATOMGetTVTimings(ScrnInfoPtr pScrn, int index, DisplayModePtr mode)
 {
     RADEONInfoPtr  info       = RADEONPTR(pScrn);
diff --git a/src/radeon_atombios.h b/src/radeon_atombios.h
index d525063..1f21c46 100644
--- a/src/radeon_atombios.h
+++ b/src/radeon_atombios.h
@@ -275,6 +275,9 @@ RADEONATOMGetTVTimings(ScrnInfoPtr pScrn, int index, DisplayModePtr mode);
 extern void
 RADEONATOMGetIGPInfo(ScrnInfoPtr pScrn);
 
+extern Bool
+RADEONGetATOMClockInfo(ScrnInfoPtr pScrn);
+
 extern uint32_t
 radeon_get_device_index(uint32_t device_support);
 extern radeon_encoder_ptr
diff --git a/src/radeon_bios.c b/src/radeon_bios.c
index ecf5403..f19d929 100644
--- a/src/radeon_bios.c
+++ b/src/radeon_bios.c
@@ -995,30 +995,7 @@ Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn)
 	return FALSE;
     } else {
 	if (info->IsAtomBios) {
-	    pll_info_block = RADEON_BIOS16 (info->MasterDataStart + 12);
-
-	    pll->reference_freq = RADEON_BIOS16 (pll_info_block + 82);
-	    pll->reference_div = 0; /* Need to derive from existing setting
-					or use a new algorithm to calculate
-					from min_input and max_input
-				     */
-	    pll->pll_out_min = RADEON_BIOS16 (pll_info_block + 78);
-	    pll->pll_out_max = RADEON_BIOS32 (pll_info_block + 32);
-
-	    if (pll->pll_out_min == 0) {
-		if (IS_AVIVO_VARIANT)
-		    pll->pll_out_min = 64800;
-		else
-		    pll->pll_out_min = 20000;
-	    }
-
-	    pll->pll_in_min = RADEON_BIOS16 (pll_info_block + 74);
-	    pll->pll_in_max = RADEON_BIOS16 (pll_info_block + 76);
-
-	    pll->xclk = RADEON_BIOS16 (pll_info_block + 72);
-
-	    info->sclk = RADEON_BIOS32(pll_info_block + 8) / 100.0;
-	    info->mclk = RADEON_BIOS32(pll_info_block + 12) / 100.0;
+	    return RADEONGetATOMClockInfo(pScrn);
 	} else {
 	    int rev;
 
commit bd89b7501f294ac645390ef144df569953c81dc4
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Sun Oct 18 16:21:36 2009 -0400

    radeon: fixup CustomEDID option
    
    - add support for analog option to force edid to analog
    mode
    - fix compilation on older xservers
    - updated man page

diff --git a/man/radeon.man b/man/radeon.man
index 8514c1c..28b1385 100644
--- a/man/radeon.man
+++ b/man/radeon.man
@@ -306,8 +306,11 @@ The default value is
 Forces the X driver to use the EDID data specified in a file rather
 than the display's EDID. Also overrides DDC monitor detection.
 .br
-You may specify a semicolon separated list of output name and filename pairs.
-The output name is something like "VGA-0" or "DVI-0";
+You may specify a semicolon separated list of output name and filename pairs
+with an optional flag, "digital" or "analog", to override the digital bit in
+the edid which is used by the driver to determine whether to use the
+analog or digital encoder associated with a DVI-I port.
+The output name is the randr output name, e.g., "VGA-0" or "DVI-0";
 consult the Xorg log for the supported output names of any given system.
 .br
 The file must contain a raw 128-byte EDID block, as captured by
@@ -316,10 +319,10 @@ get-edid.
 .br
 For example:
 .B
-Option \*qCustomEDID\*q \*qVGA-0:/tmp/edid1.bin; DVI-0:/tmp/edid2.bin\*q
+Option \*qCustomEDID\*q \*qVGA-0:/tmp/edid1.bin; DVI-0:/tmp/edid2.bin:digital\*q
 will assign the EDID from the file /tmp/edid1.bin to the output device
 VGA-0, and the EDID from the file /tmp/edid2.bin to the output device
-DVI-0.
+DVI-0 and force the DVI port to use the digital encoder.
 .br
 Note that a output name must always be specified,
 even if only one EDID is specified.
diff --git a/src/radeon_output.c b/src/radeon_output.c
index 0429088..a252363 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -260,26 +260,20 @@ RADEONGetHardCodedEDIDFromFile(xf86OutputPtr output)
 			       "Successfully read Custom EDID data for output %s from %s.\n",
 			       name, outputEDID);
 		    if (command != NULL) {
-		      if (!strcmp(command, "digital")) {
-			struct edid_version *v = &radeon_output->custom_mon->ver;
-			struct disp_features *r = &radeon_output->custom_mon->features;
-			r->input_type = 1;
-			if (v->revision == 2 || v->revision == 3) {
-			  // Nothing to do
-			} else if (v->revision >= 4) {
-			  r->input_interface = 1; // Using DVI by default
-			  r->input_bpc = 2; // 8 bits per channes by default
+			if (!strcmp(command, "digital")) {
+			    radeon_output->custom_mon->rawData[0x14] |= 0x80;
+			    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+				       "Forcing digital output for output %s.\n", name);
+			} else if (!strcmp(command, "analog")) {
+			    radeon_output->custom_mon->rawData[0x14] &= ~0x80;
+			    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+				       "Forcing analog output for output %s.\n", name);
+			} else {
+			    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+				       "Unknown custom EDID command: '%s'.\n",
+				       command);
 			}
-			radeon_output->custom_mon->rawData[0x14] |=  0x80;
-			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-				   "Forcing digital output for output %s.\n", name);
-		      } else {
-			xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-				   "Unknown custom EDID command: '%s'.\n",
-				   command);
-		      }
 		    }
-
 		} else {
 		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 			       "Custom EDID data for %s read from %s was invalid.\n",
commit 255ac8d54e3dc12e579e05edb41b40946a00eab8
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Oct 13 12:27:52 2009 -0400

    radeon: add XV_CRTC attribute for textured video
    
    This attribute allows the user to override which
    crtc is synced with when XV_VSYNC is enabled.  This
    is useful for clone modes where the user can might want
    to override the default.

diff --git a/man/radeon.man b/man/radeon.man
index 62270fb..8514c1c 100644
--- a/man/radeon.man
+++ b/man/radeon.man
@@ -616,6 +616,16 @@ It has two values: 'off'(0) and 'on'(1). The default is
 .B 'on'(1).
 
 .TP
+.BI "XV_CRTC"
+XV_CRTC is used to control which display controller (crtc) the textured
+adapter synchronizes the screen update with when XV_VSYNC is enabled.
+The default, 'auto'(-1), will sync to the display controller that more
+of the video is on.  This attribute is useful for things like clone mode
+where the user can best decide which display should be synced.
+The default is
+.B 'auto'(-1).
+
+.TP
 .BI "XV_BICUBIC"
 XV_BICUBIC is used to control whether textured adapter should apply
 a bicubic filter to smooth the output. It has three values: 'off'(0), 'on'(1)
diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index dd4d3d1..7598429 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -574,11 +574,15 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 		   sizeof(vs_alu_consts) / SQ_ALU_CONSTANT_offset, vs_alu_consts);
 
     if (pPriv->vsync) {
-	xf86CrtcPtr crtc = radeon_xv_pick_best_crtc(pScrn,
-						    pPriv->drw_x,
-						    pPriv->drw_x + pPriv->dst_w,
-						    pPriv->drw_y,
-						    pPriv->drw_y + pPriv->dst_h);
+	xf86CrtcPtr crtc;
+	if (pPriv->desired_crtc)
+	    crtc = pPriv->desired_crtc;
+	else
+	    crtc = radeon_xv_pick_best_crtc(pScrn,
+					    pPriv->drw_x,
+					    pPriv->drw_x + pPriv->dst_w,
+					    pPriv->drw_y,
+					    pPriv->drw_y + pPriv->dst_h);
 	if (crtc)
 	    cp_wait_vline_sync(pScrn, accel_state->ib, pPixmap,
 			       crtc,
diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c
index d6b221f..39c7574 100644
--- a/src/radeon_textured_video.c
+++ b/src/radeon_textured_video.c
@@ -538,15 +538,16 @@ static XF86VideoFormatRec Formats[NUM_FORMATS] =
     {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
 };
 
-#define NUM_ATTRIBUTES 1
+#define NUM_ATTRIBUTES 2
 
 static XF86AttributeRec Attributes[NUM_ATTRIBUTES+1] =
 {
     {XvSettable | XvGettable, 0, 1, "XV_VSYNC"},
+    {XvSettable | XvGettable, -1, 1, "XV_CRTC"},
     {0, 0, 0, NULL}
 };
 
-#define NUM_ATTRIBUTES_R200 6
+#define NUM_ATTRIBUTES_R200 7
 
 static XF86AttributeRec Attributes_r200[NUM_ATTRIBUTES_R200+1] =
 {
@@ -556,10 +557,11 @@ static XF86AttributeRec Attributes_r200[NUM_ATTRIBUTES_R200+1] =
     {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
     {XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
     {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"},
+    {XvSettable | XvGettable, -1, 1, "XV_CRTC"},
     {0, 0, 0, NULL}
 };
 
-#define NUM_ATTRIBUTES_R300 8
+#define NUM_ATTRIBUTES_R300 9
 
 static XF86AttributeRec Attributes_r300[NUM_ATTRIBUTES_R300+1] =
 {
@@ -571,10 +573,11 @@ static XF86AttributeRec Attributes_r300[NUM_ATTRIBUTES_R300+1] =
     {XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
     {XvSettable | XvGettable, 100, 10000, "XV_GAMMA"},
     {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"},
+    {XvSettable | XvGettable, -1, 1, "XV_CRTC"},
     {0, 0, 0, NULL}
 };
 
-#define NUM_ATTRIBUTES_R500 7
+#define NUM_ATTRIBUTES_R500 8
 
 static XF86AttributeRec Attributes_r500[NUM_ATTRIBUTES_R500+1] =
 {
@@ -585,10 +588,11 @@ static XF86AttributeRec Attributes_r500[NUM_ATTRIBUTES_R500+1] =
     {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
     {XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
     {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"},
+    {XvSettable | XvGettable, -1, 1, "XV_CRTC"},
     {0, 0, 0, NULL}
 };
 
-#define NUM_ATTRIBUTES_R600 6
+#define NUM_ATTRIBUTES_R600 7
 
 static XF86AttributeRec Attributes_r600[NUM_ATTRIBUTES_R600+1] =
 {
@@ -598,6 +602,7 @@ static XF86AttributeRec Attributes_r600[NUM_ATTRIBUTES_R600+1] =
     {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
     {XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
     {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"},
+    {XvSettable | XvGettable, -1, 1, "XV_CRTC"},
     {0, 0, 0, NULL}
 };
 
@@ -605,6 +610,7 @@ static Atom xvBicubic;
 static Atom xvVSync;
 static Atom xvBrightness, xvContrast, xvSaturation, xvHue;
 static Atom xvGamma, xvColorspace;
+static Atom xvCRTC;
 
 #define NUM_IMAGES 4
 
@@ -643,7 +649,16 @@ RADEONGetTexPortAttribute(ScrnInfoPtr  pScrn,
 	*value = pPriv->gamma;
     else if(attribute == xvColorspace)
 	*value = pPriv->transform_index;
-    else
+    else if(attribute == xvCRTC) {
+	int		c;
+	xf86CrtcConfigPtr	xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+	for (c = 0; c < xf86_config->num_crtc; c++)
+	    if (xf86_config->crtc[c] == pPriv->desired_crtc)
+		break;
+	if (c == xf86_config->num_crtc)
+	    c = -1;
+	*value = c;
+    } else
 	return BadMatch;
 
     return Success;
@@ -676,7 +691,15 @@ RADEONSetTexPortAttribute(ScrnInfoPtr  pScrn,
 	pPriv->gamma = ClipValue (value, 100, 10000);
     else if(attribute == xvColorspace)
 	pPriv->transform_index = ClipValue (value, 0, 1);
-    else
+    else if(attribute == xvCRTC) {
+	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+	if ((value < -1) || (value > xf86_config->num_crtc))
+	    return BadValue;
+	if (value < 0)
+	    pPriv->desired_crtc = NULL;
+	else
+	    pPriv->desired_crtc = xf86_config->crtc[value];
+    } else
 	return BadMatch;
 
     return Success;
@@ -759,6 +782,7 @@ RADEONSetupImageTexturedVideo(ScreenPtr pScreen)
     xvHue             = MAKE_ATOM("XV_HUE");
     xvGamma           = MAKE_ATOM("XV_GAMMA");
     xvColorspace      = MAKE_ATOM("XV_COLORSPACE");
+    xvCRTC            = MAKE_ATOM("XV_CRTC");
 
     adapt->type = XvWindowMask | XvInputMask | XvImageMask;
     adapt->flags = 0;
@@ -827,6 +851,7 @@ RADEONSetupImageTexturedVideo(ScreenPtr pScreen)
 	pPriv->hue = 0;
 	pPriv->gamma = 1000;
 	pPriv->transform_index = 0;
+	pPriv->desired_crtc = NULL;
 
 	/* gotta uninit this someplace, XXX: shouldn't be necessary for textured */
 	REGION_NULL(pScreen, &pPriv->clip);
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index 8b55efc..c7d9b02 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -351,11 +351,15 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
     FINISH_ACCEL();
 
     if (pPriv->vsync) {
-	xf86CrtcPtr crtc = radeon_xv_pick_best_crtc(pScrn,
-						    pPriv->drw_x,
-						    pPriv->drw_x + pPriv->dst_w,
-						    pPriv->drw_y,
-						    pPriv->drw_y + pPriv->dst_h);
+	xf86CrtcPtr crtc;
+	if (pPriv->desired_crtc)
+	    crtc = pPriv->desired_crtc;
+	else
+	    crtc = radeon_xv_pick_best_crtc(pScrn,
+					    pPriv->drw_x,
+					    pPriv->drw_x + pPriv->dst_w,
+					    pPriv->drw_y,
+					    pPriv->drw_y + pPriv->dst_h);
 	if (crtc)
 	    FUNC_NAME(RADEONWaitForVLine)(pScrn, pPixmap,
 					  crtc,
@@ -910,11 +914,15 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     FINISH_ACCEL();
 
     if (pPriv->vsync) {
-	xf86CrtcPtr crtc = radeon_xv_pick_best_crtc(pScrn,
-						    pPriv->drw_x,
-						    pPriv->drw_x + pPriv->dst_w,
-						    pPriv->drw_y,
-						    pPriv->drw_y + pPriv->dst_h);
+	xf86CrtcPtr crtc;
+	if (pPriv->desired_crtc)
+	    crtc = pPriv->desired_crtc;
+	else
+	    crtc = radeon_xv_pick_best_crtc(pScrn,
+					    pPriv->drw_x,
+					    pPriv->drw_x + pPriv->dst_w,
+					    pPriv->drw_y,
+					    pPriv->drw_y + pPriv->dst_h);
 	if (crtc)
 	    FUNC_NAME(RADEONWaitForVLine)(pScrn, pPixmap,
 					  crtc,
@@ -2282,11 +2290,15 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     FINISH_ACCEL();
 
     if (pPriv->vsync) {
-	xf86CrtcPtr crtc = radeon_xv_pick_best_crtc(pScrn,
-						    pPriv->drw_x,
-						    pPriv->drw_x + pPriv->dst_w,
-						    pPriv->drw_y,
-						    pPriv->drw_y + pPriv->dst_h);
+	xf86CrtcPtr crtc;
+	if (pPriv->desired_crtc)
+	    crtc = pPriv->desired_crtc;
+	else
+	    crtc = radeon_xv_pick_best_crtc(pScrn,
+					    pPriv->drw_x,
+					    pPriv->drw_x + pPriv->dst_w,
+					    pPriv->drw_y,
+					    pPriv->drw_y + pPriv->dst_h);
 	if (crtc)
 	    FUNC_NAME(RADEONWaitForVLine)(pScrn, pPixmap,
 					  crtc,
@@ -3857,11 +3869,15 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     FINISH_ACCEL();
 
     if (pPriv->vsync) {
-	xf86CrtcPtr crtc = radeon_xv_pick_best_crtc(pScrn,
-						    pPriv->drw_x,
-						    pPriv->drw_x + pPriv->dst_w,
-						    pPriv->drw_y,
-						    pPriv->drw_y + pPriv->dst_h);
+	xf86CrtcPtr crtc;
+	if (pPriv->desired_crtc)
+	    crtc = pPriv->desired_crtc;
+	else
+	    crtc = radeon_xv_pick_best_crtc(pScrn,
+					    pPriv->drw_x,
+					    pPriv->drw_x + pPriv->dst_w,
+					    pPriv->drw_y,
+					    pPriv->drw_y + pPriv->dst_h);
 	if (crtc)
 	    FUNC_NAME(RADEONWaitForVLine)(pScrn, pPixmap,
 					  crtc,
commit 801d900add4731f3c424ebb780ad2dbd7a1c6a25
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Mon Oct 12 10:00:57 2009 -0400

    ATOM: minor cleanups to pll setup

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index c901391..62402a7 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -297,7 +297,7 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
     RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
     unsigned char *RADEONMMIO = info->MMIO;
-    int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
+    int index;
     uint32_t sclock = mode->Clock;
     uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
     int major, minor, i;
@@ -309,7 +309,6 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
     radeon_encoder_ptr radeon_encoder = NULL;
     int pll_flags = 0;
     uint32_t temp;
-
     void *ptr;
     AtomBiosArgRec data;
     unsigned char *space;
@@ -357,6 +356,7 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 
     if (IS_DCE3_VARIANT) {
 	ADJUST_DISPLAY_PLL_PS_ALLOCATION adjust_pll_param;
+	index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
 
 	/* Can't really do cloning easily on DCE3 cards */
 	for (i = 0; i < xf86_config->num_output; i++) {
@@ -383,7 +383,7 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 	adjust_pll_param.ucTransmitterID = radeon_encoder->encoder_id;
 	adjust_pll_param.ucEncodeMode = atombios_get_encoder_mode(output);
 
-	data.exec.index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
+	data.exec.index = index;
 	data.exec.dataSpace = (void *)&space;
 	data.exec.pspace = &adjust_pll_param;
 
@@ -405,6 +405,7 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 	       radeon_crtc->crtc_id, (unsigned int)ref_div, (unsigned int)fb_div,
 	       (unsigned int)fb_div, (unsigned int)frac_fb_div, (unsigned int)post_div);
 
+    index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
     atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
 
     /*ErrorF("table is %d %d\n", major, minor);*/
@@ -448,7 +449,7 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 	exit(-1);
     }
 
-    data.exec.index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
+    data.exec.index = index;
     data.exec.dataSpace = (void *)&space;
     data.exec.pspace = ptr;
 
commit f4407962cd7b272e0860319f11f6a6583ef226c2
Author: Csillag Kristof <csillag.kristof at united-consult.hu>
Date:   Fri Oct 9 18:00:09 2009 -0400

    Fix some issues with CustomEDID support
    
    - Fixes a memory allocation problem introduced with the previous
    version of the CustomEDID patch (now in GIT), and
     - Enhances the syntax of the CustomEDID option so that I can force
    digital output, even if the EDID was acquired over an analog link.

diff --git a/src/radeon_output.c b/src/radeon_output.c
index 75f63b7..0429088 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -228,12 +228,14 @@ RADEONGetHardCodedEDIDFromFile(xf86OutputPtr output)
     radeon_output->custom_mon = NULL;
 
     if (EDIDlist != NULL) {
-	unsigned char edid[128];
+	unsigned char* edid = xnfcalloc(128, 1);
 	char *name = output->name;
 	char *outputEDID = strstr(EDIDlist, name);
 
 	if (outputEDID != NULL) {
 	    char *end;
+	    char *colon;
+	    char *command = NULL;
 	    int fd;
 
 	    outputEDID += strlen(name) + 1;
@@ -241,6 +243,12 @@ RADEONGetHardCodedEDIDFromFile(xf86OutputPtr output)
 	    if (end != NULL)
 		*end = 0;
 
+	    colon = strstr(outputEDID, ":");
+	    if (colon != NULL) {
+		*colon = 0;
+		command = colon + 1;
+	    }
+
 	    fd = open (outputEDID, O_RDONLY);
 	    if (fd >= 0) {
 		read(fd, edid, 128);
@@ -251,6 +259,27 @@ RADEONGetHardCodedEDIDFromFile(xf86OutputPtr output)
 		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 			       "Successfully read Custom EDID data for output %s from %s.\n",
 			       name, outputEDID);
+		    if (command != NULL) {
+		      if (!strcmp(command, "digital")) {
+			struct edid_version *v = &radeon_output->custom_mon->ver;
+			struct disp_features *r = &radeon_output->custom_mon->features;
+			r->input_type = 1;
+			if (v->revision == 2 || v->revision == 3) {
+			  // Nothing to do
+			} else if (v->revision >= 4) {
+			  r->input_interface = 1; // Using DVI by default
+			  r->input_bpc = 2; // 8 bits per channes by default
+			}
+			radeon_output->custom_mon->rawData[0x14] |=  0x80;
+			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+				   "Forcing digital output for output %s.\n", name);
+		      } else {
+			xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+				   "Unknown custom EDID command: '%s'.\n",
+				   command);
+		      }
+		    }
+
 		} else {
 		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 			       "Custom EDID data for %s read from %s was invalid.\n",
commit de55995e82c3875f70b6394fff440d695d062113
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Fri Oct 9 11:07:30 2009 -0400

    r600 EXA: fix up mask reg mixup

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 47f1624..a2ce5c9 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -284,7 +284,7 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     if (pm & 0xff000000)
 	pmask |= 8; /* A */
     BEGIN_BATCH(6);
-    EREG(accel_state->ib, CB_SHADER_MASK,                      (pmask << OUTPUT0_ENABLE_shift));
+    EREG(accel_state->ib, CB_TARGET_MASK,                      (pmask << TARGET0_ENABLE_shift));
     EREG(accel_state->ib, CB_COLOR_CONTROL,                    RADEON_ROP[alu]);
     END_BATCH();
 
@@ -611,7 +611,7 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
     if (planemask & 0xff000000)
 	pmask |= 8; /* A */
     BEGIN_BATCH(6);
-    EREG(accel_state->ib, CB_SHADER_MASK,                      (pmask << OUTPUT0_ENABLE_shift));
+    EREG(accel_state->ib, CB_TARGET_MASK,                      (pmask << TARGET0_ENABLE_shift));
     EREG(accel_state->ib, CB_COLOR_CONTROL,                    RADEON_ROP[rop]);
     END_BATCH();
 
@@ -1801,7 +1801,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     ps_setup                    (pScrn, accel_state->ib, &ps_conf);
 
     BEGIN_BATCH(9);
-    EREG(accel_state->ib, CB_SHADER_MASK,                      (0xf << OUTPUT0_ENABLE_shift));
+    EREG(accel_state->ib, CB_TARGET_MASK,                      (0xf << TARGET0_ENABLE_shift));
 
     blendcntl = R600GetBlendCntl(op, pMaskPicture, pDstPicture->format);
 
diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index ab3c498..dd4d3d1 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -516,7 +516,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 
     /* Render setup */
     BEGIN_BATCH(6);
-    EREG(accel_state->ib, CB_SHADER_MASK,                      (0x0f << OUTPUT0_ENABLE_shift));
+    EREG(accel_state->ib, CB_TARGET_MASK,                      (0x0f << TARGET0_ENABLE_shift));
     EREG(accel_state->ib, CB_COLOR_CONTROL,                    (0xcc << ROP3_shift)); /* copy */
     END_BATCH();
 
diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index 8377ae5..dd74d46 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -971,7 +971,7 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     E32(ib, 0);							// CB_CLRCMP_DST
     E32(ib, 0);							// CB_CLRCMP_MSK
 
-    EREG(ib, CB_TARGET_MASK,                      (0x0f << TARGET0_ENABLE_shift));
+    EREG(ib, CB_SHADER_MASK,                      (0xf << OUTPUT0_ENABLE_shift));
     EREG(ib, R7xx_CB_SHADER_CONTROL,              (RT0_ENABLE_bit));
 
 
commit a168caf5349b757873ad89d977772feaa7fb6e58
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Fri Oct 9 10:32:26 2009 -0400

    r600 EXA: fix some compile warnings

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 54f32a1..47f1624 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -807,7 +807,7 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
     if (accel_state->dst_mc_addr & 0xff)
 	RADEON_FALLBACK(("Bad dst offset 0x%08x\n", accel_state->dst_mc_addr));
 
-
+#if defined(XF86DRM_MODE)
     if (info->cs) {
 	radeon_cs_space_reset_bos(info->cs);
 	radeon_cs_space_add_persistent_bo(info->cs, accel_state->shaders_bo,
@@ -818,6 +818,7 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
 	if (ret)
 	    RADEON_FALLBACK(("Not enough RAM to hw accel copy operation\n"));
     }
+#endif
 
     /* return FALSE; */
 
commit fb8dda2928bd0def2b34c8c8e414129e650d6eb5
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Fri Oct 9 10:30:21 2009 -0400

    r600 EXA: properly check planemask
    
    We only support per-component masks.

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 56bd84b..54f32a1 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -95,6 +95,43 @@ uint32_t RADEON_ROP[16] = {
     RADEON_ROP3_ONE,  /* GXset          */
 };
 
+static Bool R600ValidPM(uint32_t pm, int bpp)
+{
+    uint8_t r, g, b, a;
+    Bool ret = FALSE;
+
+    switch (bpp) {
+    case 8:
+	a = pm & 0xff;
+	if ((a == 0) || (a == 0xff))
+	    ret = TRUE;
+	break;
+    case 16:
+	r = (pm >> 11) & 0x1f;
+	g = (pm >> 5) & 0x3f;
+	b = (pm >> 0) & 0x1f;
+	if (((r == 0) || (r == 0x1f)) &&
+	    ((g == 0) || (g == 0x3f)) &&
+	    ((b == 0) || (b == 0x1f)))
+	    ret = TRUE;
+	break;
+    case 32:
+	a = (pm >> 24) & 0xff;
+	r = (pm >> 16) & 0xff;
+	g = (pm >> 8) & 0xff;
+	b = (pm >> 0) & 0xff;
+	if (((a == 0) || (a == 0xff)) &&
+	    ((r == 0) || (r == 0xff)) &&
+	    ((g == 0) || (g == 0xff)) &&
+	    ((b == 0) || (b == 0xff)))
+	    ret = TRUE;
+	break;
+    default:
+	break;
+    }
+    return ret;
+}
+
 static Bool R600CheckBPP(int bpp)
 {
 	switch (bpp) {
@@ -136,10 +173,10 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     uint32_t a, r, g, b;
     float ps_alu_consts[4];
 
-    if (pPix->drawable.bitsPerPixel == 24)
-        RADEON_FALLBACK(("24bpp unsupported\n"));
     if (!R600CheckBPP(pPix->drawable.bitsPerPixel))
-        RADEON_FALLBACK(("R600CheckDatatype failed\n"));
+	RADEON_FALLBACK(("R600CheckDatatype failed\n"));
+    if (!R600ValidPM(pm, pPix->drawable.bitsPerPixel))
+	RADEON_FALLBACK(("invalid planemask\n"));
 
 #if defined(XF86DRM_MODE)
     if (info->cs) {
@@ -722,14 +759,12 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
     struct radeon_accel_state *accel_state = info->accel_state;
     int ret;
 
-    if (pSrc->drawable.bitsPerPixel == 24)
-        RADEON_FALLBACK(("24bpp unsupported\n"));
-    if (pDst->drawable.bitsPerPixel == 24)
-        RADEON_FALLBACK(("24bpp unsupported\n"));
     if (!R600CheckBPP(pSrc->drawable.bitsPerPixel))
-        RADEON_FALLBACK(("R600CheckDatatype src failed\n"));
+	RADEON_FALLBACK(("R600CheckDatatype src failed\n"));
     if (!R600CheckBPP(pDst->drawable.bitsPerPixel))
-        RADEON_FALLBACK(("R600CheckDatatype dst failed\n"));
+	RADEON_FALLBACK(("R600CheckDatatype dst failed\n"));
+    if (!R600ValidPM(planemask, pDst->drawable.bitsPerPixel))
+	RADEON_FALLBACK(("Invalid planemask\n"));
 
     accel_state->dst_pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8);
     accel_state->src_pitch[0] = exaGetPixmapPitch(pSrc) / (pSrc->drawable.bitsPerPixel / 8);
commit 1b25bad2d8ebe481ffb4b0fd3a85ab636bd4fec2
Author: Dave Airlie <airlied at linux.ie>
Date:   Fri Oct 9 20:09:52 2009 +1000

    Revert "radeon: clamp the internal FB map to the aperture size"
    
    This reverts commit 5f846360c46f5a989f5d0fde6d251cdbd61d4968.
    
    Numerous reports of system hangs since this, I'm guessing
    some sort of conflict with the drm memory setup. This code
    has always been fragile between kernel/userspace drivers.

diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index d5704d3..d039920 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -1403,15 +1403,6 @@ static void RADEONInitMemoryMap(ScrnInfoPtr pScrn)
     if (aper_size > mem_size)
 	mem_size = aper_size;
 
-    /* don't map the whole FB in the internal address space.
-     * we don't currently use fb space larger than the aperture
-     * size and on cards with 1 GB of vram, this can overflow
-     * the internal top of gart calculation on some systems.
-     * See fdo bug 24301.
-     */
-    if (mem_size > aper_size)
-	mem_size = aper_size;
-
 #ifdef XF86DRI
     /* Apply memory map limitation if using an old DRI */
     if (info->directRenderingEnabled && !info->dri->newMemoryMap) {
commit a956d478043b44c49aed39c7aa3d576ef32cadc5
Author: Dave Airlie <airlied at linux.ie>
Date:   Fri Oct 9 20:08:31 2009 +1000

    Revert "kms: setup colormap and gamma correctly."
    
    This reverts commit 60d9685abddccec17c1a9a5ec48cbe9c92543e0f.
    
    which breaks colormap on 1.6 X server
    
    Conflicts:
    
    	src/drmmode_display.c

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 8310e0b..86adfeb 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1170,4 +1170,87 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 	}
 	return TRUE;
 }
+
+static void drmmode_load_palette(ScrnInfoPtr pScrn, int numColors,
+                                 int *indices, LOCO *colors, VisualPtr pVisual)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    uint16_t       lut_r[256], lut_g[256], lut_b[256];
+    int index, j, i;
+    int c;
+
+    for (c = 0; c < xf86_config->num_crtc; c++) {
+        xf86CrtcPtr crtc = xf86_config->crtc[c];
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+        for (i = 0 ; i < 256; i++) {
+            lut_r[i] = drmmode_crtc->lut_r[i] << 6;
+            lut_g[i] = drmmode_crtc->lut_g[i] << 6;
+            lut_b[i] = drmmode_crtc->lut_b[i] << 6;
+        }
+
+        switch(pScrn->depth) {
+        case 15:
+            for (i = 0; i < numColors; i++) {
+                index = indices[i];
+                for (j = 0; j < 8; j++) {
+                    lut_r[index * 8 + j] = colors[index].red << 6;
+                    lut_g[index * 8 + j] = colors[index].green << 6;
+                    lut_b[index * 8 + j] = colors[index].blue << 6;
+                }
+            }
+         break;
+         case 16:
+             for (i = 0; i < numColors; i++) {
+                 index = indices[i];
+
+                  if (i <= 31) {
+                      for (j = 0; j < 8; j++) {
+                          lut_r[index * 8 + j] = colors[index].red << 6;
+                          lut_b[index * 8 + j] = colors[index].blue << 6;
+                      }
+                  }
+
+                  for (j = 0; j < 4; j++) {
+                      lut_g[index * 4 + j] = colors[index].green << 6;
+                  }
+              }
+	  break;
+          default:
+              for (i = 0; i < numColors; i++) {
+                  index = indices[i];
+                  lut_r[index] = colors[index].red << 6;
+                  lut_g[index] = colors[index].green << 6;
+                  lut_b[index] = colors[index].blue << 6;
+              }
+              break;
+          }
+
+    /* Make the change through RandR */
+#ifdef RANDR_12_INTERFACE
+        if (crtc->randr_crtc)
+            RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
+        else
+#endif
+            crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
+     }
+}
+
+Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
+{
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+                  "Initializing kms color map\n");
+    if (!miCreateDefColormap(pScreen))
+        return FALSE;
+    /* all radeons support 10 bit CLUTs */
+    if (!xf86HandleColormaps(pScreen, 256, 10,
+                             drmmode_load_palette, NULL,
+                             CMAP_PALETTED_TRUECOLOR
+#if 0 /* This option messes up text mode! (eich at suse.de) */
+                             | CMAP_LOAD_EVEN_IF_OFFSCREEN
+#endif
+                             | CMAP_RELOAD_ON_MODE_SWITCH))
+         return FALSE;
+    return TRUE;
+}
 #endif
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index faa6025..b3fe20c 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -767,8 +767,8 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
 //    info->PointerMoved = pScrn->PointerMoved;
 //    pScrn->PointerMoved = RADEONPointerMoved;
 
-    if (!miCreateDefColormap(pScreen))
-        return FALSE;
+    if (!drmmode_setup_colormap(pScreen, pScrn))
+	return FALSE;
 
    /* Note unused options */
     if (serverGeneration == 1)
commit a493feb94c0d84aaf5bfd84c6940d7f03974dd86
Author: Dave Airlie <airlied at redhat.com>
Date:   Fri Oct 9 15:05:25 2009 +1000

    kms: don't use scratch pixmaps at all
    
    use our own wrapper to allocate a pixmap for wrapping a bo in.

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 1e78746..8310e0b 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -48,6 +48,34 @@
 #include <X11/extensions/dpms.h>
 #endif
 
+static PixmapPtr drmmode_create_bo_pixmap(ScreenPtr pScreen,
+					  int width, int height,
+					  int depth, int bpp,
+					  int pitch, struct radeon_bo *bo)
+{
+	PixmapPtr pixmap;
+
+	pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 0);
+	if (!pixmap)
+		return NULL;
+
+	if (!(*pScreen->ModifyPixmapHeader)(pixmap, width, height,
+					    depth, bpp, pitch, NULL)) {
+		return NULL;
+	}
+
+	exaMoveInPixmap(pixmap);
+	radeon_set_pixmap_bo(pixmap, bo);
+
+	return pixmap;
+}
+
+static void drmmode_destroy_bo_pixmap(PixmapPtr pixmap)
+{
+	ScreenPtr pScreen = pixmap->drawable.pScreen;
+
+	(*pScreen->DestroyPixmap)(pixmap);
+}
 
 static void
 drmmode_ConvertFromKMode(ScrnInfoPtr	scrn,
@@ -156,21 +184,12 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode,
 		return NULL;
 	}
 
-	pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, fbcon->depth, 0);
+	pixmap = drmmode_create_bo_pixmap(pScreen, fbcon->width, fbcon->height,
+					  fbcon->depth, fbcon->bpp,
+					  fbcon->pitch, bo);
 	if (!pixmap) 
 		return NULL;
 
-	if (!(*pScreen->ModifyPixmapHeader)(pixmap, fbcon->width, fbcon->height,
-					   fbcon->depth, fbcon->bpp,
-					   fbcon->pitch, NULL)) {
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "Couldn't allocate pixmap fbcon contents\n");
-		return NULL;
-	}
-	
-	exaMoveInPixmap(pixmap);
-	radeon_set_pixmap_bo(pixmap, bo);
-
 	radeon_bo_unref(bo);
 	drmModeFreeFB(fbcon);
 	return pixmap;
@@ -202,28 +221,23 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 	if (!src)
 		return;
 
-	dst = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScrn->depth, 0);
+	dst = drmmode_create_bo_pixmap(pScreen, pScrn->virtualX,
+				       pScrn->virtualY, pScrn->depth,
+				       pScrn->bitsPerPixel, pitch,
+				       info->front_bo);
 	if (!dst)
 		goto out_free_src;
 
-	if (!(*pScreen->ModifyPixmapHeader)(dst, pScrn->virtualX,
-					    pScrn->virtualY, pScrn->depth,
-					    pScrn->bitsPerPixel, pitch,
-					    NULL))
-		goto out_free_dst;
-
-	exaMoveInPixmap(dst);
-	radeon_set_pixmap_bo(dst, info->front_bo);
 	info->accel_state->exa->PrepareCopy (src, dst,
 					     -1, -1, GXcopy, FB_ALLONES);
 	info->accel_state->exa->Copy (dst, 0, 0, 0, 0,
 				      pScrn->virtualX, pScrn->virtualY);
 	info->accel_state->exa->DoneCopy (dst);
 	radeon_cs_flush_indirect(pScrn);
- out_free_dst:
-	(*pScreen->DestroyPixmap)(dst);
+
+	drmmode_destroy_bo_pixmap(dst);
  out_free_src:
-	(*pScreen->DestroyPixmap)(src);
+	drmmode_destroy_bo_pixmap(src);
 
 }
 
@@ -445,20 +459,16 @@ drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
 
 	rotate_pitch = RADEON_ALIGN(width, 63) * drmmode->cpp;
 
-	rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
-					       width, height,
-					       pScrn->depth,
-					       pScrn->bitsPerPixel,
-					       rotate_pitch,
-					       NULL);
-
+	rotate_pixmap = drmmode_create_bo_pixmap(pScrn->pScreen,
+						 width, height,
+						 pScrn->depth,
+						 pScrn->bitsPerPixel,
+						 rotate_pitch,
+						 drmmode_crtc->rotate_bo);
 	if (rotate_pixmap == NULL) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			   "Couldn't allocate shadow pixmap for rotated CRTC\n");
 	}
-
-	if (drmmode_crtc->rotate_bo)
-		radeon_set_pixmap_bo(rotate_pixmap, drmmode_crtc->rotate_bo);
 	return rotate_pixmap;
 
 }
@@ -470,7 +480,7 @@ drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *dat
 	drmmode_ptr drmmode = drmmode_crtc->drmmode;
 
 	if (rotate_pixmap)
-	    FreeScratchPixmapHeader(rotate_pixmap);
+		drmmode_destroy_bo_pixmap(rotate_pixmap);
 
 	if (data) {
 		drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id);
commit 0caffbd6fd6b356b9b7d715c015285eaa91e3e36
Author: Dave Airlie <airlied at redhat.com>
Date:   Fri Oct 9 15:04:56 2009 +1000

    drmmode: reload cursors on modeset

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index a1ec2c2..1e78746 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -330,7 +330,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 		}
 	}
 
-
+	if (pScrn->pScreen)
+		xf86_reload_cursors(pScrn->pScreen);
 
 done:
 	if (!ret) {
commit 02e12ae6be7bc1976f63848fa2854d320d5ab36e
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Oct 7 19:56:58 2009 -0400

    ATOM: rework crtc modeset
    
    - clean up tv timing handling
    - unify SetCRTCTiming and SetCRTCDTDTiming interfaces

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 5d95241..c901391 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -189,33 +189,48 @@ atombios_crtc_dpms(xf86CrtcPtr crtc, int mode)
 }
 
 static AtomBiosResult
-atombios_set_crtc_timing(atomBiosHandlePtr atomBIOS, SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_param)
+atombios_set_crtc_timing(xf86CrtcPtr crtc, DisplayModePtr mode)
 {
+    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
+    RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
     AtomBiosArgRec data;
     unsigned char *space;
-    SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION conv_param;
-
-    conv_param.usH_Total		= cpu_to_le16(crtc_param->usH_Total);
-    conv_param.usH_Disp			= cpu_to_le16(crtc_param->usH_Disp);
-    conv_param.usH_SyncStart		= cpu_to_le16(crtc_param->usH_SyncStart);
-    conv_param.usH_SyncWidth		= cpu_to_le16(crtc_param->usH_SyncWidth);
-    conv_param.usV_Total		= cpu_to_le16(crtc_param->usV_Total);
-    conv_param.usV_Disp			= cpu_to_le16(crtc_param->usV_Disp);
-    conv_param.usV_SyncStart		= cpu_to_le16(crtc_param->usV_SyncStart);
-    conv_param.usV_SyncWidth		= cpu_to_le16(crtc_param->usV_SyncWidth);
-    conv_param.susModeMiscInfo.usAccess = cpu_to_le16(crtc_param->susModeMiscInfo.usAccess);
-    conv_param.ucCRTC			= crtc_param->ucCRTC;
-    conv_param.ucOverscanRight		= crtc_param->ucOverscanRight;
-    conv_param.ucOverscanLeft		= crtc_param->ucOverscanLeft;
-    conv_param.ucOverscanBottom		= crtc_param->ucOverscanBottom;
-    conv_param.ucOverscanTop		= crtc_param->ucOverscanTop;
-    conv_param.ucReserved		= crtc_param->ucReserved;
+    uint16_t misc = 0;
+    SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION param;
+    memset(&param, 0, sizeof(param));
+
+    param.usH_Total		= cpu_to_le16(mode->CrtcHTotal);
+    param.usH_Disp		= cpu_to_le16(mode->CrtcHDisplay);
+    param.usH_SyncStart		= cpu_to_le16(mode->CrtcHSyncStart);
+    param.usH_SyncWidth		= cpu_to_le16(mode->CrtcHSyncEnd - mode->CrtcHSyncStart);
+    param.usV_Total		= cpu_to_le16(mode->CrtcVTotal);
+    param.usV_Disp		= cpu_to_le16(mode->CrtcVDisplay);
+    param.usV_SyncStart		= cpu_to_le16(mode->CrtcVSyncStart);
+    param.usV_SyncWidth		= cpu_to_le16(mode->CrtcVSyncEnd - mode->CrtcVSyncStart);
+
+    if (mode->Flags & V_NVSYNC)
+	misc |= ATOM_VSYNC_POLARITY;
+
+    if (mode->Flags & V_NHSYNC)
+	misc |= ATOM_HSYNC_POLARITY;
+
+    if (mode->Flags & V_CSYNC)
+	misc |= ATOM_COMPOSITESYNC;
+
+    if (mode->Flags & V_INTERLACE)
+	misc |= ATOM_INTERLACE;
+
+    if (mode->Flags & V_DBLSCAN)
+	misc |= ATOM_DOUBLE_CLOCK_MODE;
+
+    param.susModeMiscInfo.usAccess      = cpu_to_le16(misc);
+    param.ucCRTC			= radeon_crtc->crtc_id;
 
     data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing);
     data.exec.dataSpace = (void *)&space;
-    data.exec.pspace = &conv_param;
+    data.exec.pspace = &param;
 
-    if (RHDAtomBiosFunc(atomBIOS->scrnIndex, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
+    if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
 	ErrorF("Set CRTC Timing success\n");
 	return ATOM_SUCCESS ;
     }
@@ -225,28 +240,48 @@ atombios_set_crtc_timing(atomBiosHandlePtr atomBIOS, SET_CRTC_TIMING_PARAMETERS_
 }
 
 static AtomBiosResult
-atombios_set_crtc_dtd_timing(atomBiosHandlePtr atomBIOS, SET_CRTC_USING_DTD_TIMING_PARAMETERS *crtc_param)
+atombios_set_crtc_dtd_timing(xf86CrtcPtr crtc, DisplayModePtr mode)
 {
+    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
+    RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
     AtomBiosArgRec data;
     unsigned char *space;
-    SET_CRTC_USING_DTD_TIMING_PARAMETERS conv_param;
-
-    conv_param.usH_Size        = cpu_to_le16(crtc_param->usH_Size);
-    conv_param.usH_Blanking_Time= cpu_to_le16(crtc_param->usH_Blanking_Time);
-    conv_param.usV_Size        = cpu_to_le16(crtc_param->usV_Size);
-    conv_param.usV_Blanking_Time= cpu_to_le16(crtc_param->usV_Blanking_Time);
-    conv_param.usH_SyncOffset= cpu_to_le16(crtc_param->usH_SyncOffset);
-    conv_param.usH_SyncWidth= cpu_to_le16(crtc_param->usH_SyncWidth);
-    conv_param.usV_SyncOffset= cpu_to_le16(crtc_param->usV_SyncOffset);
-    conv_param.usV_SyncWidth= cpu_to_le16(crtc_param->usV_SyncWidth);
-    conv_param.susModeMiscInfo.usAccess = cpu_to_le16(crtc_param->susModeMiscInfo.usAccess);
-    conv_param.ucCRTC= crtc_param->ucCRTC;
+    uint16_t misc = 0;
+    SET_CRTC_USING_DTD_TIMING_PARAMETERS param;
+    memset(&param, 0, sizeof(param));
+
+    param.usH_Size          = cpu_to_le16(mode->CrtcHDisplay);
+    param.usH_Blanking_Time = cpu_to_le16(mode->CrtcHBlankEnd - mode->CrtcHDisplay);
+    param.usV_Size          = cpu_to_le16(mode->CrtcVDisplay);
+    param.usV_Blanking_Time = cpu_to_le16(mode->CrtcVBlankEnd - mode->CrtcVDisplay);
+    param.usH_SyncOffset    = cpu_to_le16(mode->CrtcHSyncStart - mode->CrtcHDisplay);
+    param.usH_SyncWidth     = cpu_to_le16(mode->CrtcHSyncEnd - mode->CrtcHSyncStart);
+    param.usV_SyncOffset    = cpu_to_le16(mode->CrtcVSyncStart - mode->CrtcVDisplay);
+    param.usV_SyncWidth     = cpu_to_le16(mode->CrtcVSyncEnd - mode->CrtcVSyncStart);
+
+    if (mode->Flags & V_NVSYNC)
+	misc |= ATOM_VSYNC_POLARITY;
+
+    if (mode->Flags & V_NHSYNC)
+	misc |= ATOM_HSYNC_POLARITY;
+
+    if (mode->Flags & V_CSYNC)
+	misc |= ATOM_COMPOSITESYNC;
+
+    if (mode->Flags & V_INTERLACE)
+	misc |= ATOM_INTERLACE;
+
+    if (mode->Flags & V_DBLSCAN)
+	misc |= ATOM_DOUBLE_CLOCK_MODE;
+
+    param.susModeMiscInfo.usAccess = cpu_to_le16(misc);
+    param.ucCRTC= radeon_crtc->crtc_id;
 
     data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming);
     data.exec.dataSpace = (void *)&space;
-    data.exec.pspace = &conv_param;
+    data.exec.pspace = &param;
 
-    if (RHDAtomBiosFunc(atomBIOS->scrnIndex, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
+    if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
 	ErrorF("Set DTD CRTC Timing success\n");
 	return ATOM_SUCCESS ;
     }
@@ -435,106 +470,15 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc,
     ScrnInfoPtr pScrn = crtc->scrn;
     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
     RADEONInfoPtr  info = RADEONPTR(pScrn);
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
     unsigned long fb_location = crtc->scrn->fbOffset + info->fbLocation;
-    int need_tv_timings = 0;
-    int i, ret;
-    SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing;
-    SET_CRTC_USING_DTD_TIMING_PARAMETERS crtc_dtd_timing;
     Bool tilingChanged = FALSE;
-    memset(&crtc_timing, 0, sizeof(crtc_timing));
-    memset(&crtc_dtd_timing, 0, sizeof(crtc_dtd_timing));
 
     if (info->allowColorTiling) {
         radeon_crtc->can_tile = (adjusted_mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE;
 	tilingChanged = RADEONSetTiling(pScrn);
     }
 
-    for (i = 0; i < xf86_config->num_output; i++) {
-	xf86OutputPtr output = xf86_config->output[i];
-	RADEONOutputPrivatePtr radeon_output = output->driver_private;
-	radeon_tvout_ptr tvout = &radeon_output->tvout;
-
-	if (output->crtc == crtc) {
-	    if (radeon_output->MonType == MT_STV || radeon_output->MonType == MT_CTV) {
-		if (tvout->tvStd == TV_STD_NTSC ||
-		    tvout->tvStd == TV_STD_NTSC_J ||
-		    tvout->tvStd == TV_STD_PAL_M)
-		    need_tv_timings = 1;
-		else
-		    need_tv_timings = 2;
-
-	    }
-	}
-    }
-
-    crtc_timing.ucCRTC = radeon_crtc->crtc_id;
-    if (need_tv_timings) {
-	ret = RADEONATOMGetTVTimings(pScrn, need_tv_timings - 1, &crtc_timing, &adjusted_mode->Clock);
-	if (ret == FALSE) {
-	    need_tv_timings = 0;
-	}
-    }
-
-    if (!need_tv_timings) {
-	crtc_timing.usH_Total = adjusted_mode->CrtcHTotal;
-	crtc_timing.usH_Disp = adjusted_mode->CrtcHDisplay;
-	crtc_timing.usH_SyncStart = adjusted_mode->CrtcHSyncStart;
-	crtc_timing.usH_SyncWidth = adjusted_mode->CrtcHSyncEnd - adjusted_mode->CrtcHSyncStart;
-
-	crtc_timing.usV_Total = adjusted_mode->CrtcVTotal;
-	crtc_timing.usV_Disp = adjusted_mode->CrtcVDisplay;
-	crtc_timing.usV_SyncStart = adjusted_mode->CrtcVSyncStart;
-	crtc_timing.usV_SyncWidth = adjusted_mode->CrtcVSyncEnd - adjusted_mode->CrtcVSyncStart;
-
-	if (adjusted_mode->Flags & V_NVSYNC)
-	    crtc_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY;
-
-	if (adjusted_mode->Flags & V_NHSYNC)
-	    crtc_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY;
-
-	if (adjusted_mode->Flags & V_CSYNC)
-	    crtc_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC;
-
-	if (adjusted_mode->Flags & V_INTERLACE)
-	    crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE;
-
-	if (adjusted_mode->Flags & V_DBLSCAN)
-	    crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE;
-
-	if (!IS_AVIVO_VARIANT && (radeon_crtc->crtc_id == 0)) {
-	    crtc_dtd_timing.ucCRTC = radeon_crtc->crtc_id;
-	    crtc_dtd_timing.usH_Size = adjusted_mode->CrtcHDisplay;
-	    crtc_dtd_timing.usV_Size = adjusted_mode->CrtcVDisplay;
-	    crtc_dtd_timing.usH_Blanking_Time = adjusted_mode->CrtcHBlankEnd - adjusted_mode->CrtcHDisplay;
-	    crtc_dtd_timing.usV_Blanking_Time = adjusted_mode->CrtcVBlankEnd - adjusted_mode->CrtcVDisplay;
-	    crtc_dtd_timing.usH_SyncOffset = adjusted_mode->CrtcHSyncStart - adjusted_mode->CrtcHDisplay;
-	    crtc_dtd_timing.usV_SyncOffset = adjusted_mode->CrtcVSyncStart - adjusted_mode->CrtcVDisplay;
-	    crtc_dtd_timing.usH_SyncWidth = adjusted_mode->CrtcHSyncEnd - adjusted_mode->CrtcHSyncStart;
-	    crtc_dtd_timing.usV_SyncWidth = adjusted_mode->CrtcVSyncEnd - adjusted_mode->CrtcVSyncStart;
-	    ErrorF("%d %d %d %d %d %d %d %d\n", crtc_dtd_timing.usH_Size, crtc_dtd_timing.usH_SyncOffset,
-		   crtc_dtd_timing.usH_SyncWidth, crtc_dtd_timing.usH_Blanking_Time,
-		   crtc_dtd_timing.usV_Size, crtc_dtd_timing.usV_SyncOffset,
-		   crtc_dtd_timing.usV_SyncWidth, crtc_dtd_timing.usV_Blanking_Time);
-
-	    if (adjusted_mode->Flags & V_NVSYNC)
-		crtc_dtd_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY;
-
-	    if (adjusted_mode->Flags & V_NHSYNC)
-		crtc_dtd_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY;
-
-	    if (adjusted_mode->Flags & V_CSYNC)
-		crtc_dtd_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC;
-
-	    if (adjusted_mode->Flags & V_INTERLACE)
-		crtc_dtd_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE;
-
-	    if (adjusted_mode->Flags & V_DBLSCAN)
-		crtc_dtd_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE;
-	}
-    }
-
     ErrorF("Mode %dx%d - %d %d %d\n", adjusted_mode->CrtcHDisplay, adjusted_mode->CrtcVDisplay,
 	   adjusted_mode->CrtcHTotal, adjusted_mode->CrtcVTotal, adjusted_mode->Flags);
 
@@ -542,9 +486,9 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc,
     RADEONRestoreMemMapRegisters(pScrn, info->ModeReg);
 
     atombios_crtc_set_pll(crtc, adjusted_mode);
-    atombios_set_crtc_timing(info->atomBIOS, &crtc_timing);
+    atombios_set_crtc_timing(crtc, adjusted_mode);
     if (!IS_AVIVO_VARIANT && (radeon_crtc->crtc_id == 0))
-	atombios_set_crtc_dtd_timing(info->atomBIOS, &crtc_dtd_timing);
+	atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
 
     if (IS_AVIVO_VARIANT) {
 	uint32_t fb_format;
diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index d6a8333..13ef1ef 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -2127,7 +2127,7 @@ RADEONGetATOMTVInfo(xf86OutputPtr output)
 }
 
 Bool
-RADEONATOMGetTVTimings(ScrnInfoPtr pScrn, int index, SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing, int32_t *pixel_clock)
+RADEONATOMGetTVTimings(ScrnInfoPtr pScrn, int index, DisplayModePtr mode)
 {
     RADEONInfoPtr  info       = RADEONPTR(pScrn);
     ATOM_ANALOG_TV_INFO *tv_info;
@@ -2135,6 +2135,7 @@ RADEONATOMGetTVTimings(ScrnInfoPtr pScrn, int index, SET_CRTC_TIMING_PARAMETERS_
     ATOM_DTD_FORMAT *dtd_timings;
     atomDataTablesPtr atomDataPtr;
     uint8_t crev, frev;
+    uint16_t misc;
 
     atomDataPtr = info->atomBIOS->atomDataPtr;
     if (!rhdAtomGetTableRevisionAndSize(
@@ -2150,28 +2151,37 @@ RADEONATOMGetTVTimings(ScrnInfoPtr pScrn, int index, SET_CRTC_TIMING_PARAMETERS_
 	if (index > MAX_SUPPORTED_TV_TIMING)
 	    return FALSE;
 
-	crtc_timing->usH_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
-	crtc_timing->usH_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
-	crtc_timing->usH_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
-	crtc_timing->usH_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth);
-
-	crtc_timing->usV_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total);
-	crtc_timing->usV_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp);
-	crtc_timing->usV_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart);
-	crtc_timing->usV_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth);
-
-	crtc_timing->susModeMiscInfo = tv_info->aModeTimings[index].susModeMiscInfo;
-
-	crtc_timing->ucOverscanRight = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanRight);
-	crtc_timing->ucOverscanLeft = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanLeft);
-	crtc_timing->ucOverscanBottom = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanBottom);
-	crtc_timing->ucOverscanTop = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanTop);
-	*pixel_clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
+	mode->CrtcHTotal     = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
+	mode->CrtcHDisplay   = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
+	mode->CrtcHSyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
+	mode->CrtcHSyncEnd   = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart) +
+	                       le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth);
+
+	mode->CrtcVTotal     = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total);
+	mode->CrtcVDisplay   = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp);
+	mode->CrtcVSyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart);
+	mode->CrtcVSyncEnd   = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart) +
+	                       le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth);
+
+	mode->Flags = 0;
+	misc = le16_to_cpu(tv_info->aModeTimings[index].susModeMiscInfo.usAccess);
+	if (misc & ATOM_VSYNC_POLARITY)
+	    mode->Flags |= V_NVSYNC;
+	if (misc & ATOM_HSYNC_POLARITY)
+	    mode->Flags |= V_NHSYNC;
+	if (misc & ATOM_COMPOSITESYNC)
+	    mode->Flags |= V_CSYNC;
+	if (misc & ATOM_INTERLACE)
+	    mode->Flags |= V_INTERLACE;
+	if (misc & ATOM_DOUBLE_CLOCK_MODE)
+	    mode->Flags |= V_DBLSCAN;
+
+	mode->Clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
 
 	if (index == 1) {
 		/* PAL timings appear to have wrong values for totals */
-		crtc_timing->usH_Total -= 1;
-		crtc_timing->usV_Total -= 1;
+		mode->CrtcHTotal -= 1;
+		mode->CrtcVTotal -= 1;
 	}
 	break;
     case 2:
@@ -2180,18 +2190,31 @@ RADEONATOMGetTVTimings(ScrnInfoPtr pScrn, int index, SET_CRTC_TIMING_PARAMETERS_
 	    return FALSE;
 
 	dtd_timings = &tv_info_v1_2->aModeTimings[index];
-	crtc_timing->usH_Total = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHBlanking_Time);
-	crtc_timing->usH_Disp = le16_to_cpu(dtd_timings->usHActive);
-	crtc_timing->usH_SyncStart = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHSyncOffset);
-	crtc_timing->usH_SyncWidth = le16_to_cpu(dtd_timings->usHSyncWidth);
-
-	crtc_timing->usV_Total = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVBlanking_Time);
-	crtc_timing->usV_Disp = le16_to_cpu(dtd_timings->usVActive);
-	crtc_timing->usV_SyncStart = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVSyncOffset);
-	crtc_timing->usV_SyncWidth = le16_to_cpu(dtd_timings->usVSyncWidth);
-
-	crtc_timing->susModeMiscInfo.usAccess = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess);
-	*pixel_clock = le16_to_cpu(dtd_timings->usPixClk) * 10;
+	mode->CrtcHTotal     = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHBlanking_Time);
+	mode->CrtcHDisplay   = le16_to_cpu(dtd_timings->usHActive);
+	mode->CrtcHSyncStart = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHSyncOffset);
+	mode->CrtcHSyncEnd   = mode->CrtcHSyncStart + le16_to_cpu(dtd_timings->usHSyncWidth);
+
+	mode->CrtcVTotal     = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVBlanking_Time);
+	mode->CrtcVDisplay   = le16_to_cpu(dtd_timings->usVActive);
+	mode->CrtcVSyncStart = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVSyncOffset);
+	mode->CrtcVSyncEnd   = mode->CrtcVSyncStart + le16_to_cpu(dtd_timings->usVSyncWidth);
+
+	mode->Flags = 0;
+	misc = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess);
+	if (misc & ATOM_VSYNC_POLARITY)
+	    mode->Flags |= V_NVSYNC;
+	if (misc & ATOM_HSYNC_POLARITY)
+	    mode->Flags |= V_NHSYNC;
+	if (misc & ATOM_COMPOSITESYNC)
+	    mode->Flags |= V_CSYNC;
+	if (misc & ATOM_INTERLACE)
+	    mode->Flags |= V_INTERLACE;
+	if (misc & ATOM_DOUBLE_CLOCK_MODE)
+	    mode->Flags |= V_DBLSCAN;
+
+	mode->Clock = le16_to_cpu(dtd_timings->usPixClk) * 10;
+
 	break;
     }
 
diff --git a/src/radeon_atombios.h b/src/radeon_atombios.h
index 81e5a33..d525063 100644
--- a/src/radeon_atombios.h
+++ b/src/radeon_atombios.h
@@ -270,7 +270,7 @@ typedef struct _atomBiosHandle {
 # endif
 
 extern Bool
-RADEONATOMGetTVTimings(ScrnInfoPtr pScrn, int index, SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing, int32_t *pixel_clock);
+RADEONATOMGetTVTimings(ScrnInfoPtr pScrn, int index, DisplayModePtr mode);
 
 extern void
 RADEONATOMGetIGPInfo(ScrnInfoPtr pScrn);
diff --git a/src/radeon_output.c b/src/radeon_output.c
index 36ef1aa..75f63b7 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -575,6 +575,20 @@ radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 	    adjusted_mode->CrtcVSyncStart = adjusted_mode->CrtcVDisplay + 2;
     }
 
+    if (IS_AVIVO_VARIANT || info->r4xx_atom) {
+	if (radeon_output->MonType == MT_STV || radeon_output->MonType == MT_CTV) {
+	    radeon_tvout_ptr tvout = &radeon_output->tvout;
+	    ScrnInfoPtr pScrn = output->scrn;
+
+	    if (tvout->tvStd == TV_STD_NTSC ||
+		tvout->tvStd == TV_STD_NTSC_J ||
+		tvout->tvStd == TV_STD_PAL_M)
+		RADEONATOMGetTVTimings(pScrn, 0, adjusted_mode);
+	    else
+		RADEONATOMGetTVTimings(pScrn, 1, adjusted_mode);
+	}
+    }
+
     return TRUE;
 }
 
commit d499eeaf22f77a1294e99aa38a50aa6810bb684a
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Oct 7 17:43:11 2009 -0400

    ATOM: reorder crtc dpms based on bios recommendations

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index d4823da..5d95241 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -172,18 +172,18 @@ atombios_crtc_dpms(xf86CrtcPtr crtc, int mode)
     RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
     switch (mode) {
     case DPMSModeOn:
+	atombios_enable_crtc(info->atomBIOS, radeon_crtc->crtc_id, 1);
 	if (IS_DCE3_VARIANT)
 	    atombios_enable_crtc_memreq(info->atomBIOS, radeon_crtc->crtc_id, 1);
-	atombios_enable_crtc(info->atomBIOS, radeon_crtc->crtc_id, 1);
 	atombios_blank_crtc(info->atomBIOS, radeon_crtc->crtc_id, 0);
 	break;
     case DPMSModeStandby:
     case DPMSModeSuspend:
     case DPMSModeOff:
 	atombios_blank_crtc(info->atomBIOS, radeon_crtc->crtc_id, 1);
-	atombios_enable_crtc(info->atomBIOS, radeon_crtc->crtc_id, 0);
 	if (IS_DCE3_VARIANT)
 	    atombios_enable_crtc_memreq(info->atomBIOS, radeon_crtc->crtc_id, 0);
+	atombios_enable_crtc(info->atomBIOS, radeon_crtc->crtc_id, 0);
 	break;
     }
 }
diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index 0384456..d6a8333 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -2146,15 +2146,15 @@ RADEONATOMGetTVTimings(ScrnInfoPtr pScrn, int index, SET_CRTC_TIMING_PARAMETERS_
     switch(crev) {
     case 1:
 	tv_info = atomDataPtr->AnalogTV_Info.AnalogTV_Info;
-	
+
 	if (index > MAX_SUPPORTED_TV_TIMING)
 	    return FALSE;
-	
+
 	crtc_timing->usH_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
 	crtc_timing->usH_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
 	crtc_timing->usH_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
 	crtc_timing->usH_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth);
-	
+
 	crtc_timing->usV_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total);
 	crtc_timing->usV_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp);
 	crtc_timing->usV_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart);
commit 4ccd2a21f9c50515b4246f35454f76ef49006c76
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Oct 7 16:30:03 2009 -0400

    ATOM: add support for AdjustDisplayPll table
    
    Depending on the output and clock, this table will
    adjust the pixelclock accordingly.

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 341deb4..d4823da 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -269,7 +269,7 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
     SET_PIXEL_CLOCK_PS_ALLOCATION spc_param;
     PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr;
     PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr;
-    xf86OutputPtr output;
+    xf86OutputPtr output = NULL;
     RADEONOutputPrivatePtr radeon_output = NULL;
     radeon_encoder_ptr radeon_encoder = NULL;
     int pll_flags = 0;
@@ -320,8 +320,47 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 	    pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
     }
 
-    RADEONComputePLL(&info->pll, mode->Clock, &temp, &fb_div, &frac_fb_div, &ref_div, &post_div, pll_flags);
-    sclock = temp;
+    if (IS_DCE3_VARIANT) {
+	ADJUST_DISPLAY_PLL_PS_ALLOCATION adjust_pll_param;
+
+	/* 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) {
+	    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));
+	adjust_pll_param.usPixelClock = cpu_to_le16(sclock / 10);
+	adjust_pll_param.ucTransmitterID = radeon_encoder->encoder_id;
+	adjust_pll_param.ucEncodeMode = atombios_get_encoder_mode(output);
+
+	data.exec.index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
+	data.exec.dataSpace = (void *)&space;
+	data.exec.pspace = &adjust_pll_param;
+
+	ErrorF("before %d\n", adjust_pll_param.usPixelClock);
+	if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
+	    sclock = le16_to_cpu(adjust_pll_param.usPixelClock) * 10;
+	}
+	ErrorF("after %d\n", adjust_pll_param.usPixelClock);
+    }
+
+    RADEONComputePLL(&info->pll, sclock, &temp, &fb_div, &frac_fb_div, &ref_div, &post_div, pll_flags);
+    sclock = temp; /* 10 khz */
 
     xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO,
 	       "crtc(%d) Clock: mode %d, PLL %lu\n",
@@ -331,26 +370,6 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 	       radeon_crtc->crtc_id, (unsigned int)ref_div, (unsigned int)fb_div,
 	       (unsigned int)fb_div, (unsigned int)frac_fb_div, (unsigned int)post_div);
 
-    /* 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) {
-	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;
-    }
-
     atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
 
     /*ErrorF("table is %d %d\n", major, minor);*/
@@ -360,7 +379,7 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 	case 1:
 	case 2:
 	    spc2_ptr = (PIXEL_CLOCK_PARAMETERS_V2*)&spc_param.sPCLKInput;
-	    spc2_ptr->usPixelClock = cpu_to_le16(sclock);
+	    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;
@@ -372,7 +391,7 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
 	    break;
 	case 3:
 	    spc3_ptr = (PIXEL_CLOCK_PARAMETERS_V3*)&spc_param.sPCLKInput;
-	    spc3_ptr->usPixelClock = cpu_to_le16(sclock);
+	    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;
@@ -634,7 +653,6 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc,
 
 	switch (radeon_crtc->crtc_id) {
 	case 0:
-	    ErrorF("init crtc1\n");
 	    crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL) & 0xfffff0ff;
 	    crtc_gen_cntl |= (format << 8);
 	    OUTREG(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
commit 5f846360c46f5a989f5d0fde6d251cdbd61d4968
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Oct 7 17:01:55 2009 -0400

    radeon: clamp the internal FB map to the aperture size
    
    We don't use the invisible memory yet and on cards with
    large amounts of vram this can cause the top of GART
    calculation to overflow.
    
    Fixes bug fdo bug 24301:
    http://bugs.freedesktop.org/show_bug.cgi?id=24301

diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index d039920..d5704d3 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -1403,6 +1403,15 @@ static void RADEONInitMemoryMap(ScrnInfoPtr pScrn)
     if (aper_size > mem_size)
 	mem_size = aper_size;
 
+    /* don't map the whole FB in the internal address space.
+     * we don't currently use fb space larger than the aperture
+     * size and on cards with 1 GB of vram, this can overflow
+     * the internal top of gart calculation on some systems.
+     * See fdo bug 24301.
+     */
+    if (mem_size > aper_size)
+	mem_size = aper_size;
+
 #ifdef XF86DRI
     /* Apply memory map limitation if using an old DRI */
     if (info->directRenderingEnabled && !info->dri->newMemoryMap) {
commit 186bf719c394116341abff471fb4b4803650da9a
Author: Dave Airlie <airlied at redhat.com>
Date:   Wed Oct 7 17:23:36 2009 +1000

    radeon: fix rotation since mixed pixmaps.
    
    Passing null in here stops the mixed pixmap code doing it wrong,
    but I'm not 100% sure how it is meant to work, we have the
    same issue with the real front bo by the looks of it.

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index f82dec8..a1ec2c2 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -449,7 +449,7 @@ drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
 					       pScrn->depth,
 					       pScrn->bitsPerPixel,
 					       rotate_pitch,
-					       data);
+					       NULL);
 
 	if (rotate_pixmap == NULL) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
commit e08411af1aa8c7d4233ba593b84360397cdbb307
Author: Roel Kluin <roel.kluin at gmail.com>
Date:   Tue Oct 6 18:31:17 2009 -0400

    radeon: Fix duplicated bit settings
    
    [agd5f: adapted from kms patch]
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/legacy_output.c b/src/legacy_output.c
index 73c86b9..186cd25 100644
--- a/src/legacy_output.c
+++ b/src/legacy_output.c
@@ -1521,7 +1521,7 @@ RADEONInitTvDacCntl(xf86OutputPtr output, RADEONSavePtr save)
 			       R420_TV_DAC_DACADJ_MASK |
 			       R420_TV_DAC_RDACPD |
 			       R420_TV_DAC_GDACPD |
-			       R420_TV_DAC_GDACPD |
+			       R420_TV_DAC_BDACPD |
 			       R420_TV_DAC_TVENABLE);
     } else {
 	save->tv_dac_cntl = info->SavedReg->tv_dac_cntl &
@@ -1530,7 +1530,7 @@ RADEONInitTvDacCntl(xf86OutputPtr output, RADEONSavePtr save)
 			       RADEON_TV_DAC_DACADJ_MASK |
 			       RADEON_TV_DAC_RDACPD |
 			       RADEON_TV_DAC_GDACPD |
-			       RADEON_TV_DAC_GDACPD);
+			       RADEON_TV_DAC_BDACPD);
     }
 
     save->tv_dac_cntl |= (RADEON_TV_DAC_NBLANK |
diff --git a/src/radeon_pm.c b/src/radeon_pm.c
index fe8f214..d5152c8 100644
--- a/src/radeon_pm.c
+++ b/src/radeon_pm.c
@@ -226,7 +226,7 @@ static void LegacySetClockGating(ScrnInfoPtr pScrn, Bool enable)
 			R300_PIXCLK_TRANS_ALWAYS_ONb      |
 			R300_PIXCLK_TVO_ALWAYS_ONb        |
 			R300_P2G2CLK_ALWAYS_ONb           |
-			R300_P2G2CLK_ALWAYS_ONb);
+			R300_P2G2CLK_DAC_ALWAYS_ONb);
 		OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
 	    } else if (info->ChipFamily >= CHIP_FAMILY_RV350) {
 		tmp = INPLL(pScrn, R300_SCLK_CNTL2);
@@ -273,7 +273,7 @@ static void LegacySetClockGating(ScrnInfoPtr pScrn, Bool enable)
 			R300_PIXCLK_TRANS_ALWAYS_ONb      |
 			R300_PIXCLK_TVO_ALWAYS_ONb        |
 			R300_P2G2CLK_ALWAYS_ONb           |
-			R300_P2G2CLK_ALWAYS_ONb);
+			R300_P2G2CLK_DAC_ALWAYS_ONb);
 		OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
 
 		tmp = INPLL(pScrn, RADEON_MCLK_MISC);
@@ -454,8 +454,8 @@ static void LegacySetClockGating(ScrnInfoPtr pScrn, Bool enable)
 		     RADEON_PIXCLK_TMDS_ALWAYS_ONb     |
 		     R300_PIXCLK_TRANS_ALWAYS_ONb      |
 		     R300_PIXCLK_TVO_ALWAYS_ONb        |
-		     R300_P2G2CLK_ALWAYS_ONb            |
 		     R300_P2G2CLK_ALWAYS_ONb           |
+		     R300_P2G2CLK_DAC_ALWAYS_ONb       |
 		     R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
 	    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
 	} else if (info->ChipFamily >= CHIP_FAMILY_RV350) {
@@ -507,8 +507,8 @@ static void LegacySetClockGating(ScrnInfoPtr pScrn, Bool enable)
 		     RADEON_PIXCLK_TMDS_ALWAYS_ONb     |
 		     R300_PIXCLK_TRANS_ALWAYS_ONb      |
 		     R300_PIXCLK_TVO_ALWAYS_ONb        |
-		     R300_P2G2CLK_ALWAYS_ONb            |
 		     R300_P2G2CLK_ALWAYS_ONb           |
+		     R300_P2G2CLK_DAC_ALWAYS_ONb       |
 		     R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
 	    OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
 	}  else {
commit e59ae08270711512e64b70f79b6476cc2c52d230
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Tue Oct 6 00:13:09 2009 +0200

    Don't call radeon_cs_flush_indirect() without KMS.
    
    Fixes http://bugs.freedesktop.org/show_bug.cgi?id=24316 .

diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index cf1914d..7ae0d1f 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -2179,7 +2179,10 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
 	(!info->cs && (info->cp->indirectBuffer->used + 4 * 32) >
 	 info->cp->indirectBuffer->total)) {
 	FUNC_NAME(RadeonDoneComposite)(info->accel_state->dst_pix);
-	radeon_cs_flush_indirect(pScrn);
+	if (info->cs)
+	    radeon_cs_flush_indirect(pScrn);
+	else
+	    RADEONCPFlushIndirect(pScrn, 1);
 	info->accel_state->exa->PrepareComposite(info->accel_state->composite_op,
 						 info->accel_state->src_pic,
 						 info->accel_state->msk_pic,
commit 457646d734558672402b6bcd15cadb66741edbed
Author: Jerome Glisse <jglisse at redhat.com>
Date:   Mon Oct 5 15:52:42 2009 +0200

    kms: assume accel is working is info ioctl return -EINVAL
    
    -EINVAL should only happen if the info ioctl doesn't support
    the get accel query. This patch assume that on such case accel
    is working.

diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index f51913e..faa6025 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -183,8 +183,15 @@ static Bool RADEONIsAccelWorking(ScrnInfoPtr pScrn)
     ginfo.request = 0x3;
     ginfo.value = (uintptr_t)&tmp;
     r = drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
-    if (r)
+    if (r) {
+        /* If kernel is too old before 2.6.32 than assume accel is working */
+        if (r == -EINVAL) {
+            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Kernel too old missing accel "
+                       "information, assuming accel is working\n");
+            return TRUE;
+        }
         return FALSE;
+    }
     if (tmp)
         return TRUE;
     return FALSE;
@@ -439,12 +446,6 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
 		       (unsigned long long)mminfo.vram_visible);
 	}
     }
-#if 0
-    if (info->ChipFamily < CHIP_FAMILY_R600) {
-	info->useEXA = TRUE;
-	info->directRenderingEnabled = TRUE;
-    }
-#endif
     RADEONSetPitch(pScrn);
 
     /* Set display resolution */
commit 9d596562496863d65850306d2126d8df98464de4
Author: Dave Airlie <airlied at linux.ie>
Date:   Mon Oct 5 18:35:20 2009 +1000

    kms: only touch gamma stuff on 1.7
    
    for correct colormap operation you probably want 1.7

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 6f3f6df..f82dec8 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -297,8 +297,10 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 		if (!xf86CrtcRotate(crtc)) {
 			goto done;
 		}
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0)
 		crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
 				       crtc->gamma_blue, crtc->gamma_size);
+#endif
 		
 		drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
 
commit 876f43d4682df4d47d3e158f75e0ca6040f41c70
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Mon Oct 5 02:23:03 2009 -0400

    R1/2xx EXA: Minimise number of draw primitives used for Composite operations.

diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 6753f00..cf1914d 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -2060,17 +2060,35 @@ static void FUNC_NAME(RadeonDoneComposite)(PixmapPtr pDst)
 
     ENTER_DRAW(0);
 
-    if (IS_R300_3D || IS_R500_3D) {
-	if (info->accel_state->draw_header) {
-		info->accel_state->draw_header[0] = CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
-							       info->accel_state->num_vtx *
-							       info->accel_state->vtx_count);
-		info->accel_state->draw_header[1] = RADEON_CP_VC_CNTL_PRIM_TYPE_QUAD_LIST |
-		    RADEON_CP_VC_CNTL_PRIM_WALK_RING |
-		    (info->accel_state->num_vtx << RADEON_CP_VC_CNTL_NUM_SHIFT);
-		info->accel_state->draw_header = NULL;
+    if (info->accel_state->draw_header) {
+	if (info->ChipFamily < CHIP_FAMILY_R200) {
+	    info->accel_state->draw_header[0] = CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD,
+							   info->accel_state->num_vtx *
+							   info->accel_state->vtx_count + 1);
+	    info->accel_state->draw_header[2] = (RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST |
+						 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
+						 RADEON_CP_VC_CNTL_MAOS_ENABLE |
+						 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
+						 (info->accel_state->num_vtx << RADEON_CP_VC_CNTL_NUM_SHIFT));
+	} else if (IS_R300_3D || IS_R500_3D) {
+	    info->accel_state->draw_header[0] = CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
+							   info->accel_state->num_vtx *
+							   info->accel_state->vtx_count);
+	    info->accel_state->draw_header[1] = (RADEON_CP_VC_CNTL_PRIM_TYPE_QUAD_LIST |
+						 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
+						 (info->accel_state->num_vtx << RADEON_CP_VC_CNTL_NUM_SHIFT));
+	} else {
+	    info->accel_state->draw_header[0] = CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
+							   info->accel_state->num_vtx *
+							   info->accel_state->vtx_count);
+	    info->accel_state->draw_header[1] = (RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST |
+						 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
+						 (info->accel_state->num_vtx << RADEON_CP_VC_CNTL_NUM_SHIFT));
 	}
+	info->accel_state->draw_header = NULL;
+    }
 
+    if (IS_R300_3D || IS_R500_3D) {
 	BEGIN_ACCEL(3);
 	OUT_ACCEL_REG(R300_SC_CLIP_RULE, 0xAAAA);
 	OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_RB3D_DC_FLUSH_ALL);
@@ -2218,21 +2236,37 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
 
 #ifdef ACCEL_CP
     if (info->ChipFamily < CHIP_FAMILY_R200) {
-	BEGIN_RING(3 * vtx_count + 3);
-	OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD,
-			    3 * vtx_count + 1));
-	if (info->accel_state->msk_pic)
-	    OUT_RING(RADEON_CP_VC_FRMT_XY |
-		     RADEON_CP_VC_FRMT_ST0 |
-		     RADEON_CP_VC_FRMT_ST1);
-	else
-	    OUT_RING(RADEON_CP_VC_FRMT_XY |
-		     RADEON_CP_VC_FRMT_ST0);
-	OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST |
-		 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
-		 RADEON_CP_VC_CNTL_MAOS_ENABLE |
-		 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
-		 (3 << RADEON_CP_VC_CNTL_NUM_SHIFT));
+	if (!info->accel_state->draw_header) {
+	    BEGIN_RING(3);
+
+#ifdef XF86DRM_MODE
+	    if (info->cs)
+		info->accel_state->draw_header = info->cs->packets + info->cs->cdw;
+	    else
+#endif
+		info->accel_state->draw_header = __head;
+	    info->accel_state->num_vtx = 0;
+	    info->accel_state->vtx_count = vtx_count;
+
+	    OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD,
+				3 * vtx_count + 1));
+	    if (info->accel_state->msk_pic)
+		OUT_RING(RADEON_CP_VC_FRMT_XY |
+			 RADEON_CP_VC_FRMT_ST0 |
+			 RADEON_CP_VC_FRMT_ST1);
+	    else
+		OUT_RING(RADEON_CP_VC_FRMT_XY |
+			 RADEON_CP_VC_FRMT_ST0);
+	    OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST |
+		     RADEON_CP_VC_CNTL_PRIM_WALK_RING |
+		     RADEON_CP_VC_CNTL_MAOS_ENABLE |
+		     RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
+		     (3 << RADEON_CP_VC_CNTL_NUM_SHIFT));
+	    ADVANCE_RING();
+	}
+
+	info->accel_state->num_vtx += 3;
+	BEGIN_RING(3 * vtx_count);
     } else if (IS_R300_3D || IS_R500_3D) {
 	if (!info->accel_state->draw_header) {
 	    BEGIN_RING(2);
@@ -2257,12 +2291,28 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
 	info->accel_state->num_vtx += 4;
 	BEGIN_RING(4 * vtx_count);
     } else {
-	BEGIN_RING(3 * vtx_count + 2);
-	OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
-			    3 * vtx_count));
-	OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST |
-		 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
-		 (3 << RADEON_CP_VC_CNTL_NUM_SHIFT));
+	if (!info->accel_state->draw_header) {
+	    BEGIN_RING(2);
+
+#ifdef XF86DRM_MODE
+	    if (info->cs)
+		info->accel_state->draw_header = info->cs->packets + info->cs->cdw;
+	    else
+#endif
+		info->accel_state->draw_header = __head;
+	    info->accel_state->num_vtx = 0;
+	    info->accel_state->vtx_count = vtx_count;
+
+	    OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
+				3 * vtx_count));
+	    OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST |
+		     RADEON_CP_VC_CNTL_PRIM_WALK_RING |
+		     (3 << RADEON_CP_VC_CNTL_NUM_SHIFT));
+	    ADVANCE_RING();
+	}
+
+	info->accel_state->num_vtx += 3;
+	BEGIN_RING(3 * vtx_count);
     }
 
 #else /* ACCEL_CP */
commit 86cafb8affea448bdf58300044e755201b822d2a
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Oct 5 14:17:25 2009 +1000

    kms: don't use scratch pixmaps when copying fbcon.
    
    scratch pixmaps seem to interact badly with mixed pixmaps, it appears
    some state may be getting left around in the privates somewhere, since
    scratch pixmap headers don't get destroyed.

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 1b5f0ac..6f3f6df 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -156,16 +156,19 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode,
 		return NULL;
 	}
 
-	pixmap = GetScratchPixmapHeader(pScreen,
-					fbcon->width, fbcon->height,
-					fbcon->depth, fbcon->bpp,
-					fbcon->pitch, NULL);
-	if (pixmap == NULL) {
+	pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, fbcon->depth, 0);
+	if (!pixmap) 
+		return NULL;
+
+	if (!(*pScreen->ModifyPixmapHeader)(pixmap, fbcon->width, fbcon->height,
+					   fbcon->depth, fbcon->bpp,
+					   fbcon->pitch, NULL)) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			   "Couldn't allocate pixmap fbcon contents\n");
 		return NULL;
 	}
-
+	
+	exaMoveInPixmap(pixmap);
 	radeon_set_pixmap_bo(pixmap, bo);
 
 	radeon_bo_unref(bo);
@@ -199,10 +202,17 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 	if (!src)
 		return;
 
-	dst = GetScratchPixmapHeader(pScreen,
-				     pScrn->virtualX, pScrn->virtualY,
-				     pScrn->depth, pScrn->bitsPerPixel,
-				     pitch, NULL);
+	dst = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScrn->depth, 0);
+	if (!dst)
+		goto out_free_src;
+
+	if (!(*pScreen->ModifyPixmapHeader)(dst, pScrn->virtualX,
+					    pScrn->virtualY, pScrn->depth,
+					    pScrn->bitsPerPixel, pitch,
+					    NULL))
+		goto out_free_dst;
+
+	exaMoveInPixmap(dst);
 	radeon_set_pixmap_bo(dst, info->front_bo);
 	info->accel_state->exa->PrepareCopy (src, dst,
 					     -1, -1, GXcopy, FB_ALLONES);
@@ -210,8 +220,9 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 				      pScrn->virtualX, pScrn->virtualY);
 	info->accel_state->exa->DoneCopy (dst);
 	radeon_cs_flush_indirect(pScrn);
-
+ out_free_dst:
 	(*pScreen->DestroyPixmap)(dst);
+ out_free_src:
 	(*pScreen->DestroyPixmap)(src);
 
 }
commit f8471512ea9f1d38140dfe98a0f832e9f935f51b
Author: Csillag Kristof <csillag.kristof at united-consult.hu>
Date:   Sun Oct 4 18:18:56 2009 -0400

    radeon: add support for Custom EDID
    
    Allows you to specify an edid per output from a file
    to override what is detected by DDC.  Useful for
    problematic monitors or KVM switches that block
    DDC.  Specifying an EDID that is not compatible with
    your monitor could damage your monitor so use with
    caution.
    
    agd5f: cache the custom edid at startup so we don't
    have to read it from file every time the output is
    queried.

diff --git a/man/radeon.man b/man/radeon.man
index 703fe1d..62270fb 100644
--- a/man/radeon.man
+++ b/man/radeon.man
@@ -302,6 +302,34 @@ for monitor detection. This is different from NoDDC option.
 The default value is
 .B off.
 .TP 
+.BI "Option \*qCustomEDID\*q \*q" string \*q
+Forces the X driver to use the EDID data specified in a file rather
+than the display's EDID. Also overrides DDC monitor detection.
+.br
+You may specify a semicolon separated list of output name and filename pairs.
+The output name is something like "VGA-0" or "DVI-0";
+consult the Xorg log for the supported output names of any given system.
+.br
+The file must contain a raw 128-byte EDID block, as captured by
+.B
+get-edid.
+.br
+For example:
+.B
+Option \*qCustomEDID\*q \*qVGA-0:/tmp/edid1.bin; DVI-0:/tmp/edid2.bin\*q
+will assign the EDID from the file /tmp/edid1.bin to the output device
+VGA-0, and the EDID from the file /tmp/edid2.bin to the output device
+DVI-0.
+.br
+Note that a output name must always be specified,
+even if only one EDID is specified.
+.br
+.B
+Caution:
+Specifying an EDID that doesn't exactly match your display may
+damage your hardware, as it allows the driver to specify timings beyond
+the capabilities of your display. Use with care.
+.TP 
 .BI "Option \*qPanelSize\*q \*q" "string" \*q
 Should only be used when driver cannot detect the correct panel size.
 Apply to both desktop (TMDS) and laptop (LVDS) digital panels.
diff --git a/src/radeon.h b/src/radeon.h
index 9d283bb..7fd297e 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -176,6 +176,7 @@ typedef enum {
 #endif
 #endif
     OPTION_IGNORE_EDID,
+    OPTION_CUSTOM_EDID,
     OPTION_DISP_PRIORITY,
     OPTION_PANEL_SIZE,
     OPTION_MIN_DOTCLOCK,
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index e0ba9ba..d039920 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -161,6 +161,7 @@ static const OptionInfoRec RADEONOptions[] = {
 #endif
 #endif
     { OPTION_IGNORE_EDID,    "IgnoreEDID",       OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_CUSTOM_EDID,    "CustomEDID",       OPTV_ANYSTR,  {0}, FALSE },
     { OPTION_DISP_PRIORITY,  "DisplayPriority",  OPTV_ANYSTR,  {0}, FALSE },
     { OPTION_PANEL_SIZE,     "PanelSize",        OPTV_ANYSTR,  {0}, FALSE },
     { OPTION_MIN_DOTCLOCK,   "ForceMinDotClock", OPTV_FREQ,    {0}, FALSE },
diff --git a/src/radeon_output.c b/src/radeon_output.c
index 30f6f3b..36ef1aa 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -32,6 +32,7 @@
 
 #include <string.h>
 #include <stdio.h>
+#include <fcntl.h>
 
 /* X and server generic header files */
 #include "xf86.h"
@@ -215,6 +216,60 @@ monitor_is_digital(xf86MonPtr MonInfo)
     return (MonInfo->rawData[0x14] & 0x80) != 0;
 }
 
+static void
+RADEONGetHardCodedEDIDFromFile(xf86OutputPtr output)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    char *EDIDlist = (char *)xf86GetOptValString(info->Options, OPTION_CUSTOM_EDID);
+
+    radeon_output->custom_edid = FALSE;
+    radeon_output->custom_mon = NULL;
+
+    if (EDIDlist != NULL) {
+	unsigned char edid[128];
+	char *name = output->name;
+	char *outputEDID = strstr(EDIDlist, name);
+
+	if (outputEDID != NULL) {
+	    char *end;
+	    int fd;
+
+	    outputEDID += strlen(name) + 1;
+	    end = strstr(outputEDID, ";");
+	    if (end != NULL)
+		*end = 0;
+
+	    fd = open (outputEDID, O_RDONLY);
+	    if (fd >= 0) {
+		read(fd, edid, 128);
+		close(fd);
+		if (edid[1] == 0xff) {
+		    radeon_output->custom_mon = xf86InterpretEDID(output->scrn->scrnIndex, edid);
+		    radeon_output->custom_edid = TRUE;
+		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			       "Successfully read Custom EDID data for output %s from %s.\n",
+			       name, outputEDID);
+		} else {
+		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			       "Custom EDID data for %s read from %s was invalid.\n",
+			       name, outputEDID);
+		}
+	    } else {
+		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			   "Could not read custom EDID for output %s from file %s.\n",
+			   name, outputEDID);
+	    }
+	} else {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "Could not find EDID file name for output %s; using auto detection.\n",
+		       name);
+	}
+    }
+}
+
+
 static RADEONMonitorType
 radeon_ddc_connected(xf86OutputPtr output)
 {
@@ -224,7 +279,10 @@ radeon_ddc_connected(xf86OutputPtr output)
     xf86MonPtr MonInfo = NULL;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
 
-    if (radeon_output->pI2CBus) {
+    if (radeon_output->custom_edid) {
+	MonInfo = xnfcalloc(sizeof(xf86Monitor), 1);
+	*MonInfo = *radeon_output->custom_mon;
+    } else if (radeon_output->pI2CBus) {
 	if (info->get_hardcoded_edid_from_bios)
 	    MonInfo = RADEONGetHardCodedEDIDFromBIOS(output);
 	if (MonInfo == NULL) {
@@ -2802,6 +2860,7 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn)
 	xf86OutputPtr output = xf86_config->output[i];
 
 	output->possible_clones = radeon_output_clones(pScrn, output);
+	RADEONGetHardCodedEDIDFromFile(output);
     }
 
     return TRUE;
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index 9b2cd70..0ae3a87 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -261,6 +261,9 @@ typedef struct _RADEONOutputPrivateRec {
     I2CBusPtr         pI2CBus;
     RADEONI2CBusRec   ddc_i2c;
     Bool shared_ddc;
+
+    Bool custom_edid;
+    xf86MonPtr custom_mon;
     // router info
     // HDP info
 
commit 60d9685abddccec17c1a9a5ec48cbe9c92543e0f
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Oct 5 12:41:30 2009 +1000

    kms: setup colormap and gamma correctly.
    
    We need to program the gamma at modeset. no need to use
    old cmap interface at all.

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index ecfc629..1b5f0ac 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -286,7 +286,9 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 		if (!xf86CrtcRotate(crtc)) {
 			goto done;
 		}
-
+		crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
+				       crtc->gamma_blue, crtc->gamma_size);
+		
 		drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
 
 		fb_id = drmmode->fb_id;
@@ -1144,87 +1146,4 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 	}
 	return TRUE;
 }
-
-static void drmmode_load_palette(ScrnInfoPtr pScrn, int numColors,
-                                 int *indices, LOCO *colors, VisualPtr pVisual)
-{
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    uint16_t       lut_r[256], lut_g[256], lut_b[256];
-    int index, j, i;
-    int c;
-
-    for (c = 0; c < xf86_config->num_crtc; c++) {
-        xf86CrtcPtr crtc = xf86_config->crtc[c];
-	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
-
-        for (i = 0 ; i < 256; i++) {
-            lut_r[i] = drmmode_crtc->lut_r[i] << 6;
-            lut_g[i] = drmmode_crtc->lut_g[i] << 6;
-            lut_b[i] = drmmode_crtc->lut_b[i] << 6;
-        }
-
-        switch(pScrn->depth) {
-        case 15:
-            for (i = 0; i < numColors; i++) {
-                index = indices[i];
-                for (j = 0; j < 8; j++) {
-                    lut_r[index * 8 + j] = colors[index].red << 6;
-                    lut_g[index * 8 + j] = colors[index].green << 6;
-                    lut_b[index * 8 + j] = colors[index].blue << 6;
-                }
-            }
-         break;
-         case 16:
-             for (i = 0; i < numColors; i++) {
-                 index = indices[i];
-
-                  if (i <= 31) {
-                      for (j = 0; j < 8; j++) {
-                          lut_r[index * 8 + j] = colors[index].red << 6;
-                          lut_b[index * 8 + j] = colors[index].blue << 6;
-                      }
-                  }
-
-                  for (j = 0; j < 4; j++) {
-                      lut_g[index * 4 + j] = colors[index].green << 6;
-                  }
-              }
-	  break;
-          default:
-              for (i = 0; i < numColors; i++) {
-                  index = indices[i];
-                  lut_r[index] = colors[index].red << 6;
-                  lut_g[index] = colors[index].green << 6;
-                  lut_b[index] = colors[index].blue << 6;
-              }
-              break;
-          }
-
-    /* Make the change through RandR */
-#ifdef RANDR_12_INTERFACE
-        if (crtc->randr_crtc)
-            RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
-        else
-#endif
-            crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
-     }
-}
-
-Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
-{
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-                  "Initializing kms color map\n");
-    if (!miCreateDefColormap(pScreen))
-        return FALSE;
-    /* all radeons support 10 bit CLUTs */
-    if (!xf86HandleColormaps(pScreen, 256, 10,
-                             drmmode_load_palette, NULL,
-                             CMAP_PALETTED_TRUECOLOR
-#if 0 /* This option messes up text mode! (eich at suse.de) */
-                             | CMAP_LOAD_EVEN_IF_OFFSCREEN
-#endif
-                             | CMAP_RELOAD_ON_MODE_SWITCH))
-         return FALSE;
-    return TRUE;
-}
 #endif
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 432cee7..f51913e 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -766,8 +766,8 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
 //    info->PointerMoved = pScrn->PointerMoved;
 //    pScrn->PointerMoved = RADEONPointerMoved;
 
-    if (!drmmode_setup_colormap(pScreen, pScrn))
-	return FALSE;
+    if (!miCreateDefColormap(pScreen))
+        return FALSE;
 
    /* Note unused options */
     if (serverGeneration == 1)
commit b0b10e548fd69b3ff67a0f9b71456b89c61cb4d6
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Sun Oct 4 17:07:32 2009 -0400

    R6/7xx EXA: Add support for BGRA picture formats.
    
    Also add mysteriously missing case statements for ABGR destination formats.

diff --git a/src/r600_exa.c b/src/r600_exa.c
index f6f2007..56bd84b 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -136,8 +136,6 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     uint32_t a, r, g, b;
     float ps_alu_consts[4];
 
-    //return FALSE;
-
     if (pPix->drawable.bitsPerPixel == 24)
         RADEON_FALLBACK(("24bpp unsupported\n"));
     if (!R600CheckBPP(pPix->drawable.bitsPerPixel))
@@ -723,8 +721,6 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
     RADEONInfoPtr info = RADEONPTR(pScrn);
     struct radeon_accel_state *accel_state = info->accel_state;
     int ret;
-    
-    //return FALSE;
 
     if (pSrc->drawable.bitsPerPixel == 24)
         RADEON_FALLBACK(("24bpp unsupported\n"));
@@ -1161,6 +1157,10 @@ static struct formatinfo R600TexFormats[] = {
     {PICT_x8r8g8b8,	FMT_8_8_8_8},
     {PICT_a8b8g8r8,	FMT_8_8_8_8},
     {PICT_x8b8g8r8,	FMT_8_8_8_8},
+#ifdef PICT_TYPE_BGRA
+    {PICT_b8g8r8a8,	FMT_8_8_8_8},
+    {PICT_b8g8r8x8,	FMT_8_8_8_8},
+#endif
     {PICT_r5g6b5,	FMT_5_6_5},
     {PICT_a1r5g5b5,	FMT_1_5_5_5},
     {PICT_x1r5g5b5,     FMT_1_5_5_5},
@@ -1204,6 +1204,12 @@ static Bool R600GetDestFormat(PicturePtr pDstPicture, uint32_t *dst_format)
     switch (pDstPicture->format) {
     case PICT_a8r8g8b8:
     case PICT_x8r8g8b8:
+    case PICT_a8b8g8r8:
+    case PICT_x8b8g8r8:
+#ifdef PICT_TYPE_BGRA
+    case PICT_b8g8r8a8:
+    case PICT_b8g8r8x8:
+#endif
 	*dst_format = COLOR_8_8_8_8;
 	break;
     case PICT_r5g6b5:
@@ -1349,6 +1355,20 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
 	pix_b = SQ_SEL_Z; /* B */
 	pix_a = SQ_SEL_1; /* A */
 	break;
+#ifdef PICT_TYPE_BGRA
+    case PICT_b8g8r8a8:
+	pix_r = SQ_SEL_Y; /* R */
+	pix_g = SQ_SEL_Z; /* G */
+	pix_b = SQ_SEL_W; /* B */
+	pix_a = SQ_SEL_X; /* A */
+	break;
+    case PICT_b8g8r8x8:
+	pix_r = SQ_SEL_Y; /* R */
+	pix_g = SQ_SEL_Z; /* G */
+	pix_b = SQ_SEL_W; /* B */
+	pix_a = SQ_SEL_1; /* A */
+	break;
+#endif
     case PICT_x1r5g5b5:
     case PICT_x8r8g8b8:
     case PICT_r5g6b5:
@@ -1595,7 +1615,6 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     shader_config_t vs_conf, ps_conf;
     int ret;
 
-    //return FALSE;
     /* return FALSE; */
 
     if (pDst->drawable.bitsPerPixel < 8 || pSrc->drawable.bitsPerPixel < 8)
@@ -1777,6 +1796,16 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     default:
 	cb_conf.comp_swap = 1; /* ARGB */
 	break;
+    case PICT_a8b8g8r8:
+    case PICT_x8b8g8r8:
+	cb_conf.comp_swap = 0; /* ABGR */
+	break;
+#ifdef PICT_TYPE_BGRA
+    case PICT_b8g8r8a8:
+    case PICT_b8g8r8x8:
+	cb_conf.comp_swap = 3; /* BGRA */
+	break;
+#endif
     case PICT_r5g6b5:
 	cb_conf.comp_swap = 2; /* RGB */
 	break;
commit 8404c37b2ff95aba31db97676f106ec2f30fda7f
Author: Dave Airlie <airlied at linux.ie>
Date:   Sun Oct 4 18:18:51 2009 +1000

    radeon: fix build without kms

diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 7bc8ef0..6753f00 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -2237,9 +2237,11 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
 	if (!info->accel_state->draw_header) {
 	    BEGIN_RING(2);
 
+#ifdef XF86DRM_MODE
 	    if (info->cs)
 		info->accel_state->draw_header = info->cs->packets + info->cs->cdw;
 	    else
+#endif
 		info->accel_state->draw_header = __head;
 	    info->accel_state->num_vtx = 0;
 	    info->accel_state->vtx_count = vtx_count;
commit 9460ea864b12ec1fbd11c5d9a20bb5a4279d9d3d
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Sat Oct 3 16:33:33 2009 +0200

    Fix KMS on big endian machines.
    
    Requires at least xserver 1.7 to work properly.
    
    Also make sure the front buffer is and stays tiled if colour tiling is enabled.

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index c9037b4..ecfc629 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -915,6 +915,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 	int screen_size;
 	int cpp = info->CurrentLayout.pixel_bytes;
 	struct radeon_bo *front_bo;
+	uint32_t tiling_flags = 0;
 
 	if (scrn->virtualX == width && scrn->virtualY == height)
 		return TRUE;
@@ -948,6 +949,22 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
 	if (!info->front_bo)
 		goto fail;
 
+	if (info->allowColorTiling)
+	    tiling_flags |= RADEON_TILING_MACRO;
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+	switch (cpp) {
+	case 4:
+	    tiling_flags |= RADEON_TILING_SWAP_32BIT;
+	    break;
+	case 2:
+	    tiling_flags |= RADEON_TILING_SWAP_16BIT;
+	    break;
+	}
+#endif
+	if (tiling_flags)
+	    radeon_bo_set_tiling(info->front_bo,
+				 tiling_flags | RADEON_TILING_SURFACE, pitch * cpp);
+
 	ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
 			   scrn->bitsPerPixel, pitch * cpp,
 			   info->front_bo->handle,
diff --git a/src/radeon.h b/src/radeon.h
index 0322bf0..9d283bb 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -463,6 +463,7 @@ typedef struct _atomBiosHandle *atomBiosHandlePtr;
 struct radeon_exa_pixmap_priv {
     struct radeon_bo *bo;
     int flags;
+    Bool bo_mapped;
 };
 
 typedef struct {
diff --git a/src/radeon_drm.h b/src/radeon_drm.h
index f974e19..49a5f81 100644
--- a/src/radeon_drm.h
+++ b/src/radeon_drm.h
@@ -802,9 +802,10 @@ struct drm_radeon_gem_create {
 
 #define RADEON_TILING_MACRO 0x1
 #define RADEON_TILING_MICRO 0x2
-#define RADEON_TILING_SWAP  0x4
-#define RADEON_TILING_SURFACE  0x8 /* this object requires a surface
-				    * when mapped - i.e. front buffer */
+#define RADEON_TILING_SWAP_16BIT  0x4
+#define RADEON_TILING_SWAP_32BIT  0x8
+#define RADEON_TILING_SURFACE     0x10 /* this object requires a surface
+					* when mapped - i.e. front buffer */
 
 struct drm_radeon_gem_set_tiling {
 	uint32_t	handle;
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 6cf9598..99a93a4 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -339,10 +339,18 @@ static void RADEONFinishAccess_BE(PixmapPtr pPix, int index)
 #ifdef XF86DRM_MODE
 Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
 {
-    ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
+    ScreenPtr pScreen = pPix->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     struct radeon_exa_pixmap_priv *driver_priv;
     int ret;
 
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+    /* May need to handle byte swapping in DownloadFrom/UploadToScreen */
+    if (pPix->drawable.bitsPerPixel > 8 &&
+	pPix != pScreen->GetScreenPixmap(pScreen))
+	return FALSE;
+#endif
+
     driver_priv = exaGetPixmapDriverPrivate(pPix);
     if (!driver_priv)
       return FALSE;
@@ -357,6 +365,7 @@ Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
       FatalError("failed to map pixmap %d\n", ret);
       return FALSE;
     }
+    driver_priv->bo_mapped = TRUE;
 
     pPix->devPrivate.ptr = driver_priv->bo->ptr;
 
@@ -368,7 +377,7 @@ void RADEONFinishAccess_CS(PixmapPtr pPix, int index)
     struct radeon_exa_pixmap_priv *driver_priv;
 
     driver_priv = exaGetPixmapDriverPrivate(pPix);
-    if (!driver_priv)
+    if (!driver_priv || !driver_priv->bo_mapped)
         return;
 
     radeon_bo_unmap(driver_priv->bo);
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 98aca93..d5a3103 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -450,15 +450,18 @@ static Bool
 RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
 		       char *src, int src_pitch)
 {
-    RINFO_FROM_SCREEN(pDst->drawable.pScreen);
+    ScreenPtr pScreen = pDst->drawable.pScreen;
+    RINFO_FROM_SCREEN(pScreen);
     struct radeon_exa_pixmap_priv *driver_priv;
     struct radeon_bo *scratch;
+    unsigned char *dst;
     unsigned size;
     uint32_t datatype = 0;
     uint32_t dst_domain;
     uint32_t dst_pitch_offset;
     unsigned bpp = pDst->drawable.bitsPerPixel;
     uint32_t scratch_pitch = (w * bpp / 8 + 63) & ~63;
+    uint32_t swap = RADEON_HOST_DATA_SWAP_NONE;
     Bool r;
     int i;
 
@@ -466,11 +469,34 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
 	return FALSE;
 
     driver_priv = exaGetPixmapDriverPrivate(pDst);
+    if (!driver_priv || !driver_priv->bo)
+	return FALSE;
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+    switch (bpp) {
+    case 32:
+	swap = RADEON_HOST_DATA_SWAP_32BIT;
+	break;
+    case 16:
+	swap = RADEON_HOST_DATA_SWAP_16BIT;
+	break;
+    }
+#endif
 
     /* If we know the BO won't be busy, don't bother */
     if (driver_priv->bo->cref == 1 &&
-	!radeon_bo_is_busy(driver_priv->bo, &dst_domain))
+	!radeon_bo_is_busy(driver_priv->bo, &dst_domain)) {
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+	/* Can't return FALSE here if we need to swap bytes */
+	if (swap != RADEON_HOST_DATA_SWAP_NONE &&
+	    driver_priv->bo != info->front_bo) {
+	    scratch = driver_priv->bo;
+	    scratch_pitch = pDst->devKind;
+	    goto copy;
+	}
+#endif
 	return FALSE;
+    }
 
     size = scratch_pitch * h;
     scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0);
@@ -486,6 +512,7 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
         goto out;
     }
 
+copy:
     r = radeon_bo_map(scratch, 0);
     if (r) {
         r = FALSE;
@@ -493,22 +520,28 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
     }
     r = TRUE;
     size = w * bpp / 8;
+    dst = scratch->ptr;
+    if (scratch == driver_priv->bo)
+	dst += y * scratch_pitch + x * bpp / 8;
     for (i = 0; i < h; i++) {
-        memcpy(scratch->ptr + i * scratch_pitch, src, size);
+        RADEONCopySwap(dst + i * scratch_pitch, (uint8_t*)src, size, swap);
         src += src_pitch;
     }
     radeon_bo_unmap(scratch);
 
-    RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype);
-    RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset);
-    ACCEL_PREAMBLE();
-    RADEON_SWITCH_TO_2D();
-    RADEONBlitChunk(pScrn, scratch, driver_priv->bo, datatype, scratch_pitch << 16,
-                    dst_pitch_offset, 0, 0, x, y, w, h,
-                    RADEON_GEM_DOMAIN_GTT, RADEON_GEM_DOMAIN_VRAM);
+    if (scratch != driver_priv->bo) {
+	RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype);
+	RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset);
+	ACCEL_PREAMBLE();
+	RADEON_SWITCH_TO_2D();
+	RADEONBlitChunk(pScrn, scratch, driver_priv->bo, datatype, scratch_pitch << 16,
+			dst_pitch_offset, 0, 0, x, y, w, h,
+			RADEON_GEM_DOMAIN_GTT, RADEON_GEM_DOMAIN_VRAM);
+    }
 
 out:
-    radeon_bo_unref(scratch);
+    if (scratch != driver_priv->bo)
+	radeon_bo_unref(scratch);
     return r;
 }
 
@@ -525,12 +558,26 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
     uint32_t src_pitch_offset;
     unsigned bpp = pSrc->drawable.bitsPerPixel;
     uint32_t scratch_pitch = (w * bpp / 8 + 63) & ~63;
+    uint32_t swap = RADEON_HOST_DATA_SWAP_NONE;
     Bool r;
 
     if (bpp < 8)
 	return FALSE;
 
     driver_priv = exaGetPixmapDriverPrivate(pSrc);
+    if (!driver_priv || !driver_priv->bo)
+	return FALSE;
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+    switch (bpp) {
+    case 32:
+	swap = RADEON_HOST_DATA_SWAP_32BIT;
+	break;
+    case 16:
+	swap = RADEON_HOST_DATA_SWAP_16BIT;
+	break;
+    }
+#endif
 
     /* If we know the BO won't end up in VRAM anyway, don't bother */
     if (driver_priv->bo->cref > 1) {
@@ -546,8 +593,17 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
     if (!src_domain)
 	radeon_bo_is_busy(driver_priv->bo, &src_domain);
 
-    if (src_domain != RADEON_GEM_DOMAIN_VRAM)
+    if (src_domain != RADEON_GEM_DOMAIN_VRAM) {
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+	/* Can't return FALSE here if we need to swap bytes */
+	if (swap != RADEON_HOST_DATA_SWAP_NONE) {
+	    scratch = driver_priv->bo;
+	    scratch_pitch = pSrc->devKind;
+	    goto copy;
+	}
+#endif
 	return FALSE;
+    }
 
     size = scratch_pitch * h;
     scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0);
@@ -572,6 +628,7 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
                     RADEON_GEM_DOMAIN_GTT);
     FLUSH_RING();
 
+copy:
     r = radeon_bo_map(scratch, 0);
     if (r) {
         r = FALSE;
@@ -579,15 +636,19 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
     }
     r = TRUE;
     w *= bpp / 8;
-    size = 0;
+    if (scratch == driver_priv->bo)
+	size = y * scratch_pitch + x * bpp / 8;
+    else
+	size = 0;
     while (h--) {
-        memcpy(dst, scratch->ptr + size, w);
+        RADEONCopySwap((uint8_t*)dst, scratch->ptr + size, w, swap);
         size += scratch_pitch;
         dst += dst_pitch;
     }
     radeon_bo_unmap(scratch);
 out:
-    radeon_bo_unref(scratch);
+    if (scratch != driver_priv->bo)
+	radeon_bo_unref(scratch);
     return r;
 }
 #endif
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index bd6020b..432cee7 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -887,6 +887,11 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
                     return FALSE;
                 }
 
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+		radeon_bo_set_tiling(info->cursor_bo[c], RADEON_TILING_SWAP_32BIT |
+				     RADEON_TILING_SURFACE, stride);
+#endif
+
                 if (radeon_bo_map(info->cursor_bo[c], 1)) {
                     ErrorF("Failed to map cursor buffer memory\n");
                 }
@@ -907,6 +912,8 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
     info->dri->textureSize = 0;
 
     if (info->front_bo == NULL) {
+	uint32_t tiling_flags = 0;
+
         info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size,
                                         0, RADEON_GEM_DOMAIN_VRAM, 0);
         if (info->r600_shadow_fb == TRUE) {
@@ -915,8 +922,22 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
             }
         }
         if (info->allowColorTiling) {
-            radeon_bo_set_tiling(info->front_bo, RADEON_TILING_MACRO, stride);
+	    tiling_flags |= RADEON_TILING_MACRO;
         }
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+	switch (cpp) {
+	case 4:
+	    tiling_flags |= RADEON_TILING_SWAP_32BIT;
+	    break;
+	case 2:
+	    tiling_flags |= RADEON_TILING_SWAP_16BIT;
+	    break;
+	}
+#endif
+	if (tiling_flags) {
+            radeon_bo_set_tiling(info->front_bo,
+				 tiling_flags | RADEON_TILING_SURFACE, stride);
+	}
     }
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer size: %dK\n", info->front_bo->size/1024);
diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c
index 04a2401..d6b221f 100644
--- a/src/radeon_textured_video.c
+++ b/src/radeon_textured_video.c
@@ -709,7 +709,13 @@ Bool radeon_load_bicubic_texture(ScrnInfoPtr pScrn)
 	} else
 	    bicubic_addr = (uint8_t *)(info->FB + info->bicubic_offset);
 
-	RADEONCopyData(pScrn, (uint8_t *)bicubic_tex_512, bicubic_addr, 1024, 1024, 1, 512, 2);
+	RADEONCopySwap(bicubic_addr, (uint8_t *)bicubic_tex_512, 1024,
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+		       RADEON_HOST_DATA_SWAP_16BIT
+#else
+		       RADEON_HOST_DATA_SWAP_NONE
+#endif
+);
 	if (info->cs)
 	    radeon_bo_unmap(info->bicubic_bo);
     }
diff --git a/src/radeon_video.c b/src/radeon_video.c
index f1fe72b..7aaa266 100644
--- a/src/radeon_video.c
+++ b/src/radeon_video.c
@@ -2198,36 +2198,37 @@ RADEONCopyData(
     else
 #endif /* XF86DRI */
     {
-#if X_BYTE_ORDER == X_BIG_ENDIAN
-	unsigned char *RADEONMMIO = info->MMIO;
-	unsigned int swapper = info->ModeReg->surface_cntl &
-		~(RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP |
-		  RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP1_SWP_16BPP);
+	int swap = RADEON_HOST_DATA_SWAP_NONE;
 
-	switch(bpp) {
-	case 2:
-	    swapper |= RADEON_NONSURF_AP0_SWP_16BPP
-		    |  RADEON_NONSURF_AP1_SWP_16BPP;
-	    break;
-	case 4:
-	    swapper |= RADEON_NONSURF_AP0_SWP_32BPP
-		    |  RADEON_NONSURF_AP1_SWP_32BPP;
-	    break;
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+	if (info->kms_enabled) {
+	    switch(bpp) {
+	    case 2:
+		swap = RADEON_HOST_DATA_SWAP_16BIT;
+		break;
+	    case 4:
+		swap = RADEON_HOST_DATA_SWAP_32BIT;
+		break;
+	    }
+	} else if (bpp != pScrn->bitsPerPixel) {
+	    if (bpp == 8)
+		swap = RADEON_HOST_DATA_SWAP_32BIT;
+	    else
+		swap = RADEON_HOST_DATA_SWAP_HDW;
 	}
-	OUTREG(RADEON_SURFACE_CNTL, swapper);
 #endif
+
 	w *= bpp;
 
-	while (h--) {
-	    memcpy(dst, src, w);
-	    src += srcPitch;
-	    dst += dstPitch;
+	if (dstPitch == w && dstPitch == srcPitch)
+	    RADEONCopySwap(dst, src, h * dstPitch, swap);
+	else {
+	    while (h--) {
+		RADEONCopySwap(dst, src, w, swap);
+		src += srcPitch;
+		dst += dstPitch;
+	    }
 	}
-
-#if X_BYTE_ORDER == X_BIG_ENDIAN
-	/* restore byte swapping */
-	OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl);
-#endif
     }
 }
 
@@ -2282,9 +2283,10 @@ RADEONCopyRGB24Data(
     {
 #if X_BYTE_ORDER == X_BIG_ENDIAN
 	unsigned char *RADEONMMIO = info->MMIO;
-	OUTREG(RADEON_SURFACE_CNTL, (info->ModeReg->surface_cntl
-				   | RADEON_NONSURF_AP0_SWP_32BPP)
-				  & ~RADEON_NONSURF_AP0_SWP_16BPP);
+
+	if (!info->kms_enabled)
+	    OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl &
+		   ~(RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP0_SWP_32BPP));
 #endif
 
 	for (j = 0; j < h; j++) {
@@ -2292,13 +2294,15 @@ RADEONCopyRGB24Data(
 	    sptr = src + j * srcPitch;
 
 	    for (i = 0; i < w; i++, sptr += 3) {
-		dptr[i] = (sptr[2] << 16) | (sptr[1] << 8) | sptr[0];
+		dptr[i] = cpu_to_le32((sptr[2] << 16) | (sptr[1] << 8) | sptr[0]);
 	    }
 	}
 
 #if X_BYTE_ORDER == X_BIG_ENDIAN
-	/* restore byte swapping */
-	OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl);
+	if (!info->kms_enabled) {
+	    /* restore byte swapping */
+	    OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl);
+	}
 #endif
     }
 }
@@ -2377,9 +2381,10 @@ RADEONCopyMungedData(
 
 #if X_BYTE_ORDER == X_BIG_ENDIAN
 	unsigned char *RADEONMMIO = info->MMIO;
-	OUTREG(RADEON_SURFACE_CNTL, (info->ModeReg->surface_cntl
-				   | RADEON_NONSURF_AP0_SWP_32BPP)
-				  & ~RADEON_NONSURF_AP0_SWP_16BPP);
+
+	if (!info->kms_enabled)
+	    OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl &
+		   ~(RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP0_SWP_32BPP));
 #endif
 
 	w /= 2;
@@ -2391,16 +2396,16 @@ RADEONCopyMungedData(
 	    i = w;
 	    while( i > 4 )
 	    {
-		dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
-		dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
-		dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
-		dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
+		dst[0] = cpu_to_le32(s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24));
+		dst[1] = cpu_to_le32(s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24));
+		dst[2] = cpu_to_le32(s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24));
+		dst[3] = cpu_to_le32(s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24));
 		dst += 4; s2 += 4; s3 += 4; s1 += 8;
 		i -= 4;
 	    }
 	    while( i-- )
 	    {
-		dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
+		dst[0] = cpu_to_le32(s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24));
 		dst++; s2++; s3++;
 		s1 += 2;
 	    }
@@ -2414,8 +2419,10 @@ RADEONCopyMungedData(
 	    }	
 	}
 #if X_BYTE_ORDER == X_BIG_ENDIAN
-	/* restore byte swapping */
-	OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl);
+	if (!info->kms_enabled) {
+	    /* restore byte swapping */
+	    OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl);
+	}
 #endif
     }
 }
commit aee6b6f2c120baf477b4845ddc1a94637c31db2f
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Sat Oct 3 16:33:33 2009 +0200

    EXA: Bail earlier from PrepareCopy hook on trivially unsupportable conditions.

diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index c74b9d9..98aca93 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -275,6 +275,15 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc,   PixmapPtr pDst,
     uint32_t datatype, src_pitch_offset, dst_pitch_offset;
     TRACE;
 
+    if (pDst->drawable.bitsPerPixel == 24)
+	RADEON_FALLBACK(("24bpp unsupported"));
+    if (!RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype))
+	RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n"));
+    if (!RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset))
+	RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch source failed\n"));
+    if (!RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset))
+	RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch dest failed\n"));
+
     RADEON_SWITCH_TO_2D();
 
 #ifdef XF86DRM_MODE
@@ -302,15 +311,6 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc,   PixmapPtr pDst,
     info->accel_state->ydir = ydir;
     info->accel_state->dst_pix = pDst;
 
-    if (pDst->drawable.bitsPerPixel == 24)
-	RADEON_FALLBACK(("24bpp unsupported"));
-    if (!RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype))
-	RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n"));
-    if (!RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset))
-	RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch source failed\n"));
-    if (!RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset))
-	RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch dest failed\n"));
-
     FUNC_NAME(RADEONDoPrepareCopy)(pScrn, src_pitch_offset, dst_pitch_offset,
 				   datatype, rop, planemask);
 
commit 30031b169def5caadb394225919a6079a0957142
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Sat Oct 3 16:33:33 2009 +0200

    R3/5xx EXA: Add support for BGRA picture formats.
    
    Also add mysteriously missing case statements for ABGR destination formats.

diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index c266fb7..7bc8ef0 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -125,6 +125,10 @@ static struct formatinfo R300TexFormats[] = {
     {PICT_x8r8g8b8,	R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8)},
     {PICT_a8b8g8r8,	R300_EASY_TX_FORMAT(Z, Y, X, W, W8Z8Y8X8)},
     {PICT_x8b8g8r8,	R300_EASY_TX_FORMAT(Z, Y, X, ONE, W8Z8Y8X8)},
+#ifdef PICT_TYPE_BGRA
+    {PICT_b8g8r8a8,	R300_EASY_TX_FORMAT(W, Z, Y, X, W8Z8Y8X8)},
+    {PICT_b8g8r8x8,	R300_EASY_TX_FORMAT(W, Z, Y, ONE, W8Z8Y8X8)},
+#endif
     {PICT_r5g6b5,	R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)},
     {PICT_a1r5g5b5,	R300_EASY_TX_FORMAT(X, Y, Z, W, W1Z5Y5X5)},
     {PICT_x1r5g5b5,	R300_EASY_TX_FORMAT(X, Y, Z, ONE, W1Z5Y5X5)},
@@ -163,6 +167,12 @@ static Bool R300GetDestFormat(PicturePtr pDstPicture, uint32_t *dst_format)
     switch (pDstPicture->format) {
     case PICT_a8r8g8b8:
     case PICT_x8r8g8b8:
+    case PICT_a8b8g8r8:
+    case PICT_x8b8g8r8:
+#ifdef PICT_TYPE_BGRA
+    case PICT_b8g8r8a8:
+    case PICT_b8g8r8x8:
+#endif
 	*dst_format = R300_COLORFORMAT_ARGB8888;
 	break;
     case PICT_r5g6b5:
@@ -1559,6 +1569,16 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 		      R300_OUT_FMT_C2_SEL_BLUE |
 		      R300_OUT_FMT_C3_SEL_ALPHA);
 	break;
+#ifdef PICT_TYPE_BGRA
+    case PICT_b8g8r8a8:
+    case PICT_b8g8r8x8:
+	output_fmt = (R300_OUT_FMT_C4_8 |
+		      R300_OUT_FMT_C0_SEL_ALPHA |
+		      R300_OUT_FMT_C1_SEL_RED |
+		      R300_OUT_FMT_C2_SEL_GREEN |
+		      R300_OUT_FMT_C3_SEL_BLUE);
+	break;
+#endif
     case PICT_a8:
 	output_fmt = (R300_OUT_FMT_C4_8 |
 		      R300_OUT_FMT_C0_SEL_ALPHA);
commit 4b4ce36081ca151c24e028c54b59986f41731a73
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Sat Oct 3 16:33:32 2009 +0200

    R3/5xx EXA: Minimise number of draw primitives used for Composite operations.
    
    This should reduce the kernel CS checker overhead, if nothing else.
    
    I'll leave porting this to other chipset families to others who can test it.

diff --git a/src/radeon.h b/src/radeon.h
index db7b26b..0322bf0 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -687,6 +687,9 @@ struct radeon_accel_state {
     /* Size of tiles ... set to 65536x65536 if not tiling in that direction */
     Bool              src_tile_width;
     Bool              src_tile_height;
+    uint32_t          *draw_header;
+    unsigned          vtx_count;
+    unsigned          num_vtx;
 
     Bool              vsync;
 
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 6053eef..c266fb7 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -2041,6 +2041,16 @@ static void FUNC_NAME(RadeonDoneComposite)(PixmapPtr pDst)
     ENTER_DRAW(0);
 
     if (IS_R300_3D || IS_R500_3D) {
+	if (info->accel_state->draw_header) {
+		info->accel_state->draw_header[0] = CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
+							       info->accel_state->num_vtx *
+							       info->accel_state->vtx_count);
+		info->accel_state->draw_header[1] = RADEON_CP_VC_CNTL_PRIM_TYPE_QUAD_LIST |
+		    RADEON_CP_VC_CNTL_PRIM_WALK_RING |
+		    (info->accel_state->num_vtx << RADEON_CP_VC_CNTL_NUM_SHIFT);
+		info->accel_state->draw_header = NULL;
+	}
+
 	BEGIN_ACCEL(3);
 	OUT_ACCEL_REG(R300_SC_CLIP_RULE, 0xAAAA);
 	OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_RB3D_DC_FLUSH_ALL);
@@ -2126,8 +2136,10 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
     /* ErrorF("RadeonComposite (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n",
        srcX, srcY, maskX, maskY,dstX, dstY, w, h); */
 
-#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
-    if (info->cs && CS_FULL(info->cs)) {
+#if defined(ACCEL_CP)
+    if ((info->cs && CS_FULL(info->cs)) ||
+	(!info->cs && (info->cp->indirectBuffer->used + 4 * 32) >
+	 info->cp->indirectBuffer->total)) {
 	FUNC_NAME(RadeonDoneComposite)(info->accel_state->dst_pix);
 	radeon_cs_flush_indirect(pScrn);
 	info->accel_state->exa->PrepareComposite(info->accel_state->composite_op,
@@ -2202,12 +2214,26 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
 		 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
 		 (3 << RADEON_CP_VC_CNTL_NUM_SHIFT));
     } else if (IS_R300_3D || IS_R500_3D) {
-	BEGIN_RING(4 * vtx_count + 4);
-	OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
-			    4 * vtx_count));
-	OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_QUAD_LIST |
-		 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
-		 (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
+	if (!info->accel_state->draw_header) {
+	    BEGIN_RING(2);
+
+	    if (info->cs)
+		info->accel_state->draw_header = info->cs->packets + info->cs->cdw;
+	    else
+		info->accel_state->draw_header = __head;
+	    info->accel_state->num_vtx = 0;
+	    info->accel_state->vtx_count = vtx_count;
+
+	    OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
+				4 * vtx_count));
+	    OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_QUAD_LIST |
+		     RADEON_CP_VC_CNTL_PRIM_WALK_RING |
+		     (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
+	    ADVANCE_RING();
+	}
+
+	info->accel_state->num_vtx += 4;
+	BEGIN_RING(4 * vtx_count);
     } else {
 	BEGIN_RING(3 * vtx_count + 2);
 	OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
@@ -2267,10 +2293,6 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
 		xFixedToFloat(srcTopRight.x) / info->accel_state->texW[0],     xFixedToFloat(srcTopRight.y) / info->accel_state->texH[0]);
     }
 
-    if (IS_R300_3D || IS_R500_3D)
-	/* flushing is pipelined, free/finish is not */
-	OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D);
-
 #ifdef ACCEL_CP
     ADVANCE_RING();
 #else
commit eade1e5be159c9f2965d611925596d33cab11d6d
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Sat Oct 3 16:33:32 2009 +0200

    EXA: Don't always flush when switching between 2D/3D engines with KMS.
    
    This seems to work fine here now and help 2D performance quite a bit, let's see
    if it breaks anybody else's setup...

diff --git a/src/radeon.h b/src/radeon.h
index e4f5334..db7b26b 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -1532,9 +1532,13 @@ do {									\
 	uint32_t flush = 0;                                             \
 	switch (info->accel_state->engineMode) {			\
 	case EXA_ENGINEMODE_UNKNOWN:					\
-	case EXA_ENGINEMODE_3D:						\
 	    flush = 1;                                                  \
+	    break;							\
+	case EXA_ENGINEMODE_3D:						\
+	    flush = !info->cs || CS_FULL(info->cs);			\
+	    break;							\
 	case EXA_ENGINEMODE_2D:						\
+	    flush = info->cs && CS_FULL(info->cs);			\
 	    break;							\
 	}								\
 	if (flush) {							\
@@ -1555,7 +1559,9 @@ do {									\
 	    break;							\
 	case EXA_ENGINEMODE_2D:						\
 	    flush = !info->cs || CS_FULL(info->cs);			\
+	    break;							\
 	case EXA_ENGINEMODE_3D:						\
+	    flush = info->cs && CS_FULL(info->cs);			\
 	    break;							\
 	}								\
 	if (flush) {							\
commit 926e414fc835ace141c066830d11d8ce32dbb06c
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Sat Oct 3 16:33:32 2009 +0200

    KMS: Double-buffer textured video source image upload.
    
    In order to avoid stalling on previous frame.
    
    OTOH without KMS we can't do this but have to wait for the previous frame to
    finish rendering.

diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index 5e6c561..ab3c498 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -224,7 +224,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     if (info->cs) {
 	accel_state->dst_mc_addr = 0;
 	accel_state->src_mc_addr[0] = 0;
-	accel_state->src_bo[0] = pPriv->src_bo;
+	accel_state->src_bo[0] = pPriv->src_bo[pPriv->currentBuffer];
 	accel_state->src_bo[1] = NULL;
 	accel_state->dst_bo = radeon_get_pixmap_bo(pPixmap);
 
diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c
index b708f52..04a2401 100644
--- a/src/radeon_textured_video.c
+++ b/src/radeon_textured_video.c
@@ -319,16 +319,19 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
 	if (info->ChipFamily >= CHIP_FAMILY_R600)
 	    pPriv->video_offset = radeon_legacy_allocate_memory(pScrn,
 								&pPriv->video_memory,
-								size * 2, 256);
+								size, 256);
 	else
 	    pPriv->video_offset = radeon_legacy_allocate_memory(pScrn,
 								&pPriv->video_memory,
-								size * 2, 64);
+								size, 64);
 	if (pPriv->video_offset == 0)
 	    return BadAlloc;
 
-	if (info->cs)
-	    pPriv->src_bo = pPriv->video_memory;
+	if (info->cs) {
+	    pPriv->src_bo[0] = pPriv->video_memory;
+	    radeon_legacy_allocate_memory(pScrn, (void*)&pPriv->src_bo[1], size,
+					  info->ChipFamily >= CHIP_FAMILY_R600 ? 256 : 64);
+	}
     }
 
     /* Bicubic filter loading */
@@ -366,14 +369,21 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
 
     pPriv->src_offset = pPriv->video_offset;
     if (info->cs) {
+	struct radeon_bo *src_bo;
 	int ret;
-	ret = radeon_bo_map(pPriv->src_bo, 1);
+
+	pPriv->currentBuffer ^= 1;
+
+	src_bo = pPriv->src_bo[pPriv->currentBuffer];
+
+	ret = radeon_bo_map(src_bo, 1);
 	if (ret)
 	    return BadAlloc;
 
-	pPriv->src_addr = pPriv->src_bo->ptr;
+	pPriv->src_addr = src_bo->ptr;
     } else {
 	pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset);
+	RADEONWaitForIdleMMIO(pScrn);
     }
     pPriv->src_pitch = dstPitch;
 
@@ -460,7 +470,7 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
 
 #if defined(XF86DRM_MODE)
     if (info->cs)
-	radeon_bo_unmap(pPriv->src_bo);
+	radeon_bo_unmap(pPriv->src_bo[pPriv->currentBuffer]);
 #endif
 #ifdef XF86DRI
     if (info->directRenderingEnabled) {
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index d26e7c0..8b55efc 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -93,6 +93,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
     RADEONInfoPtr info = RADEONPTR(pScrn);
     PixmapPtr pPixmap = pPriv->pPixmap;
     struct radeon_exa_pixmap_priv *driver_priv;
+    struct radeon_bo *src_bo = pPriv->src_bo[pPriv->currentBuffer];
     uint32_t txformat, txsize, txpitch, txoffset;
     uint32_t dst_pitch, dst_format;
     uint32_t colorpitch;
@@ -107,7 +108,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	int ret;
 
 	radeon_cs_space_reset_bos(info->cs);
-        radeon_cs_space_add_persistent_bo(info->cs, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+        radeon_cs_space_add_persistent_bo(info->cs, src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	if (pPriv->bicubic_enabled)
 	    radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
@@ -237,7 +238,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		      RADEON_CLAMP_T_CLAMP_LAST |
 		      RADEON_YUV_TO_RGB);
 	OUT_ACCEL_REG(RADEON_PP_TXFORMAT_0, txformat | RADEON_TXFORMAT_ST_ROUTE_STQ0);
-	OUT_TEXTURE_REG(RADEON_PP_TXOFFSET_0, txoffset, pPriv->src_bo);
+	OUT_TEXTURE_REG(RADEON_PP_TXOFFSET_0, txoffset, src_bo);
 	OUT_ACCEL_REG(RADEON_PP_TXCBLEND_0,
 		      RADEON_COLOR_ARG_A_ZERO |
 		      RADEON_COLOR_ARG_B_ZERO |
@@ -264,7 +265,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		      RADEON_CLAMP_S_CLAMP_LAST |
 		      RADEON_CLAMP_T_CLAMP_LAST);
 	OUT_ACCEL_REG(RADEON_PP_TXFORMAT_1, txformat | RADEON_TXFORMAT_ST_ROUTE_STQ1);
-	OUT_TEXTURE_REG(RADEON_PP_TXOFFSET_1, txoffset + pPriv->planeu_offset, pPriv->src_bo);
+	OUT_TEXTURE_REG(RADEON_PP_TXOFFSET_1, txoffset + pPriv->planeu_offset, src_bo);
 	OUT_ACCEL_REG(RADEON_PP_TXCBLEND_1,
 		      RADEON_COLOR_ARG_A_ZERO |
 		      RADEON_COLOR_ARG_B_ZERO |
@@ -288,7 +289,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		      RADEON_CLAMP_S_CLAMP_LAST |
 		      RADEON_CLAMP_T_CLAMP_LAST);
 	OUT_ACCEL_REG(RADEON_PP_TXFORMAT_2, txformat | RADEON_TXFORMAT_ST_ROUTE_STQ1);
-	OUT_TEXTURE_REG(RADEON_PP_TXOFFSET_2, txoffset + pPriv->planev_offset, pPriv->src_bo);
+	OUT_TEXTURE_REG(RADEON_PP_TXOFFSET_2, txoffset + pPriv->planev_offset, src_bo);
 	OUT_ACCEL_REG(RADEON_PP_TXCBLEND_2,
 		      RADEON_COLOR_ARG_A_ZERO |
 		      RADEON_COLOR_ARG_B_ZERO |
@@ -321,7 +322,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		      RADEON_CLAMP_T_CLAMP_LAST |
 		      RADEON_YUV_TO_RGB);
 	OUT_ACCEL_REG(RADEON_PP_TXFORMAT_0, txformat | RADEON_TXFORMAT_ST_ROUTE_STQ0);
-	OUT_TEXTURE_REG(RADEON_PP_TXOFFSET_0, txoffset, pPriv->src_bo);
+	OUT_TEXTURE_REG(RADEON_PP_TXOFFSET_0, txoffset, src_bo);
 	OUT_ACCEL_REG(RADEON_PP_TXCBLEND_0,
 		      RADEON_COLOR_ARG_A_ZERO |
 		      RADEON_COLOR_ARG_B_ZERO |
@@ -468,6 +469,7 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     RADEONInfoPtr info = RADEONPTR(pScrn);
     PixmapPtr pPixmap = pPriv->pPixmap;
     struct radeon_exa_pixmap_priv *driver_priv;
+    struct radeon_bo *src_bo = pPriv->src_bo[pPriv->currentBuffer];
     uint32_t txformat;
     uint32_t txfilter, txsize, txpitch, txoffset;
     uint32_t dst_pitch, dst_format;
@@ -493,7 +495,7 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	int ret;
 
 	radeon_cs_space_reset_bos(info->cs);
-        radeon_cs_space_add_persistent_bo(info->cs, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+        radeon_cs_space_add_persistent_bo(info->cs, src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	if (pPriv->bicubic_enabled)
 	    radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
@@ -660,21 +662,21 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 		      (pPriv->w - 1) |
 		      ((pPriv->h - 1) << RADEON_TEX_VSIZE_SHIFT));
 	OUT_ACCEL_REG(R200_PP_TXPITCH_0, pPriv->src_pitch - 32);
-	OUT_TEXTURE_REG(R200_PP_TXOFFSET_0, txoffset, pPriv->src_bo);
+	OUT_TEXTURE_REG(R200_PP_TXOFFSET_0, txoffset, src_bo);
 
 	OUT_ACCEL_REG(R200_PP_TXFILTER_1, txfilter);
 	OUT_ACCEL_REG(R200_PP_TXFORMAT_1, txformat | R200_TXFORMAT_ST_ROUTE_STQ1);
 	OUT_ACCEL_REG(R200_PP_TXFORMAT_X_1, 0);
 	OUT_ACCEL_REG(R200_PP_TXSIZE_1, txsize);
 	OUT_ACCEL_REG(R200_PP_TXPITCH_1, txpitch);
-	OUT_TEXTURE_REG(R200_PP_TXOFFSET_1, txoffset + pPriv->planeu_offset, pPriv->src_bo);
+	OUT_TEXTURE_REG(R200_PP_TXOFFSET_1, txoffset + pPriv->planeu_offset, src_bo);
 
 	OUT_ACCEL_REG(R200_PP_TXFILTER_2, txfilter);
 	OUT_ACCEL_REG(R200_PP_TXFORMAT_2, txformat | R200_TXFORMAT_ST_ROUTE_STQ1);
 	OUT_ACCEL_REG(R200_PP_TXFORMAT_X_2, 0);
 	OUT_ACCEL_REG(R200_PP_TXSIZE_2, txsize);
 	OUT_ACCEL_REG(R200_PP_TXPITCH_2, txpitch);
-	OUT_TEXTURE_REG(R200_PP_TXOFFSET_2, txoffset + pPriv->planev_offset, pPriv->src_bo);
+	OUT_TEXTURE_REG(R200_PP_TXOFFSET_2, txoffset + pPriv->planev_offset, src_bo);
 
 	/* similar to r300 code. Note the big problem is that hardware constants
 	 * are 8 bits only, representing 0.0-1.0. We can get that up (using bias
@@ -816,7 +818,7 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 		      (pPriv->w - 1) |
 		      ((pPriv->h - 1) << RADEON_TEX_VSIZE_SHIFT));
 	OUT_ACCEL_REG(R200_PP_TXPITCH_0, pPriv->src_pitch - 32);
-	OUT_TEXTURE_REG(R200_PP_TXOFFSET_0, txoffset, pPriv->src_bo);
+	OUT_TEXTURE_REG(R200_PP_TXOFFSET_0, txoffset, src_bo);
 
 	/* MAD temp1 / 2, const0.a * 2, temp0.ggg, -const0.rgb */
 	OUT_ACCEL_REG(R200_PP_TXCBLEND_0,
@@ -1017,6 +1019,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     RADEONInfoPtr info = RADEONPTR(pScrn);
     PixmapPtr pPixmap = pPriv->pPixmap;
     struct radeon_exa_pixmap_priv *driver_priv;
+    struct radeon_bo *src_bo = pPriv->src_bo[pPriv->currentBuffer];
     uint32_t txfilter, txformat0, txformat1, txoffset, txpitch;
     uint32_t dst_pitch, dst_format;
     uint32_t txenable, colorpitch, bicubic_offset;
@@ -1032,7 +1035,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	int ret;
 
 	radeon_cs_space_reset_bos(info->cs);
-	radeon_cs_space_add_persistent_bo(info->cs, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_add_persistent_bo(info->cs, src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	if (pPriv->bicubic_enabled)
 	  radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
@@ -1161,7 +1164,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     else
 	OUT_ACCEL_REG(R300_TX_FORMAT1_0, txformat1);
     OUT_ACCEL_REG(R300_TX_FORMAT2_0, txpitch);
-    OUT_TEXTURE_REG(R300_TX_OFFSET_0, txoffset, pPriv->src_bo);
+    OUT_TEXTURE_REG(R300_TX_OFFSET_0, txoffset, src_bo);
     FINISH_ACCEL();
 
     txenable = R300_TEX_0_ENABLE;
@@ -1183,13 +1186,13 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	OUT_ACCEL_REG(R300_TX_FORMAT0_1, txformat0);
 	OUT_ACCEL_REG(R300_TX_FORMAT1_1, R300_TX_FORMAT_X8 | R300_TX_FORMAT_CACHE_FOURTH_REGION_2);
 	OUT_ACCEL_REG(R300_TX_FORMAT2_1, txpitch);
-	OUT_TEXTURE_REG(R300_TX_OFFSET_1, txoffset + pPriv->planeu_offset, pPriv->src_bo);
+	OUT_TEXTURE_REG(R300_TX_OFFSET_1, txoffset + pPriv->planeu_offset, src_bo);
 	OUT_ACCEL_REG(R300_TX_FILTER0_2, txfilter | (2 << R300_TX_ID_SHIFT));
 	OUT_ACCEL_REG(R300_TX_FILTER1_2, 0);
 	OUT_ACCEL_REG(R300_TX_FORMAT0_2, txformat0);
 	OUT_ACCEL_REG(R300_TX_FORMAT1_2, R300_TX_FORMAT_X8 | R300_TX_FORMAT_CACHE_FOURTH_REGION_3);
 	OUT_ACCEL_REG(R300_TX_FORMAT2_2, txpitch);
-	OUT_TEXTURE_REG(R300_TX_OFFSET_2, txoffset + pPriv->planev_offset, pPriv->src_bo);
+	OUT_TEXTURE_REG(R300_TX_OFFSET_2, txoffset + pPriv->planev_offset, src_bo);
 	FINISH_ACCEL();
 	txenable |= R300_TEX_1_ENABLE | R300_TEX_2_ENABLE;
     }
@@ -2465,6 +2468,7 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     RADEONInfoPtr info = RADEONPTR(pScrn);
     PixmapPtr pPixmap = pPriv->pPixmap;
     struct radeon_exa_pixmap_priv *driver_priv;
+    struct radeon_bo *src_bo = pPriv->src_bo[pPriv->currentBuffer];
     uint32_t txfilter, txformat0, txformat1, txoffset, txpitch;
     uint32_t dst_pitch, dst_format;
     uint32_t txenable, colorpitch, bicubic_offset;
@@ -2480,7 +2484,7 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	int ret;
 
 	radeon_cs_space_reset_bos(info->cs);
-	radeon_cs_space_add_persistent_bo(info->cs, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_add_persistent_bo(info->cs, src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	if (pPriv->bicubic_enabled)
 	    radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
@@ -2612,7 +2616,7 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     OUT_ACCEL_REG(R300_TX_FORMAT0_0, txformat0);
     OUT_ACCEL_REG(R300_TX_FORMAT1_0, txformat1);
     OUT_ACCEL_REG(R300_TX_FORMAT2_0, txpitch);
-    OUT_TEXTURE_REG(R300_TX_OFFSET_0, txoffset, pPriv->src_bo);
+    OUT_TEXTURE_REG(R300_TX_OFFSET_0, txoffset, src_bo);
     FINISH_ACCEL();
 
     txenable = R300_TEX_0_ENABLE;
diff --git a/src/radeon_video.h b/src/radeon_video.h
index 989942c..1b8f684 100644
--- a/src/radeon_video.h
+++ b/src/radeon_video.h
@@ -119,7 +119,7 @@ typedef struct {
     int src_x, src_y;
     int vsync;
 
-    struct radeon_bo *src_bo;
+    struct radeon_bo *src_bo[2];
 } RADEONPortPrivRec, *RADEONPortPrivPtr;
 
 /* Reference color space transform data */
commit 6a3b75fae4147244212298ff55c7ab36c3d80d30
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Sat Oct 3 16:33:31 2009 +0200

    KMS: Don't hide HW cursor when it's updated.
    
    Inspired by the intel driver; might avoid/reduce HW cursor flicker in some
    cases.

diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 94e6272..bd6020b 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -479,6 +479,7 @@ static Bool RADEONCursorInit_KMS(ScreenPtr pScreen)
 			      (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
 			       HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
 			       HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
+			       HARDWARE_CURSOR_UPDATE_UNHIDDEN |
 			       HARDWARE_CURSOR_ARGB));
 }
 
commit c4ba15b4871c70cced7f1761e24be692cdb28d2b
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Sat Oct 3 16:33:31 2009 +0200

    Fix some compiler warnings.

diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index fa49392..94e6272 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -181,7 +181,7 @@ static Bool RADEONIsAccelWorking(ScrnInfoPtr pScrn)
 
     memset(&ginfo, 0, sizeof(ginfo));
     ginfo.request = 0x3;
-    ginfo.value = (uint64_t)&tmp;
+    ginfo.value = (uintptr_t)&tmp;
     r = drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
     if (r)
         return FALSE;
@@ -434,7 +434,9 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
 	    info->gart_size = mminfo.gart_size;
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		       "mem size init: gart size :%llx vram size: s:%llx visible:%llx\n",
-		       mminfo.gart_size, mminfo.vram_size, mminfo.vram_visible);
+		       (unsigned long long)mminfo.gart_size,
+		       (unsigned long long)mminfo.vram_size,
+		       (unsigned long long)mminfo.vram_visible);
 	}
     }
 #if 0
commit cc45856a18dd3e6f7e44d9eb507b31419da70977
Author: Kenneth Graunke <kenny at whitecape.org>
Date:   Fri Oct 2 14:31:36 2009 -0400

    radeon: Remove gatos message from driver startup
    
    Remove a message on driver startup which directs people to the old GATOS
    website; said site contains highly out of date software which is no longer
    necessary.

diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 24ef513..e0ba9ba 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -3118,10 +3118,6 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
     info->MMIO = NULL;
 
     xf86DrvMsg(pScrn->scrnIndex, X_NOTICE,
-	       "For information on using the multimedia capabilities\n\tof this"
-	       " adapter, please see http://gatos.sf.net.\n");
-
-    xf86DrvMsg(pScrn->scrnIndex, X_NOTICE,
 	       "MergedFB support has been removed and replaced with"
 	       " xrandr 1.2 support\n");
 
commit d302481493ff61eb7f8648b7afe7407b6b653cf7
Author: Jerome Glisse <jglisse at redhat.com>
Date:   Wed Sep 16 15:18:40 2009 +0200

    radeon/kms: fallback to shadowfb if kernel report acceleration is off
    
    This will fallback to shadowfb is GPU accel failed somewhere during
    KMS kernel init.

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index e6b948c..c9037b4 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -183,7 +183,7 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 	int i;
 	int pitch = pScrn->displayWidth * info->CurrentLayout.pixel_bytes;
 
-	if (info->ChipFamily >= CHIP_FAMILY_R600)
+	if (info->accelOn == FALSE)
 		return;
 
 	for (i = 0; i < xf86_config->num_crtc; i++) {
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index e2f716e..fa49392 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -172,6 +172,24 @@ static void RADEONBlockHandler_KMS(int i, pointer blockData,
     radeon_cs_flush_indirect(pScrn);
 }
 
+static Bool RADEONIsAccelWorking(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    struct drm_radeon_info ginfo;
+    int r;
+    uint32_t tmp;
+
+    memset(&ginfo, 0, sizeof(ginfo));
+    ginfo.request = 0x3;
+    ginfo.value = (uint64_t)&tmp;
+    r = drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
+    if (r)
+        return FALSE;
+    if (tmp)
+        return TRUE;
+    return FALSE;
+}
+
 static Bool RADEONPreInitAccel_KMS(ScrnInfoPtr pScrn)
 {
     RADEONInfoPtr  info = RADEONPTR(pScrn);
@@ -180,16 +198,14 @@ static Bool RADEONPreInitAccel_KMS(ScrnInfoPtr pScrn)
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to allocate accel_state rec!\n");
 	return FALSE;
     }
-#if 0
-    if (info->ChipFamily >= CHIP_FAMILY_R600) {
+    if (!RADEONIsAccelWorking(pScrn)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Using shadowfb for KMS on R600+\n");
+		   "GPU accel not working, using shadowfb for KMS\n");
 	info->r600_shadow_fb = TRUE;
 	if (!xf86LoadSubModule(pScrn, "shadow"))
 	    info->r600_shadow_fb = FALSE;
 	return TRUE;
     }
-#endif
 
     if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
 	(info->ChipFamily == CHIP_FAMILY_RS200) ||
@@ -421,12 +437,12 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
 		       mminfo.gart_size, mminfo.vram_size, mminfo.vram_visible);
 	}
     }
-
+#if 0
     if (info->ChipFamily < CHIP_FAMILY_R600) {
 	info->useEXA = TRUE;
 	info->directRenderingEnabled = TRUE;
     }
-
+#endif
     RADEONSetPitch(pScrn);
 
     /* Set display resolution */
@@ -663,6 +679,10 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
 		   "Direct rendering disabled\n");
     }
 
+    if (info->r600_shadow_fb) {
+        xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
+        info->accelOn = FALSE;
+    } else {
     if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
 	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		       "Initializing Acceleration\n");
@@ -679,6 +699,7 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
 	xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
 	info->accelOn = FALSE;
     }
+    }
 
     /* Init DPMS */
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
@@ -706,11 +727,12 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
      */
     /* xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset); */
 #endif
-
-    /* Init Xv */
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Initializing Xv\n");
-    RADEONInitVideo(pScreen);
+    if (info->r600_shadow_fb == FALSE) {
+        /* Init Xv */
+        xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+                       "Initializing Xv\n");
+        RADEONInitVideo(pScreen);
+    }
 
     if (info->r600_shadow_fb == TRUE) {
         if (!shadowSetup(pScreen)) {
@@ -770,7 +792,6 @@ Bool RADEONEnterVT_KMS(int scrnIndex, int flags)
     ret = drmSetMaster(info->dri->drmFD);
     if (ret)
 	ErrorF("Unable to retrieve master\n");
-
     info->accel_state->XInited3D = FALSE;
     info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
 
commit 7968e1fb89f6b59d1654df48249bf4b81990c008
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Fri Sep 25 19:05:38 2009 -0400

    radeon: fix segfault in MMIO path in RADEONInit3DEngine
    
    fixes fdo bug 24158.
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index c0625c4..8c46235 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -82,7 +82,7 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 	case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break;
 	}
 
-	if (info->dri->pKernelDRMVersion->version_major < 2) {
+	if (!info->cs) {
 	    size = (info->ChipFamily >= CHIP_FAMILY_R420) ? 5 : 4;
 	    BEGIN_ACCEL(size);
 	    OUT_ACCEL_REG(R300_GB_TILE_CONFIG, gb_tile_config);
@@ -95,8 +95,8 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 	}
 
 	if (IS_R500_3D) {
-	    su_reg_dest = ((1 << info->accel_state->num_gb_pipes) - 1);
-	    if (info->dri->pKernelDRMVersion->version_major < 2) {
+	    if (!info->cs) {
+		su_reg_dest = ((1 << info->accel_state->num_gb_pipes) - 1);
 		BEGIN_ACCEL(2);
 		OUT_ACCEL_REG(R500_SU_REG_DEST, su_reg_dest);
 		OUT_ACCEL_REG(R500_VAP_INDEX_OFFSET, 0);
@@ -116,7 +116,7 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 	OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, R300_ZC_FLUSH | R300_ZC_FREE);
 	FINISH_ACCEL();
 
-	if (info->dri->pKernelDRMVersion->version_major < 2) {
+	if (!info->cs) {
 	    BEGIN_ACCEL(3);
 	    OUT_ACCEL_REG(R300_GB_MSPOS0, ((6 << R300_MS_X0_SHIFT) |
 					   (6 << R300_MS_Y0_SHIFT) |
commit 0380a9cf98d34e88dd81370ade5525680ec89c02
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Fri Sep 25 16:46:43 2009 -0400

    kms/r600: add support for vline relocs
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index f5e6bce..8377ae5 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -318,12 +318,6 @@ void cp_wait_vline_sync(ScrnInfoPtr pScrn, drmBufPtr ib, PixmapPtr pPix,
     RADEONInfoPtr  info = RADEONPTR(pScrn);
     uint32_t offset;
 
-    //XXX FIXME
-#if defined(XF86DRM_MODE)
-    if (info->cs)
-	return;
-#endif
-
     if (!crtc)
         return;
 
@@ -333,7 +327,10 @@ void cp_wait_vline_sync(ScrnInfoPtr pScrn, drmBufPtr ib, PixmapPtr pPix,
     if (!crtc->enabled)
         return;
 
-    {
+    if (info->cs) {
+        if (pPix != pScrn->pScreen->GetScreenPixmap(pScrn->pScreen))
+	    return;
+    } else {
 #ifdef USE_EXA
 	if (info->useEXA)
 	    offset = exaGetPixmapOffset(pPix);
@@ -352,10 +349,34 @@ void cp_wait_vline_sync(ScrnInfoPtr pScrn, drmBufPtr ib, PixmapPtr pPix,
     if (start > crtc->mode.VDisplay)
         return;
 
+#if defined(XF86DRM_MODE)
+    if (info->cs) {
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+	BEGIN_BATCH(11);
+	/* set the VLINE range */
+	EREG(ib, AVIVO_D1MODE_VLINE_START_END, /* this is just a marker */
+	     (start << AVIVO_D1MODE_VLINE_START_SHIFT) |
+	     (stop << AVIVO_D1MODE_VLINE_END_SHIFT));
+
+	/* tell the CP to poll the VLINE state register */
+	PACK3(ib, IT_WAIT_REG_MEM, 6);
+	E32(ib, IT_WAIT_REG | IT_WAIT_EQ);
+	E32(ib, IT_WAIT_ADDR(AVIVO_D1MODE_VLINE_STATUS));
+	E32(ib, 0);
+	E32(ib, 0);                          // Ref value
+	E32(ib, AVIVO_D1MODE_VLINE_STAT);    // Mask
+	E32(ib, 10);                         // Wait interval
+	/* add crtc reloc */
+	PACK3(ib, IT_NOP, 1);
+	E32(ib, drmmode_crtc->mode_crtc->crtc_id);
+	END_BATCH();
+    } else
+#endif
     {
 	RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
 
-	BEGIN_BATCH(10);
+	BEGIN_BATCH(9);
 	/* set the VLINE range */
 	EREG(ib, AVIVO_D1MODE_VLINE_START_END + radeon_crtc->crtc_offset,
 	     (start << AVIVO_D1MODE_VLINE_START_SHIFT) |
commit 3efecebb10de7f7bacf9f8c57ae20fd508097294
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Fri Sep 25 14:44:41 2009 -0400

    radeon: fix vline handling for kms
    
    drm crtc ids do not correspond to actual hw crtcs,
    as such the vline stuff was never enabled for Xv.
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/r600_state.h b/src/r600_state.h
index cb039d4..46c18f9 100644
--- a/src/r600_state.h
+++ b/src/r600_state.h
@@ -286,7 +286,7 @@ void
 cp_set_surface_sync(ScrnInfoPtr pScrn, drmBufPtr ib, uint32_t sync_type, uint32_t size, uint64_t mc_addr,
 		    struct radeon_bo *bo, uint32_t rdomains, uint32_t wdomain);
 void
-cp_wait_vline_sync(ScrnInfoPtr pScrn, drmBufPtr ib, PixmapPtr pPix, int crtc, int start, int stop);
+cp_wait_vline_sync(ScrnInfoPtr pScrn, drmBufPtr ib, PixmapPtr pPix, xf86CrtcPtr crtc, int start, int stop);
 void
 fs_setup(ScrnInfoPtr pScrn, drmBufPtr ib, shader_config_t *fs_conf);
 void
diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index e30cfcb..5e6c561 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -579,14 +579,11 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 						    pPriv->drw_x + pPriv->dst_w,
 						    pPriv->drw_y,
 						    pPriv->drw_y + pPriv->dst_h);
-	if (crtc) {
-	    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
-
+	if (crtc)
 	    cp_wait_vline_sync(pScrn, accel_state->ib, pPixmap,
-			       radeon_crtc->crtc_id,
+			       crtc,
 			       pPriv->drw_y - crtc->y,
 			       (pPriv->drw_y - crtc->y) + pPriv->dst_h);
-	}
     }
 
     while (nBox--) {
diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index 0e2f8a9..f5e6bce 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -313,12 +313,10 @@ cp_set_surface_sync(ScrnInfoPtr pScrn, drmBufPtr ib, uint32_t sync_type, uint32_
 
 /* inserts a wait for vline in the command stream */
 void cp_wait_vline_sync(ScrnInfoPtr pScrn, drmBufPtr ib, PixmapPtr pPix,
-	int crtc, int start, int stop)
+			xf86CrtcPtr crtc, int start, int stop)
 {
     RADEONInfoPtr  info = RADEONPTR(pScrn);
-    xf86CrtcConfigPtr  xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     uint32_t offset;
-    RADEONCrtcPrivatePtr radeon_crtc;
 
     //XXX FIXME
 #if defined(XF86DRM_MODE)
@@ -326,49 +324,53 @@ void cp_wait_vline_sync(ScrnInfoPtr pScrn, drmBufPtr ib, PixmapPtr pPix,
 	return;
 #endif
 
-    if ((crtc < 0) || (crtc > 1))
+    if (!crtc)
         return;
 
     if (stop < start)
         return;
 
-    if (!xf86_config->crtc[crtc]->enabled)
+    if (!crtc->enabled)
         return;
 
+    {
 #ifdef USE_EXA
-    if (info->useEXA)
-        offset = exaGetPixmapOffset(pPix);
-    else
+	if (info->useEXA)
+	    offset = exaGetPixmapOffset(pPix);
+	else
 #endif
-        offset = pPix->devPrivate.ptr - info->FB;
+	    offset = pPix->devPrivate.ptr - info->FB;
 
-    /* if drawing to front buffer */
-    if (offset != 0)
-        return;
+	/* if drawing to front buffer */
+	if (offset != 0)
+	    return;
+    }
 
     start = max(start, 0);
-    stop = min(stop, xf86_config->crtc[crtc]->mode.VDisplay);
+    stop = min(stop, crtc->mode.VDisplay);
 
-    if (start > xf86_config->crtc[crtc]->mode.VDisplay)
+    if (start > crtc->mode.VDisplay)
         return;
 
-    radeon_crtc = xf86_config->crtc[crtc]->driver_private;
-
-    BEGIN_BATCH(10);
-    /* set the VLINE range */
-    EREG(ib, AVIVO_D1MODE_VLINE_START_END + radeon_crtc->crtc_offset,
-         (start << AVIVO_D1MODE_VLINE_START_SHIFT) |
-         (stop << AVIVO_D1MODE_VLINE_END_SHIFT));
-
-    /* tell the CP to poll the VLINE state register */
-    PACK3(ib, IT_WAIT_REG_MEM, 6);
-    E32(ib, IT_WAIT_REG | IT_WAIT_EQ);
-    E32(ib, IT_WAIT_ADDR(AVIVO_D1MODE_VLINE_STATUS + radeon_crtc->crtc_offset));
-    E32(ib, 0);
-    E32(ib, 0);                          // Ref value
-    E32(ib, AVIVO_D1MODE_VLINE_STAT);    // Mask
-    E32(ib, 10);                         // Wait interval
-    END_BATCH();
+    {
+	RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
+
+	BEGIN_BATCH(10);
+	/* set the VLINE range */
+	EREG(ib, AVIVO_D1MODE_VLINE_START_END + radeon_crtc->crtc_offset,
+	     (start << AVIVO_D1MODE_VLINE_START_SHIFT) |
+	     (stop << AVIVO_D1MODE_VLINE_END_SHIFT));
+
+	/* tell the CP to poll the VLINE state register */
+	PACK3(ib, IT_WAIT_REG_MEM, 6);
+	E32(ib, IT_WAIT_REG | IT_WAIT_EQ);
+	E32(ib, IT_WAIT_ADDR(AVIVO_D1MODE_VLINE_STATUS + radeon_crtc->crtc_offset));
+	E32(ib, 0);
+	E32(ib, 0);                          // Ref value
+	E32(ib, AVIVO_D1MODE_VLINE_STAT);    // Mask
+	E32(ib, 10);                         // Wait interval
+	END_BATCH();
+    }
 }
 
 void
diff --git a/src/radeon.h b/src/radeon.h
index fc21955..e4f5334 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -1111,11 +1111,11 @@ extern Bool radeon_card_posted(ScrnInfoPtr pScrn);
 #ifdef XF86DRI
 extern void RADEONWaitForIdleCP(ScrnInfoPtr pScrn);
 extern void RADEONWaitForVLineCP(ScrnInfoPtr pScrn, PixmapPtr pPix,
-	int crtc, int start, int stop);
+				 xf86CrtcPtr crtc, int start, int stop);
 #endif
 extern void RADEONWaitForIdleMMIO(ScrnInfoPtr pScrn);
 extern void RADEONWaitForVLineMMIO(ScrnInfoPtr pScrn, PixmapPtr pPix,
-	int crtc, int start, int stop);
+				   xf86CrtcPtr crtc, int start, int stop);
 
 /* radeon_crtc.c */
 extern void radeon_crtc_dpms(xf86CrtcPtr crtc, int mode);
diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index 6387e4f..c0625c4 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -825,55 +825,21 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 
 }
 
-#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
-void drmmode_wait_for_vline(ScrnInfoPtr pScrn, PixmapPtr pPix,
-			    int crtc, int start, int stop)
-{
-    RADEONInfoPtr  info = RADEONPTR(pScrn);
-    xf86CrtcConfigPtr  xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[crtc]->driver_private;
-    ACCEL_PREAMBLE();
-
-    BEGIN_ACCEL(3);
-
-    if (IS_AVIVO_VARIANT) {
-	uint32_t reg = AVIVO_D1MODE_VLINE_START_END; /* this is just a marker */
-	OUT_ACCEL_REG(reg,
-		      ((start << AVIVO_D1MODE_VLINE_START_SHIFT) |
-		       (stop << AVIVO_D1MODE_VLINE_END_SHIFT) |
-		       AVIVO_D1MODE_VLINE_INV));
-    } else {
-	OUT_ACCEL_REG(RADEON_CRTC_GUI_TRIG_VLINE, /* another placeholder */
-		      ((start << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
-		      (stop << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
-		      RADEON_CRTC_GUI_TRIG_VLINE_INV |
-		      RADEON_CRTC_GUI_TRIG_VLINE_STALL));
-    }
-    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
-				      RADEON_ENG_DISPLAY_SELECT_CRTC0));
-
-    OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_NOP, 0));
-    OUT_RING(drmmode_crtc->mode_crtc->crtc_id);
-    FINISH_ACCEL();
-}
-#endif
-
 /* inserts a wait for vline in the command stream */
 void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix,
-	int crtc, int start, int stop)
+				   xf86CrtcPtr crtc, int start, int stop)
 {
     RADEONInfoPtr  info = RADEONPTR(pScrn);
-    xf86CrtcConfigPtr  xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     uint32_t offset;
     ACCEL_PREAMBLE();
 
-    if ((crtc < 0) || (crtc > 1))
+    if (!crtc)
 	return;
 
     if (stop < start)
 	return;
 
-    if (!xf86_config->crtc[crtc]->enabled)
+    if (!crtc->enabled)
 	return;
 
     if (info->cs) {
@@ -893,50 +859,68 @@ void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix,
     }
 
     start = max(start, 0);
-    stop = min(stop, xf86_config->crtc[crtc]->mode.VDisplay);
+    stop = min(stop, crtc->mode.VDisplay);
 
-    if (start > xf86_config->crtc[crtc]->mode.VDisplay)
+    if (start > crtc->mode.VDisplay)
 	return;
 
 #if defined(ACCEL_CP) && defined(XF86DRM_MODE)
-    if (info->kms_enabled) {
-	drmmode_wait_for_vline(pScrn, pPix, crtc, start, stop);
-	return;
-    }
-#endif
-
-    BEGIN_ACCEL(2);
-
-    if (IS_AVIVO_VARIANT) {
-	RADEONCrtcPrivatePtr radeon_crtc = xf86_config->crtc[crtc]->driver_private;
+    if (info->cs) {
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 
-	OUT_ACCEL_REG(AVIVO_D1MODE_VLINE_START_END + radeon_crtc->crtc_offset,
-		      ((start << AVIVO_D1MODE_VLINE_START_SHIFT) |
-		       (stop << AVIVO_D1MODE_VLINE_END_SHIFT) |
-		       AVIVO_D1MODE_VLINE_INV));
-    } else {
-	if (crtc == 0)
-	    OUT_ACCEL_REG(RADEON_CRTC_GUI_TRIG_VLINE,
-			  ((start << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
-			   (stop << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
-			   RADEON_CRTC_GUI_TRIG_VLINE_INV |
-			   RADEON_CRTC_GUI_TRIG_VLINE_STALL));
-	else
-	    OUT_ACCEL_REG(RADEON_CRTC2_GUI_TRIG_VLINE,
+	BEGIN_ACCEL(3);
+	if (IS_AVIVO_VARIANT) {
+	    OUT_ACCEL_REG(AVIVO_D1MODE_VLINE_START_END, /* this is just a marker */
+			  ((start << AVIVO_D1MODE_VLINE_START_SHIFT) |
+			   (stop << AVIVO_D1MODE_VLINE_END_SHIFT) |
+			   AVIVO_D1MODE_VLINE_INV));
+	} else {
+	    OUT_ACCEL_REG(RADEON_CRTC_GUI_TRIG_VLINE, /* another placeholder */
 			  ((start << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
 			   (stop << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
 			   RADEON_CRTC_GUI_TRIG_VLINE_INV |
 			   RADEON_CRTC_GUI_TRIG_VLINE_STALL));
-    }
-
-    if (crtc == 0)
+	}
 	OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
 					  RADEON_ENG_DISPLAY_SELECT_CRTC0));
-    else
-	OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
-					  RADEON_ENG_DISPLAY_SELECT_CRTC1));
 
-    FINISH_ACCEL();
+	OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_NOP, 0));
+	OUT_RING(drmmode_crtc->mode_crtc->crtc_id);
+	FINISH_ACCEL();
+    } else
+#endif
+    {
+	RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
+
+	BEGIN_ACCEL(2);
+	if (IS_AVIVO_VARIANT) {
+	    OUT_ACCEL_REG(AVIVO_D1MODE_VLINE_START_END + radeon_crtc->crtc_offset,
+			  ((start << AVIVO_D1MODE_VLINE_START_SHIFT) |
+			   (stop << AVIVO_D1MODE_VLINE_END_SHIFT) |
+			   AVIVO_D1MODE_VLINE_INV));
+	} else {
+	    if (radeon_crtc->crtc_id == 0)
+		OUT_ACCEL_REG(RADEON_CRTC_GUI_TRIG_VLINE,
+			      ((start << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
+			       (stop << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
+			       RADEON_CRTC_GUI_TRIG_VLINE_INV |
+			       RADEON_CRTC_GUI_TRIG_VLINE_STALL));
+	    else
+		OUT_ACCEL_REG(RADEON_CRTC2_GUI_TRIG_VLINE,
+			      ((start << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
+			       (stop << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
+			       RADEON_CRTC_GUI_TRIG_VLINE_INV |
+			       RADEON_CRTC_GUI_TRIG_VLINE_STALL));
+	}
+
+	if (radeon_crtc->crtc_id == 0)
+	    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
+					      RADEON_ENG_DISPLAY_SELECT_CRTC0));
+	else
+	    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
+					      RADEON_ENG_DISPLAY_SELECT_CRTC1));
+	FINISH_ACCEL();
+    }
 }
 
 /* MMIO:
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 7b9164e..6cf9598 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -211,11 +211,12 @@ Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
  * syncing per-blit is unrealistic so,
  * we sync to whichever crtc has a larger area.
  */
-int RADEONBiggerCrtcArea(PixmapPtr pPix)
+xf86CrtcPtr RADEONBiggerCrtcArea(PixmapPtr pPix)
 {
     ScrnInfoPtr pScrn =  xf86Screens[pPix->drawable.pScreen->myNum];
     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int c, crtc_num = -1, area = 0;
+    int c, area = 0;
+    xf86CrtcPtr ret_crtc = NULL;
 
     for (c = 0; c < xf86_config->num_crtc; c++) {
 	xf86CrtcPtr crtc = xf86_config->crtc[c];
@@ -225,11 +226,11 @@ int RADEONBiggerCrtcArea(PixmapPtr pPix)
 
 	if ((crtc->mode.HDisplay * crtc->mode.VDisplay) > area) {
 	    area = crtc->mode.HDisplay * crtc->mode.VDisplay;
-	    crtc_num = c;
+	    ret_crtc = crtc;
 	}
     }
 
-    return crtc_num;
+    return ret_crtc;
 }
 
 #if X_BYTE_ORDER == X_BIG_ENDIAN
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index f069d8f..d26e7c0 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -355,14 +355,11 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 						    pPriv->drw_x + pPriv->dst_w,
 						    pPriv->drw_y,
 						    pPriv->drw_y + pPriv->dst_h);
-	if (crtc) {
-	    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
-
+	if (crtc)
 	    FUNC_NAME(RADEONWaitForVLine)(pScrn, pPixmap,
-					  radeon_crtc->crtc_id,
+					  crtc,
 					  pPriv->drw_y - crtc->y,
 					  (pPriv->drw_y - crtc->y) + pPriv->dst_h);
-	}
     }
     /*
      * Rendering of the actual polygon is done in two different
@@ -916,14 +913,11 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 						    pPriv->drw_x + pPriv->dst_w,
 						    pPriv->drw_y,
 						    pPriv->drw_y + pPriv->dst_h);
-	if (crtc) {
-	    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
-
+	if (crtc)
 	    FUNC_NAME(RADEONWaitForVLine)(pScrn, pPixmap,
-					  radeon_crtc->crtc_id,
+					  crtc,
 					  pPriv->drw_y - crtc->y,
 					  (pPriv->drw_y - crtc->y) + pPriv->dst_h);
-	}
     }
     /*
      * Rendering of the actual polygon is done in two different
@@ -2290,14 +2284,11 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 						    pPriv->drw_x + pPriv->dst_w,
 						    pPriv->drw_y,
 						    pPriv->drw_y + pPriv->dst_h);
-	if (crtc) {
-	    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
-
+	if (crtc)
 	    FUNC_NAME(RADEONWaitForVLine)(pScrn, pPixmap,
-					  radeon_crtc->crtc_id,
+					  crtc,
 					  pPriv->drw_y - crtc->y,
 					  (pPriv->drw_y - crtc->y) + pPriv->dst_h);
-	}
     }
     /*
      * Rendering of the actual polygon is done in two different
@@ -3867,14 +3858,11 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 						    pPriv->drw_x + pPriv->dst_w,
 						    pPriv->drw_y,
 						    pPriv->drw_y + pPriv->dst_h);
-	if (crtc) {
-	    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
-
+	if (crtc)
 	    FUNC_NAME(RADEONWaitForVLine)(pScrn, pPixmap,
-					  radeon_crtc->crtc_id,
+					  crtc,
 					  pPriv->drw_y - crtc->y,
 					  (pPriv->drw_y - crtc->y) + pPriv->dst_h);
-	}
     }
     /*
      * Rendering of the actual polygon is done in two different
commit 9733dcde0a21b7503aa20254724f2910b541b990
Author: Dave Airlie <airlied at linux.ie>
Date:   Sat Sep 26 06:15:58 2009 +1000

    r600: fix build

diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index 1798091..e30cfcb 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -234,7 +234,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	radeon_cs_space_add_persistent_bo(info->cs, accel_state->src_bo[0],
 					  RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 	radeon_cs_space_add_persistent_bo(info->cs, accel_state->dst_bo,
-					  0, RADEON_GEM_DOMAIN_VRAM, 0);
+					  0, RADEON_GEM_DOMAIN_VRAM);
 	if (radeon_cs_space_check(info->cs))
 	    return;
     } else
commit ff18595eace42ddfc931f4f948cb5adf59ebcf52
Author: Dave Airlie <airlied at linux.ie>
Date:   Sat Sep 26 06:04:51 2009 +1000

    r600/xv: fix dst bo write domain

diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index c9df284..1798091 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -234,7 +234,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	radeon_cs_space_add_persistent_bo(info->cs, accel_state->src_bo[0],
 					  RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 	radeon_cs_space_add_persistent_bo(info->cs, accel_state->dst_bo,
-					  RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+					  0, RADEON_GEM_DOMAIN_VRAM, 0);
 	if (radeon_cs_space_check(info->cs))
 	    return;
     } else
commit 718a611f3cc7f5eea95cd73a9dcc7913c922fcbc
Author: Dave Airlie <airlied at linux.ie>
Date:   Sat Sep 26 06:03:51 2009 +1000

    radeon: fix zaphod

diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index a9aafd3..24ef513 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -3746,6 +3746,8 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen,
     memset(info->FB + pScrn->fbOffset, 0,
            pScrn->virtualY * pScrn->displayWidth * info->CurrentLayout.pixel_bytes);
 
+    pScrn->pScreen = pScreen;
+
     /* set the modes with desired rotation, etc. */
     if (!xf86SetDesiredModes (pScrn))
 	return FALSE;
commit 86c367be517e992aabc1bcfea2a2dde1a1ae520c
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Fri Sep 25 13:03:44 2009 -0400

    r600: fix bo accounting for Xv
    
    fixes Xv after changes in:
    8f80e37eed3ec028718b4e71bbb9b598847fd94e
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index b6f7b39..c9df284 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -227,6 +227,16 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	accel_state->src_bo[0] = pPriv->src_bo;
 	accel_state->src_bo[1] = NULL;
 	accel_state->dst_bo = radeon_get_pixmap_bo(pPixmap);
+
+	radeon_cs_space_reset_bos(info->cs);
+	radeon_cs_space_add_persistent_bo(info->cs, accel_state->shaders_bo,
+					  RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_add_persistent_bo(info->cs, accel_state->src_bo[0],
+					  RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_add_persistent_bo(info->cs, accel_state->dst_bo,
+					  RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	if (radeon_cs_space_check(info->cs))
+	    return;
     } else
 #endif
     {
diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c
index 932759b..b708f52 100644
--- a/src/radeon_textured_video.c
+++ b/src/radeon_textured_video.c
@@ -458,8 +458,10 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
     pPriv->w = width;
     pPriv->h = height;
 
+#if defined(XF86DRM_MODE)
     if (info->cs)
 	radeon_bo_unmap(pPriv->src_bo);
+#endif
 #ifdef XF86DRI
     if (info->directRenderingEnabled) {
 	if (IS_R600_3D)
commit 8f80e37eed3ec028718b4e71bbb9b598847fd94e
Author: Dave Airlie <airlied at linux.ie>
Date:   Fri Sep 25 11:37:38 2009 +1000

    r600: space check wasn't correct.
    
    the r6xx space check code was incorrect for the DFS case, since
    the dst bo was in GTT but the hardcoded cp_start function
    assumed the bos were where it thought.
    
    Ripped out assumptions and replaced with code more like other radeons.

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 40c7c04..f6f2007 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -108,6 +108,14 @@ static Bool R600CheckBPP(int bpp)
 	return FALSE;
 }
 
+#if defined(XF86DRM_MODE)
+static inline void radeon_add_pixmap(struct radeon_cs *cs, PixmapPtr pPix, int read_domains, int write_domain)
+{
+    struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix);
+
+    radeon_cs_space_add_persistent_bo(cs, driver_priv->bo, read_domains, write_domain);
+}
+#endif
 
 static void
 R600DoneSolid(PixmapPtr pPix);
@@ -137,6 +145,14 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 
 #if defined(XF86DRM_MODE)
     if (info->cs) {
+	radeon_cs_space_reset_bos(info->cs);
+	radeon_cs_space_add_persistent_bo(info->cs, accel_state->shaders_bo,
+					  RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_add_pixmap(info->cs, pPix, 0, RADEON_GEM_DOMAIN_VRAM);
+	r = radeon_cs_space_check(info->cs);
+	if (r)
+	    RADEON_FALLBACK(("Not enough RAM to hw accel solid operation\n"));
+
 	accel_state->dst_mc_addr = 0;
 	accel_state->dst_bo = radeon_get_pixmap_bo(pPix);
 	accel_state->src_bo[0] = NULL;
@@ -706,7 +722,8 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
     ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
     RADEONInfoPtr info = RADEONPTR(pScrn);
     struct radeon_accel_state *accel_state = info->accel_state;
-
+    int ret;
+    
     //return FALSE;
 
     if (pSrc->drawable.bitsPerPixel == 24)
@@ -759,6 +776,18 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
     if (accel_state->dst_mc_addr & 0xff)
 	RADEON_FALLBACK(("Bad dst offset 0x%08x\n", accel_state->dst_mc_addr));
 
+
+    if (info->cs) {
+	radeon_cs_space_reset_bos(info->cs);
+	radeon_cs_space_add_persistent_bo(info->cs, accel_state->shaders_bo,
+					  RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_add_pixmap(info->cs, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
+	ret = radeon_cs_space_check(info->cs);
+	if (ret)
+	    RADEON_FALLBACK(("Not enough RAM to hw accel copy operation\n"));
+    }
+
     /* return FALSE; */
 
 #ifdef SHOW_VERTEXES
@@ -1261,10 +1290,6 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
 #if defined(XF86DRM_MODE)
     if (info->cs) {
 	accel_state->src_mc_addr[unit] = 0;
-	accel_state->src_bo[unit] = radeon_get_pixmap_bo(pPix);
-	radeon_cs_space_add_persistent_bo(info->cs, accel_state->src_bo[unit],
-					  RADEON_GEM_DOMAIN_VRAM, 0);
-	radeon_cs_space_check(info->cs);
     } else
 #endif
 	accel_state->src_mc_addr[unit] = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset;
@@ -1568,6 +1593,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     uint32_t blendcntl, dst_format;
     cb_config_t cb_conf;
     shader_config_t vs_conf, ps_conf;
+    int ret;
 
     //return FALSE;
     /* return FALSE; */
@@ -1597,8 +1623,21 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     if (info->cs) {
 	accel_state->dst_mc_addr = 0;
 	accel_state->dst_bo = radeon_get_pixmap_bo(pDst);
-	accel_state->src_bo[0] = NULL;
-	accel_state->src_bo[1] = NULL;
+	accel_state->src_bo[0] = radeon_get_pixmap_bo(pSrc);
+	if (pMask)
+	    accel_state->src_bo[1] = radeon_get_pixmap_bo(pMask);
+
+	radeon_cs_space_reset_bos(info->cs);
+	radeon_cs_space_add_persistent_bo(info->cs, accel_state->shaders_bo,
+					  RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_add_pixmap(info->cs, pSrc,
+			  RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	if (pMask)
+	    radeon_add_pixmap(info->cs, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
+	ret = radeon_cs_space_check(info->cs);
+	if (ret)
+	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
     } else
 #endif
 	accel_state->dst_mc_addr = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
@@ -2113,12 +2152,6 @@ R600DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
 }
 
 #if defined(XF86DRM_MODE)
-static inline void radeon_add_pixmap(struct radeon_cs *cs, PixmapPtr pPix, int read_domains, int write_domain)
-{
-    struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix);
-
-    radeon_cs_space_add_persistent_bo(cs, driver_priv->bo, read_domains, write_domain);
-}
 
 static Bool
 R600UploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
@@ -2153,6 +2186,8 @@ R600UploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
 	return FALSE;
     }
     radeon_cs_space_reset_bos(info->cs);
+    radeon_cs_space_add_persistent_bo(info->cs, info->accel_state->shaders_bo,
+				      RADEON_GEM_DOMAIN_VRAM, 0);
     radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
     radeon_cs_space_add_persistent_bo(info->cs, scratch, RADEON_GEM_DOMAIN_GTT, 0);
     r = radeon_cs_space_check(info->cs);
@@ -2233,6 +2268,8 @@ R600DownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
 	return FALSE;
     }
     radeon_cs_space_reset_bos(info->cs);
+    radeon_cs_space_add_persistent_bo(info->cs, info->accel_state->shaders_bo,
+				      RADEON_GEM_DOMAIN_VRAM, 0);
     radeon_add_pixmap(info->cs, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
     radeon_cs_space_add_persistent_bo(info->cs, scratch, 0, RADEON_GEM_DOMAIN_GTT);
     r = radeon_cs_space_check(info->cs);
diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index 3202d51..0e2f8a9 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -1203,25 +1203,10 @@ r600_cp_start(ScrnInfoPtr pScrn)
     if (info->cs) {
 	if (!r600_vb_get(pScrn))
 	    return -1;
-	radeon_cs_space_reset_bos(info->cs);
-	radeon_cs_space_add_persistent_bo(info->cs, accel_state->shaders_bo,
-					  RADEON_GEM_DOMAIN_VRAM, 0);
-	if (accel_state->src_bo[0])
-	    radeon_cs_space_add_persistent_bo(info->cs, accel_state->src_bo[0],
-					      RADEON_GEM_DOMAIN_VRAM, 0);
-	if (accel_state->src_bo[1])
-	    radeon_cs_space_add_persistent_bo(info->cs, accel_state->src_bo[1],
-					      RADEON_GEM_DOMAIN_VRAM, 0);
-	if (accel_state->dst_bo)
-	    radeon_cs_space_add_persistent_bo(info->cs, accel_state->dst_bo,
-					      RADEON_GEM_DOMAIN_VRAM, 0);
 	if (accel_state->vb_bo)
-	    radeon_cs_space_add_persistent_bo(info->cs, accel_state->vb_bo,
-					      RADEON_GEM_DOMAIN_GTT, 0);
-	if (accel_state->copy_area_bo)
-	    radeon_cs_space_add_persistent_bo(info->cs,
-					      accel_state->copy_area_bo,
-					      RADEON_GEM_DOMAIN_VRAM, 0);
+	  radeon_cs_space_add_persistent_bo(info->cs, accel_state->vb_bo,
+					    RADEON_GEM_DOMAIN_GTT, 0);
+
 	radeon_cs_space_check(info->cs);
     } else
 #endif
commit 90669f6cb5ada9067d6fccc7f54c69b367862f42
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Sep 24 10:40:40 2009 -0400

    radeon: remove old pre-randr rotation cruft
    
    leftover from the randr 1.2 conversion.
    
    Signed-off-by: Alex Deucher <alexdeucher at gmail.com>

diff --git a/src/radeon.h b/src/radeon.h
index fc9614e..fc21955 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -951,8 +951,6 @@ typedef struct {
     unsigned long FbFreeStart, FbFreeSize;
     unsigned char*      BIOSCopy;
 
-    Rotation rotation;
-    void (*PointerMoved)(int, int, int);
     CreateScreenResourcesProcPtr CreateScreenResources;
 
     /* if no devices are connected at server startup */
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 2de682f..a9aafd3 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -3261,33 +3261,6 @@ static void RADEONBlockHandler(int i, pointer blockData,
 }
 
 static void
-RADEONPointerMoved(int index, int x, int y)
-{
-    ScrnInfoPtr pScrn = xf86Screens[index];
-    RADEONInfoPtr  info  = RADEONPTR(pScrn);
-    int newX = x, newY = y;
-
-    switch (info->rotation) {
-    case RR_Rotate_0:
-	break;
-    case RR_Rotate_90:
-	newX = y;
-	newY = pScrn->pScreen->width - x - 1;
-	break;
-    case RR_Rotate_180:
-	newX = pScrn->pScreen->width - x - 1;
-	newY = pScrn->pScreen->height - y - 1;
-	break;
-    case RR_Rotate_270:
-	newX = pScrn->pScreen->height - y - 1;
-	newY = x;
-	break;
-    }
-
-    (*info->PointerMoved)(index, newX, newY);
-}
-
-static void
 RADEONInitBIOSRegisters(ScrnInfoPtr pScrn)
 {
     RADEONInfoPtr  info  = RADEONPTR(pScrn);
@@ -3790,10 +3763,6 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen,
    if (!xf86CrtcScreenInit (pScreen))
        return FALSE;
 
-    /* Wrap pointer motion to flip touch screen around */
-    info->PointerMoved = pScrn->PointerMoved;
-    pScrn->PointerMoved = RADEONPointerMoved;
-
     /* Colormap setup */
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
                    "Initializing color map\n");
commit 97a4e747bfac14f34646c55ddf639e8fe22f2f55
Author: Michael Olbrich <m.olbrich at pengutronix.de>
Date:   Sun Sep 20 14:19:41 2009 +0200

    use AC_CHECK_HEADER instead of AC_CHECK_FILE
    
    AC_CHECK_FILE is not possible when cross-compiling. Use AC_CHECK_HEADER /
    AC_PREPROC_IFELSE instead.
    
    [ Michel Dänzer: Shuffled things around slightly to make it work on my setup ]
    
    Signed-off-by: Michael Olbrich <m.olbrich at pengutronix.de>
    Signed-off-by: Michel Dänzer <daenzer at vmware.com>

diff --git a/configure.ac b/configure.ac
index 9d769ea..162c839 100644
--- a/configure.ac
+++ b/configure.ac
@@ -102,14 +102,21 @@ sdkdir=$(pkg-config --variable=sdkdir xorg-server)
 AC_HEADER_STDC
 
 if test "$DRI" != no; then
-	AC_CHECK_FILE([${sdkdir}/dri.h],
-                      [have_dri_h="yes"], [have_dri_h="no"])
-	AC_CHECK_FILE([${sdkdir}/sarea.h],
-                      [have_sarea_h="yes"], [have_sarea_h="no"])
-	AC_CHECK_FILE([${sdkdir}/dristruct.h],
-                      [have_dristruct_h="yes"], [have_dristruct_h="no"])
-	AC_CHECK_FILE([${sdkdir}/damage.h],
-                      [have_damage_h="yes"], [have_damage_h="no"])
+	PKG_CHECK_MODULES(DRI, [libdrm >= 2.2 xf86driproto])
+	save_CPPFLAGS="$CPPFLAGS"
+	CPPFLAGS="$XORG_CFLAGS $DRI_CFLAGS"
+	AC_CHECK_HEADER([dri.h],
+                      [have_dri_h="yes"], [have_dri_h="no"],[-])
+	AC_CHECK_HEADER([sarea.h],
+                      [have_sarea_h="yes"], [have_sarea_h="no"],[-])
+	AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[
+#include <xorg-server.h>
+#include <dristruct.h>
+                      ]])],
+                      [have_dristruct_h="yes"], [have_dristruct_h="no"],[-])
+	AC_CHECK_HEADER([damage.h],
+                      [have_damage_h="yes"], [have_damage_h="no"],[-])
+	CPPFLAGS="$save_CPPFLAGS"
 fi
 
 AC_MSG_CHECKING([whether to include DRI support])
@@ -126,7 +133,6 @@ AC_MSG_RESULT([$DRI])
 
 AM_CONDITIONAL(DRI, test x$DRI = xyes)
 if test "$DRI" = yes; then
-	PKG_CHECK_MODULES(DRI, [libdrm >= 2.2 xf86driproto])
         AC_DEFINE(XF86DRI,1,[Enable DRI driver support])
         AC_DEFINE(XF86DRI_DEVEL,1,[Enable developmental DRI driver support])
 	if test "$have_damage_h" = yes; then
commit 579070ed9f0218a975e840331b6fe9fa8fd05789
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Sat Sep 19 19:15:14 2009 -0400

    kms: disable dga
    
    Can be dangerous with kms:
    http://lists.freedesktop.org/archives/xorg-devel/2009-September/002113.html

diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index a0ed165..e2f716e 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -701,7 +701,10 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
 
     /* DGA setup */
 #ifdef XFreeXDGA
-    xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset);
+    /* DGA is dangerous on kms as the base and framebuffer location may change:
+     * http://lists.freedesktop.org/archives/xorg-devel/2009-September/002113.html
+     */
+    /* xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset); */
 #endif
 
     /* Init Xv */
commit da7487f6ac7b32ed7866af53da2925aa52ed7aae
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Sat Sep 19 13:08:02 2009 -0400

    kms: init dga using xf86DiDGAInit
    
    fixes cursor problems in games like UT2004 and Penumbra Overture
    
    see fdo bug 24034

diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index faa0cfd..a0ed165 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -699,6 +699,11 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
 	}
     }
 
+    /* DGA setup */
+#ifdef XFreeXDGA
+    xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset);
+#endif
+
     /* Init Xv */
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "Initializing Xv\n");
commit 52279251fae9df99c569c16e2522bbd346d8ec38
Author: Dave Airlie <airlied at redhat.com>
Date:   Fri Sep 18 14:29:32 2009 +1000

    avivo: disable VGA rendering core when starting X.
    
    this thing can be rendering to VRAM when we don't expect it.
    turn it off.
    
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 67fb9b7..2de682f 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -3849,6 +3849,9 @@ void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn,
 
 	    RADEONWaitForIdleMMIO(pScrn);
 
+            /* disable VGA rendering core */
+    	    OUTREG(AVIVO_VGA_RENDER_CONTROL, INREG(AVIVO_VGA_RENDER_CONTROL) &~ AVIVO_VGA_VSTATUS_CNTL_MASK);
+
 	    OUTREG(AVIVO_D1VGA_CONTROL, INREG(AVIVO_D1VGA_CONTROL) & ~AVIVO_DVGA_CONTROL_MODE_ENABLE);
 	    OUTREG(AVIVO_D2VGA_CONTROL, INREG(AVIVO_D2VGA_CONTROL) & ~AVIVO_DVGA_CONTROL_MODE_ENABLE);
 
@@ -4327,6 +4330,7 @@ avivo_save(ScrnInfoPtr pScrn, RADEONSavePtr save)
     //    state->vga_fb_start = INREG(AVIVO_VGA_FB_START);
     state->vga1_cntl = INREG(AVIVO_D1VGA_CONTROL);
     state->vga2_cntl = INREG(AVIVO_D2VGA_CONTROL);
+    state->vga_render_control = INREG(AVIVO_VGA_RENDER_CONTROL);
 
     state->crtc_master_en = INREG(AVIVO_DC_CRTC_MASTER_EN);
     state->crtc_tv_control = INREG(AVIVO_DC_CRTC_TV_CONTROL);
@@ -5061,6 +5065,7 @@ avivo_restore(ScrnInfoPtr pScrn, RADEONSavePtr restore)
     OUTREG(AVIVO_D2CRTC_BLANK_CONTROL, state->crtc2.blank_control);
 
     /* Dbl check */
+    OUTREG(AVIVO_VGA_RENDER_CONTROL, state->vga_render_control);
     OUTREG(AVIVO_D1VGA_CONTROL, state->vga1_cntl);
     OUTREG(AVIVO_D2VGA_CONTROL, state->vga2_cntl);
 
@@ -5073,6 +5078,7 @@ static void avivo_restore_vga_regs(ScrnInfoPtr pScrn, RADEONSavePtr restore)
     unsigned char *RADEONMMIO = info->MMIO;
     struct avivo_state *state = &restore->avivo;
 
+    OUTREG(AVIVO_VGA_RENDER_CONTROL, state->vga_render_control);
     OUTREG(AVIVO_D1VGA_CONTROL, state->vga1_cntl);
     OUTREG(AVIVO_D2VGA_CONTROL, state->vga2_cntl);
 }
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index 9cac15c..9b2cd70 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -341,6 +341,7 @@ struct avivo_state
 
     uint32_t vga1_cntl;
     uint32_t vga2_cntl;
+    uint32_t vga_render_control;
 
     uint32_t crtc_master_en;
     uint32_t crtc_tv_control;
commit 2c46bafcb77c4125a27c18ad6ca2f6de5f143a2d
Author: Pauli Nieminen <suokkos at gmail.com>
Date:   Thu Sep 17 15:13:51 2009 +0300

    Fix configuration to disable KMS if not finding libdrm_radeon.
    
    Most of KMS building was disabled if LIBDRM_RADEON was not detected. But at
    least configure was reporting KMS enabled even tough it was realy disabled.

diff --git a/configure.ac b/configure.ac
index 66f76aa..9d769ea 100644
--- a/configure.ac
+++ b/configure.ac
@@ -146,6 +146,8 @@ if test "$DRI" = yes; then
 			if test "x$LIBDRM_RADEON" = xyes; then
 			   	AC_DEFINE(XF86DRM_MODE,1,[DRM kernel modesetting])
 				AC_DEFINE(RADEON_DRI2, 1,[Enable DRI2 code])
+                        else
+                                DRM_MODE=no
 			fi
         	fi
 	fi
commit ee9f6d802988a4d7f7985687036db854f4a14fe5
Author: Pauli Nieminen <suokkos at gmail.com>
Date:   Mon Sep 14 16:36:48 2009 +0300

    radeon: Add missing libdrm_radeon cflags to compiler paramaters.
    
    This fixes compilation if libdrm_radeon is installed to non-standard location like /opt.

diff --git a/src/Makefile.am b/src/Makefile.am
index e0434f4..93f237c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -73,7 +73,16 @@ if USE_EXA
 RADEON_EXA_SOURCES = radeon_exa.c r600_exa.c r6xx_accel.c r600_textured_videofuncs.c r600_shader.c
 endif
 
-AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ @XMODES_CFLAGS@ -DDISABLE_EASF -DENABLE_ALL_SERVICE_FUNCTIONS -DATOM_BIOS -DATOM_BIOS_PARSER -DDRIVER_PARSER
+AM_CFLAGS = \
+            @LIBDRM_RADEON_CFLAGS@ \
+            @XORG_CFLAGS@ \
+            @DRI_CFLAGS@ \
+            @XMODES_CFLAGS@ \
+            -DDISABLE_EASF \
+            -DENABLE_ALL_SERVICE_FUNCTIONS \
+            -DATOM_BIOS \
+            -DATOM_BIOS_PARSER \
+            -DDRIVER_PARSER
 
 INCLUDES = -I$(srcdir)/AtomBios/includes
 
commit ac853ca0a950d6147cd6a0b4a1b089f5d2f080ea
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Fri Sep 11 14:25:31 2009 -0400

    atom: fix typo in asus quirks
    
    Should be DVI-I, not DVI-D

diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index b1cb559..0384456 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -1630,7 +1630,7 @@ static void RADEONApplyATOMQuirks(ScrnInfoPtr pScrn, int index)
 	(PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) &&
 	(PCI_SUB_DEVICE_ID(info->PciInfo) == 0x01da)) {
 	if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A)
-	    info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_D;
+	    info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_I;
     }
 
     /* ASUS HD 3450 board lists the DVI port as HDMI */
@@ -1638,7 +1638,7 @@ static void RADEONApplyATOMQuirks(ScrnInfoPtr pScrn, int index)
 	(PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) &&
 	(PCI_SUB_DEVICE_ID(info->PciInfo) == 0x01e2)) {
 	if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A)
-	    info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_D;
+	    info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_I;
     }
 
     /* some BIOSes seem to report DAC on HDMI - usually this is a board with
commit a88f60e7b789cd23a79e6e18a7e3fa008d15aa77
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Sep 10 13:42:31 2009 -0400

    r600: add CS UTS and DFS hooks

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 86da68c..40c7c04 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -2112,6 +2112,165 @@ R600DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
 
 }
 
+#if defined(XF86DRM_MODE)
+static inline void radeon_add_pixmap(struct radeon_cs *cs, PixmapPtr pPix, int read_domains, int write_domain)
+{
+    struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix);
+
+    radeon_cs_space_add_persistent_bo(cs, driver_priv->bo, read_domains, write_domain);
+}
+
+static Bool
+R600UploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
+		     char *src, int src_pitch)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    struct radeon_exa_pixmap_priv *driver_priv;
+    struct radeon_bo *scratch;
+    unsigned size;
+    uint32_t dst_domain;
+    int bpp = pDst->drawable.bitsPerPixel;
+    uint32_t scratch_pitch = (w * bpp / 8 + 255) & ~255;
+    uint32_t src_pitch_hw = scratch_pitch / (bpp / 8);
+    uint32_t dst_pitch_hw = exaGetPixmapPitch(pDst) / (bpp / 8);
+    Bool r;
+    int i;
+
+    if (bpp < 8)
+	return FALSE;
+
+    driver_priv = exaGetPixmapDriverPrivate(pDst);
+
+    /* If we know the BO won't be busy, don't bother */
+    if (driver_priv->bo->cref == 1 &&
+	!radeon_bo_is_busy(driver_priv->bo, &dst_domain))
+	return FALSE;
+
+    size = scratch_pitch * h;
+    scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0);
+    if (scratch == NULL) {
+	return FALSE;
+    }
+    radeon_cs_space_reset_bos(info->cs);
+    radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
+    radeon_cs_space_add_persistent_bo(info->cs, scratch, RADEON_GEM_DOMAIN_GTT, 0);
+    r = radeon_cs_space_check(info->cs);
+    if (r) {
+        r = FALSE;
+        goto out;
+    }
+
+    r = radeon_bo_map(scratch, 0);
+    if (r) {
+        r = FALSE;
+        goto out;
+    }
+    r = TRUE;
+    size = w * bpp / 8;
+    for (i = 0; i < h; i++) {
+        memcpy(scratch->ptr + i * scratch_pitch, src, size);
+        src += src_pitch;
+    }
+    radeon_bo_unmap(scratch);
+
+    /* blit from gart to vram */
+    R600DoPrepareCopy(pScrn,
+		      src_pitch_hw, w, h,
+		      0, scratch, bpp,
+		      dst_pitch_hw, pDst->drawable.width, pDst->drawable.height,
+		      0, radeon_get_pixmap_bo(pDst), bpp,
+		      3, 0xffffffff);
+    R600AppendCopyVertex(pScrn, 0, 0, x, y, w, h);
+    R600DoCopy(pScrn);
+
+out:
+    radeon_bo_unref(scratch);
+    return r;
+}
+
+static Bool
+R600DownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
+			 int h, char *dst, int dst_pitch)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    struct radeon_exa_pixmap_priv *driver_priv;
+    struct radeon_bo *scratch;
+    unsigned size;
+    uint32_t src_domain = 0;
+    int bpp = pSrc->drawable.bitsPerPixel;
+    uint32_t scratch_pitch = (w * bpp / 8 + 255) & ~255;
+    uint32_t dst_pitch_hw = scratch_pitch / (bpp / 8);
+    uint32_t src_pitch_hw = exaGetPixmapPitch(pSrc) / (bpp / 8);
+    Bool r;
+
+    if (bpp < 8)
+	return FALSE;
+
+    driver_priv = exaGetPixmapDriverPrivate(pSrc);
+
+    /* If we know the BO won't end up in VRAM anyway, don't bother */
+    if (driver_priv->bo->cref > 1) {
+	src_domain = driver_priv->bo->space_accounted & 0xffff;
+	if (!src_domain)
+	    src_domain = driver_priv->bo->space_accounted >> 16;
+
+	if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) ==
+	    (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM))
+	    src_domain = 0;
+    }
+
+    if (!src_domain)
+	radeon_bo_is_busy(driver_priv->bo, &src_domain);
+
+    if (src_domain != RADEON_GEM_DOMAIN_VRAM)
+	return FALSE;
+
+    size = scratch_pitch * h;
+    scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0);
+    if (scratch == NULL) {
+	return FALSE;
+    }
+    radeon_cs_space_reset_bos(info->cs);
+    radeon_add_pixmap(info->cs, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+    radeon_cs_space_add_persistent_bo(info->cs, scratch, 0, RADEON_GEM_DOMAIN_GTT);
+    r = radeon_cs_space_check(info->cs);
+    if (r) {
+        r = FALSE;
+        goto out;
+    }
+
+    /* blit from vram to gart */
+    R600DoPrepareCopy(pScrn,
+		      src_pitch_hw, pSrc->drawable.width, pSrc->drawable.height,
+		      0, radeon_get_pixmap_bo(pSrc), bpp,
+		      dst_pitch_hw, w, h,
+		      0, scratch, bpp,
+		      3, 0xffffffff);
+    R600AppendCopyVertex(pScrn, x, y, 0, 0, w, h);
+    R600DoCopy(pScrn);
+
+    r = radeon_bo_map(scratch, 0);
+    if (r) {
+        r = FALSE;
+        goto out;
+    }
+    r = TRUE;
+    w *= bpp / 8;
+    size = 0;
+    while (h--) {
+        memcpy(dst, scratch->ptr + size, w);
+        size += scratch_pitch;
+        dst += dst_pitch;
+    }
+    radeon_bo_unmap(scratch);
+out:
+    radeon_bo_unref(scratch);
+    return r;
+}
+#endif
+
 static int
 R600MarkSync(ScreenPtr pScreen)
 {
@@ -2305,8 +2464,8 @@ R600DrawInit(ScreenPtr pScreen)
 	info->accel_state->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen;
 	info->accel_state->exa->PrepareAccess = RADEONPrepareAccess_CS;
 	info->accel_state->exa->FinishAccess = RADEONFinishAccess_CS;
-	info->accel_state->exa->UploadToScreen = NULL;
-	info->accel_state->exa->DownloadFromScreen = NULL;
+	info->accel_state->exa->UploadToScreen = R600UploadToScreenCS;
+	info->accel_state->exa->DownloadFromScreen = R600DownloadFromScreenCS;
     } else
 #endif
 #endif
commit 0bb0ff0e55aaf8e64017d204e376a14f0a7384a3
Author: Dave Airlie <airlied at linux.ie>
Date:   Thu Sep 10 11:48:00 2009 +1000

    r6xx: fix EXA crash with gtkperf -a
    
    unmapping was getting unbalanced.

diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index 985595e..3202d51 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -48,7 +48,7 @@ void r600_cs_flush_indirect(ScrnInfoPtr pScrn)
     if (!info->cs->cdw)
 	return;
 
-    if (info->accel_state->vb_bo) {
+    if (info->accel_state->vb_ptr) {
 	radeon_bo_unmap(info->accel_state->vb_bo);
 	info->accel_state->vb_ptr = NULL;
     }
@@ -106,9 +106,10 @@ void R600IBDiscard(ScrnInfoPtr pScrn, drmBufPtr ib)
     int ret;
     RADEONInfoPtr info = RADEONPTR(pScrn);
     if (info->cs) {
-	if (info->accel_state->vb_bo)
+	if (info->accel_state->vb_ptr) {
 	    radeon_bo_unmap(info->accel_state->vb_bo);
-	info->accel_state->vb_bo = NULL;
+	    info->accel_state->vb_ptr = NULL;
+        }
 	if (CS_FULL(info->cs)) {
 	    r600_cs_flush_indirect(pScrn);
 	    return;
commit 10a58d54857484b6e89763ecf463f54dc290c702
Author: Dave Airlie <airlied at redhat.com>
Date:   Wed Sep 9 14:24:49 2009 +1000

    kms: add property support.
    
    this adds support to the userspace DDX to get properties from the kernel
    and expose them over randr. Its most liberated from the Intel driver.

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 1b4985d..e6b948c 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -587,9 +587,15 @@ static void
 drmmode_output_destroy(xf86OutputPtr output)
 {
 	drmmode_output_private_ptr drmmode_output = output->driver_private;
+	int i;
 
 	if (drmmode_output->edid_blob)
 		drmModeFreePropertyBlob(drmmode_output->edid_blob);
+	for (i = 0; i < drmmode_output->num_props; i++) {
+	    drmModeFreeProperty(drmmode_output->props[i].mode_prop);
+	    xfree(drmmode_output->props[i].atoms);
+	}
+	xfree(drmmode_output->props);
 	drmModeFreeConnector(drmmode_output->mode_output);
 	xfree(drmmode_output);
 	output->driver_private = NULL;
@@ -607,8 +613,171 @@ drmmode_output_dpms(xf86OutputPtr output, int mode)
 	return;
 }
 
+
+static Bool
+drmmode_property_ignore(drmModePropertyPtr prop)
+{
+    if (!prop)
+	return TRUE;
+    /* ignore blob prop */
+    if (prop->flags & DRM_MODE_PROP_BLOB)
+	return TRUE;
+    /* ignore standard property */
+    if (!strcmp(prop->name, "EDID") ||
+	    !strcmp(prop->name, "DPMS"))
+	return TRUE;
+
+    return FALSE;
+}
+
+static void
+drmmode_output_create_resources(xf86OutputPtr output)
+{
+    drmmode_output_private_ptr drmmode_output = output->driver_private;
+    drmModeConnectorPtr mode_output = drmmode_output->mode_output;
+    drmmode_ptr drmmode = drmmode_output->drmmode;
+    drmModePropertyPtr drmmode_prop;
+    int i, j, err;
+
+    drmmode_output->props = xcalloc(mode_output->count_props, sizeof(drmmode_prop_rec));
+    if (!drmmode_output->props)
+	return;
+    
+    drmmode_output->num_props = 0;
+    for (i = 0, j = 0; i < mode_output->count_props; i++) {
+	drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]);
+	if (drmmode_property_ignore(drmmode_prop)) {
+	    drmModeFreeProperty(drmmode_prop);
+	    continue;
+	}
+	drmmode_output->props[j].mode_prop = drmmode_prop;
+	drmmode_output->props[j].value = mode_output->prop_values[i];
+	drmmode_output->num_props++;
+	j++;
+    }
+
+    for (i = 0; i < drmmode_output->num_props; i++) {
+	drmmode_prop_ptr p = &drmmode_output->props[i];
+	drmmode_prop = p->mode_prop;
+
+	if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
+	    INT32 range[2];
+
+	    p->num_atoms = 1;
+	    p->atoms = xcalloc(p->num_atoms, sizeof(Atom));
+	    if (!p->atoms)
+		continue;
+	    p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
+	    range[0] = drmmode_prop->values[0];
+	    range[1] = drmmode_prop->values[1];
+	    err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
+		    FALSE, TRUE,
+		    drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
+		    2, range);
+	    if (err != 0) {
+		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+			"RRConfigureOutputProperty error, %d\n", err);
+	    }
+	    err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
+		    XA_INTEGER, 32, PropModeReplace, 1, &p->value, FALSE, TRUE);
+	    if (err != 0) {
+		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+			"RRChangeOutputProperty error, %d\n", err);
+	    }
+	} else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
+	    p->num_atoms = drmmode_prop->count_enums + 1;
+	    p->atoms = xcalloc(p->num_atoms, sizeof(Atom));
+	    if (!p->atoms)
+		continue;
+	    p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
+	    for (j = 1; j <= drmmode_prop->count_enums; j++) {
+		struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
+		p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
+	    }
+	    err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
+		    FALSE, FALSE,
+		    drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
+		    p->num_atoms - 1, (INT32 *)&p->atoms[1]);
+	    if (err != 0) {
+		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+			"RRConfigureOutputProperty error, %d\n", err);
+	    }
+	    for (j = 0; j < drmmode_prop->count_enums; j++)
+		if (drmmode_prop->enums[j].value == p->value)
+		    break;
+	    /* there's always a matching value */
+	    err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
+		    XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE);
+	    if (err != 0) {
+		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+			"RRChangeOutputProperty error, %d\n", err);
+	    }
+	}
+    }
+}
+
+static Bool
+drmmode_output_set_property(xf86OutputPtr output, Atom property,
+		RRPropertyValuePtr value)
+{
+    drmmode_output_private_ptr drmmode_output = output->driver_private;
+    drmmode_ptr drmmode = drmmode_output->drmmode;
+    int i;
+
+    for (i = 0; i < drmmode_output->num_props; i++) {
+	drmmode_prop_ptr p = &drmmode_output->props[i];
+
+	if (p->atoms[0] != property)
+	    continue;
+
+	if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
+	    uint32_t val;
+
+	    if (value->type != XA_INTEGER || value->format != 32 ||
+		    value->size != 1)
+		return FALSE;
+	    val = *(uint32_t *)value->data;
+
+	    drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
+		    p->mode_prop->prop_id, (uint64_t)val);
+	    return TRUE;
+	} else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
+	    Atom	atom;
+	    const char	*name;
+	    int		j;
+
+	    if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
+		return FALSE;
+	    memcpy(&atom, value->data, 4);
+	    name = NameForAtom(atom);
+
+	    /* search for matching name string, then set its value down */
+	    for (j = 0; j < p->mode_prop->count_enums; j++) {
+		if (!strcmp(p->mode_prop->enums[j].name, name)) {
+		    drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
+			    p->mode_prop->prop_id, p->mode_prop->enums[j].value);
+		    return TRUE;
+		}
+	    }
+	}
+    }
+
+    return TRUE;
+}
+
+static Bool
+drmmode_output_get_property(xf86OutputPtr output, Atom property)
+{
+    return TRUE;
+}
+
 static const xf86OutputFuncsRec drmmode_output_funcs = {
     .dpms = drmmode_output_dpms,
+    .create_resources = drmmode_output_create_resources,
+#ifdef RANDR_12_INTERFACE
+    .set_property = drmmode_output_set_property,
+    .get_property = drmmode_output_get_property,
+#endif
 #if 0
 
     .save = drmmode_crt_save,
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 2713bab..1410afe 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -53,12 +53,22 @@ typedef struct {
 } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
 
 typedef struct {
+    drmModePropertyPtr mode_prop;
+    uint64_t value;
+    int num_atoms; /* if range prop, num_atoms == 1; if enum prop, num_atoms == num_enums + 1 */
+    Atom *atoms;
+} drmmode_prop_rec, *drmmode_prop_ptr;
+
+
+typedef struct {
     drmmode_ptr drmmode;
     int output_id;
     drmModeConnectorPtr mode_output;
     drmModeEncoderPtr mode_encoder;
     drmModePropertyBlobPtr edid_blob;
     int dpms_enum_id;
+    int num_props;
+    drmmode_prop_ptr props;
 } drmmode_output_private_rec, *drmmode_output_private_ptr;
 
 
commit fad9ee6cdae5ae45e6406e3071a84276f1b59a85
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Sep 8 17:50:50 2009 -0400

    radeon: replace dga code with DiDGA

diff --git a/src/Makefile.am b/src/Makefile.am
index 57a365b..e0434f4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -92,7 +92,7 @@ radeon_drv_la_LTLIBRARIES = radeon_drv.la
 radeon_drv_la_LDFLAGS = -module -avoid-version
 radeon_drv_ladir = @moduledir@/drivers
 radeon_drv_la_SOURCES = \
-	radeon_accel.c radeon_cursor.c radeon_dga.c radeon_legacy_memory.c \
+	radeon_accel.c radeon_cursor.c radeon_legacy_memory.c \
 	radeon_driver.c radeon_video.c radeon_bios.c radeon_mm_i2c.c \
 	radeon_vip.c radeon_misc.c radeon_probe.c \
 	legacy_crtc.c legacy_output.c \
diff --git a/src/radeon.h b/src/radeon.h
index 7fdd8f5..fc9614e 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -858,12 +858,6 @@ typedef struct {
     int               pix24bpp;         /* Depth of pixmap for 24bpp fb      */
     Bool              dac6bits;         /* Use 6 bit DAC?                    */
 
-    DGAModePtr        DGAModes;
-    int               numDGAModes;
-    Bool              DGAactive;
-    int               DGAViewportStatus;
-    DGAFunctionRec    DGAFuncs;
-
     RADEONFBLayout    CurrentLayout;
 
 #ifdef XF86DRI
@@ -1151,9 +1145,6 @@ extern void radeon_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg);
 extern void radeon_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y);
 extern void radeon_crtc_show_cursor(xf86CrtcPtr crtc);
 
-/* radeon_dga.c */
-extern Bool RADEONDGAInit(ScreenPtr pScreen);
-
 #ifdef XF86DRI
 /* radeon_dri.c */
 extern void RADEONDRIAllocatePCIGARTTable(ScreenPtr pScreen);
diff --git a/src/radeon_dga.c b/src/radeon_dga.c
deleted file mode 100644
index 6b0fabe..0000000
--- a/src/radeon_dga.c
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
- *                VA Linux Systems Inc., Fremont, California.
- *
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation on the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
- * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/*
- * Authors:
- *   Kevin E. Martin <martin at xfree86.org>
- *
- * Credits:
- *
- *   Thanks to Ove KÃ¥ven <ovek at transgaming.com> for writing the Rage 128
- *   DGA support.  Portions of this file are based on the initialization
- *   code for that driver.
- *
- */
-
-#include <string.h>
-
-				/* Driver data structures */
-#include "radeon.h"
-#include "radeon_probe.h"
-#ifdef XF86DRI
-#include "radeon_drm.h"
-#endif
-
-				/* X and server generic header files */
-#include "xf86.h"
-
-				/* DGA support */
-#include "dgaproc.h"
-
-
-static Bool RADEON_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
-				   int *, int *, int *);
-static Bool RADEON_SetMode(ScrnInfoPtr, DGAModePtr);
-static int  RADEON_GetViewport(ScrnInfoPtr);
-static void RADEON_SetViewport(ScrnInfoPtr, int, int, int);
-#ifdef USE_XAA
-static void RADEON_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
-static void RADEON_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
-static void RADEON_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
-				 unsigned long);
-#endif
-
-static DGAModePtr RADEONSetupDGAMode(ScrnInfoPtr pScrn,
-				     DGAModePtr modes,
-				     int *num,
-				     int bitsPerPixel,
-				     int depth,
-				     Bool pixmap,
-				     int secondPitch,
-				     unsigned long red,
-				     unsigned long green,
-				     unsigned long blue,
-				     short visualClass)
-{
-    RADEONInfoPtr   info     = RADEONPTR(pScrn);
-    DGAModePtr      newmodes = NULL;
-    DGAModePtr      currentMode;
-    DisplayModePtr  pMode;
-    DisplayModePtr  firstMode;
-    unsigned int    size;
-    int             pitch;
-    int             Bpp      = bitsPerPixel >> 3;
-
-SECOND_PASS:
-
-    pMode = firstMode = pScrn->modes;
-
-    while (1) {
-	pitch = pScrn->displayWidth;
-	size = pitch * Bpp * pMode->VDisplay;
-
-	if ((!secondPitch || (pitch != secondPitch)) &&
-	    (size <= info->FbMapSize)) {
-
-	    if (secondPitch)
-		pitch = secondPitch;
-
-	    if (!(newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec))))
-		break;
-
-	    modes       = newmodes;
-	    currentMode = modes + *num;
-
-	    currentMode->mode           = pMode;
-	    currentMode->flags          = DGA_CONCURRENT_ACCESS;
-
-	    if (pixmap)
-		currentMode->flags     |= DGA_PIXMAP_AVAILABLE;
-
-#ifdef USE_EXA
-	    if (info->useEXA) {
-		/* We need to fill in RADEON_FillRect and RADEON_BlitRect and
-		 * connect them in RADEONDGAInit before turning these on.
-		 */
-		/*if (info->exa.accel.PrepareSolid && info->exa.accel.Solid)
-		    currentMode->flags    |= DGA_FILL_RECT;
-		if (info->exa.accel.PrepareCopy && info->exa.accel.Copy)
-		    currentMode->flags    |= DGA_BLIT_RECT | DGA_BLIT_RECT_TRANS;*/
-	    }
-#endif /* USE_EXA */
-#ifdef USE_XAA
-	    if (!info->useEXA && info->accel_state->accel) {
-	      if (info->accel_state->accel->SetupForSolidFill &&
-		  info->accel_state->accel->SubsequentSolidFillRect)
-		 currentMode->flags    |= DGA_FILL_RECT;
-	      if (info->accel_state->accel->SetupForScreenToScreenCopy &&
-		  info->accel_state->accel->SubsequentScreenToScreenCopy)
-		 currentMode->flags    |= DGA_BLIT_RECT | DGA_BLIT_RECT_TRANS;
-	      if (currentMode->flags &
-		  (DGA_PIXMAP_AVAILABLE | DGA_FILL_RECT |
-		   DGA_BLIT_RECT | DGA_BLIT_RECT_TRANS))
-		  currentMode->flags   &= ~DGA_CONCURRENT_ACCESS;
-	    }
-#endif /* USE_XAA */
-
-	    if (pMode->Flags & V_DBLSCAN)
-		currentMode->flags     |= DGA_DOUBLESCAN;
-	    if (pMode->Flags & V_INTERLACE)
-		currentMode->flags     |= DGA_INTERLACED;
-
-	    currentMode->byteOrder      = pScrn->imageByteOrder;
-	    currentMode->depth          = depth;
-	    currentMode->bitsPerPixel   = bitsPerPixel;
-	    currentMode->red_mask       = red;
-	    currentMode->green_mask     = green;
-	    currentMode->blue_mask      = blue;
-	    currentMode->visualClass    = visualClass;
-	    currentMode->viewportWidth  = pMode->HDisplay;
-	    currentMode->viewportHeight = pMode->VDisplay;
-	    currentMode->xViewportStep  = 8;
-	    currentMode->yViewportStep  = 1;
-	    currentMode->viewportFlags  = DGA_FLIP_RETRACE;
-	    currentMode->offset         = 0;
-	    currentMode->address        = (unsigned char*)info->LinearAddr;
-	    currentMode->bytesPerScanline = pitch * Bpp;
-	    currentMode->imageWidth     = pitch;
-	    currentMode->imageHeight    = (info->FbMapSize
-					   / currentMode->bytesPerScanline);
-	    currentMode->pixmapWidth    = currentMode->imageWidth;
-	    currentMode->pixmapHeight   = currentMode->imageHeight;
-	    currentMode->maxViewportX   = (currentMode->imageWidth
-					   - currentMode->viewportWidth);
-	    /* this might need to get clamped to some maximum */
-	    currentMode->maxViewportY   = (currentMode->imageHeight
-					   - currentMode->viewportHeight);
-	    (*num)++;
-	}
-
-	pMode = pMode->next;
-	if (pMode == firstMode)
-	    break;
-    }
-
-    if (secondPitch) {
-	secondPitch = 0;
-	goto SECOND_PASS;
-    }
-
-    return modes;
-}
-
-Bool RADEONDGAInit(ScreenPtr pScreen)
-{
-    ScrnInfoPtr    pScrn = xf86Screens[pScreen->myNum];
-    RADEONInfoPtr  info  = RADEONPTR(pScrn);
-    DGAModePtr     modes = NULL;
-    int            num   = 0;
-
-    /* 8 */
-    modes = RADEONSetupDGAMode(pScrn, modes, &num, 8, 8,
-			       (pScrn->bitsPerPixel == 8),
-				((pScrn->bitsPerPixel != 8)
-				 ? 0 : pScrn->displayWidth),
-			       0, 0, 0, PseudoColor);
-
-    /* 15 */
-    modes = RADEONSetupDGAMode(pScrn, modes, &num, 16, 15,
-			       (pScrn->bitsPerPixel == 16),
-			       ((pScrn->depth != 15)
-				? 0 : pScrn->displayWidth),
-			       0x7c00, 0x03e0, 0x001f, TrueColor);
-
-    modes = RADEONSetupDGAMode(pScrn, modes, &num, 16, 15,
-			       (pScrn->bitsPerPixel == 16),
-			       ((pScrn->depth != 15)
-				? 0 : pScrn->displayWidth),
-			       0x7c00, 0x03e0, 0x001f, DirectColor);
-
-    /* 16 */
-    modes = RADEONSetupDGAMode(pScrn, modes, &num, 16, 16,
-			       (pScrn->bitsPerPixel == 16),
-			       ((pScrn->depth != 16)
-				? 0 : pScrn->displayWidth),
-			       0xf800, 0x07e0, 0x001f, TrueColor);
-
-    modes = RADEONSetupDGAMode(pScrn, modes, &num, 16, 16,
-			       (pScrn->bitsPerPixel == 16),
-			       ((pScrn->depth != 16)
-				? 0 : pScrn->displayWidth),
-			       0xf800, 0x07e0, 0x001f, DirectColor);
-
-    /* 32 */
-    modes = RADEONSetupDGAMode(pScrn, modes, &num, 32, 24,
-			       (pScrn->bitsPerPixel == 32),
-			       ((pScrn->bitsPerPixel != 32)
-				? 0 : pScrn->displayWidth),
-			       0xff0000, 0x00ff00, 0x0000ff, TrueColor);
-
-    modes = RADEONSetupDGAMode(pScrn, modes, &num, 32, 24,
-			       (pScrn->bitsPerPixel == 32),
-			       ((pScrn->bitsPerPixel != 32)
-				? 0 : pScrn->displayWidth),
-			       0xff0000, 0x00ff00, 0x0000ff, DirectColor);
-
-    info->numDGAModes = num;
-    info->DGAModes    = modes;
-
-    info->DGAFuncs.OpenFramebuffer       = RADEON_OpenFramebuffer;
-    info->DGAFuncs.CloseFramebuffer      = NULL;
-    info->DGAFuncs.SetMode               = RADEON_SetMode;
-    info->DGAFuncs.SetViewport           = RADEON_SetViewport;
-    info->DGAFuncs.GetViewport           = RADEON_GetViewport;
-
-    info->DGAFuncs.Sync                  = NULL;
-    info->DGAFuncs.FillRect              = NULL;
-    info->DGAFuncs.BlitRect              = NULL;
-    info->DGAFuncs.BlitTransRect         = NULL;
-
-#ifdef USE_EXA
-    /*info->DGAFuncs.Sync              = info->exa.accel->Sync;*/
-    if (info->useEXA) {
-	/*if (info->exa.accel.PrepareSolid && info->exa.accel.Solid) {
-	    info->DGAFuncs.FillRect      = RADEON_FillRect;
-	}
-	if (info->exa.accel.PrepareCopy && info->exa.accel.Copy) {
-	    info->DGAFuncs.BlitRect      = RADEON_BlitRect;
-	}*/
-    }
-#endif /* USE_EXA */
-#ifdef USE_XAA
-    if (!info->useEXA && info->accel_state->accel) {
-	info->DGAFuncs.Sync              = info->accel_state->accel->Sync;
-	if (info->accel_state->accel->SetupForSolidFill &&
-	    info->accel_state->accel->SubsequentSolidFillRect)
-	    info->DGAFuncs.FillRect      = RADEON_FillRect;
-	if (info->accel_state->accel->SetupForScreenToScreenCopy &&
-	    info->accel_state->accel->SubsequentScreenToScreenCopy) {
-	    info->DGAFuncs.BlitRect      = RADEON_BlitRect;
-	    info->DGAFuncs.BlitTransRect = RADEON_BlitTransRect;
-	}
-    }
-#endif /* USE_XAA */
-
-    return DGAInit(pScreen, &info->DGAFuncs, modes, num);
-}
-
-static Bool RADEON_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
-{
-    static RADEONFBLayout  SavedLayouts[MAXSCREENS];
-    int                    indx = pScrn->pScreen->myNum;
-    RADEONInfoPtr          info = RADEONPTR(pScrn);
-
-    if (!pMode) { /* restore the original mode */
-	/* put the ScreenParameters back */
-	if (info->DGAactive)
-	    memcpy(&info->CurrentLayout, &SavedLayouts[indx],
-		   sizeof(RADEONFBLayout));
-
-	pScrn->currentMode = info->CurrentLayout.mode;
-
-	RADEONSwitchMode(indx, pScrn->currentMode, 0);
-#ifdef XF86DRI
-	if (info->directRenderingEnabled) {
-	    RADEONCP_STOP(pScrn, info);
-	}
-#endif
-	if (info->accelOn)
-	    RADEONEngineInit(pScrn);
-#ifdef XF86DRI
-	if (info->directRenderingEnabled) {
-	    RADEONCP_START(pScrn, info);
-	}
-#endif
-	RADEONAdjustFrame(indx, 0, 0, 0);
-	info->DGAactive = FALSE;
-    } else {
-	if (!info->DGAactive) {  /* save the old parameters */
-	    memcpy(&SavedLayouts[indx], &info->CurrentLayout,
-		   sizeof(RADEONFBLayout));
-	    info->DGAactive = TRUE;
-	}
-
-	info->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel;
-	info->CurrentLayout.depth        = pMode->depth;
-	info->CurrentLayout.displayWidth = (pMode->bytesPerScanline /
-					    (pMode->bitsPerPixel >> 3));
-	info->CurrentLayout.pixel_bytes  = pMode->bitsPerPixel / 8;
-	info->CurrentLayout.pixel_code   = (pMode->bitsPerPixel != 16
-					    ? pMode->bitsPerPixel
-					    : pMode->depth);
-	/* RADEONModeInit() will set the mode field */
-
-	RADEONSwitchMode(indx, pMode->mode, 0);
-
-#ifdef XF86DRI
-	if (info->directRenderingEnabled) {
-	    RADEONCP_STOP(pScrn, info);
-	}
-#endif
-	if (info->accelOn)
-	    RADEONEngineInit(pScrn);
-#ifdef XF86DRI
-	if (info->directRenderingEnabled) {
-	    RADEONCP_START(pScrn, info);
-	}
-#endif
-    }
-
-    return TRUE;
-}
-
-static int RADEON_GetViewport(ScrnInfoPtr pScrn)
-{
-    RADEONInfoPtr  info = RADEONPTR(pScrn);
-
-    return info->DGAViewportStatus;
-}
-
-static void RADEON_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
-{
-    RADEONInfoPtr  info = RADEONPTR(pScrn);
-
-    RADEONAdjustFrame(pScrn->pScreen->myNum, x, y, flags);
-    info->DGAViewportStatus = 0;  /* FIXME */
-}
-
-
-#ifdef USE_XAA
-
-static void RADEON_FillRect(ScrnInfoPtr pScrn,
-			    int x, int y, int w, int h,
-			    unsigned long color)
-{
-    RADEONInfoPtr  info = RADEONPTR(pScrn);
-
-#ifdef USE_EXA
-    /* XXX */
-    if (info->useEXA) {
-	/*
-	info->exa.accel.PrepareSolid(pScrn, color, GXcopy, (uint32_t)(~0));
-	info->exa.accel.Solid(pScrn, x, y, x+w, y+h);
-	info->exa.accel.DoneSolid();
-	*/
-	RADEON_MARK_SYNC(info, pScrn);
-    }
-#endif /* USE_EXA */
-#ifdef USE_XAA
-    if (!info->useEXA) {
-	(*info->accel_state->accel->SetupForSolidFill)(pScrn, color, GXcopy, (uint32_t)(~0));
-	(*info->accel_state->accel->SubsequentSolidFillRect)(pScrn, x, y, w, h);
-        if (pScrn->bitsPerPixel == info->CurrentLayout.bitsPerPixel)
-	    RADEON_MARK_SYNC(info, pScrn);
-    }
-#endif /* USE_XAA */
-
-}
-
-static void RADEON_BlitRect(ScrnInfoPtr pScrn,
-			    int srcx, int srcy, int w, int h,
-			    int dstx, int dsty)
-{
-    RADEONInfoPtr  info = RADEONPTR(pScrn);
-    int            xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
-    int            ydir = (srcy < dsty) ? -1 : 1;
-
-	#ifdef USE_EXA
-    /* XXX */
-    if (info->useEXA) {
-	/*
-	info->exa.accel.PrepareCopy(pScrn, color, GXcopy, (uint32_t)(~0));
-	info->exa.accel.Copy(pScrn, srcx, srcy, dstx, dsty, w, h);
-	info->exa.accel.DoneCopy();
-	*/
-	RADEON_MARK_SYNC(info, pScrn);
-    }
-#endif /* USE_EXA */
-#ifdef USE_XAA
-    if (!info->useEXA) {
-	(*info->accel_state->accel->SetupForScreenToScreenCopy)(pScrn, xdir, ydir,
-								GXcopy, (uint32_t)(~0), -1);
-	(*info->accel_state->accel->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy,
-								  dstx, dsty, w, h);
-        if (pScrn->bitsPerPixel == info->CurrentLayout.bitsPerPixel)
-	    RADEON_MARK_SYNC(info, pScrn);
-    }
-#endif /* USE_XAA */
-}
-
-static void RADEON_BlitTransRect(ScrnInfoPtr pScrn,
-				 int srcx, int srcy, int w, int h,
-				 int dstx, int dsty, unsigned long color)
-{
-    RADEONInfoPtr  info = RADEONPTR(pScrn);
-    int            xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
-    int            ydir = (srcy < dsty) ? -1 : 1;
-
-    info->accel_state->XAAForceTransBlit = TRUE;
-    (*info->accel_state->accel->SetupForScreenToScreenCopy)(pScrn, xdir, ydir,
-							    GXcopy, (uint32_t)(~0), color);
-
-    info->accel_state->XAAForceTransBlit = FALSE;
-
-    (*info->accel_state->accel->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy,
-							      dstx, dsty, w, h);
-
-    if (pScrn->bitsPerPixel == info->CurrentLayout.bitsPerPixel)
-        RADEON_MARK_SYNC(info, pScrn);
-}
-
-#endif /* USE_XAA */
-
-static Bool RADEON_OpenFramebuffer(ScrnInfoPtr pScrn,
-				   char **name,
-				   unsigned char **mem,
-				   int *size, int *offset, int *flags)
-{
-    RADEONInfoPtr  info = RADEONPTR(pScrn);
-
-    *name   = NULL;             /* no special device */
-    *mem    = (unsigned char*)info->LinearAddr;
-    *size   = info->FbMapSize;
-    *offset = 0;
-    *flags  = 0; /* DGA_NEED_ROOT; -- don't need root, just /dev/mem access */
-
-    return TRUE;
-}
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index e766093..67fb9b7 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -3754,9 +3754,9 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen,
     }
 
     /* DGA setup */
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Initializing DGA\n");
-    RADEONDGAInit(pScreen);
+#ifdef XFreeXDGA
+    xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset);
+#endif
 
     /* Init Xv */
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
@@ -5880,10 +5880,6 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen)
     info->cursor = NULL;
 
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Disposing DGA\n");
-    if (info->DGAModes) xfree(info->DGAModes);
-    info->DGAModes = NULL;
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "Unmapping memory\n");
     RADEONUnmapMem(pScrn);
 
commit 651fe5a47435c6a5cc1cdfb33c5c6601d692adcb
Author: Adam Jackson <ajax at redhat.com>
Date:   Tue Sep 8 13:21:07 2009 +1000

    radeon: fix dri2 struct zeroing

diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index e94107c..db46d27 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -321,7 +321,7 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
 {
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     RADEONInfoPtr info = RADEONPTR(pScrn);
-    DRI2InfoRec dri2_info;
+    DRI2InfoRec dri2_info = { 0 };
     int fd;
     char *bus_id;
     char *tmp_bus_id;
commit 6990f2ac6478bf92929a4400ef84fb2142699204
Merge: 917f2d7... 853f4c3...
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Sep 8 11:26:32 2009 +1000

    Merge branch 'r6xx-cs'

commit 853f4c3d1ea8f975ab2855f18d3ae336a4095091
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Sep 8 11:25:39 2009 +1000

    r600: more alignment fixups + vb map/unmap
    
    I'm not so sure the vb map/unmap is a good idea, I think
    it pretty much locksteps the cpu/gpu, so we should really
    work out if we really need to flush this often, since
    mesa doesn't have to and we are just doing 3D ops.

diff --git a/src/r600_exa.c b/src/r600_exa.c
index db4c0b1..c143b69 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -780,8 +780,7 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
 		radeon_bo_unref(accel_state->copy_area_bo);
 		accel_state->copy_area_bo = NULL;
 	    }
-	    accel_state->copy_area_bo = radeon_bo_open(info->bufmgr, 0, size,
-						       4096,
+	    accel_state->copy_area_bo = radeon_bo_open(info->bufmgr, 0, size, 0,
 						       RADEON_GEM_DOMAIN_VRAM,
 						       0);
 	    if (accel_state->copy_area_bo == NULL) {
@@ -789,7 +788,7 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
 		return FALSE;
 	    }
 	    radeon_cs_space_add_persistent_bo(info->cs, accel_state->copy_area_bo,
-					      RADEON_GEM_DOMAIN_VRAM, 0);
+					      0, RADEON_GEM_DOMAIN_VRAM);
 	    if (radeon_cs_space_check(info->cs)) {
 		radeon_bo_unref(accel_state->copy_area_bo);
 		accel_state->copy_area_bo = NULL;
@@ -2157,7 +2156,7 @@ R600AllocShaders(ScrnInfoPtr pScrn, ScreenPtr pScreen)
 #ifdef XF86DRM_MODE
 #if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 4)
     if (info->cs) {
-	accel_state->shaders_bo = radeon_bo_open(info->bufmgr, 0, size, 4096,
+	accel_state->shaders_bo = radeon_bo_open(info->bufmgr, 0, size, 0,
 						 RADEON_GEM_DOMAIN_VRAM, 0);
 	if (accel_state->shaders_bo == NULL) {
 	    ErrorF("Allocating shader failed\n");
diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index 6346e52..985595e 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -50,8 +50,7 @@ void r600_cs_flush_indirect(ScrnInfoPtr pScrn)
 
     if (info->accel_state->vb_bo) {
 	radeon_bo_unmap(info->accel_state->vb_bo);
-	radeon_bo_ref(info->accel_state->vb_bo);
-	info->accel_state->vb_bo = NULL;
+	info->accel_state->vb_ptr = NULL;
     }
 
     radeon_cs_emit(info->cs);
@@ -1161,15 +1160,17 @@ r600_vb_get(ScrnInfoPtr pScrn)
 	if (accel_state->vb_bo == NULL) {
 	    accel_state->vb_mc_addr = 0;
 	    accel_state->vb_bo = radeon_bo_open(info->bufmgr, 0, 16 * 1024,
-						4096, RADEON_GEM_DOMAIN_GTT, 0);
+						0, RADEON_GEM_DOMAIN_GTT, 0);
 	    if (accel_state->vb_bo == NULL)
 		return FALSE;
+	    accel_state->vb_total = 16 * 1024;
+	}
+	if (!accel_state->vb_ptr) {
 	    ret = radeon_bo_map(accel_state->vb_bo, 1);
 	    if (ret) {
 		FatalError("failed to vb %d\n", ret);
 		return FALSE;
 	    }
-	    accel_state->vb_total = 16 * 1024;
 	    accel_state->vb_ptr = accel_state->vb_bo->ptr;
 	}
     } else
commit 917f2d7cd1815279710939edc27133ca6609460f
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Sun Sep 6 10:53:29 2009 -0400

    RV280: add agp quirk
    
    deb bug 545040

diff --git a/src/radeon_dri.c b/src/radeon_dri.c
index 8a7ed83..d67d649 100644
--- a/src/radeon_dri.c
+++ b/src/radeon_dri.c
@@ -800,7 +800,9 @@ static radeon_agpmode_quirk radeon_agpmode_quirk_list[] = {
     /* VIA VT8377 Host Bridge / RV280 Needs AGPMode 4 (ati ML) */
     { PCI_VENDOR_VIA,0x3189,    PCI_VENDOR_ATI,0x5964,  0x148c,0x2073,           4 },
     /* VIA VT8377 Host Bridge / RV280 Needs AGPMode 4 (fdo #12544) */
-    { PCI_VENDOR_VIA,0x3189,    PCI_VENDOR_ATI,0x5964,  0x1043,0xc008,           4 },
+    { PCI_VENDOR_VIA,0x3189,    PCI_VENDOR_ATI,0x5964,  PCI_VENDOR_ASUS,0xc008,  4 },
+    /* VIA VT8377 Host Bridge / RV280 Needs AGPMode 4 (deb #545040) */
+    { PCI_VENDOR_VIA,0x3189,    PCI_VENDOR_ATI,0x5960,  PCI_VENDOR_ASUS,0x004c,  4 },
 
     /* ATI Host Bridge / RV280 [M9+] Needs AGPMode 1 (phoronix forum) */
     { PCI_VENDOR_ATI,0xcbb2,    PCI_VENDOR_ATI,0x5c61,  PCI_VENDOR_SONY,0x8175,  1 },
commit 78fcbf577ad6eba6399cc39f74b7ce5f9c8e265e
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Thu Sep 3 14:55:05 2009 +0200

    EXA: Check for solid/gradient pictures the same way for all generations.
    
    In particular, also catch them for >= R300.

diff --git a/src/r600_exa.c b/src/r600_exa.c
index f2ddc67..d2df1db 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -1344,6 +1344,9 @@ static Bool R600CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP
     if (op >= (int) (sizeof(R600BlendOp) / sizeof(R600BlendOp[0])))
 	RADEON_FALLBACK(("Unsupported Composite op 0x%x\n", op));
 
+    if (!pSrcPicture->pDrawable)
+	RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
+
     pSrcPixmap = RADEONGetDrawablePixmap(pSrcPicture->pDrawable);
 
     max_tex_w = 8192;
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index f842b97..6053eef 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -489,7 +489,7 @@ static Bool R100CheckComposite(int op, PicturePtr pSrcPicture,
 	RADEON_FALLBACK(("Unsupported Composite op 0x%x\n", op));
 
     if (!pSrcPicture->pDrawable)
-	return FALSE;
+	RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
 
     /* r100 limit should be 2048, there are issues with 2048
      * see 197a62704742a4a19736c2637ac92d1dc5ab34ed
@@ -865,7 +865,7 @@ static Bool R200CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP
 	RADEON_FALLBACK(("Unsupported Composite op 0x%x\n", op));
 
     if (!pSrcPicture->pDrawable)
-	return FALSE;
+	RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
 
     /* r200 limit should be 2048, there are issues with 2048
      * see bug 19269
@@ -1315,6 +1315,9 @@ static Bool R300CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP
     if (op >= sizeof(RadeonBlendOp) / sizeof(RadeonBlendOp[0]))
 	RADEON_FALLBACK(("Unsupported Composite op 0x%x\n", op));
 
+    if (!pSrcPicture->pDrawable)
+	RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
+
     pSrcPixmap = RADEONGetDrawablePixmap(pSrcPicture->pDrawable);
 
     if (IS_R500_3D) {
commit 794ae743c305331741e7cf45dd71c755fe325ed5
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Wed Sep 2 09:19:17 2009 +0200

    EXA: Fix Composite restart dst/src switcheroo.
    
    Fixes http://bugs.freedesktop.org/show_bug.cgi?id=22636 .
    
    Now, where's that brown paper bag? :}

diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index c3beadc..f842b97 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -2128,12 +2128,12 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
 	FUNC_NAME(RadeonDoneComposite)(info->accel_state->dst_pix);
 	radeon_cs_flush_indirect(pScrn);
 	info->accel_state->exa->PrepareComposite(info->accel_state->composite_op,
-						 info->accel_state->dst_pic,
-						 info->accel_state->msk_pic,
 						 info->accel_state->src_pic,
-						 info->accel_state->dst_pix,
+						 info->accel_state->msk_pic,
+						 info->accel_state->dst_pic,
+						 info->accel_state->src_pix,
 						 info->accel_state->msk_pix,
-						 info->accel_state->src_pix);
+						 info->accel_state->dst_pix);
     }
 #endif
 
commit c4ab50c5eafca3d04129a72453496eb8afb26b34
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Sep 1 13:43:00 2009 -0400

    radeon: add some notes about DVO setup

diff --git a/src/legacy_output.c b/src/legacy_output.c
index 7134ee1..73c86b9 100644
--- a/src/legacy_output.c
+++ b/src/legacy_output.c
@@ -1216,14 +1216,25 @@ RADEONInitFP2Registers(xf86OutputPtr output, RADEONSavePtr save,
 	if ((info->Chipset == PCI_CHIP_RV350_NP) &&
 	    (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1028) &&
 	    (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x2001))
-	    save->fp2_gen_cntl |= R300_FP2_DVO_CLOCK_MODE_SINGLE; /* Dell Inspiron 8600 */
+	    save->fp2_gen_cntl |= R200_FP2_DVO_CLOCK_MODE_SINGLE; /* Dell Inspiron 8600 */
 	else
-	    save->fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE;
+	    save->fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R200_FP2_DVO_CLOCK_MODE_SINGLE;
+    }
+
 #if 0
-	if (mode->Clock > 165000)
+    /* DVO configurations:
+     * SDR single channel (data rate 165 Mhz, port width 12 bits)
+     * DDR single channel (data rate 330 Mhz, port width 12 bits)
+     * SDR dual   channel (data rate 330 Mhz, port width 24 bits)
+     * - dual channel is only available on r3xx+
+     */
+    if (info->ChipFamily >= CHIP_FAMILY_R200) {
+	if (sdr)
+	    save->fp2_gen_cntl |= R200_FP2_DVO_RATE_SEL_SDR;
+	if (IS_R300_VARIANT && dual channel)
 	    save->fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;
-#endif
     }
+#endif
 
     if (IsPrimary) {
 	if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) {
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index 3a4eda1..5467286 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -882,7 +882,7 @@
 #       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 R300_FP2_DVO_CLOCK_MODE_SINGLE  (1 << 28)
+#       define R200_FP2_DVO_CLOCK_MODE_SINGLE  (1 << 28)
 #       define R300_FP2_DVO_DUAL_CHANNEL_EN    (1 << 29)
 #define RADEON_FP_H_SYNC_STRT_WID           0x02c4
 #define RADEON_FP_H2_SYNC_STRT_WID          0x03c4
commit 22fbd6476f4b3513378e848affc4dd269e9d4498
Author: Dave Airlie <airlied at itt42.(none)>
Date:   Tue Sep 1 15:22:57 2009 +1000

    r100/r200: seriously WRAP is illegal for rectangular textures
    
    unless we scale all the bos up to POT

diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 69d8140..c3beadc 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -415,7 +415,10 @@ static Bool FUNC_NAME(R100TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 
     switch (repeatType) {
 	case RepeatNormal:
-	    txfilter |= RADEON_CLAMP_S_WRAP | RADEON_CLAMP_T_WRAP;
+	    if (txformat & RADEON_TXFORMAT_NON_POWER2)
+		txfilter |= RADEON_CLAMP_S_CLAMP_LAST | RADEON_CLAMP_T_CLAMP_LAST;
+	    else
+	        txfilter |= RADEON_CLAMP_S_WRAP | RADEON_CLAMP_T_WRAP;
 	    break;
 	case RepeatPad:
 	    txfilter |= RADEON_CLAMP_S_CLAMP_LAST | RADEON_CLAMP_T_CLAMP_LAST;
@@ -799,7 +802,10 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 
     switch (repeatType) {
 	case RepeatNormal:
-	    txfilter |= R200_CLAMP_S_WRAP | R200_CLAMP_T_WRAP;
+	    if (txformat & R200_TXFORMAT_NON_POWER2)
+		txfilter |= R200_CLAMP_S_CLAMP_LAST | R200_CLAMP_T_CLAMP_LAST;
+	    else
+	        txfilter |= R200_CLAMP_S_WRAP | R200_CLAMP_T_WRAP;
 	    break;
 	case RepeatPad:
 	    txfilter |= R200_CLAMP_S_CLAMP_LAST | R200_CLAMP_T_CLAMP_LAST;
commit 8f4196e88855f10762254fca9e0a0988e7b5562f
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Mon Aug 31 19:41:59 2009 -0400

    r6xx/r7xx: various CS fixes from Dave

diff --git a/src/r600_exa.c b/src/r600_exa.c
index cfe041f..db4c0b1 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -720,6 +720,7 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
 
     accel_state->dst_pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8);
     accel_state->src_pitch[0] = exaGetPixmapPitch(pSrc) / (pSrc->drawable.bitsPerPixel / 8);
+    accel_state->same_surface = FALSE;
 
 #if defined(XF86DRM_MODE)
     if (info->cs) {
@@ -728,11 +729,15 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
 	accel_state->src_bo[0] = radeon_get_pixmap_bo(pSrc);
 	accel_state->src_bo[1] = NULL;
 	accel_state->dst_bo = radeon_get_pixmap_bo(pDst);
+	if (accel_state->dst_bo == accel_state->src_bo[0])
+	    accel_state->same_surface = TRUE;
     } else
 #endif
     {
 	accel_state->src_mc_addr[0] = exaGetPixmapOffset(pSrc) + info->fbLocation + pScrn->fbOffset;
 	accel_state->dst_mc_addr = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
+	if (exaGetPixmapOffset(pSrc) == exaGetPixmapOffset(pDst))
+	    accel_state->same_surface = TRUE;
     }
 
     accel_state->src_width[0] = pSrc->drawable.width;
@@ -766,9 +771,8 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
     accel_state->rop = rop;
     accel_state->planemask = planemask;
 
-    if (exaGetPixmapOffset(pSrc) == exaGetPixmapOffset(pDst)) {
+    if (accel_state->same_surface == TRUE) {
 	unsigned long size = pDst->drawable.height * accel_state->dst_pitch * pDst->drawable.bitsPerPixel/8;
-	accel_state->same_surface = TRUE;
 
 #if defined(XF86DRM_MODE)
 	if (info->cs) {
@@ -802,9 +806,7 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
 	    }
 	    accel_state->copy_area = exaOffscreenAlloc(pDst->drawable.pScreen, size, 256, TRUE, NULL, NULL);
 	}
-    } else {
-	accel_state->same_surface = FALSE;
-
+    } else
 	R600DoPrepareCopy(pScrn,
 			  accel_state->src_pitch[0], pSrc->drawable.width, pSrc->drawable.height,
 			  accel_state->src_mc_addr[0], accel_state->src_bo[0], pSrc->drawable.bitsPerPixel,
@@ -812,8 +814,6 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
 			  accel_state->dst_mc_addr, accel_state->dst_bo, pDst->drawable.bitsPerPixel,
 			  rop, planemask);
 
-    }
-
     return TRUE;
 }
 
@@ -853,8 +853,8 @@ R600OverlapCopy(PixmapPtr pDst,
     }
 #endif
 
-    if (is_overlap(srcX, srcX + w, srcY, srcY + h,
-		   dstX, dstX + w, dstY, dstY + h)) {
+    if (is_overlap(srcX, srcX + (w - 1), srcY, srcY + (h - 1),
+		   dstX, dstX + (w - 1), dstY, dstY + (h - 1))) {
         /* Calculate height/width of non-overlapping area */
         hchunk = (srcX < dstX) ? (dstX - srcX) : (srcX - dstX);
         vchunk = (srcY < dstY) ? (dstY - srcY) : (srcY - dstY);
@@ -1008,7 +1008,8 @@ R600Copy(PixmapPtr pDst,
 #endif
 
     if (accel_state->same_surface &&
-	is_overlap(srcX, srcX + w, srcY, srcY + h, dstX, dstX + w, dstY, dstY + h)) {
+	is_overlap(srcX, srcX + (w - 1), srcY, srcY + (h - 1),
+		   dstX, dstX + (w - 1), dstY, dstY + (h - 1))) {
 	if (accel_state->copy_area) {
 	    uint32_t pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8);
 	    uint32_t orig_offset, tmp_offset;
diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index 7c7f469..6346e52 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -48,9 +48,11 @@ void r600_cs_flush_indirect(ScrnInfoPtr pScrn)
     if (!info->cs->cdw)
 	return;
 
-    if (info->accel_state->vb_bo)
+    if (info->accel_state->vb_bo) {
 	radeon_bo_unmap(info->accel_state->vb_bo);
-    info->accel_state->vb_bo = NULL;
+	radeon_bo_ref(info->accel_state->vb_bo);
+	info->accel_state->vb_bo = NULL;
+    }
 
     radeon_cs_emit(info->cs);
     radeon_cs_erase(info->cs);
commit a32384f9b9ed73c14484a380dfa14652ed478ad6
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Mon Aug 31 13:26:05 2009 -0400

    r1xx: fix textured video
    
    Copy/paste bug from when kms support was added.

diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index 35fc316..f069d8f 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -237,7 +237,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		      RADEON_CLAMP_T_CLAMP_LAST |
 		      RADEON_YUV_TO_RGB);
 	OUT_ACCEL_REG(RADEON_PP_TXFORMAT_0, txformat | RADEON_TXFORMAT_ST_ROUTE_STQ0);
-	OUT_TEXTURE_REG(R200_PP_TXOFFSET_0, txoffset, pPriv->src_bo);
+	OUT_TEXTURE_REG(RADEON_PP_TXOFFSET_0, txoffset, pPriv->src_bo);
 	OUT_ACCEL_REG(RADEON_PP_TXCBLEND_0,
 		      RADEON_COLOR_ARG_A_ZERO |
 		      RADEON_COLOR_ARG_B_ZERO |
@@ -264,7 +264,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		      RADEON_CLAMP_S_CLAMP_LAST |
 		      RADEON_CLAMP_T_CLAMP_LAST);
 	OUT_ACCEL_REG(RADEON_PP_TXFORMAT_1, txformat | RADEON_TXFORMAT_ST_ROUTE_STQ1);
-	OUT_TEXTURE_REG(R200_PP_TXOFFSET_1, txoffset + pPriv->planeu_offset, pPriv->src_bo);
+	OUT_TEXTURE_REG(RADEON_PP_TXOFFSET_1, txoffset + pPriv->planeu_offset, pPriv->src_bo);
 	OUT_ACCEL_REG(RADEON_PP_TXCBLEND_1,
 		      RADEON_COLOR_ARG_A_ZERO |
 		      RADEON_COLOR_ARG_B_ZERO |
@@ -288,7 +288,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		      RADEON_CLAMP_S_CLAMP_LAST |
 		      RADEON_CLAMP_T_CLAMP_LAST);
 	OUT_ACCEL_REG(RADEON_PP_TXFORMAT_2, txformat | RADEON_TXFORMAT_ST_ROUTE_STQ1);
-	OUT_TEXTURE_REG(R200_PP_TXOFFSET_2, txoffset + pPriv->planev_offset, pPriv->src_bo);
+	OUT_TEXTURE_REG(RADEON_PP_TXOFFSET_2, txoffset + pPriv->planev_offset, pPriv->src_bo);
 	OUT_ACCEL_REG(RADEON_PP_TXCBLEND_2,
 		      RADEON_COLOR_ARG_A_ZERO |
 		      RADEON_COLOR_ARG_B_ZERO |
commit 3d6bf0f8cf128ee67d448491be44d345547b75c5
Author: Pauli Nieminen <suokkos at gmail.com>
Date:   Fri Aug 28 17:05:44 2009 +0300

    radeon: Fix DRI2BufferPtr to be DRI2Buffer2Ptr for xserver 1.6.
    
    Bump requirement for xserver in KMS mode to 1.6.2 for DRI2Buffer2Ptr.

diff --git a/configure.ac b/configure.ac
index 48375ee..66f76aa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -140,7 +140,7 @@ if test "$DRI" = yes; then
 	   	AC_CHECK_HEADER(xf86drmMode.h,[DRM_MODE=yes],[DRM_MODE=no],[#include <stdint.h>
 #include <stdlib.h>])
 		if test "x$DRM_MODE" = xyes; then
-		   	PKG_CHECK_MODULES(LIBDRM_RADEON, [xorg-server >= 1.6 libdrm_radeon],
+			PKG_CHECK_MODULES(LIBDRM_RADEON, [xorg-server >= 1.6.2 libdrm_radeon],
 			[LIBDRM_RADEON=yes], [LIBDRM_RADEON=no])
 
 			if test "x$LIBDRM_RADEON" = xyes; then
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 613fde8..051cc78 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -46,6 +46,12 @@
 #define USE_DRI2_1_1_0
 #endif
 
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,0, 0)
+typedef DRI2BufferPtr BufferPtr;
+#else
+typedef DRI2Buffer2Ptr BufferPtr;
+#endif
+
 struct dri2_buffer_priv {
     PixmapPtr   pixmap;
     unsigned int attachment;
@@ -53,13 +59,13 @@ struct dri2_buffer_priv {
 
 
 #ifndef USE_DRI2_1_1_0
-static DRI2BufferPtr
+static BufferPtr
 radeon_dri2_create_buffers(DrawablePtr drawable,
                            unsigned int *attachments,
                            int count)
 {
     ScreenPtr pScreen = drawable->pScreen;
-    DRI2BufferPtr buffers;
+    BufferPtr buffers;
     struct dri2_buffer_priv *privates;
     PixmapPtr pixmap, depth_pixmap;
     struct radeon_exa_pixmap_priv *driver_priv;
@@ -131,13 +137,13 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
     return buffers;
 }
 #else
-static DRI2BufferPtr
+static BufferPtr
 radeon_dri2_create_buffer(DrawablePtr drawable,
                           unsigned int attachment,
                           unsigned int format)
 {
     ScreenPtr pScreen = drawable->pScreen;
-    DRI2BufferPtr buffers;
+    BufferPtr buffers;
     struct dri2_buffer_priv *privates;
     PixmapPtr pixmap, depth_pixmap;
     struct radeon_exa_pixmap_priv *driver_priv;
@@ -214,7 +220,7 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
 #ifndef USE_DRI2_1_1_0
 static void
 radeon_dri2_destroy_buffers(DrawablePtr drawable,
-                            DRI2BufferPtr buffers,
+                            BufferPtr buffers,
                             int count)
 {
     ScreenPtr pScreen = drawable->pScreen;
@@ -232,7 +238,7 @@ radeon_dri2_destroy_buffers(DrawablePtr drawable,
 }
 #else
 static void
-radeon_dri2_destroy_buffer(DrawablePtr drawable, DRI2BufferPtr buffers)
+radeon_dri2_destroy_buffer(DrawablePtr drawable, BufferPtr buffers)
 {
     if(buffers)
     {
@@ -251,8 +257,8 @@ radeon_dri2_destroy_buffer(DrawablePtr drawable, DRI2BufferPtr buffers)
 static void
 radeon_dri2_copy_region(DrawablePtr drawable,
                         RegionPtr region,
-                        DRI2BufferPtr dest_buffer,
-                        DRI2BufferPtr src_buffer)
+                        BufferPtr dest_buffer,
+                        BufferPtr src_buffer)
 {
     struct dri2_buffer_priv *src_private = src_buffer->driverPrivate;
     struct dri2_buffer_priv *dst_private = dest_buffer->driverPrivate;
commit 6521dbf3884185ca5692d35d879d251890cc4f08
Author: Roland Scheidegger <sroland at tungstengraphics.com>
Date:   Sat Aug 29 12:11:03 2009 +0200

    r100/r200: fix section size mismatch for textured video
    
    this fixes the driver complaining though reportedly it still does
    not work (on r100)

diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index 1d6b2e7..35fc316 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -218,7 +218,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	txpitch = ((pPriv->src_pitch >> 1) + 63) & ~63;
 	txpitch -= 32;
 
-	BEGIN_ACCEL(23);
+	BEGIN_ACCEL_RELOC(23, 3);
 
 	OUT_ACCEL_REG(RADEON_SE_VTX_FMT, (RADEON_SE_VTX_FMT_XY |
 					  RADEON_SE_VTX_FMT_ST0 |
@@ -307,7 +307,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	FINISH_ACCEL();
     } else {
 	vtx_count = 4;
-	BEGIN_ACCEL(9);
+	BEGIN_ACCEL_RELOC(9, 1);
 
 	OUT_ACCEL_REG(RADEON_SE_VTX_FMT, (RADEON_SE_VTX_FMT_XY |
 					  RADEON_SE_VTX_FMT_ST0));
@@ -643,7 +643,7 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	txpitch = ((pPriv->src_pitch >> 1) + 63) & ~63;
 	txpitch -= 32;
 
-	BEGIN_ACCEL(36);
+	BEGIN_ACCEL_RELOC(36, 3);
 
 	OUT_ACCEL_REG(RADEON_PP_CNTL,
 		      RADEON_TEX_0_ENABLE | RADEON_TEX_1_ENABLE | RADEON_TEX_2_ENABLE |
@@ -801,7 +801,7 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     } else {
 	vtx_count = 4;
 
-	BEGIN_ACCEL(24);
+	BEGIN_ACCEL_RELOC(24, 1);
 
 	OUT_ACCEL_REG(RADEON_PP_CNTL,
 		      RADEON_TEX_0_ENABLE |
commit 39dfac41eebbcdacb1ae0c17cea325ea2966c4a5
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Fri Aug 28 12:20:04 2009 +0200

    EXA: RENDER repeat fix and more cleanup.
    
    Apparently changing pPict->repeatType causes badness, see
    http://bugs.freedesktop.org/show_bug.cgi?id=23560 .
    
    Now we just use a normalized repeatType value derived from pPict->repeat and
    pPict->repeatType everywhere.

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 57867f1..f2ddc67 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -1062,6 +1062,7 @@ static Bool R600CheckCompositeTexture(PicturePtr pPict,
 {
     int w = pPict->pDrawable->width;
     int h = pPict->pDrawable->height;
+    unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
     unsigned int i;
     int max_tex_w, max_tex_h;
 
@@ -1092,7 +1093,7 @@ static Bool R600CheckCompositeTexture(PicturePtr pPict,
      * clipping.
      */
     /* FIXME R6xx */
-    if (pPict->transform != 0 && !pPict->repeat && PICT_FORMAT_A(pPict->format) == 0) {
+    if (pPict->transform != 0 && repeatType == RepeatNone && PICT_FORMAT_A(pPict->format) == 0) {
 	if (!(((op == PictOpSrc) || (op == PictOpClear)) && (PICT_FORMAT_A(pDstPict->format) == 0)))
 	    RADEON_FALLBACK(("REPEAT_NONE unsupported for transformed xRGB source\n"));
     }
@@ -1108,6 +1109,7 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
     struct radeon_accel_state *accel_state = info->accel_state;
     int w = pPict->pDrawable->width;
     int h = pPict->pDrawable->height;
+    unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
     unsigned int i;
     tex_resource_t  tex_res;
     tex_sampler_t   tex_samp;
@@ -1258,11 +1260,7 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
     tex_samp.id                 = unit;
     tex_samp.border_color       = SQ_TEX_BORDER_COLOR_TRANS_BLACK;
 
-    /* Unfortunately we can't rely on the X server doing this for us */
-    if (!pPict->repeat)
-	pPict->repeatType = RepeatNone;
-
-    switch (pPict->repeatType) {
+    switch (repeatType) {
     case RepeatNormal:
 	tex_samp.clamp_x            = SQ_TEX_WRAP;
 	tex_samp.clamp_y            = SQ_TEX_WRAP;
@@ -1280,7 +1278,7 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
 	tex_samp.clamp_y            = SQ_TEX_CLAMP_BORDER;
 	break;
     default:
-	RADEON_FALLBACK(("Bad repeat 0x%x\n", pPict->repeatType));
+	RADEON_FALLBACK(("Bad repeat 0x%x\n", repeatType));
     }
 
     switch (pPict->filter) {
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index cc97760..69d8140 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -233,10 +233,11 @@ static Bool RADEONCheckTexturePOT(PicturePtr pPict, Bool canTile)
 {
     int w = pPict->pDrawable->width;
     int h = pPict->pDrawable->height;
+    unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
 
-    if (pPict->repeat && pPict->repeatType != RepeatPad &&
+    if ((repeatType == RepeatNormal || repeatType == RepeatReflect) &&
 	((w & (w - 1)) != 0 || (h & (h - 1)) != 0) &&
-	!(pPict->repeatType == RepeatNormal && !pPict->transform && canTile))
+	!(repeatType == RepeatNormal && !pPict->transform && canTile))
 	RADEON_FALLBACK(("NPOT repeating %s unsupported (%dx%d), transform=%d\n",
 			 canTile ? "source" : "mask", w, h, pPict->transform != 0));
 
@@ -280,11 +281,12 @@ static Bool RADEONSetupSourceTile(PicturePtr pPict,
 				  Bool needMatchingPitch)
 {
     RINFO_FROM_SCREEN(pPix->drawable.pScreen);
+    unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
 
     info->accel_state->need_src_tile_x = info->accel_state->need_src_tile_y = FALSE;
     info->accel_state->src_tile_width = info->accel_state->src_tile_height = 65536; /* "infinite" */
 	    
-    if (pPict->repeat && pPict->repeatType != RepeatPad) {
+    if (repeatType == RepeatNormal || repeatType == RepeatReflect) {
 	Bool badPitch = needMatchingPitch && !RADEONPitchMatches(pPix);
 	
 	int w = pPict->pDrawable->width;
@@ -300,7 +302,7 @@ static Bool RADEONSetupSourceTile(PicturePtr pPict,
 
 	    if ((info->accel_state->need_src_tile_x ||
 		 info->accel_state->need_src_tile_y) &&
-		pPict->repeatType != RepeatNormal)
+		repeatType != RepeatNormal)
 		RADEON_FALLBACK(("Can only tile RepeatNormal at this time\n"));
 
 	    if (!canTile1d)
@@ -362,7 +364,8 @@ static Bool FUNC_NAME(R100TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
     uint32_t txfilter, txformat, txoffset, txpitch;
     int w = pPict->pDrawable->width;
     int h = pPict->pDrawable->height;
-    Bool repeat = pPict->repeat && pPict->repeatType != RepeatPad &&
+    unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
+    Bool repeat = (repeatType == RepeatNormal || repeatType == RepeatReflect) &&
 	!(unit == 0 && (info->accel_state->need_src_tile_x || info->accel_state->need_src_tile_y));
     int i;
     struct radeon_exa_pixmap_priv *driver_priv;
@@ -410,11 +413,7 @@ static Bool FUNC_NAME(R100TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 	RADEON_FALLBACK(("Bad filter 0x%x\n", pPict->filter));
     }
 
-    /* Unfortunately we can't rely on the X server doing this for us */
-    if (!pPict->repeat)
-	pPict->repeatType = RepeatNone;
-
-    switch (pPict->repeatType) {
+    switch (repeatType) {
 	case RepeatNormal:
 	    txfilter |= RADEON_CLAMP_S_WRAP | RADEON_CLAMP_T_WRAP;
 	    break;
@@ -747,7 +746,8 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
     uint32_t txfilter, txformat, txoffset, txpitch;
     int w = pPict->pDrawable->width;
     int h = pPict->pDrawable->height;
-    Bool repeat = pPict->repeat && pPict->repeatType != RepeatPad &&
+    unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
+    Bool repeat = (repeatType == RepeatNormal || repeatType == RepeatReflect) &&
 	!(unit == 0 && (info->accel_state->need_src_tile_x || info->accel_state->need_src_tile_y));
     int i;
     struct radeon_exa_pixmap_priv *driver_priv;
@@ -797,11 +797,7 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 	RADEON_FALLBACK(("Bad filter 0x%x\n", pPict->filter));
     }
 
-    /* Unfortunately we can't rely on the X server doing this for us */
-    if (!pPict->repeat)
-	pPict->repeatType = RepeatNone;
-
-    switch (pPict->repeatType) {
+    switch (repeatType) {
 	case RepeatNormal:
 	    txfilter |= R200_CLAMP_S_WRAP | R200_CLAMP_T_WRAP;
 	    break;
@@ -1059,6 +1055,7 @@ static Bool R300CheckCompositeTexture(PicturePtr pPict,
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     RADEONInfoPtr info = RADEONPTR(pScrn);
 
+    unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
     int w = pPict->pDrawable->width;
     int h = pPict->pDrawable->height;
     int i;
@@ -1108,7 +1105,7 @@ static Bool R300CheckCompositeTexture(PicturePtr pPict,
      * matter. I have not, however, verified that the X server always does such
      * clipping.
      */
-    if (pPict->transform != 0 && !pPict->repeat && PICT_FORMAT_A(pPict->format) == 0) {
+    if (pPict->transform != 0 && repeatType == RepeatNone && PICT_FORMAT_A(pPict->format) == 0) {
 	if (!(((op == PictOpSrc) || (op == PictOpClear)) && (PICT_FORMAT_A(pDstPict->format) == 0)))
 	    RADEON_FALLBACK(("REPEAT_NONE unsupported for transformed xRGB source\n"));
     }
@@ -1126,6 +1123,7 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
     int w = pPict->pDrawable->width;
     int h = pPict->pDrawable->height;
     int i, pixel_shift;
+    unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
     struct radeon_exa_pixmap_priv *driver_priv;
     ACCEL_PREAMBLE();
 
@@ -1179,11 +1177,7 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 
     txfilter = (unit << R300_TX_ID_SHIFT);
 
-    /* Unfortunately we can't rely on the X server doing this for us */
-    if (!pPict->repeat)
-	pPict->repeatType = RepeatNone;
-
-    switch (pPict->repeatType) {
+    switch (repeatType) {
     case RepeatNormal:
 	if (unit != 0 || !info->accel_state->need_src_tile_x)
 	    txfilter |= R300_TX_CLAMP_S(R300_TX_CLAMP_WRAP);
@@ -1221,7 +1215,7 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 	RADEON_FALLBACK(("Bad filter 0x%x\n", pPict->filter));
     }
 
-    BEGIN_ACCEL_RELOC(pPict->repeat ? 6 : 7, 1);
+    BEGIN_ACCEL_RELOC(repeatType == RepeatNone ? 7 : 6, 1);
     OUT_ACCEL_REG(R300_TX_FILTER0_0 + (unit * 4), txfilter);
     OUT_ACCEL_REG(R300_TX_FILTER1_0 + (unit * 4), 0);
     OUT_ACCEL_REG(R300_TX_FORMAT0_0 + (unit * 4), txformat0);
@@ -1230,7 +1224,7 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 
     EMIT_READ_OFFSET((R300_TX_OFFSET_0 + (unit * 4)), txoffset, pPix);
 
-    if (!pPict->repeat)
+    if (repeatType == RepeatNone)
 	OUT_ACCEL_REG(R300_TX_BORDER_COLOR_0 + (unit * 4), 0);
     FINISH_ACCEL();
 
commit 7d36f13afa5da742aa6c989a2652e92c96e5f80e
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Thu Aug 27 09:52:11 2009 +0200

    KMS: Remove explicit radeon_bo_wait calls before radeon_bo_map.
    
    libdrm_radeon always takes care of this implicitly now.

diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index b7013c9..ca4c523 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -350,8 +350,6 @@ static Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
     if (driver_priv->bo->cref > 1)
         radeon_cs_flush_indirect(pScrn);
     
-    radeon_bo_wait(driver_priv->bo);
-
     /* flush IB */
     ret = radeon_bo_map(driver_priv->bo, 1);
     if (ret) {
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 58cd527..c74b9d9 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -572,7 +572,6 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
                     RADEON_GEM_DOMAIN_GTT);
     FLUSH_RING();
 
-    radeon_bo_wait(scratch);
     r = radeon_bo_map(scratch, 0);
     if (r) {
         r = FALSE;
diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c
index a9d6fc3..932759b 100644
--- a/src/radeon_textured_video.c
+++ b/src/radeon_textured_video.c
@@ -367,7 +367,6 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
     pPriv->src_offset = pPriv->video_offset;
     if (info->cs) {
 	int ret;
-	radeon_bo_wait(pPriv->src_bo);
 	ret = radeon_bo_map(pPriv->src_bo, 1);
 	if (ret)
 	    return BadAlloc;
@@ -690,7 +689,6 @@ Bool radeon_load_bicubic_texture(ScrnInfoPtr pScrn)
 	uint8_t *bicubic_addr;
 	int ret;
 	if (info->cs) {
-	    radeon_bo_wait(info->bicubic_bo);
 	    ret = radeon_bo_map(info->bicubic_bo, 1);
 	    if (ret)
 		return FALSE;
commit 066c90e8f5b93c80195dc43486ad3efa083a1f3a
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Thu Aug 27 09:52:11 2009 +0200

    KMS: Don't use a blit for UploadToScreen if the pixmap BO will be idle anyway.
    
    Direct CPU writes should be at least as fast in that case.

diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index d95adb5..58cd527 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -455,6 +455,7 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
     struct radeon_bo *scratch;
     unsigned size;
     uint32_t datatype = 0;
+    uint32_t dst_domain;
     uint32_t dst_pitch_offset;
     unsigned bpp = pDst->drawable.bitsPerPixel;
     uint32_t scratch_pitch = (w * bpp / 8 + 63) & ~63;
@@ -466,6 +467,11 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
 
     driver_priv = exaGetPixmapDriverPrivate(pDst);
 
+    /* If we know the BO won't be busy, don't bother */
+    if (driver_priv->bo->cref == 1 &&
+	!radeon_bo_is_busy(driver_priv->bo, &dst_domain))
+	return FALSE;
+
     size = scratch_pitch * h;
     scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0);
     if (scratch == NULL) {
commit 174b61bb786a841cebd354e23b4b0caa85b541aa
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Thu Aug 27 09:52:11 2009 +0200

    KMS: DownloadFromScreen improvements.
    
    * Drop superfluous RADEONDownloadFromScreenGTT function, EXA does the same
      thing when we return FALSE.
    * Take unflushed operations into account for determining which GEM domain the
      pixmap BO will end up in.
    * Only use a blit if it ends up in VRAM.

diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index f937c4e..d95adb5 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -507,33 +507,6 @@ out:
 }
 
 static Bool
-RADEONDownloadFromScreenGTT(PixmapPtr pSrc, int x, int y, int w,
-			    int h, char *dst, int dst_pitch)
-{
-    struct radeon_exa_pixmap_priv *driver_priv;
-    int src_pitch = exaGetPixmapPitch(pSrc);
-    int bpp = pSrc->drawable.bitsPerPixel;
-    int src_offset;
-    int r;
-
-    driver_priv = exaGetPixmapDriverPrivate(pSrc);
-    r = radeon_bo_map(driver_priv->bo, 0);
-    if (r)
-	return FALSE;
-
-    src_offset = (x * bpp / 8) + (y * src_pitch);
-    w *= bpp / 8;
-
-    while (h--) {
-        memcpy(dst, driver_priv->bo->ptr + src_offset, w);
-        src_offset += src_pitch;
-        dst += dst_pitch;
-    }
-    radeon_bo_unmap(driver_priv->bo);
-    return TRUE;
-}
-
-static Bool
 RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
                            int h, char *dst, int dst_pitch)
 {
@@ -542,23 +515,33 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
     struct radeon_bo *scratch;
     unsigned size;
     uint32_t datatype = 0;
+    uint32_t src_domain = 0;
     uint32_t src_pitch_offset;
     unsigned bpp = pSrc->drawable.bitsPerPixel;
     uint32_t scratch_pitch = (w * bpp / 8 + 63) & ~63;
     Bool r;
-    uint32_t src_domain;
-    int busy;
 
     if (bpp < 8)
 	return FALSE;
 
     driver_priv = exaGetPixmapDriverPrivate(pSrc);
- 
-    busy = radeon_bo_is_busy(driver_priv->bo, &src_domain);
 
-    if (src_domain == RADEON_GEM_DOMAIN_GTT)
-	return RADEONDownloadFromScreenGTT(pSrc, x, y, w, h,
-					   dst, dst_pitch);
+    /* If we know the BO won't end up in VRAM anyway, don't bother */
+    if (driver_priv->bo->cref > 1) {
+	src_domain = driver_priv->bo->space_accounted & 0xffff;
+	if (!src_domain)
+	    src_domain = driver_priv->bo->space_accounted >> 16;
+
+	if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) ==
+	    (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM))
+	    src_domain = 0;
+    }
+
+    if (!src_domain)
+	radeon_bo_is_busy(driver_priv->bo, &src_domain);
+
+    if (src_domain != RADEON_GEM_DOMAIN_VRAM)
+	return FALSE;
 
     size = scratch_pitch * h;
     scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0);
commit 7623e169e1f7d5afbd4108de03f28098bca519db
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Thu Aug 27 09:52:11 2009 +0200

    EXA: Allocate pixmap BOs in VRAM.
    
    This is the intention with EXA in xserver Git, and IME it improves performance
    significantly even with older versions.

diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 3f3c9ba..b7013c9 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -390,8 +390,8 @@ void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align)
     if (size == 0)
 	return new_priv;
 
-    new_priv->bo = radeon_bo_open(info->bufmgr, 0, size,
-				  align, 0, 0);
+    new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, align,
+				  RADEON_GEM_DOMAIN_VRAM, 0);
     if (!new_priv->bo) {
 	xfree(new_priv);
 	ErrorF("Failed to alloc memory\n");
@@ -442,8 +442,8 @@ void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
 
     *new_pitch = padded_width;
 
-    new_priv->bo = radeon_bo_open(info->bufmgr, 0, size,
-				  0, 0, 0);
+    new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, 0,
+				  RADEON_GEM_DOMAIN_VRAM, 0);
     if (!new_priv->bo) {
 	xfree(new_priv);
 	ErrorF("Failed to alloc memory\n");
commit b90b823790657707b5bf7249095833bef959b0e8
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Thu Aug 27 09:52:11 2009 +0200

    DRI2: Set tiling for depth/stencil buffers with all DRI2 interface versions.

diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index c303f7b..613fde8 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -91,6 +91,10 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
         } else {
 	    /* tile the back buffer */
 	    switch(attachments[i]) {
+	    case DRI2BufferDepth:
+	    case DRI2BufferDepthStencil:
+		flags = RADEON_CREATE_PIXMAP_TILING_MACRO | RADEON_CREATE_PIXMAP_TILING_MICRO;
+		break;
 	    case DRI2BufferBackLeft:
 	    case DRI2BufferBackRight:
 	    case DRI2BufferFakeFrontLeft:
commit 27d9664f8862d1948dd32021f8e9bcb94f23e4ef
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Thu Aug 27 09:52:10 2009 +0200

    EXA: RENDER repeat cleanups.
    
    We can't rely on the server setting pPict->repeatType to something sensible
    when pPict->repeat is FALSE, but we can do it ourselves.

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 3e77515..57867f1 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -1258,30 +1258,29 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
     tex_samp.id                 = unit;
     tex_samp.border_color       = SQ_TEX_BORDER_COLOR_TRANS_BLACK;
 
-    if (pPict->repeat) {
-	switch (pPict->repeatType) {
-	case RepeatNormal:
-	    tex_samp.clamp_x            = SQ_TEX_WRAP;
-	    tex_samp.clamp_y            = SQ_TEX_WRAP;
-	    break;
-	case RepeatPad:
-	    tex_samp.clamp_x            = SQ_TEX_CLAMP_LAST_TEXEL;
-	    tex_samp.clamp_y            = SQ_TEX_CLAMP_LAST_TEXEL;
-	    break;
-	case RepeatReflect:
-	    tex_samp.clamp_x            = SQ_TEX_MIRROR;
-	    tex_samp.clamp_y            = SQ_TEX_MIRROR;
-	    break;
-	case RepeatNone:
-	    tex_samp.clamp_x            = SQ_TEX_CLAMP_BORDER;
-	    tex_samp.clamp_y            = SQ_TEX_CLAMP_BORDER;
-	    break;
-	default:
-	    RADEON_FALLBACK(("Bad repeat 0x%x\n", pPict->repeatType));
-	}
-    } else {
+    /* Unfortunately we can't rely on the X server doing this for us */
+    if (!pPict->repeat)
+	pPict->repeatType = RepeatNone;
+
+    switch (pPict->repeatType) {
+    case RepeatNormal:
+	tex_samp.clamp_x            = SQ_TEX_WRAP;
+	tex_samp.clamp_y            = SQ_TEX_WRAP;
+	break;
+    case RepeatPad:
+	tex_samp.clamp_x            = SQ_TEX_CLAMP_LAST_TEXEL;
+	tex_samp.clamp_y            = SQ_TEX_CLAMP_LAST_TEXEL;
+	break;
+    case RepeatReflect:
+	tex_samp.clamp_x            = SQ_TEX_MIRROR;
+	tex_samp.clamp_y            = SQ_TEX_MIRROR;
+	break;
+    case RepeatNone:
 	tex_samp.clamp_x            = SQ_TEX_CLAMP_BORDER;
 	tex_samp.clamp_y            = SQ_TEX_CLAMP_BORDER;
+	break;
+    default:
+	RADEON_FALLBACK(("Bad repeat 0x%x\n", pPict->repeatType));
     }
 
     switch (pPict->filter) {
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 4dbdc14..cc97760 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -410,6 +410,10 @@ static Bool FUNC_NAME(R100TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 	RADEON_FALLBACK(("Bad filter 0x%x\n", pPict->filter));
     }
 
+    /* Unfortunately we can't rely on the X server doing this for us */
+    if (!pPict->repeat)
+	pPict->repeatType = RepeatNone;
+
     switch (pPict->repeatType) {
 	case RepeatNormal:
 	    txfilter |= RADEON_CLAMP_S_WRAP | RADEON_CLAMP_T_WRAP;
@@ -793,6 +797,10 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 	RADEON_FALLBACK(("Bad filter 0x%x\n", pPict->filter));
     }
 
+    /* Unfortunately we can't rely on the X server doing this for us */
+    if (!pPict->repeat)
+	pPict->repeatType = RepeatNone;
+
     switch (pPict->repeatType) {
 	case RepeatNormal:
 	    txfilter |= R200_CLAMP_S_WRAP | R200_CLAMP_T_WRAP;
@@ -1171,36 +1179,36 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 
     txfilter = (unit << R300_TX_ID_SHIFT);
 
-    if (pPict->repeat) {
-	switch (pPict->repeatType) {
-	case RepeatNormal:
-	    if (unit != 0 || !info->accel_state->need_src_tile_x)
-		txfilter |= R300_TX_CLAMP_S(R300_TX_CLAMP_WRAP);
-	    else
-		txfilter |= R300_TX_CLAMP_S(R300_TX_CLAMP_CLAMP_GL);
+    /* Unfortunately we can't rely on the X server doing this for us */
+    if (!pPict->repeat)
+	pPict->repeatType = RepeatNone;
 
-	    if (unit != 0 || !info->accel_state->need_src_tile_y)
-		txfilter |= R300_TX_CLAMP_T(R300_TX_CLAMP_WRAP);
-	    else
-		txfilter |= R300_TX_CLAMP_T(R300_TX_CLAMP_CLAMP_GL);
+    switch (pPict->repeatType) {
+    case RepeatNormal:
+	if (unit != 0 || !info->accel_state->need_src_tile_x)
+	    txfilter |= R300_TX_CLAMP_S(R300_TX_CLAMP_WRAP);
+	else
+	    txfilter |= R300_TX_CLAMP_S(R300_TX_CLAMP_CLAMP_GL);
+	
+	if (unit != 0 || !info->accel_state->need_src_tile_y)
+	    txfilter |= R300_TX_CLAMP_T(R300_TX_CLAMP_WRAP);
+	else
+	    txfilter |= R300_TX_CLAMP_T(R300_TX_CLAMP_CLAMP_GL);
 
-	    break;
-	case RepeatPad:
-	    txfilter |= R300_TX_CLAMP_S(R300_TX_CLAMP_CLAMP_LAST) |
-		        R300_TX_CLAMP_T(R300_TX_CLAMP_CLAMP_LAST);
-	    break;
-	case RepeatReflect:
-	    txfilter |= R300_TX_CLAMP_S(R300_TX_CLAMP_MIRROR) |
-		        R300_TX_CLAMP_T(R300_TX_CLAMP_MIRROR);
-	    break;
-	case RepeatNone:
-	    txfilter |= R300_TX_CLAMP_S(R300_TX_CLAMP_CLAMP_GL) |
-		        R300_TX_CLAMP_T(R300_TX_CLAMP_CLAMP_GL);
-	    break;
-	}
-    } else
+	break;
+    case RepeatPad:
+	txfilter |= R300_TX_CLAMP_S(R300_TX_CLAMP_CLAMP_LAST) |
+	    R300_TX_CLAMP_T(R300_TX_CLAMP_CLAMP_LAST);
+	break;
+    case RepeatReflect:
+	txfilter |= R300_TX_CLAMP_S(R300_TX_CLAMP_MIRROR) |
+	    R300_TX_CLAMP_T(R300_TX_CLAMP_MIRROR);
+	break;
+    case RepeatNone:
 	txfilter |= R300_TX_CLAMP_S(R300_TX_CLAMP_CLAMP_GL) |
-	            R300_TX_CLAMP_T(R300_TX_CLAMP_CLAMP_GL);
+	    R300_TX_CLAMP_T(R300_TX_CLAMP_CLAMP_GL);
+	break;
+    }
 
     switch (pPict->filter) {
     case PictFilterNearest:
commit 9b5517fcf7f2397a1a814d396fc9dc24769a6d9f
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Thu Aug 27 09:52:10 2009 +0200

    Throttle DRI2 buffer swaps / frontbuffer flushes.

diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index b52f965..c303f7b 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -275,6 +275,25 @@ radeon_dri2_copy_region(DrawablePtr drawable,
     (*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0);
     ValidateGC(&dst_pixmap->drawable, gc);
 
+    /* If this is a full buffer swap or frontbuffer flush, throttle on the
+     * previous one
+     */
+    if (dst_private->attachment == DRI2BufferFrontLeft) {
+	if (REGION_NUM_RECTS(region) == 1) {
+	    BoxPtr extents = REGION_EXTENTS(pScreen, region);
+
+	    if (extents->x1 == 0 && extents->y1 == 0 &&
+		extents->x2 == drawable->width &&
+		extents->y2 == drawable->height) {
+		struct radeon_exa_pixmap_priv *exa_priv =
+		    exaGetPixmapDriverPrivate(dst_pixmap);
+
+		if (exa_priv && exa_priv->bo)
+		    radeon_bo_wait(exa_priv->bo);
+	    }
+	}
+    }
+
     vsync = info->accel_state->vsync;
     info->accel_state->vsync = TRUE;
 
commit e87f0f50f31a59ca1f60d4582d4a57ed00854fb7
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Aug 26 02:13:38 2009 -0400

    r6xx/r7xx: set EXA_HANDLES_PIXMAPS

diff --git a/src/r600_exa.c b/src/r600_exa.c
index f2136ae..cfe041f 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -128,7 +128,7 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     uint32_t a, r, g, b;
     float ps_alu_consts[4];
 
-    return FALSE;
+    //return FALSE;
 
     if (pPix->drawable.bitsPerPixel == 24)
         RADEON_FALLBACK(("24bpp unsupported\n"));
@@ -707,7 +707,7 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
     RADEONInfoPtr info = RADEONPTR(pScrn);
     struct radeon_accel_state *accel_state = info->accel_state;
 
-    return FALSE;
+    //return FALSE;
 
     if (pSrc->drawable.bitsPerPixel == 24)
         RADEON_FALLBACK(("24bpp unsupported\n"));
@@ -1569,7 +1569,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     cb_config_t cb_conf;
     shader_config_t vs_conf, ps_conf;
 
-    return FALSE;
+    //return FALSE;
     /* return FALSE; */
 
     if (pDst->drawable.bitsPerPixel < 8 || pSrc->drawable.bitsPerPixel < 8)
@@ -2325,6 +2325,17 @@ R600DrawInit(ScreenPtr pScreen)
 #ifdef EXA_SUPPORTS_PREPARE_AUX
     info->accel_state->exa->flags |= EXA_SUPPORTS_PREPARE_AUX;
 #endif
+
+#ifdef XF86DRM_MODE
+#ifdef EXA_HANDLES_PIXMAPS
+    if (info->cs) {
+	info->accel_state->exa->flags |= EXA_HANDLES_PIXMAPS;
+//#ifdef EXA_MIXED_PIXMAPS
+//	info->accel_state->exa->flags |= EXA_MIXED_PIXMAPS;
+//#endif
+    }
+#endif
+#endif
     info->accel_state->exa->pixmapOffsetAlign = 256;
     info->accel_state->exa->pixmapPitchAlign = 256;
 
commit 3212c26b90c0f6f1a7248b4da3ed985a9c2e9381
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Aug 26 01:42:10 2009 -0400

    r6xx/r7xx: more WIP

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 462bbb8..f2136ae 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -352,11 +352,6 @@ R600DoneSolid(PixmapPtr pPix)
     CLEAR (draw_conf);
     CLEAR (vtx_res);
 
-#ifdef XF86DRM_MODE
-    if (info->cs)
-	radeon_bo_unmap(accel_state->vb_bo);
-#endif
-
     if (accel_state->vb_index == 0) {
         R600IBDiscard(pScrn, accel_state->ib);
         r600_vb_discard(pScrn);
@@ -405,11 +400,6 @@ R600DoneSolid(PixmapPtr pPix)
 			accel_state->dst_bo, RADEON_GEM_DOMAIN_VRAM, 0);
 
     R600CPFlushIndirect(pScrn, accel_state->ib);
-
-    accel_state->src_bo[0] = NULL;
-    accel_state->src_bo[1] = NULL;
-    accel_state->dst_bo = NULL;
-    accel_state->vb_bo = NULL;
 }
 
 static void
@@ -453,6 +443,10 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
     r600_cp_start(pScrn);
 
     /* Init */
+#if defined(XF86DRM_MODE)
+    if (info->cs)
+	accel_state->XInited3D = FALSE;
+#endif
     start_3d(pScrn, accel_state->ib);
 
     set_default_state(pScrn, accel_state->ib);
@@ -619,11 +613,6 @@ R600DoCopy(ScrnInfoPtr pScrn)
     CLEAR (draw_conf);
     CLEAR (vtx_res);
 
-#ifdef XF86DRM_MODE
-    if (info->cs)
-	radeon_bo_unmap(accel_state->vb_bo);
-#endif
-
     if (accel_state->vb_index == 0) {
         R600IBDiscard(pScrn, accel_state->ib);
         r600_vb_discard(pScrn);
@@ -1092,10 +1081,7 @@ R600DoneCopy(PixmapPtr pDst)
 	    exaOffscreenFree(pDst->drawable.pScreen, accel_state->copy_area);
 	accel_state->copy_area = NULL;
     }
-    accel_state->src_bo[0] = NULL;
-    accel_state->src_bo[1] = NULL;
-    accel_state->dst_bo = NULL;
-    accel_state->vb_bo = NULL;
+
 }
 
 
@@ -1611,6 +1597,8 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     if (info->cs) {
 	accel_state->dst_mc_addr = 0;
 	accel_state->dst_bo = radeon_get_pixmap_bo(pDst);
+	accel_state->src_bo[0] = NULL;
+	accel_state->src_bo[1] = NULL;
     } else
 #endif
 	accel_state->dst_mc_addr = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
@@ -1633,6 +1621,10 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     r600_cp_start(pScrn);
 
     /* Init */
+#if defined(XF86DRM_MODE)
+    if (info->cs)
+	accel_state->XInited3D = FALSE;
+#endif
     start_3d(pScrn, accel_state->ib);
 
     set_default_state(pScrn, accel_state->ib);
@@ -1714,7 +1706,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     ps_conf.bo                  = accel_state->shaders_bo;
     ps_setup                    (pScrn, accel_state->ib, &ps_conf);
 
-    BEGIN_BATCH(12);
+    BEGIN_BATCH(9);
     EREG(accel_state->ib, CB_SHADER_MASK,                      (0xf << OUTPUT0_ENABLE_shift));
 
     blendcntl = R600GetBlendCntl(op, pMaskPicture, pDstPicture->format);
@@ -1893,11 +1885,6 @@ static void R600DoneComposite(PixmapPtr pDst)
     CLEAR (draw_conf);
     CLEAR (vtx_res);
 
-#ifdef XF86DRM_MODE
-    if (info->cs)
-	radeon_bo_unmap(accel_state->vb_bo);
-#endif
-
     if (accel_state->vb_index == 0) {
         R600IBDiscard(pScrn, accel_state->ib);
         r600_vb_discard(pScrn);
@@ -1954,10 +1941,6 @@ static void R600DoneComposite(PixmapPtr pDst)
 
     R600CPFlushIndirect(pScrn, accel_state->ib);
 
-    accel_state->src_bo[0] = NULL;
-    accel_state->src_bo[1] = NULL;
-    accel_state->dst_bo = NULL;
-    accel_state->vb_bo = NULL;
 }
 
 Bool
diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index a6e2559..b6f7b39 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -65,11 +65,6 @@ R600DoneTexturedVideo(ScrnInfoPtr pScrn)
     CLEAR (draw_conf);
     CLEAR (vtx_res);
 
-#ifdef XF86DRM_MODE
-    if (info->cs)
-	radeon_bo_unmap(accel_state->vb_bo);
-#endif
-
     if (accel_state->vb_index == 0) {
         R600IBDiscard(pScrn, accel_state->ib);
         r600_vb_discard(pScrn);
@@ -117,9 +112,6 @@ R600DoneTexturedVideo(ScrnInfoPtr pScrn)
 			accel_state->dst_bo, 0, RADEON_GEM_DOMAIN_VRAM);
 
     R600CPFlushIndirect(pScrn, accel_state->ib);
-    accel_state->dst_bo = NULL;
-    accel_state->src_bo[0] = NULL;
-    accel_state->src_bo[1] = NULL;
 }
 
 void
@@ -261,6 +253,10 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     r600_cp_start(pScrn);
 
     /* Init */
+#if defined(XF86DRM_MODE)
+    if (info->cs)
+	accel_state->XInited3D = FALSE;
+#endif
     start_3d(pScrn, accel_state->ib);
 
     set_default_state(pScrn, accel_state->ib);
diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index 8a2b1ae..7c7f469 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -39,6 +39,7 @@
 
 #include "radeon_drm.h"
 
+#if defined(XF86DRM_MODE)
 void r600_cs_flush_indirect(ScrnInfoPtr pScrn)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
@@ -46,6 +47,11 @@ void r600_cs_flush_indirect(ScrnInfoPtr pScrn)
 
     if (!info->cs->cdw)
 	return;
+
+    if (info->accel_state->vb_bo)
+	radeon_bo_unmap(info->accel_state->vb_bo);
+    info->accel_state->vb_bo = NULL;
+
     radeon_cs_emit(info->cs);
     radeon_cs_erase(info->cs);
 
@@ -53,6 +59,7 @@ void r600_cs_flush_indirect(ScrnInfoPtr pScrn)
     if (ret)
 	ErrorF("space check failed in flush\n");
 }
+#endif
 
 /* Flush the indirect buffer to the kernel for submission to the card */
 void R600CPFlushIndirect(ScrnInfoPtr pScrn, drmBufPtr ib)
@@ -98,6 +105,9 @@ void R600IBDiscard(ScrnInfoPtr pScrn, drmBufPtr ib)
     int ret;
     RADEONInfoPtr info = RADEONPTR(pScrn);
     if (info->cs) {
+	if (info->accel_state->vb_bo)
+	    radeon_bo_unmap(info->accel_state->vb_bo);
+	info->accel_state->vb_bo = NULL;
 	if (CS_FULL(info->cs)) {
 	    r600_cs_flush_indirect(pScrn);
 	    return;
commit 5a08e68cc254fb255e631b456e331c32456ef0e7
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Aug 25 19:24:41 2009 -0400

    r6xx/r7xx: fix some define problems in Xv code

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 09eb6ee..462bbb8 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -128,7 +128,7 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     uint32_t a, r, g, b;
     float ps_alu_consts[4];
 
-    //return FALSE;
+    return FALSE;
 
     if (pPix->drawable.bitsPerPixel == 24)
         RADEON_FALLBACK(("24bpp unsupported\n"));
diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index 10d6f4f..a6e2559 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -228,7 +228,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     CLEAR (vs_conf);
     CLEAR (ps_conf);
 
-#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
+#if defined(XF86DRM_MODE)
     if (info->cs) {
 	accel_state->dst_mc_addr = 0;
 	accel_state->src_mc_addr[0] = 0;
@@ -269,7 +269,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     set_screen_scissor(pScrn, accel_state->ib, 0, 0, pPixmap->drawable.width, pPixmap->drawable.height);
     set_window_scissor(pScrn, accel_state->ib, 0, 0, pPixmap->drawable.width, pPixmap->drawable.height);
 
-#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
+#if defined(XF86DRM_MODE)
     if (info->cs) {
 	accel_state->vs_mc_addr = accel_state->xv_vs_offset;
 	accel_state->ps_mc_addr = accel_state->xv_ps_offset;
commit 9aa214e125b7927d62b9fe124a851d0373c24d7e
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Aug 25 18:45:49 2009 -0400

    r6xx/r7xx: fix reloc for vtx buffer

diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index 6e4c8ea..8a2b1ae 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -494,7 +494,7 @@ set_vtx_resource(ScrnInfoPtr pScrn, drmBufPtr ib, vtx_resource_t *res)
     E32(ib, 0);							// 4: n/a
     E32(ib, 0);							// 5: n/a
     E32(ib, SQ_TEX_VTX_VALID_BUFFER << SQ_VTX_CONSTANT_WORD6_0__TYPE_shift);	// 6: TYPE
-    RELOC_BATCH(res->bo, RADEON_GEM_DOMAIN_VRAM, 0);
+    RELOC_BATCH(res->bo, RADEON_GEM_DOMAIN_GTT, 0);
     END_BATCH();
 }
 
commit bba51187055932ecd466f5f817428d6c773747b9
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Aug 25 18:37:15 2009 -0400

    R6xx/r7xx: unmap vb bo when done

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 1d7802a..09eb6ee 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -352,6 +352,11 @@ R600DoneSolid(PixmapPtr pPix)
     CLEAR (draw_conf);
     CLEAR (vtx_res);
 
+#ifdef XF86DRM_MODE
+    if (info->cs)
+	radeon_bo_unmap(accel_state->vb_bo);
+#endif
+
     if (accel_state->vb_index == 0) {
         R600IBDiscard(pScrn, accel_state->ib);
         r600_vb_discard(pScrn);
@@ -614,6 +619,11 @@ R600DoCopy(ScrnInfoPtr pScrn)
     CLEAR (draw_conf);
     CLEAR (vtx_res);
 
+#ifdef XF86DRM_MODE
+    if (info->cs)
+	radeon_bo_unmap(accel_state->vb_bo);
+#endif
+
     if (accel_state->vb_index == 0) {
         R600IBDiscard(pScrn, accel_state->ib);
         r600_vb_discard(pScrn);
@@ -1883,6 +1893,11 @@ static void R600DoneComposite(PixmapPtr pDst)
     CLEAR (draw_conf);
     CLEAR (vtx_res);
 
+#ifdef XF86DRM_MODE
+    if (info->cs)
+	radeon_bo_unmap(accel_state->vb_bo);
+#endif
+
     if (accel_state->vb_index == 0) {
         R600IBDiscard(pScrn, accel_state->ib);
         r600_vb_discard(pScrn);
diff --git a/src/r600_state.h b/src/r600_state.h
index 6ca88cf..cb039d4 100644
--- a/src/r600_state.h
+++ b/src/r600_state.h
@@ -188,9 +188,12 @@ do {					\
 	radeon_cs_end(info->cs, __FILE__, __func__, __LINE__);	\
 } while(0)
 #define RELOC_BATCH(bo, rd, wd)					\
-do {								\
-    if (info->cs)							\
-	OUT_RING_RELOC((bo), (rd), (wd));				\
+do {							\
+    if (info->cs) {							\
+	int _ret;							\
+	_ret = radeon_cs_write_reloc(info->cs, (bo), (rd), (wd), 0);	\
+	if (_ret) ErrorF("reloc emit failure %d (%s %d)\n", _ret, __func__, __LINE__); \
+    }									\
 } while(0)
 #define E32(ib, dword)                                                  \
 do {                                                                    \
diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index 631a40c..10d6f4f 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -65,6 +65,11 @@ R600DoneTexturedVideo(ScrnInfoPtr pScrn)
     CLEAR (draw_conf);
     CLEAR (vtx_res);
 
+#ifdef XF86DRM_MODE
+    if (info->cs)
+	radeon_bo_unmap(accel_state->vb_bo);
+#endif
+
     if (accel_state->vb_index == 0) {
         R600IBDiscard(pScrn, accel_state->ib);
         r600_vb_discard(pScrn);
commit 599adfc1f5e6d708be7ad30f4871de3046775727
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Aug 25 18:13:14 2009 -0400

    r6xx/r7xx: fix flipped domains

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 4d09d6e..1d7802a 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -658,7 +658,7 @@ R600DoCopy(ScrnInfoPtr pScrn)
     /* sync dst surface */
     cp_set_surface_sync(pScrn, accel_state->ib, (CB_ACTION_ENA_bit | CB0_DEST_BASE_ENA_bit),
 			accel_state->dst_size, accel_state->dst_mc_addr,
-			accel_state->dst_bo, 0, RADEON_GEM_DOMAIN_VRAM);
+			accel_state->dst_bo, RADEON_GEM_DOMAIN_VRAM, 0);
 
     R600CPFlushIndirect(pScrn, accel_state->ib);
 }
commit 2e83cca8d7efaf1a6836cfb9ea5893fd9d70175f
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Aug 25 18:05:43 2009 -0400

    r6xx/r7xx: more cs exa wip

diff --git a/src/r600_exa.c b/src/r600_exa.c
index b6a1a15..4d09d6e 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -167,8 +167,6 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 #endif
 
     r600_cp_start(pScrn);
-    if (!r600_vb_get(pScrn))
-	RADEON_FALLBACK(("Can't get VB\n"));
 
     /* Init */
 #if defined(XF86DRM_MODE)
@@ -325,8 +323,6 @@ R600Solid(PixmapPtr pPix, int x1, int y1, int x2, int y2)
     if (((accel_state->vb_index + 3) * 8) > accel_state->vb_total) {
         R600DoneSolid(pPix);
 	r600_cp_start(pScrn);
-	if (!r600_vb_get(pScrn))
-	    return;
     }
 
     vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*8);
@@ -408,6 +404,7 @@ R600DoneSolid(PixmapPtr pPix)
     accel_state->src_bo[0] = NULL;
     accel_state->src_bo[1] = NULL;
     accel_state->dst_bo = NULL;
+    accel_state->vb_bo = NULL;
 }
 
 static void
@@ -449,8 +446,6 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
     accel_state->dst_bo = dst_bo;
 
     r600_cp_start(pScrn);
-    if (!r600_vb_get(pScrn))
-	return;
 
     /* Init */
     start_3d(pScrn, accel_state->ib);
@@ -681,8 +676,6 @@ R600AppendCopyVertex(ScrnInfoPtr pScrn,
     if (((accel_state->vb_index + 3) * 16) > accel_state->vb_total) {
         R600DoCopy(pScrn);
 	r600_cp_start(pScrn);
-	if (!r600_vb_get(pScrn))
-	    return;
     }
 
     vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*16);
@@ -1092,6 +1085,7 @@ R600DoneCopy(PixmapPtr pDst)
     accel_state->src_bo[0] = NULL;
     accel_state->src_bo[1] = NULL;
     accel_state->dst_bo = NULL;
+    accel_state->vb_bo = NULL;
 }
 
 
@@ -1627,8 +1621,6 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     CLEAR (ps_conf);
 
     r600_cp_start(pScrn);
-    if (!r600_vb_get(pScrn))
-	RADEON_FALLBACK(("Can't get VB\n"));
 
     /* Init */
     start_3d(pScrn, accel_state->ib);
@@ -1818,8 +1810,6 @@ static void R600Composite(PixmapPtr pDst,
         if (((accel_state->vb_index + 3) * 24) > accel_state->vb_total) {
             R600DoneComposite(pDst);
 	    r600_cp_start(pScrn);
-	    if (!r600_vb_get(pScrn))
-		return;
         }
 
         vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*24);
@@ -1858,8 +1848,6 @@ static void R600Composite(PixmapPtr pDst,
         if (((accel_state->vb_index + 3) * 16) > accel_state->vb_total) {
             R600DoneComposite(pDst);
 	    r600_cp_start(pScrn);
-	    if (!r600_vb_get(pScrn))
-		return;
         }
 
         vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*16);
@@ -1954,6 +1942,7 @@ static void R600DoneComposite(PixmapPtr pDst)
     accel_state->src_bo[0] = NULL;
     accel_state->src_bo[1] = NULL;
     accel_state->dst_bo = NULL;
+    accel_state->vb_bo = NULL;
 }
 
 Bool
@@ -2374,6 +2363,11 @@ R600DrawInit(ScreenPtr pScreen)
 
     info->accel_state->XInited3D = FALSE;
     info->accel_state->copy_area = NULL;
+    info->accel_state->src_bo[0] = NULL;
+    info->accel_state->src_bo[1] = NULL;
+    info->accel_state->dst_bo = NULL;
+    info->accel_state->copy_area_bo = NULL;
+    info->accel_state->vb_bo = NULL;
 
     if (!R600AllocShaders(pScrn, pScreen))
 	return FALSE;
diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index 9cbfea4..631a40c 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -254,8 +254,6 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 #endif
 
     r600_cp_start(pScrn);
-    if (!r600_vb_get(pScrn))
-	return;
 
     /* Init */
     start_3d(pScrn, accel_state->ib);
@@ -587,8 +585,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 
         if (((accel_state->vb_index + 3) * 16) > accel_state->vb_total) {
             R600DoneTexturedVideo(pScrn);
-            accel_state->ib = RADEONCPGetBuffer(pScrn);
-            r600_vb_get(pScrn);
+	    r600_cp_start(pScrn);
         }
 
         vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*16);
diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index 4aa4650..6e4c8ea 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -1188,7 +1188,7 @@ r600_cp_start(ScrnInfoPtr pScrn)
 #if defined(XF86DRM_MODE)
     if (info->cs) {
 	if (!r600_vb_get(pScrn))
-	    return FALSE;
+	    return -1;
 	radeon_cs_space_reset_bos(info->cs);
 	radeon_cs_space_add_persistent_bo(info->cs, accel_state->shaders_bo,
 					  RADEON_GEM_DOMAIN_VRAM, 0);
@@ -1198,10 +1198,12 @@ r600_cp_start(ScrnInfoPtr pScrn)
 	if (accel_state->src_bo[1])
 	    radeon_cs_space_add_persistent_bo(info->cs, accel_state->src_bo[1],
 					      RADEON_GEM_DOMAIN_VRAM, 0);
-	radeon_cs_space_add_persistent_bo(info->cs, accel_state->dst_bo,
-					  RADEON_GEM_DOMAIN_VRAM, 0);
-	radeon_cs_space_add_persistent_bo(info->cs, accel_state->vb_bo,
-					  RADEON_GEM_DOMAIN_GTT, 0);
+	if (accel_state->dst_bo)
+	    radeon_cs_space_add_persistent_bo(info->cs, accel_state->dst_bo,
+					      RADEON_GEM_DOMAIN_VRAM, 0);
+	if (accel_state->vb_bo)
+	    radeon_cs_space_add_persistent_bo(info->cs, accel_state->vb_bo,
+					      RADEON_GEM_DOMAIN_GTT, 0);
 	if (accel_state->copy_area_bo)
 	    radeon_cs_space_add_persistent_bo(info->cs,
 					      accel_state->copy_area_bo,
commit 65852de027989c105246fa4e4eed432f29525a22
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Aug 25 17:29:42 2009 -0400

    r6xx/r7xx EXA: WIP

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 03d3d8c..b6a1a15 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -128,6 +128,8 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     uint32_t a, r, g, b;
     float ps_alu_consts[4];
 
+    //return FALSE;
+
     if (pPix->drawable.bitsPerPixel == 24)
         RADEON_FALLBACK(("24bpp unsupported\n"));
     if (!R600CheckBPP(pPix->drawable.bitsPerPixel))
@@ -713,6 +715,8 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
     RADEONInfoPtr info = RADEONPTR(pScrn);
     struct radeon_accel_state *accel_state = info->accel_state;
 
+    return FALSE;
+
     if (pSrc->drawable.bitsPerPixel == 24)
         RADEON_FALLBACK(("24bpp unsupported\n"));
     if (pDst->drawable.bitsPerPixel == 24)
@@ -1575,6 +1579,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     cb_config_t cb_conf;
     shader_config_t vs_conf, ps_conf;
 
+    return FALSE;
     /* return FALSE; */
 
     if (pDst->drawable.bitsPerPixel < 8 || pSrc->drawable.bitsPerPixel < 8)
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index cd398c6..faa0cfd 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -180,7 +180,7 @@ static Bool RADEONPreInitAccel_KMS(ScrnInfoPtr pScrn)
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to allocate accel_state rec!\n");
 	return FALSE;
     }
-
+#if 0
     if (info->ChipFamily >= CHIP_FAMILY_R600) {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		   "Using shadowfb for KMS on R600+\n");
@@ -189,7 +189,7 @@ static Bool RADEONPreInitAccel_KMS(ScrnInfoPtr pScrn)
 	    info->r600_shadow_fb = FALSE;
 	return TRUE;
     }
-
+#endif
 
     if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
 	(info->ChipFamily == CHIP_FAMILY_RS200) ||
commit 69ec7a35e2a0a3d802ec093a6aab2d7ed2cc88be
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Aug 25 16:14:02 2009 -0400

    r6xx/r7xx: first pass at kms accel support
    
    Adapted from various patches from Dave and Jerome.

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 555748b..03d3d8c 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -133,7 +133,15 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     if (!R600CheckBPP(pPix->drawable.bitsPerPixel))
         RADEON_FALLBACK(("R600CheckDatatype failed\n"));
 
-    accel_state->dst_mc_addr = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset;
+#if defined(XF86DRM_MODE)
+    if (info->cs) {
+	accel_state->dst_mc_addr = 0;
+	accel_state->dst_bo = radeon_get_pixmap_bo(pPix);
+	accel_state->src_bo[0] = NULL;
+	accel_state->src_bo[1] = NULL;
+    } else
+#endif
+	accel_state->dst_mc_addr = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset;
     accel_state->dst_size = exaGetPixmapPitch(pPix) * pPix->drawable.height;
     accel_state->dst_pitch = exaGetPixmapPitch(pPix) / (pPix->drawable.bitsPerPixel / 8);
 
@@ -156,10 +164,15 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 	   pPix->drawable.bitsPerPixel, exaGetPixmapPitch(pPix));
 #endif
 
-    accel_state->ib = RADEONCPGetBuffer(pScrn);
-    r600_vb_get(pScrn);
+    r600_cp_start(pScrn);
+    if (!r600_vb_get(pScrn))
+	RADEON_FALLBACK(("Can't get VB\n"));
 
     /* Init */
+#if defined(XF86DRM_MODE)
+    if (info->cs)
+	accel_state->XInited3D = FALSE;
+#endif
     start_3d(pScrn, accel_state->ib);
 
     set_default_state(pScrn, accel_state->ib);
@@ -168,10 +181,18 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     set_screen_scissor(pScrn, accel_state->ib, 0, 0, pPix->drawable.width, pPix->drawable.height);
     set_window_scissor(pScrn, accel_state->ib, 0, 0, pPix->drawable.width, pPix->drawable.height);
 
-    accel_state->vs_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
-	accel_state->solid_vs_offset;
-    accel_state->ps_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
-	accel_state->solid_ps_offset;
+#if defined(XF86DRM_MODE)
+    if (info->cs) {
+	accel_state->vs_mc_addr = accel_state->solid_vs_offset;
+	accel_state->ps_mc_addr = accel_state->solid_ps_offset;
+    } else
+#endif
+    {
+	accel_state->vs_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
+	    accel_state->solid_vs_offset;
+	accel_state->ps_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
+	    accel_state->solid_ps_offset;
+    }
     accel_state->vs_size = 512;
     accel_state->ps_size = 512;
 
@@ -179,16 +200,19 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 
     /* flush SQ cache */
     cp_set_surface_sync(pScrn, accel_state->ib, SH_ACTION_ENA_bit,
-			accel_state->vs_size, accel_state->vs_mc_addr);
+			accel_state->vs_size, accel_state->vs_mc_addr,
+			accel_state->shaders_bo, RADEON_GEM_DOMAIN_VRAM, 0);
 
     vs_conf.shader_addr         = accel_state->vs_mc_addr;
     vs_conf.num_gprs            = 2;
     vs_conf.stack_size          = 0;
+    vs_conf.bo                  = accel_state->shaders_bo;
     vs_setup                    (pScrn, accel_state->ib, &vs_conf);
 
     /* flush SQ cache */
     cp_set_surface_sync(pScrn, accel_state->ib, SH_ACTION_ENA_bit,
-			accel_state->ps_size, accel_state->ps_mc_addr);
+			accel_state->ps_size, accel_state->ps_mc_addr,
+			accel_state->shaders_bo, RADEON_GEM_DOMAIN_VRAM, 0);
 
     ps_conf.shader_addr         = accel_state->ps_mc_addr;
     ps_conf.num_gprs            = 1;
@@ -196,6 +220,7 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     ps_conf.uncached_first_inst = 1;
     ps_conf.clamp_consts        = 0;
     ps_conf.export_mode         = 2;
+    ps_conf.bo                  = accel_state->shaders_bo;
     ps_setup                    (pScrn, accel_state->ib, &ps_conf);
 
     /* Render setup */
@@ -216,6 +241,7 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     cb_conf.w = accel_state->dst_pitch;
     cb_conf.h = pPix->drawable.height;
     cb_conf.base = accel_state->dst_mc_addr;
+    cb_conf.bo = accel_state->dst_bo;
 
     if (pPix->drawable.bitsPerPixel == 8) {
 	cb_conf.format = COLOR_8;
@@ -296,8 +322,9 @@ R600Solid(PixmapPtr pPix, int x1, int y1, int x2, int y2)
 
     if (((accel_state->vb_index + 3) * 8) > accel_state->vb_total) {
         R600DoneSolid(pPix);
-        accel_state->ib = RADEONCPGetBuffer(pScrn);
-        r600_vb_get(pScrn);
+	r600_cp_start(pScrn);
+	if (!r600_vb_get(pScrn))
+	    return;
     }
 
     vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*8);
@@ -342,10 +369,12 @@ R600DoneSolid(PixmapPtr pPix)
 	(info->ChipFamily == CHIP_FAMILY_RS880) ||
 	(info->ChipFamily == CHIP_FAMILY_RV710))
 	cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit,
-			    accel_state->vb_size, accel_state->vb_mc_addr);
+			    accel_state->vb_size, accel_state->vb_mc_addr,
+			    accel_state->vb_bo, RADEON_GEM_DOMAIN_GTT, 0);
     else
 	cp_set_surface_sync(pScrn, accel_state->ib, VC_ACTION_ENA_bit,
-			    accel_state->vb_size, accel_state->vb_mc_addr);
+			    accel_state->vb_size, accel_state->vb_mc_addr,
+			    accel_state->vb_bo, RADEON_GEM_DOMAIN_GTT, 0);
 
     /* Vertex buffer setup */
     vtx_res.id              = SQ_VTX_RESOURCE_vs;
@@ -353,6 +382,7 @@ R600DoneSolid(PixmapPtr pPix)
     vtx_res.vtx_num_entries = accel_state->vb_size / 4;
     vtx_res.mem_req_size    = 1;
     vtx_res.vb_addr         = accel_state->vb_mc_addr;
+    vtx_res.bo              = accel_state->vb_bo;
     set_vtx_resource        (pScrn, accel_state->ib, &vtx_res);
 
     /* Draw */
@@ -368,15 +398,22 @@ R600DoneSolid(PixmapPtr pPix)
 
     /* sync dst surface */
     cp_set_surface_sync(pScrn, accel_state->ib, (CB_ACTION_ENA_bit | CB0_DEST_BASE_ENA_bit),
-			accel_state->dst_size, accel_state->dst_mc_addr);
+			accel_state->dst_size, accel_state->dst_mc_addr,
+			accel_state->dst_bo, RADEON_GEM_DOMAIN_VRAM, 0);
 
     R600CPFlushIndirect(pScrn, accel_state->ib);
+
+    accel_state->src_bo[0] = NULL;
+    accel_state->src_bo[1] = NULL;
+    accel_state->dst_bo = NULL;
 }
 
 static void
 R600DoPrepareCopy(ScrnInfoPtr pScrn,
-		  int src_pitch, int src_width, int src_height, uint32_t src_offset, int src_bpp,
-		  int dst_pitch, int dst_width, int dst_height, uint32_t dst_offset, int dst_bpp,
+		  int src_pitch, int src_width, int src_height,
+		  uint32_t src_offset, struct radeon_bo *src_bo, int src_bpp,
+		  int dst_pitch, int dst_width, int dst_height,
+		  uint32_t dst_offset, struct radeon_bo *dst_bo, int dst_bpp,
 		  int rop, Pixel planemask)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
@@ -393,8 +430,25 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
     CLEAR (vs_conf);
     CLEAR (ps_conf);
 
-    accel_state->ib = RADEONCPGetBuffer(pScrn);
-    r600_vb_get(pScrn);
+    accel_state->src_size[0] = src_pitch * src_height * (src_bpp/8);
+    accel_state->src_mc_addr[0] = src_offset;
+    accel_state->src_pitch[0] = src_pitch;
+    accel_state->src_width[0] = src_width;
+    accel_state->src_height[0] = src_height;
+    accel_state->src_bpp[0] = src_bpp;
+    accel_state->src_bo[0] = src_bo;
+    accel_state->src_bo[1] = NULL;
+
+    accel_state->dst_size = dst_pitch * dst_height * (dst_bpp/8);
+    accel_state->dst_mc_addr = dst_offset;
+    accel_state->dst_pitch = dst_pitch;
+    accel_state->dst_height = dst_height;
+    accel_state->dst_bpp = dst_bpp;
+    accel_state->dst_bo = dst_bo;
+
+    r600_cp_start(pScrn);
+    if (!r600_vb_get(pScrn))
+	return;
 
     /* Init */
     start_3d(pScrn, accel_state->ib);
@@ -405,10 +459,18 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
     set_screen_scissor(pScrn, accel_state->ib, 0, 0, dst_width, dst_height);
     set_window_scissor(pScrn, accel_state->ib, 0, 0, dst_width, dst_height);
 
-    accel_state->vs_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
-	accel_state->copy_vs_offset;
-    accel_state->ps_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
-	accel_state->copy_ps_offset;
+#if defined(XF86DRM_MODE)
+    if (info->cs) {
+	accel_state->vs_mc_addr = accel_state->copy_vs_offset;
+	accel_state->ps_mc_addr = accel_state->copy_ps_offset;
+    } else
+#endif
+    {
+	accel_state->vs_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
+	    accel_state->copy_vs_offset;
+	accel_state->ps_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
+	    accel_state->copy_ps_offset;
+    }
     accel_state->vs_size = 512;
     accel_state->ps_size = 512;
 
@@ -416,16 +478,19 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
 
     /* flush SQ cache */
     cp_set_surface_sync(pScrn, accel_state->ib, SH_ACTION_ENA_bit,
-			accel_state->vs_size, accel_state->vs_mc_addr);
+			accel_state->vs_size, accel_state->vs_mc_addr,
+			accel_state->shaders_bo, RADEON_GEM_DOMAIN_VRAM, 0);
 
     vs_conf.shader_addr         = accel_state->vs_mc_addr;
     vs_conf.num_gprs            = 2;
     vs_conf.stack_size          = 0;
+    vs_conf.bo                  = accel_state->shaders_bo;
     vs_setup                    (pScrn, accel_state->ib, &vs_conf);
 
     /* flush SQ cache */
     cp_set_surface_sync(pScrn, accel_state->ib, SH_ACTION_ENA_bit,
-			accel_state->ps_size, accel_state->ps_mc_addr);
+			accel_state->ps_size, accel_state->ps_mc_addr,
+			accel_state->shaders_bo, RADEON_GEM_DOMAIN_VRAM, 0);
 
     ps_conf.shader_addr         = accel_state->ps_mc_addr;
     ps_conf.num_gprs            = 1;
@@ -433,18 +498,13 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
     ps_conf.uncached_first_inst = 1;
     ps_conf.clamp_consts        = 0;
     ps_conf.export_mode         = 2;
+    ps_conf.bo                  = accel_state->shaders_bo;
     ps_setup                    (pScrn, accel_state->ib, &ps_conf);
 
-    accel_state->src_size[0] = src_pitch * src_height * (src_bpp/8);
-    accel_state->src_mc_addr[0] = src_offset;
-    accel_state->src_pitch[0] = src_pitch;
-    accel_state->src_width[0] = src_width;
-    accel_state->src_height[0] = src_height;
-    accel_state->src_bpp[0] = src_bpp;
-
     /* flush texture cache */
     cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit,
-			accel_state->src_size[0], accel_state->src_mc_addr[0]);
+			accel_state->src_size[0], accel_state->src_mc_addr[0],
+			accel_state->src_bo[0], RADEON_GEM_DOMAIN_VRAM, 0);
 
     /* Texture */
     tex_res.id                  = 0;
@@ -455,6 +515,8 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
     tex_res.dim                 = SQ_TEX_DIM_2D;
     tex_res.base                = accel_state->src_mc_addr[0];
     tex_res.mip_base            = accel_state->src_mc_addr[0];
+    tex_res.bo                  = accel_state->src_bo[0];
+    tex_res.mip_bo              = accel_state->src_bo[0];
     if (src_bpp == 8) {
 	tex_res.format              = FMT_8;
 	tex_res.dst_sel_x           = SQ_SEL_1; /* R */
@@ -506,16 +568,11 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
     EREG(accel_state->ib, CB_COLOR_CONTROL,                    RADEON_ROP[rop]);
     END_BATCH();
 
-    accel_state->dst_size = dst_pitch * dst_height * (dst_bpp/8);
-    accel_state->dst_mc_addr = dst_offset;
-    accel_state->dst_pitch = dst_pitch;
-    accel_state->dst_height = dst_height;
-    accel_state->dst_bpp = dst_bpp;
-
     cb_conf.id = 0;
     cb_conf.w = accel_state->dst_pitch;
     cb_conf.h = dst_height;
     cb_conf.base = accel_state->dst_mc_addr;
+    cb_conf.bo = accel_state->dst_bo;
     if (dst_bpp == 8) {
 	cb_conf.format = COLOR_8;
 	cb_conf.comp_swap = 3; /* A */
@@ -575,10 +632,12 @@ R600DoCopy(ScrnInfoPtr pScrn)
 	(info->ChipFamily == CHIP_FAMILY_RS880) ||
 	(info->ChipFamily == CHIP_FAMILY_RV710))
 	cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit,
-			    accel_state->vb_size, accel_state->vb_mc_addr);
+			    accel_state->vb_size, accel_state->vb_mc_addr,
+			    accel_state->vb_bo, RADEON_GEM_DOMAIN_GTT, 0);
     else
 	cp_set_surface_sync(pScrn, accel_state->ib, VC_ACTION_ENA_bit,
-			    accel_state->vb_size, accel_state->vb_mc_addr);
+			    accel_state->vb_size, accel_state->vb_mc_addr,
+			    accel_state->vb_bo, RADEON_GEM_DOMAIN_GTT, 0);
 
     /* Vertex buffer setup */
     vtx_res.id              = SQ_VTX_RESOURCE_vs;
@@ -586,6 +645,7 @@ R600DoCopy(ScrnInfoPtr pScrn)
     vtx_res.vtx_num_entries = accel_state->vb_size / 4;
     vtx_res.mem_req_size    = 1;
     vtx_res.vb_addr         = accel_state->vb_mc_addr;
+    vtx_res.bo              = accel_state->vb_bo;
     set_vtx_resource        (pScrn, accel_state->ib, &vtx_res);
 
     draw_conf.prim_type          = DI_PT_RECTLIST;
@@ -600,7 +660,8 @@ R600DoCopy(ScrnInfoPtr pScrn)
 
     /* sync dst surface */
     cp_set_surface_sync(pScrn, accel_state->ib, (CB_ACTION_ENA_bit | CB0_DEST_BASE_ENA_bit),
-			accel_state->dst_size, accel_state->dst_mc_addr);
+			accel_state->dst_size, accel_state->dst_mc_addr,
+			accel_state->dst_bo, 0, RADEON_GEM_DOMAIN_VRAM);
 
     R600CPFlushIndirect(pScrn, accel_state->ib);
 }
@@ -617,8 +678,9 @@ R600AppendCopyVertex(ScrnInfoPtr pScrn,
 
     if (((accel_state->vb_index + 3) * 16) > accel_state->vb_total) {
         R600DoCopy(pScrn);
-        accel_state->ib = RADEONCPGetBuffer(pScrn);
-        r600_vb_get(pScrn);
+	r600_cp_start(pScrn);
+	if (!r600_vb_get(pScrn))
+	    return;
     }
 
     vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*16);
@@ -663,8 +725,19 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
     accel_state->dst_pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8);
     accel_state->src_pitch[0] = exaGetPixmapPitch(pSrc) / (pSrc->drawable.bitsPerPixel / 8);
 
-    accel_state->src_mc_addr[0] = exaGetPixmapOffset(pSrc) + info->fbLocation + pScrn->fbOffset;
-    accel_state->dst_mc_addr = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
+#if defined(XF86DRM_MODE)
+    if (info->cs) {
+	accel_state->src_mc_addr[0] = 0;
+	accel_state->dst_mc_addr = 0;
+	accel_state->src_bo[0] = radeon_get_pixmap_bo(pSrc);
+	accel_state->src_bo[1] = NULL;
+	accel_state->dst_bo = radeon_get_pixmap_bo(pDst);
+    } else
+#endif
+    {
+	accel_state->src_mc_addr[0] = exaGetPixmapOffset(pSrc) + info->fbLocation + pScrn->fbOffset;
+	accel_state->dst_mc_addr = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
+    }
 
     accel_state->src_width[0] = pSrc->drawable.width;
     accel_state->src_height[0] = pSrc->drawable.height;
@@ -701,19 +774,46 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
 	unsigned long size = pDst->drawable.height * accel_state->dst_pitch * pDst->drawable.bitsPerPixel/8;
 	accel_state->same_surface = TRUE;
 
-	if (accel_state->copy_area) {
-	    exaOffscreenFree(pDst->drawable.pScreen, accel_state->copy_area);
-	    accel_state->copy_area = NULL;
+#if defined(XF86DRM_MODE)
+	if (info->cs) {
+	    if (accel_state->copy_area_bo) {
+		radeon_bo_unref(accel_state->copy_area_bo);
+		accel_state->copy_area_bo = NULL;
+	    }
+	    accel_state->copy_area_bo = radeon_bo_open(info->bufmgr, 0, size,
+						       4096,
+						       RADEON_GEM_DOMAIN_VRAM,
+						       0);
+	    if (accel_state->copy_area_bo == NULL) {
+		R600IBDiscard(pScrn, accel_state->ib);
+		return FALSE;
+	    }
+	    radeon_cs_space_add_persistent_bo(info->cs, accel_state->copy_area_bo,
+					      RADEON_GEM_DOMAIN_VRAM, 0);
+	    if (radeon_cs_space_check(info->cs)) {
+		radeon_bo_unref(accel_state->copy_area_bo);
+		accel_state->copy_area_bo = NULL;
+		R600IBDiscard(pScrn, accel_state->ib);
+		return FALSE;
+	    }
+	    accel_state->copy_area = (void*)accel_state->copy_area_bo;
+	} else
+#endif
+	{
+	    if (accel_state->copy_area) {
+		exaOffscreenFree(pDst->drawable.pScreen, accel_state->copy_area);
+		accel_state->copy_area = NULL;
+	    }
+	    accel_state->copy_area = exaOffscreenAlloc(pDst->drawable.pScreen, size, 256, TRUE, NULL, NULL);
 	}
-	accel_state->copy_area = exaOffscreenAlloc(pDst->drawable.pScreen, size, 256, TRUE, NULL, NULL);
     } else {
 	accel_state->same_surface = FALSE;
 
 	R600DoPrepareCopy(pScrn,
 			  accel_state->src_pitch[0], pSrc->drawable.width, pSrc->drawable.height,
-			  accel_state->src_mc_addr[0], pSrc->drawable.bitsPerPixel,
+			  accel_state->src_mc_addr[0], accel_state->src_bo[0], pSrc->drawable.bitsPerPixel,
 			  accel_state->dst_pitch, pDst->drawable.width, pDst->drawable.height,
-			  accel_state->dst_mc_addr, pDst->drawable.bitsPerPixel,
+			  accel_state->dst_mc_addr, accel_state->dst_bo, pDst->drawable.bitsPerPixel,
 			  rop, planemask);
 
     }
@@ -745,6 +845,17 @@ R600OverlapCopy(PixmapPtr pDst,
     uint32_t dst_pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8);
     uint32_t dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
     int i, hchunk, vchunk;
+    struct radeon_bo *dst_bo = NULL;
+
+#if defined(XF86DRM_MODE)
+    if (info->cs) {
+	dst_offset = 0;
+	dst_bo = radeon_get_pixmap_bo(pDst);
+	radeon_cs_space_add_persistent_bo(info->cs, dst_bo,
+					  RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_check(info->cs);
+    }
+#endif
 
     if (is_overlap(srcX, srcX + w, srcY, srcY + h,
 		   dstX, dstX + w, dstY, dstY + h)) {
@@ -760,8 +871,10 @@ R600OverlapCopy(PixmapPtr pDst,
             if ((w / hchunk) <= (h / vchunk)) { /* reduce to horizontal  */
                 if (srcY > dstY ) { /* diagonal up */
                     R600DoPrepareCopy(pScrn,
-                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height,
+				      dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height,
+				      dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
                                       accel_state->rop, accel_state->planemask);
                     R600AppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, w, vchunk);
                     R600DoCopy(pScrn);
@@ -770,8 +883,10 @@ R600OverlapCopy(PixmapPtr pDst,
                     dstY = dstY + vchunk;
                 } else { /* diagonal down */
                     R600DoPrepareCopy(pScrn,
-                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height,
+				      dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height,
+				      dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
                                       accel_state->rop, accel_state->planemask);
                     R600AppendCopyVertex(pScrn, srcX, srcY + h - vchunk, dstX, dstY + h - vchunk, w, vchunk);
                     R600DoCopy(pScrn);
@@ -781,8 +896,10 @@ R600OverlapCopy(PixmapPtr pDst,
             } else { /* reduce to vertical */
                 if (srcX > dstX ) { /* diagonal left */
                     R600DoPrepareCopy(pScrn,
-                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height,
+				      dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height,
+				      dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
                                       accel_state->rop, accel_state->planemask);
                     R600AppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, hchunk, h);
                     R600DoCopy(pScrn);
@@ -791,8 +908,10 @@ R600OverlapCopy(PixmapPtr pDst,
                     dstX = dstX + hchunk;
                 } else { /* diagonal right */
                     R600DoPrepareCopy(pScrn,
-                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height,
+				      dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height,
+				      dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
                                       accel_state->rop, accel_state->planemask);
                     R600AppendCopyVertex(pScrn, srcX + w - hchunk, srcY, dstX + w - hchunk, dstY, hchunk, h);
                     R600DoCopy(pScrn);
@@ -807,8 +926,10 @@ R600OverlapCopy(PixmapPtr pDst,
 		/* copy right to left */
 		for (i = w; i > 0; i -= hchunk) {
 		    R600DoPrepareCopy(pScrn,
-				      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-				      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+				      dst_pitch, pDst->drawable.width, pDst->drawable.height,
+				      dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
+				      dst_pitch, pDst->drawable.width, pDst->drawable.height,
+				      dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
 				      accel_state->rop, accel_state->planemask);
 		    R600AppendCopyVertex(pScrn, srcX + i - hchunk, srcY, dstX + i - hchunk, dstY, hchunk, h);
 		    R600DoCopy(pScrn);
@@ -817,8 +938,10 @@ R600OverlapCopy(PixmapPtr pDst,
 		/* copy left to right */
 		for (i = 0; i < w; i += hchunk) {
 		    R600DoPrepareCopy(pScrn,
-				      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-				      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+				      dst_pitch, pDst->drawable.width, pDst->drawable.height,
+				      dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
+				      dst_pitch, pDst->drawable.width, pDst->drawable.height,
+				      dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
 				      accel_state->rop, accel_state->planemask);
 
 		    R600AppendCopyVertex(pScrn, srcX + i, srcY, dstX + i, dstY, hchunk, h);
@@ -830,8 +953,10 @@ R600OverlapCopy(PixmapPtr pDst,
 		/* copy top to bottom */
                 for (i = 0; i < h; i += vchunk) {
                     R600DoPrepareCopy(pScrn,
-                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height,
+				      dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height,
+				      dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
                                       accel_state->rop, accel_state->planemask);
 
                     if (vchunk > h - i) vchunk = h - i;
@@ -842,8 +967,10 @@ R600OverlapCopy(PixmapPtr pDst,
 		/* copy bottom to top */
                 for (i = h; i > 0; i -= vchunk) {
                     R600DoPrepareCopy(pScrn,
-                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height,
+				      dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height,
+				      dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
                                       accel_state->rop, accel_state->planemask);
 
                     if (vchunk > i) vchunk = i;
@@ -854,8 +981,10 @@ R600OverlapCopy(PixmapPtr pDst,
 	}
     } else {
 	R600DoPrepareCopy(pScrn,
-			  dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-			  dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+			  dst_pitch, pDst->drawable.width, pDst->drawable.height,
+			  dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
+			  dst_pitch, pDst->drawable.width, pDst->drawable.height,
+			  dst_offset, dst_bo, pDst->drawable.bitsPerPixel,
 			  accel_state->rop, accel_state->planemask);
 
 	R600AppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, w, h);
@@ -872,27 +1001,45 @@ R600Copy(PixmapPtr pDst,
     ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
     RADEONInfoPtr info = RADEONPTR(pScrn);
     struct radeon_accel_state *accel_state = info->accel_state;
+    struct radeon_bo *bo = NULL;
 
     if (accel_state->same_surface && (srcX == dstX) && (srcY == dstY))
 	return;
 
-    if (accel_state->same_surface && is_overlap(srcX, srcX + w, srcY, srcY + h, dstX, dstX + w, dstY, dstY + h)) {
+#if defined(XF86DRM_MODE)
+    if (info->cs)
+	bo = radeon_get_pixmap_bo(pDst);
+#endif
+
+    if (accel_state->same_surface &&
+	is_overlap(srcX, srcX + w, srcY, srcY + h, dstX, dstX + w, dstY, dstY + h)) {
 	if (accel_state->copy_area) {
 	    uint32_t pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8);
 	    uint32_t orig_offset, tmp_offset;
 
-	    tmp_offset = accel_state->copy_area->offset + info->fbLocation + pScrn->fbOffset;
-	    orig_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
-
+#if defined(XF86DRM_MODE)
+	    if (info->cs) {
+		tmp_offset = 0;
+		orig_offset = 0;
+	    } else
+#endif
+	    {
+		tmp_offset = accel_state->copy_area->offset + info->fbLocation + pScrn->fbOffset;
+		orig_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
+	    }
 	    R600DoPrepareCopy(pScrn,
-			      pitch, pDst->drawable.width, pDst->drawable.height, orig_offset, pDst->drawable.bitsPerPixel,
-			      pitch, pDst->drawable.width, pDst->drawable.height, tmp_offset, pDst->drawable.bitsPerPixel,
+			      pitch, pDst->drawable.width, pDst->drawable.height,
+			      orig_offset, bo, pDst->drawable.bitsPerPixel,
+			      pitch, pDst->drawable.width, pDst->drawable.height,
+			      tmp_offset, accel_state->copy_area_bo, pDst->drawable.bitsPerPixel,
 			      accel_state->rop, accel_state->planemask);
 	    R600AppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, w, h);
 	    R600DoCopy(pScrn);
 	    R600DoPrepareCopy(pScrn,
-			      pitch, pDst->drawable.width, pDst->drawable.height, tmp_offset, pDst->drawable.bitsPerPixel,
-			      pitch, pDst->drawable.width, pDst->drawable.height, orig_offset, pDst->drawable.bitsPerPixel,
+			      pitch, pDst->drawable.width, pDst->drawable.height,
+			      tmp_offset, accel_state->copy_area_bo, pDst->drawable.bitsPerPixel,
+			      pitch, pDst->drawable.width, pDst->drawable.height,
+			      orig_offset, bo, pDst->drawable.bitsPerPixel,
 			      accel_state->rop, accel_state->planemask);
 	    R600AppendCopyVertex(pScrn, dstX, dstY, dstX, dstY, w, h);
 	    R600DoCopy(pScrn);
@@ -900,11 +1047,20 @@ R600Copy(PixmapPtr pDst,
 	    R600OverlapCopy(pDst, srcX, srcY, dstX, dstY, w, h);
     } else if (accel_state->same_surface) {
 	uint32_t pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8);
-	uint32_t offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
+	uint32_t offset;
+
+#if defined(XF86DRM_MODE)
+	    if (info->cs)
+		offset = 0;
+	    else
+#endif
+		offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
 
 	R600DoPrepareCopy(pScrn,
-			  pitch, pDst->drawable.width, pDst->drawable.height, offset, pDst->drawable.bitsPerPixel,
-			  pitch, pDst->drawable.width, pDst->drawable.height, offset, pDst->drawable.bitsPerPixel,
+			  pitch, pDst->drawable.width, pDst->drawable.height,
+			  offset, bo, pDst->drawable.bitsPerPixel,
+			  pitch, pDst->drawable.width, pDst->drawable.height,
+			  offset, bo, pDst->drawable.bitsPerPixel,
 			  accel_state->rop, accel_state->planemask);
 	R600AppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, w, h);
 	R600DoCopy(pScrn);
@@ -925,10 +1081,13 @@ R600DoneCopy(PixmapPtr pDst)
 	R600DoCopy(pScrn);
 
     if (accel_state->copy_area) {
-	exaOffscreenFree(pDst->drawable.pScreen, accel_state->copy_area);
+	if (!info->cs)
+	    exaOffscreenFree(pDst->drawable.pScreen, accel_state->copy_area);
 	accel_state->copy_area = NULL;
     }
-
+    accel_state->src_bo[0] = NULL;
+    accel_state->src_bo[1] = NULL;
+    accel_state->dst_bo = NULL;
 }
 
 
@@ -1103,7 +1262,16 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
     CLEAR (tex_res);
     CLEAR (tex_samp);
 
-    accel_state->src_mc_addr[unit] = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset;
+#if defined(XF86DRM_MODE)
+    if (info->cs) {
+	accel_state->src_mc_addr[unit] = 0;
+	accel_state->src_bo[unit] = radeon_get_pixmap_bo(pPix);
+	radeon_cs_space_add_persistent_bo(info->cs, accel_state->src_bo[unit],
+					  RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_check(info->cs);
+    } else
+#endif
+	accel_state->src_mc_addr[unit] = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset;
     accel_state->src_pitch[unit] = exaGetPixmapPitch(pPix) / (pPix->drawable.bitsPerPixel / 8);
     accel_state->src_size[unit] = exaGetPixmapPitch(pPix) * pPix->drawable.height;
 
@@ -1122,7 +1290,8 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
 
     /* flush texture cache */
     cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit,
-			accel_state->src_size[unit], accel_state->src_mc_addr[unit]);
+			accel_state->src_size[unit], accel_state->src_mc_addr[unit],
+			accel_state->src_bo[unit], RADEON_GEM_DOMAIN_VRAM, 0);
 
     /* Texture */
     tex_res.id                  = unit;
@@ -1134,6 +1303,8 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
     tex_res.base                = accel_state->src_mc_addr[unit];
     tex_res.mip_base            = accel_state->src_mc_addr[unit];
     tex_res.format              = R600TexFormats[i].card_fmt;
+    tex_res.bo                  = accel_state->src_bo[unit];
+    tex_res.mip_bo              = accel_state->src_bo[unit];
     tex_res.request_size        = 1;
 
     /* component swizzles */
@@ -1406,6 +1577,9 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
 
     /* return FALSE; */
 
+    if (pDst->drawable.bitsPerPixel < 8 || pSrc->drawable.bitsPerPixel < 8)
+	return FALSE;
+
     if (pMask) {
 	accel_state->msk_pic = pMaskPicture;
 	if (pMaskPicture->componentAlpha) {
@@ -1424,7 +1598,13 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
 	accel_state->src_alpha = FALSE;
     }
 
-    accel_state->dst_mc_addr = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
+#if defined(XF86DRM_MODE)
+    if (info->cs) {
+	accel_state->dst_mc_addr = 0;
+	accel_state->dst_bo = radeon_get_pixmap_bo(pDst);
+    } else
+#endif
+	accel_state->dst_mc_addr = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
     accel_state->dst_pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8);
     accel_state->dst_size = exaGetPixmapPitch(pDst) * pDst->drawable.height;
 
@@ -1441,8 +1621,9 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     CLEAR (vs_conf);
     CLEAR (ps_conf);
 
-    accel_state->ib = RADEONCPGetBuffer(pScrn);
-    r600_vb_get(pScrn);
+    r600_cp_start(pScrn);
+    if (!r600_vb_get(pScrn))
+	RADEON_FALLBACK(("Can't get VB\n"));
 
     /* Init */
     start_3d(pScrn, accel_state->ib);
@@ -1470,16 +1651,31 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
 
     if (pMask) {
 	set_bool_consts(pScrn, accel_state->ib, SQ_BOOL_CONST_vs, (1 << 0));
-	accel_state->ps_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
-	    accel_state->comp_mask_ps_offset;
+#if defined(XF86DRM_MODE)
+	if (info->cs)
+	    accel_state->ps_mc_addr = accel_state->comp_mask_ps_offset;
+	else
+#endif
+	    accel_state->ps_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
+		accel_state->comp_mask_ps_offset;
     } else {
 	set_bool_consts(pScrn, accel_state->ib, SQ_BOOL_CONST_vs, (0 << 0));
-	accel_state->ps_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
+#if defined(XF86DRM_MODE)
+	if (info->cs)
+	    accel_state->ps_mc_addr = accel_state->comp_ps_offset;
+	else
+#endif
+	    accel_state->ps_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
 	    accel_state->comp_ps_offset;
     }
 
-    accel_state->vs_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
-	accel_state->comp_vs_offset;
+#if defined(XF86DRM_MODE)
+    if (info->cs)
+	accel_state->vs_mc_addr = accel_state->comp_vs_offset;
+    else
+#endif
+	accel_state->vs_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
+	    accel_state->comp_vs_offset;
 
     accel_state->vs_size = 512;
     accel_state->ps_size = 512;
@@ -1488,16 +1684,19 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
 
     /* flush SQ cache */
     cp_set_surface_sync(pScrn, accel_state->ib, SH_ACTION_ENA_bit,
-			accel_state->vs_size, accel_state->vs_mc_addr);
+			accel_state->vs_size, accel_state->vs_mc_addr,
+			accel_state->shaders_bo, RADEON_GEM_DOMAIN_VRAM, 0);
 
     vs_conf.shader_addr         = accel_state->vs_mc_addr;
     vs_conf.num_gprs            = 3;
     vs_conf.stack_size          = 1;
+    vs_conf.bo                  = accel_state->shaders_bo;
     vs_setup                    (pScrn, accel_state->ib, &vs_conf);
 
     /* flush SQ cache */
     cp_set_surface_sync(pScrn, accel_state->ib, SH_ACTION_ENA_bit,
-			accel_state->ps_size, accel_state->ps_mc_addr);
+			accel_state->ps_size, accel_state->ps_mc_addr,
+			accel_state->shaders_bo, RADEON_GEM_DOMAIN_VRAM, 0);
 
     ps_conf.shader_addr         = accel_state->ps_mc_addr;
     ps_conf.num_gprs            = 3;
@@ -1505,6 +1704,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     ps_conf.uncached_first_inst = 1;
     ps_conf.clamp_consts        = 0;
     ps_conf.export_mode         = 2;
+    ps_conf.bo                  = accel_state->shaders_bo;
     ps_setup                    (pScrn, accel_state->ib, &ps_conf);
 
     BEGIN_BATCH(12);
@@ -1529,6 +1729,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     cb_conf.h = pDst->drawable.height;
     cb_conf.base = accel_state->dst_mc_addr;
     cb_conf.format = dst_format;
+    cb_conf.bo = accel_state->dst_bo;
 
     switch (pDstPicture->format) {
     case PICT_a8r8g8b8:
@@ -1611,8 +1812,9 @@ static void R600Composite(PixmapPtr pDst,
 
         if (((accel_state->vb_index + 3) * 24) > accel_state->vb_total) {
             R600DoneComposite(pDst);
-            accel_state->ib = RADEONCPGetBuffer(pScrn);
-            r600_vb_get(pScrn);
+	    r600_cp_start(pScrn);
+	    if (!r600_vb_get(pScrn))
+		return;
         }
 
         vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*24);
@@ -1650,8 +1852,9 @@ static void R600Composite(PixmapPtr pDst,
     } else {
         if (((accel_state->vb_index + 3) * 16) > accel_state->vb_total) {
             R600DoneComposite(pDst);
-            accel_state->ib = RADEONCPGetBuffer(pScrn);
-            r600_vb_get(pScrn);
+	    r600_cp_start(pScrn);
+	    if (!r600_vb_get(pScrn))
+		return;
         }
 
         vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*16);
@@ -1701,6 +1904,7 @@ static void R600DoneComposite(PixmapPtr pDst)
 	vtx_res.vtx_num_entries = accel_state->vb_size / 4;
 	vtx_res.mem_req_size    = 1;
 	vtx_res.vb_addr         = accel_state->vb_mc_addr;
+	vtx_res.bo              = accel_state->vb_bo;
     } else {
 	accel_state->vb_size = accel_state->vb_index * 16;
 	vtx_res.id              = SQ_VTX_RESOURCE_vs;
@@ -1708,6 +1912,7 @@ static void R600DoneComposite(PixmapPtr pDst)
 	vtx_res.vtx_num_entries = accel_state->vb_size / 4;
 	vtx_res.mem_req_size    = 1;
 	vtx_res.vb_addr         = accel_state->vb_mc_addr;
+	vtx_res.bo              = accel_state->vb_bo;
     }
     /* flush vertex cache */
     if ((info->ChipFamily == CHIP_FAMILY_RV610) ||
@@ -1716,12 +1921,14 @@ static void R600DoneComposite(PixmapPtr pDst)
 	(info->ChipFamily == CHIP_FAMILY_RS880) ||
 	(info->ChipFamily == CHIP_FAMILY_RV710))
 	cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit,
-			    accel_state->vb_size, accel_state->vb_mc_addr);
+			    accel_state->vb_size, accel_state->vb_mc_addr,
+			    accel_state->vb_bo, RADEON_GEM_DOMAIN_GTT, 0);
     else
 	cp_set_surface_sync(pScrn, accel_state->ib, VC_ACTION_ENA_bit,
-			    accel_state->vb_size, accel_state->vb_mc_addr);
+			    accel_state->vb_size, accel_state->vb_mc_addr,
+			    accel_state->vb_bo, RADEON_GEM_DOMAIN_GTT, 0);
 
-    set_vtx_resource        (pScrn, accel_state->ib, &vtx_res);
+    set_vtx_resource(pScrn, accel_state->ib, &vtx_res);
 
     draw_conf.prim_type          = DI_PT_RECTLIST;
     draw_conf.vgt_draw_initiator = DI_SRC_SEL_AUTO_INDEX;
@@ -1734,9 +1941,14 @@ static void R600DoneComposite(PixmapPtr pDst)
     wait_3d_idle_clean(pScrn, accel_state->ib);
 
     cp_set_surface_sync(pScrn, accel_state->ib, (CB_ACTION_ENA_bit | CB0_DEST_BASE_ENA_bit),
-			accel_state->dst_size, accel_state->dst_mc_addr);
+			accel_state->dst_size, accel_state->dst_mc_addr,
+			accel_state->dst_bo, RADEON_GEM_DOMAIN_VRAM, 0);
 
     R600CPFlushIndirect(pScrn, accel_state->ib);
+
+    accel_state->src_bo[0] = NULL;
+    accel_state->src_bo[1] = NULL;
+    accel_state->dst_bo = NULL;
 }
 
 Bool
@@ -1753,6 +1965,7 @@ R600CopyToVRAM(ScrnInfoPtr pScrn,
     int scratch_offset = 0, hpass, temph;
     char *dst;
     drmBufPtr scratch;
+    struct radeon_bo *bo = NULL;
 
     if (dst_pitch & 7)
 	return FALSE;
@@ -1795,8 +2008,10 @@ R600CopyToVRAM(ScrnInfoPtr pScrn,
 	}
 	/* blit from scratch to vram */
 	R600DoPrepareCopy(pScrn,
-			  scratch_pitch, w, oldhpass, offset, bpp,
-			  dst_pitch, dst_width, dst_height, dst_mc_addr, bpp,
+			  scratch_pitch, w, oldhpass,
+			  offset, bo, bpp,
+			  dst_pitch, dst_width, dst_height,
+			  dst_mc_addr, bo, bpp,
 			  3, 0xffffffff);
 	R600AppendCopyVertex(pScrn, 0, 0, x, y, w, oldhpass);
 	R600DoCopy(pScrn);
@@ -1842,6 +2057,7 @@ R600DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
     uint32_t scratch_pitch = scratch_pitch_bytes / (bpp / 8);
     int wpass = w * (bpp/8);
     drmBufPtr scratch;
+    struct radeon_bo *bo = NULL;
 
     /* RV740 seems to be particularly problematic with small xfers */
     if ((info->ChipFamily == CHIP_FAMILY_RV740) && (w < 32 || h < 32))
@@ -1859,8 +2075,10 @@ R600DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
 
     /* blit from vram to scratch */
     R600DoPrepareCopy(pScrn,
-		      src_pitch, src_width, src_height, src_mc_addr, bpp,
-		      scratch_pitch, src_width, hpass, scratch_mc_addr, bpp,
+		      src_pitch, src_width, src_height,
+		      src_mc_addr, bo, bpp,
+		      scratch_pitch, src_width, hpass,
+		      scratch_mc_addr, bo, bpp,
 		      3, 0xffffffff);
     R600AppendCopyVertex(pScrn, x, y, 0, 0, w, hpass);
     R600DoCopy(pScrn);
@@ -1876,8 +2094,10 @@ R600DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
 	    scratch_offset = scratch->total/2 - scratch_offset;
 	    /* blit from vram to scratch */
 	    R600DoPrepareCopy(pScrn,
-			      src_pitch, src_width, src_height, src_mc_addr, bpp,
-			      scratch_pitch, src_width, hpass, scratch_mc_addr + scratch_offset, bpp,
+			      src_pitch, src_width, src_height,
+			      src_mc_addr, bo, bpp,
+			      scratch_pitch, src_width, hpass,
+			      scratch_mc_addr + scratch_offset, bo, bpp,
 			      3, 0xffffffff);
 	    R600AppendCopyVertex(pScrn, x, y, 0, 0, w, hpass);
 	    R600DoCopy(pScrn);
@@ -1919,7 +2139,12 @@ R600Sync(ScreenPtr pScreen, int marker)
     struct radeon_accel_state *accel_state = info->accel_state;
 
     if (accel_state->exaMarkerSynced != marker) {
-	RADEONWaitForIdleCP(pScrn);
+#ifdef XF86DRM_MODE
+#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 4)
+	if (!info->cs)
+#endif
+#endif
+	    RADEONWaitForIdleCP(pScrn);
 	accel_state->exaMarkerSynced = marker;
     }
 
@@ -1936,11 +2161,27 @@ R600AllocShaders(ScrnInfoPtr pScrn, ScreenPtr pScreen)
 
     accel_state->shaders = NULL;
 
-    accel_state->shaders = exaOffscreenAlloc(pScreen, size, 256,
-					     TRUE, NULL, NULL);
+#ifdef XF86DRM_MODE
+#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 4)
+    if (info->cs) {
+	accel_state->shaders_bo = radeon_bo_open(info->bufmgr, 0, size, 4096,
+						 RADEON_GEM_DOMAIN_VRAM, 0);
+	if (accel_state->shaders_bo == NULL) {
+	    ErrorF("Allocating shader failed\n");
+	    return FALSE;
+	}
+	return TRUE;
+    } else
+#endif
+#endif
+    {
+	accel_state->shaders = exaOffscreenAlloc(pScreen, size, 256,
+						 TRUE, NULL, NULL);
+
+	if (accel_state->shaders == NULL)
+	    return FALSE;
+    }
 
-    if (accel_state->shaders == NULL)
-	return FALSE;
     return TRUE;
 }
 
@@ -1951,8 +2192,21 @@ R600LoadShaders(ScrnInfoPtr pScrn)
     struct radeon_accel_state *accel_state = info->accel_state;
     RADEONChipFamily ChipSet = info->ChipFamily;
     uint32_t *shader;
-
-    shader = (pointer)((char *)info->FB + accel_state->shaders->offset);
+#ifdef XF86DRM_MODE
+#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 4)
+    int ret;
+
+    if (info->cs) {
+	ret = radeon_bo_map(accel_state->shaders_bo, 1);
+	if (ret) {
+	    FatalError("failed to map shader %d\n", ret);
+	    return FALSE;
+	}
+	shader = accel_state->shaders_bo->ptr;
+    } else
+#endif
+#endif
+	shader = (pointer)((char *)info->FB + accel_state->shaders->offset);
 
     /*  solid vs --------------------------------------- */
     accel_state->solid_vs_offset = 0;
@@ -1990,6 +2244,14 @@ R600LoadShaders(ScrnInfoPtr pScrn)
     accel_state->xv_ps_offset = 4096;
     R600_xv_ps(ChipSet, shader + accel_state->xv_ps_offset / 4);
 
+#ifdef XF86DRM_MODE
+#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 4)
+    if (info->cs) {
+	radeon_bo_unmap(accel_state->shaders_bo);
+    }
+#endif
+#endif
+
     return TRUE;
 }
 
@@ -2018,7 +2280,6 @@ R600FinishAccess(PixmapPtr pPix, int index)
 
 }
 
-
 Bool
 R600DrawInit(ScreenPtr pScreen)
 {
@@ -2044,13 +2305,28 @@ R600DrawInit(ScreenPtr pScreen)
     info->accel_state->exa->MarkSync = R600MarkSync;
     info->accel_state->exa->WaitMarker = R600Sync;
 
-    info->accel_state->exa->PrepareAccess = R600PrepareAccess;
-    info->accel_state->exa->FinishAccess = R600FinishAccess;
-
-    /* AGP seems to have problems with gart transfers */
-    if (info->accelDFS) {
-	info->accel_state->exa->UploadToScreen = R600UploadToScreen;
-	info->accel_state->exa->DownloadFromScreen = R600DownloadFromScreen;
+#ifdef XF86DRM_MODE
+#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 4)
+    if (info->cs) {
+	info->accel_state->exa->CreatePixmap = RADEONEXACreatePixmap;
+	info->accel_state->exa->DestroyPixmap = RADEONEXADestroyPixmap;
+	info->accel_state->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen;
+	info->accel_state->exa->PrepareAccess = RADEONPrepareAccess_CS;
+	info->accel_state->exa->FinishAccess = RADEONFinishAccess_CS;
+	info->accel_state->exa->UploadToScreen = NULL;
+	info->accel_state->exa->DownloadFromScreen = NULL;
+    } else
+#endif
+#endif
+    {
+	info->accel_state->exa->PrepareAccess = R600PrepareAccess;
+	info->accel_state->exa->FinishAccess = R600FinishAccess;
+
+	/* AGP seems to have problems with gart transfers */
+	if (info->accelDFS) {
+	    info->accel_state->exa->UploadToScreen = R600UploadToScreen;
+	    info->accel_state->exa->DownloadFromScreen = R600DownloadFromScreen;
+	}
     }
 
     info->accel_state->exa->flags = EXA_OFFSCREEN_PIXMAPS;
@@ -2083,8 +2359,13 @@ R600DrawInit(ScreenPtr pScreen)
 	return FALSE;
     }
 
-    if (!info->gartLocation)
-	return FALSE;
+#ifdef XF86DRM_MODE
+#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 4)
+    if (!info->cs)
+#endif
+#endif
+	if (!info->gartLocation)
+	    return FALSE;
 
     info->accel_state->XInited3D = FALSE;
     info->accel_state->copy_area = NULL;
diff --git a/src/r600_state.h b/src/r600_state.h
index 10b1022..6ca88cf 100644
--- a/src/r600_state.h
+++ b/src/r600_state.h
@@ -50,6 +50,7 @@ typedef struct {
     int round_mode;
     int tile_compact;
     int source_format;
+    struct radeon_bo *bo;
 } cb_config_t;
 
 /* Depth buffer */
@@ -63,6 +64,7 @@ typedef struct {
     int tile_surface_en;
     int tile_compact;
     int zrange_precision;
+    struct radeon_bo *bo;
 } db_config_t;
 
 /* Shader */
@@ -79,6 +81,7 @@ typedef struct {
     int clamp_consts;
     int export_mode;
     int uncached_first_inst;
+    struct radeon_bo *bo;
 } shader_config_t;
 
 /* Vertex buffer / vtx resource */
@@ -94,6 +97,7 @@ typedef struct {
     int srf_mode_all;
     int endian;
     int mem_req_size;
+    struct radeon_bo *bo;
 } vtx_resource_t;
 
 /* Texture resource */
@@ -129,6 +133,8 @@ typedef struct {
     int mpeg_clamp;
     int perf_modulation;
     int interlaced;
+    struct radeon_bo *bo;
+    struct radeon_bo *mip_bo;
 } tex_resource_t;
 
 /* Texture sampler */
@@ -170,15 +176,43 @@ typedef struct {
     uint32_t num_indices;
 } draw_config_t;
 
+#if defined(XF86DRM_MODE)
+#define BEGIN_BATCH(n)				\
+do {					\
+    if (info->cs)			\
+	radeon_ddx_cs_start(pScrn, (n), __FILE__, __func__, __LINE__);	\
+} while(0)
+#define END_BATCH()				\
+do {					\
+    if (info->cs)			\
+	radeon_cs_end(info->cs, __FILE__, __func__, __LINE__);	\
+} while(0)
+#define RELOC_BATCH(bo, rd, wd)					\
+do {								\
+    if (info->cs)							\
+	OUT_RING_RELOC((bo), (rd), (wd));				\
+} while(0)
+#define E32(ib, dword)                                                  \
+do {                                                                    \
+    if (info->cs)							\
+	radeon_cs_write_dword(info->cs, (dword));			\
+    else {								\
+	uint32_t *ib_head = (pointer)(char*)(ib)->address;		\
+	ib_head[(ib)->used >> 2] = (dword);				\
+	(ib)->used += 4;						\
+    }									\
+} while (0)
+#else
 #define BEGIN_BATCH(n) do {} while(0)
 #define END_BATCH() do {} while(0)
-
+#define RELOC_BATCH(bo, wd, rd) do {} while(0)
 #define E32(ib, dword)                                                  \
 do {                                                                    \
     uint32_t *ib_head = (pointer)(char*)(ib)->address;			\
     ib_head[(ib)->used >> 2] = (dword);					\
     (ib)->used += 4;							\
 } while (0)
+#endif
 
 #define EFLOAT(ib, val)							\
 do {								        \
@@ -246,7 +280,8 @@ start_3d(ScrnInfoPtr pScrn, drmBufPtr ib);
 void
 set_render_target(ScrnInfoPtr pScrn, drmBufPtr ib, cb_config_t *cb_conf);
 void
-cp_set_surface_sync(ScrnInfoPtr pScrn, drmBufPtr ib, uint32_t sync_type, uint32_t size, uint64_t mc_addr);
+cp_set_surface_sync(ScrnInfoPtr pScrn, drmBufPtr ib, uint32_t sync_type, uint32_t size, uint64_t mc_addr,
+		    struct radeon_bo *bo, uint32_t rdomains, uint32_t wdomain);
 void
 cp_wait_vline_sync(ScrnInfoPtr pScrn, drmBufPtr ib, PixmapPtr pPix, int crtc, int start, int stop);
 void
@@ -282,9 +317,18 @@ draw_immd(ScrnInfoPtr pScrn, drmBufPtr ib, draw_config_t *draw_conf, uint32_t *i
 void
 draw_auto(ScrnInfoPtr pScrn, drmBufPtr ib, draw_config_t *draw_conf);
 
-void
+Bool
 r600_vb_get(ScrnInfoPtr pScrn);
 void
 r600_vb_discard(ScrnInfoPtr pScrn);
+int
+r600_cp_start(ScrnInfoPtr pScrn);
+
+extern Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index);
+extern void RADEONFinishAccess_CS(PixmapPtr pPix, int index);
+extern void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align);
+extern void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv);
+extern struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix);
+extern Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix);
 
 #endif
diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index 6739616..9cbfea4 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -80,10 +80,12 @@ R600DoneTexturedVideo(ScrnInfoPtr pScrn)
 	(info->ChipFamily == CHIP_FAMILY_RS880) ||
 	(info->ChipFamily == CHIP_FAMILY_RV710))
 	cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit,
-			    accel_state->vb_size, accel_state->vb_mc_addr);
+			    accel_state->vb_size, accel_state->vb_mc_addr,
+			    accel_state->vb_bo, RADEON_GEM_DOMAIN_GTT, 0);
     else
 	cp_set_surface_sync(pScrn, accel_state->ib, VC_ACTION_ENA_bit,
-			    accel_state->vb_size, accel_state->vb_mc_addr);
+			    accel_state->vb_size, accel_state->vb_mc_addr,
+			    accel_state->vb_bo, RADEON_GEM_DOMAIN_GTT, 0);
 
     /* Vertex buffer setup */
     vtx_res.id              = SQ_VTX_RESOURCE_vs;
@@ -91,6 +93,7 @@ R600DoneTexturedVideo(ScrnInfoPtr pScrn)
     vtx_res.vtx_num_entries = accel_state->vb_size / 4;
     vtx_res.mem_req_size    = 1;
     vtx_res.vb_addr         = accel_state->vb_mc_addr;
+    vtx_res.bo              = accel_state->vb_bo;
     set_vtx_resource        (pScrn, accel_state->ib, &vtx_res);
 
     draw_conf.prim_type          = DI_PT_RECTLIST;
@@ -105,9 +108,13 @@ R600DoneTexturedVideo(ScrnInfoPtr pScrn)
 
     /* sync destination surface */
     cp_set_surface_sync(pScrn, accel_state->ib, (CB_ACTION_ENA_bit | CB0_DEST_BASE_ENA_bit),
-			accel_state->dst_size, accel_state->dst_mc_addr);
+			accel_state->dst_size, accel_state->dst_mc_addr,
+			accel_state->dst_bo, 0, RADEON_GEM_DOMAIN_VRAM);
 
     R600CPFlushIndirect(pScrn, accel_state->ib);
+    accel_state->dst_bo = NULL;
+    accel_state->src_bo[0] = NULL;
+    accel_state->src_bo[1] = NULL;
 }
 
 void
@@ -216,6 +223,19 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     CLEAR (vs_conf);
     CLEAR (ps_conf);
 
+#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
+    if (info->cs) {
+	accel_state->dst_mc_addr = 0;
+	accel_state->src_mc_addr[0] = 0;
+	accel_state->src_bo[0] = pPriv->src_bo;
+	accel_state->src_bo[1] = NULL;
+	accel_state->dst_bo = radeon_get_pixmap_bo(pPixmap);
+    } else
+#endif
+    {
+	accel_state->dst_mc_addr = exaGetPixmapOffset(pPixmap) + info->fbLocation + pScrn->fbOffset;
+	accel_state->src_mc_addr[0] = pPriv->src_offset + info->fbLocation + pScrn->fbOffset;
+    }
     accel_state->dst_pitch = exaGetPixmapPitch(pPixmap) / (pPixmap->drawable.bitsPerPixel / 8);
     accel_state->src_pitch[0] = pPriv->src_pitch;
 
@@ -233,8 +253,9 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     dstyoff = 0;
 #endif
 
-    accel_state->ib = RADEONCPGetBuffer(pScrn);
-    r600_vb_get(pScrn);
+    r600_cp_start(pScrn);
+    if (!r600_vb_get(pScrn))
+	return;
 
     /* Init */
     start_3d(pScrn, accel_state->ib);
@@ -245,11 +266,18 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     set_screen_scissor(pScrn, accel_state->ib, 0, 0, pPixmap->drawable.width, pPixmap->drawable.height);
     set_window_scissor(pScrn, accel_state->ib, 0, 0, pPixmap->drawable.width, pPixmap->drawable.height);
 
-    accel_state->vs_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
-	accel_state->xv_vs_offset;
-
-    accel_state->ps_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
-	accel_state->xv_ps_offset;
+#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
+    if (info->cs) {
+	accel_state->vs_mc_addr = accel_state->xv_vs_offset;
+	accel_state->ps_mc_addr = accel_state->xv_ps_offset;
+    } else
+#endif
+    {
+	accel_state->vs_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
+	    accel_state->xv_vs_offset;
+	accel_state->ps_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
+	    accel_state->xv_ps_offset;
+    }
 
     /* PS bool constant */
     switch(pPriv->id) {
@@ -271,16 +299,19 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 
     /* flush SQ cache */
     cp_set_surface_sync(pScrn, accel_state->ib, SH_ACTION_ENA_bit,
-			accel_state->vs_size, accel_state->vs_mc_addr);
+			accel_state->vs_size, accel_state->vs_mc_addr,
+			accel_state->shaders_bo, RADEON_GEM_DOMAIN_VRAM, 0);
 
     vs_conf.shader_addr         = accel_state->vs_mc_addr;
     vs_conf.num_gprs            = 2;
     vs_conf.stack_size          = 0;
+    vs_conf.bo                  = accel_state->shaders_bo;
     vs_setup                    (pScrn, accel_state->ib, &vs_conf);
 
     /* flush SQ cache */
     cp_set_surface_sync(pScrn, accel_state->ib, SH_ACTION_ENA_bit,
-			accel_state->ps_size, accel_state->ps_mc_addr);
+			accel_state->ps_size, accel_state->ps_mc_addr,
+			accel_state->shaders_bo, RADEON_GEM_DOMAIN_VRAM, 0);
 
     ps_conf.shader_addr         = accel_state->ps_mc_addr;
     ps_conf.num_gprs            = 3;
@@ -288,6 +319,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     ps_conf.uncached_first_inst = 1;
     ps_conf.clamp_consts        = 0;
     ps_conf.export_mode         = 2;
+    ps_conf.bo                  = accel_state->shaders_bo;
     ps_setup                    (pScrn, accel_state->ib, &ps_conf);
 
     /* PS alu constants */
@@ -298,12 +330,12 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     switch(pPriv->id) {
     case FOURCC_YV12:
     case FOURCC_I420:
-	accel_state->src_mc_addr[0] = pPriv->src_offset + info->fbLocation + pScrn->fbOffset;
 	accel_state->src_size[0] = accel_state->src_pitch[0] * pPriv->h;
 
 	/* flush texture cache */
 	cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit, accel_state->src_size[0],
-			    accel_state->src_mc_addr[0]);
+			    accel_state->src_mc_addr[0],
+			    accel_state->src_bo[0], RADEON_GEM_DOMAIN_VRAM, 0);
 
 	/* Y texture */
 	tex_res.id                  = 0;
@@ -314,6 +346,8 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	tex_res.dim                 = SQ_TEX_DIM_2D;
 	tex_res.base                = accel_state->src_mc_addr[0];
 	tex_res.mip_base            = accel_state->src_mc_addr[0];
+	tex_res.bo                  = accel_state->src_bo[0];
+	tex_res.mip_bo              = accel_state->src_bo[0];
 
 	tex_res.format              = FMT_8;
 	tex_res.dst_sel_x           = SQ_SEL_X; /* Y */
@@ -345,7 +379,8 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	/* U or V texture */
 	cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit,
 			    accel_state->src_size[0] / 4,
-			    accel_state->src_mc_addr[0] + pPriv->planev_offset);
+			    accel_state->src_mc_addr[0] + pPriv->planev_offset,
+			    accel_state->src_bo[0], RADEON_GEM_DOMAIN_VRAM, 0);
 
 	tex_res.id                  = 1;
 	tex_res.format              = FMT_8;
@@ -369,7 +404,8 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	/* U or V texture */
 	cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit,
 			    accel_state->src_size[0] / 4,
-			    accel_state->src_mc_addr[0] + pPriv->planeu_offset);
+			    accel_state->src_mc_addr[0] + pPriv->planeu_offset,
+			    accel_state->src_bo[0], RADEON_GEM_DOMAIN_VRAM, 0);
 
 	tex_res.id                  = 2;
 	tex_res.format              = FMT_8;
@@ -393,12 +429,12 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     case FOURCC_UYVY:
     case FOURCC_YUY2:
     default:
-	accel_state->src_mc_addr[0] = pPriv->src_offset + info->fbLocation + pScrn->fbOffset;
 	accel_state->src_size[0] = accel_state->src_pitch[0] * pPriv->h;
 
 	/* flush texture cache */
 	cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit, accel_state->src_size[0],
-			    accel_state->src_mc_addr[0]);
+			    accel_state->src_mc_addr[0],
+			    accel_state->src_bo[0], RADEON_GEM_DOMAIN_VRAM, 0);
 
 	/* Y texture */
 	tex_res.id                  = 0;
@@ -409,6 +445,8 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	tex_res.dim                 = SQ_TEX_DIM_2D;
 	tex_res.base                = accel_state->src_mc_addr[0];
 	tex_res.mip_base            = accel_state->src_mc_addr[0];
+	tex_res.bo                  = accel_state->src_bo[0];
+	tex_res.mip_bo              = accel_state->src_bo[0];
 
 	tex_res.format              = FMT_8_8;
 	if (pPriv->id == FOURCC_UYVY)
@@ -474,12 +512,10 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     END_BATCH();
 
     cb_conf.id = 0;
-
-    accel_state->dst_mc_addr = exaGetPixmapOffset(pPixmap) + info->fbLocation + pScrn->fbOffset;
-
     cb_conf.w = accel_state->dst_pitch;
     cb_conf.h = pPixmap->drawable.height;
     cb_conf.base = accel_state->dst_mc_addr;
+    cb_conf.bo = accel_state->dst_bo;
 
     switch (pPixmap->drawable.bitsPerPixel) {
     case 16:
diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index 059c3cc..4aa4650 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -39,6 +39,21 @@
 
 #include "radeon_drm.h"
 
+void r600_cs_flush_indirect(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    int ret;
+
+    if (!info->cs->cdw)
+	return;
+    radeon_cs_emit(info->cs);
+    radeon_cs_erase(info->cs);
+
+    ret = radeon_cs_space_check(info->cs);
+    if (ret)
+	ErrorF("space check failed in flush\n");
+}
+
 /* Flush the indirect buffer to the kernel for submission to the card */
 void R600CPFlushIndirect(ScrnInfoPtr pScrn, drmBufPtr ib)
 {
@@ -47,13 +62,20 @@ void R600CPFlushIndirect(ScrnInfoPtr pScrn, drmBufPtr ib)
     int                start  = 0;
     drm_radeon_indirect_t  indirect;
 
+#if defined(XF86DRM_MODE)
+    if (info->cs) {
+	r600_cs_flush_indirect(pScrn);
+	return;
+    }
+#endif
+
     if (!buffer) return;
 
     //xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Flushing buffer %d\n",
     //       buffer->idx);
 
     while (buffer->used & 0x3c){
-	BEGIN_BATCH();
+	BEGIN_BATCH(1);
         E32(buffer, CP_PACKET2()); /* fill up to multiple of 16 dwords */
 	END_BATCH();
     }
@@ -72,6 +94,20 @@ void R600CPFlushIndirect(ScrnInfoPtr pScrn, drmBufPtr ib)
 
 void R600IBDiscard(ScrnInfoPtr pScrn, drmBufPtr ib)
 {
+#if defined(XF86DRM_MODE)
+    int ret;
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    if (info->cs) {
+	if (CS_FULL(info->cs)) {
+	    r600_cs_flush_indirect(pScrn);
+	    return;
+	}
+	radeon_cs_erase(info->cs);
+	ret = radeon_cs_space_check(info->cs);
+	if (ret)
+	    ErrorF("space check failed in flush\n");
+    }
+#endif
     if (!ib) return;
 
     ib->used = 0;
@@ -81,6 +117,7 @@ void R600IBDiscard(ScrnInfoPtr pScrn, drmBufPtr ib)
 void
 wait_3d_idle_clean(ScrnInfoPtr pScrn, drmBufPtr ib)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
 
     //flush caches, don't generate timestamp
     BEGIN_BATCH(5);
@@ -95,6 +132,8 @@ wait_3d_idle_clean(ScrnInfoPtr pScrn, drmBufPtr ib)
 void
 wait_3d_idle(ScrnInfoPtr pScrn, drmBufPtr ib)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+
     BEGIN_BATCH(3);
     EREG(ib, WAIT_UNTIL,                          WAIT_3D_IDLE_bit);
     END_BATCH();
@@ -212,19 +251,19 @@ set_render_target(ScrnInfoPtr pScrn, drmBufPtr ib, cb_config_t *cb_conf)
     h = (cb_conf->h + 7) & ~7;
     slice = ((cb_conf->w * h) / 64) - 1;
 
-    if ((info->ChipFamily > CHIP_FAMILY_R600) &&
-	(info->ChipFamily < CHIP_FAMILY_RV770))
-	BEGIN_BATCH(23);
-    else
-	BEGIN_BATCH(21);
+    BEGIN_BATCH(3 + 2);
     EREG(ib, (CB_COLOR0_BASE + (4 * cb_conf->id)), (cb_conf->base >> 8));
+    RELOC_BATCH(cb_conf->bo, RADEON_GEM_DOMAIN_VRAM, 0);
+    END_BATCH();
 
     // rv6xx workaround
     if ((info->ChipFamily > CHIP_FAMILY_R600) &&
 	(info->ChipFamily < CHIP_FAMILY_RV770)) {
+	BEGIN_BATCH(20);
 	PACK3(ib, IT_SURFACE_BASE_UPDATE, 1);
 	E32(ib, (2 << cb_conf->id));
-    }
+    } else
+	BEGIN_BATCH(18);
 
     // pitch only for ARRAY_LINEAR_GENERAL, other tiling modes require addrlib
     EREG(ib, (CB_COLOR0_SIZE + (4 * cb_conf->id)), ((pitch << PITCH_TILE_MAX_shift)	|
@@ -240,20 +279,23 @@ set_render_target(ScrnInfoPtr pScrn, drmBufPtr ib, cb_config_t *cb_conf)
 }
 
 void
-cp_set_surface_sync(ScrnInfoPtr pScrn, drmBufPtr ib, uint32_t sync_type, uint32_t size, uint64_t mc_addr)
+cp_set_surface_sync(ScrnInfoPtr pScrn, drmBufPtr ib, uint32_t sync_type, uint32_t size, uint64_t mc_addr,
+		    struct radeon_bo *bo, uint32_t rdomains, uint32_t wdomain)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
     uint32_t cp_coher_size;
     if (size == 0xffffffff)
 	cp_coher_size = 0xffffffff;
     else
 	cp_coher_size = ((size + 255) >> 8);
 
-    BEGIN_BATCH(5);
+    BEGIN_BATCH(5 + 2);
     PACK3(ib, IT_SURFACE_SYNC, 4);
     E32(ib, sync_type);
     E32(ib, cp_coher_size);
     E32(ib, (mc_addr >> 8));
     E32(ib, 10); /* poll interval */
+    RELOC_BATCH(bo, rdomains, wdomain);
     END_BATCH();
 }
 
@@ -266,6 +308,12 @@ void cp_wait_vline_sync(ScrnInfoPtr pScrn, drmBufPtr ib, PixmapPtr pPix,
     uint32_t offset;
     RADEONCrtcPrivatePtr radeon_crtc;
 
+    //XXX FIXME
+#if defined(XF86DRM_MODE)
+    if (info->cs)
+	return;
+#endif
+
     if ((crtc < 0) || (crtc > 1))
         return;
 
@@ -314,6 +362,7 @@ void cp_wait_vline_sync(ScrnInfoPtr pScrn, drmBufPtr ib, PixmapPtr pPix,
 void
 fs_setup(ScrnInfoPtr pScrn, drmBufPtr ib, shader_config_t *fs_conf)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
     uint32_t sq_pgm_resources;
 
     sq_pgm_resources = ((fs_conf->num_gprs << NUM_GPRS_shift) |
@@ -322,8 +371,12 @@ fs_setup(ScrnInfoPtr pScrn, drmBufPtr ib, shader_config_t *fs_conf)
     if (fs_conf->dx10_clamp)
 	sq_pgm_resources |= SQ_PGM_RESOURCES_FS__DX10_CLAMP_bit;
 
-    BEGIN_BATCH(9);
+    BEGIN_BATCH(3 + 2);
     EREG(ib, SQ_PGM_START_FS, fs_conf->shader_addr >> 8);
+    RELOC_BATCH(fs_conf->bo, RADEON_GEM_DOMAIN_VRAM, 0);
+    END_BATCH();
+
+    BEGIN_BATCH(6);
     EREG(ib, SQ_PGM_RESOURCES_FS, sq_pgm_resources);
     EREG(ib, SQ_PGM_CF_OFFSET_FS, 0);
     END_BATCH();
@@ -332,6 +385,7 @@ fs_setup(ScrnInfoPtr pScrn, drmBufPtr ib, shader_config_t *fs_conf)
 void
 vs_setup(ScrnInfoPtr pScrn, drmBufPtr ib, shader_config_t *vs_conf)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
     uint32_t sq_pgm_resources;
 
     sq_pgm_resources = ((vs_conf->num_gprs << NUM_GPRS_shift) |
@@ -344,8 +398,12 @@ vs_setup(ScrnInfoPtr pScrn, drmBufPtr ib, shader_config_t *vs_conf)
     if (vs_conf->uncached_first_inst)
 	sq_pgm_resources |= UNCACHED_FIRST_INST_bit;
 
-    BEGIN_BATCH(9);
+    BEGIN_BATCH(3 + 2);
     EREG(ib, SQ_PGM_START_VS, vs_conf->shader_addr >> 8);
+    RELOC_BATCH(vs_conf->bo, RADEON_GEM_DOMAIN_VRAM, 0);
+    END_BATCH();
+
+    BEGIN_BATCH(6);
     EREG(ib, SQ_PGM_RESOURCES_VS, sq_pgm_resources);
     EREG(ib, SQ_PGM_CF_OFFSET_VS, 0);
     END_BATCH();
@@ -354,6 +412,7 @@ vs_setup(ScrnInfoPtr pScrn, drmBufPtr ib, shader_config_t *vs_conf)
 void
 ps_setup(ScrnInfoPtr pScrn, drmBufPtr ib, shader_config_t *ps_conf)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
     uint32_t sq_pgm_resources;
 
     sq_pgm_resources = ((ps_conf->num_gprs << NUM_GPRS_shift) |
@@ -368,8 +427,12 @@ ps_setup(ScrnInfoPtr pScrn, drmBufPtr ib, shader_config_t *ps_conf)
     if (ps_conf->clamp_consts)
 	sq_pgm_resources |= CLAMP_CONSTS_bit;
 
-    BEGIN_BATCH(12);
+    BEGIN_BATCH(3 + 2);
     EREG(ib, SQ_PGM_START_PS, ps_conf->shader_addr >> 8);
+    RELOC_BATCH(ps_conf->bo, RADEON_GEM_DOMAIN_VRAM, 0);
+    END_BATCH();
+
+    BEGIN_BATCH(9);
     EREG(ib, SQ_PGM_RESOURCES_PS, sq_pgm_resources);
     EREG(ib, SQ_PGM_EXPORTS_PS, ps_conf->export_mode);
     EREG(ib, SQ_PGM_CF_OFFSET_PS, 0);
@@ -379,10 +442,11 @@ ps_setup(ScrnInfoPtr pScrn, drmBufPtr ib, shader_config_t *ps_conf)
 void
 set_alu_consts(ScrnInfoPtr pScrn, drmBufPtr ib, int offset, int count, float *const_buf)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
     int i;
     const int countreg = count * (SQ_ALU_CONSTANT_offset >> 2);
 
-    BEGIN_BATCH(2 + count_reg);
+    BEGIN_BATCH(2 + countreg);
     PACK0(ib, SQ_ALU_CONSTANT + offset * SQ_ALU_CONSTANT_offset, countreg);
     for (i = 0; i < countreg; i++)
 	EFLOAT(ib, const_buf[i]);
@@ -392,6 +456,7 @@ set_alu_consts(ScrnInfoPtr pScrn, drmBufPtr ib, int offset, int count, float *co
 void
 set_bool_consts(ScrnInfoPtr pScrn, drmBufPtr ib, int offset, uint32_t val)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
     /* bool register order is: ps, vs, gs; one register each
      * 1 bits per bool; 32 bools each for ps, vs, gs.
      */
@@ -403,6 +468,7 @@ set_bool_consts(ScrnInfoPtr pScrn, drmBufPtr ib, int offset, uint32_t val)
 void
 set_vtx_resource(ScrnInfoPtr pScrn, drmBufPtr ib, vtx_resource_t *res)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
     uint32_t sq_vtx_constant_word2;
 
     sq_vtx_constant_word2 = ((((res->vb_addr) >> 32) & BASE_ADDRESS_HI_mask) |
@@ -419,7 +485,7 @@ set_vtx_resource(ScrnInfoPtr pScrn, drmBufPtr ib, vtx_resource_t *res)
     if (res->srf_mode_all)
 	    sq_vtx_constant_word2 |= SQ_VTX_CONSTANT_WORD2_0__SRF_MODE_ALL_bit;
 
-    BEGIN_BATCH(9);
+    BEGIN_BATCH(9 + 2);
     PACK0(ib, SQ_VTX_RESOURCE + res->id * SQ_VTX_RESOURCE_offset, 7);
     E32(ib, res->vb_addr & 0xffffffff);				// 0: BASE_ADDRESS
     E32(ib, (res->vtx_num_entries << 2) - 1);			// 1: SIZE
@@ -428,12 +494,14 @@ set_vtx_resource(ScrnInfoPtr pScrn, drmBufPtr ib, vtx_resource_t *res)
     E32(ib, 0);							// 4: n/a
     E32(ib, 0);							// 5: n/a
     E32(ib, SQ_TEX_VTX_VALID_BUFFER << SQ_VTX_CONSTANT_WORD6_0__TYPE_shift);	// 6: TYPE
+    RELOC_BATCH(res->bo, RADEON_GEM_DOMAIN_VRAM, 0);
     END_BATCH();
 }
 
 void
 set_tex_resource(ScrnInfoPtr pScrn, drmBufPtr ib, tex_resource_t *tex_res)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
     uint32_t sq_tex_resource_word0, sq_tex_resource_word1, sq_tex_resource_word4;
     uint32_t sq_tex_resource_word5, sq_tex_resource_word6;
 
@@ -483,7 +551,7 @@ set_tex_resource(ScrnInfoPtr pScrn, drmBufPtr ib, tex_resource_t *tex_res)
     if (tex_res->interlaced)
 	sq_tex_resource_word6 |= INTERLACED_bit;
 
-    BEGIN_BATCH(9);
+    BEGIN_BATCH(9 + 4);
     PACK0(ib, SQ_TEX_RESOURCE + tex_res->id * SQ_TEX_RESOURCE_offset, 7);
     E32(ib, sq_tex_resource_word0);
     E32(ib, sq_tex_resource_word1);
@@ -492,12 +560,15 @@ set_tex_resource(ScrnInfoPtr pScrn, drmBufPtr ib, tex_resource_t *tex_res)
     E32(ib, sq_tex_resource_word4);
     E32(ib, sq_tex_resource_word5);
     E32(ib, sq_tex_resource_word6);
+    RELOC_BATCH(tex_res->bo, RADEON_GEM_DOMAIN_VRAM, 0);
+    RELOC_BATCH(tex_res->mip_bo, RADEON_GEM_DOMAIN_VRAM, 0);
     END_BATCH();
 }
 
 void
 set_tex_sampler (ScrnInfoPtr pScrn, drmBufPtr ib, tex_sampler_t *s)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
     uint32_t sq_tex_sampler_word0, sq_tex_sampler_word1, sq_tex_sampler_word2;
 
     sq_tex_sampler_word0 = ((s->clamp_x       << SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_shift)		|
@@ -549,6 +620,8 @@ set_tex_sampler (ScrnInfoPtr pScrn, drmBufPtr ib, tex_sampler_t *s)
 void
 set_screen_scissor(ScrnInfoPtr pScrn, drmBufPtr ib, int x1, int y1, int x2, int y2)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+
     BEGIN_BATCH(6);
     EREG(ib, PA_SC_SCREEN_SCISSOR_TL,              ((x1 << PA_SC_SCREEN_SCISSOR_TL__TL_X_shift) |
 						    (y1 << PA_SC_SCREEN_SCISSOR_TL__TL_Y_shift)));
@@ -560,6 +633,7 @@ set_screen_scissor(ScrnInfoPtr pScrn, drmBufPtr ib, int x1, int y1, int x2, int
 void
 set_vport_scissor(ScrnInfoPtr pScrn, drmBufPtr ib, int id, int x1, int y1, int x2, int y2)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
 
     BEGIN_BATCH(6);
     EREG(ib, PA_SC_VPORT_SCISSOR_0_TL +
@@ -575,6 +649,7 @@ set_vport_scissor(ScrnInfoPtr pScrn, drmBufPtr ib, int id, int x1, int y1, int x
 void
 set_generic_scissor(ScrnInfoPtr pScrn, drmBufPtr ib, int x1, int y1, int x2, int y2)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
 
     BEGIN_BATCH(6);
     EREG(ib, PA_SC_GENERIC_SCISSOR_TL,            ((x1 << PA_SC_GENERIC_SCISSOR_TL__TL_X_shift) |
@@ -588,6 +663,8 @@ set_generic_scissor(ScrnInfoPtr pScrn, drmBufPtr ib, int x1, int y1, int x2, int
 void
 set_window_scissor(ScrnInfoPtr pScrn, drmBufPtr ib, int x1, int y1, int x2, int y2)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+
     BEGIN_BATCH(6);
     EREG(ib, PA_SC_WINDOW_SCISSOR_TL,             ((x1 << PA_SC_WINDOW_SCISSOR_TL__TL_X_shift) |
 						   (y1 << PA_SC_WINDOW_SCISSOR_TL__TL_Y_shift) |
@@ -600,6 +677,8 @@ set_window_scissor(ScrnInfoPtr pScrn, drmBufPtr ib, int x1, int y1, int x2, int
 void
 set_clip_rect(ScrnInfoPtr pScrn, drmBufPtr ib, int id, int x1, int y1, int x2, int y2)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+
     BEGIN_BATCH(6);
     EREG(ib, PA_SC_CLIPRECT_0_TL +
 	 id * PA_SC_CLIPRECT_0_TL_offset,     ((x1 << PA_SC_CLIPRECT_0_TL__TL_X_shift) |
@@ -966,6 +1045,7 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     END_BATCH();
 
     // clear FS
+    fs_conf.bo = accel_state->shaders_bo;
     fs_setup(pScrn, ib, &fs_conf);
 
     // VGT
@@ -1006,6 +1086,7 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
 void
 draw_immd(ScrnInfoPtr pScrn, drmBufPtr ib, draw_config_t *draw_conf, uint32_t *indices)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
     uint32_t i, count;
 
     // calculate num of packets
@@ -1043,6 +1124,8 @@ draw_immd(ScrnInfoPtr pScrn, drmBufPtr ib, draw_config_t *draw_conf, uint32_t *i
 void
 draw_auto(ScrnInfoPtr pScrn, drmBufPtr ib, draw_config_t *draw_conf)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+
     BEGIN_BATCH(10);
     EREG(ib, VGT_PRIMITIVE_TYPE, draw_conf->prim_type);
     PACK3(ib, IT_INDEX_TYPE, 1);
@@ -1055,22 +1138,82 @@ draw_auto(ScrnInfoPtr pScrn, drmBufPtr ib, draw_config_t *draw_conf)
     END_BATCH();
 }
 
-void
+Bool
 r600_vb_get(ScrnInfoPtr pScrn)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
     struct radeon_accel_state *accel_state = info->accel_state;
-
-    accel_state->vb_mc_addr = info->gartLocation + info->dri->bufStart +
-                              (accel_state->ib->idx * accel_state->ib->total) +
-                              (accel_state->ib->total / 2);
-    accel_state->vb_total = (accel_state->ib->total / 2);
-    accel_state->vb_ptr = (pointer)((char*)accel_state->ib->address +
-                                           (accel_state->ib->total / 2));
+#if defined(XF86DRM_MODE)
+    int ret;
+    if (info->cs) {
+	if (accel_state->vb_bo == NULL) {
+	    accel_state->vb_mc_addr = 0;
+	    accel_state->vb_bo = radeon_bo_open(info->bufmgr, 0, 16 * 1024,
+						4096, RADEON_GEM_DOMAIN_GTT, 0);
+	    if (accel_state->vb_bo == NULL)
+		return FALSE;
+	    ret = radeon_bo_map(accel_state->vb_bo, 1);
+	    if (ret) {
+		FatalError("failed to vb %d\n", ret);
+		return FALSE;
+	    }
+	    accel_state->vb_total = 16 * 1024;
+	    accel_state->vb_ptr = accel_state->vb_bo->ptr;
+	}
+    } else
+#endif
+    {
+	accel_state->vb_mc_addr = info->gartLocation + info->dri->bufStart +
+	    (accel_state->ib->idx*accel_state->ib->total)+
+	    (accel_state->ib->total / 2);
+	accel_state->vb_total = (accel_state->ib->total / 2);
+	accel_state->vb_ptr = (pointer)((char*)accel_state->ib->address +
+					(accel_state->ib->total / 2));
+    }
     accel_state->vb_index = 0;
+    return TRUE;
 }
 
 void
 r600_vb_discard(ScrnInfoPtr pScrn)
 {
 }
+
+int
+r600_cp_start(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    struct radeon_accel_state *accel_state = info->accel_state;
+
+#if defined(XF86DRM_MODE)
+    if (info->cs) {
+	if (!r600_vb_get(pScrn))
+	    return FALSE;
+	radeon_cs_space_reset_bos(info->cs);
+	radeon_cs_space_add_persistent_bo(info->cs, accel_state->shaders_bo,
+					  RADEON_GEM_DOMAIN_VRAM, 0);
+	if (accel_state->src_bo[0])
+	    radeon_cs_space_add_persistent_bo(info->cs, accel_state->src_bo[0],
+					      RADEON_GEM_DOMAIN_VRAM, 0);
+	if (accel_state->src_bo[1])
+	    radeon_cs_space_add_persistent_bo(info->cs, accel_state->src_bo[1],
+					      RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_add_persistent_bo(info->cs, accel_state->dst_bo,
+					  RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_add_persistent_bo(info->cs, accel_state->vb_bo,
+					  RADEON_GEM_DOMAIN_GTT, 0);
+	if (accel_state->copy_area_bo)
+	    radeon_cs_space_add_persistent_bo(info->cs,
+					      accel_state->copy_area_bo,
+					      RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_check(info->cs);
+    } else
+#endif
+    {
+	accel_state->ib = RADEONCPGetBuffer(pScrn);
+	if (!r600_vb_get(pScrn)) {
+	    return -1;
+	}
+    }
+    return 0;
+}
diff --git a/src/radeon.h b/src/radeon.h
index 3a3631e..7fdd8f5 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -696,9 +696,11 @@ struct radeon_accel_state {
     int               vb_total;
     void              *vb_ptr;
     uint32_t          vb_size;
+    struct radeon_bo  *vb_bo;
 
     // shader storage
     ExaOffscreenArea  *shaders;
+    struct radeon_bo  *shaders_bo;
     uint32_t          solid_vs_offset;
     uint32_t          solid_ps_offset;
     uint32_t          copy_vs_offset;
@@ -710,12 +712,14 @@ struct radeon_accel_state {
     uint32_t          xv_ps_offset;
 
     //size/addr stuff
+    struct radeon_bo  *src_bo[2];
     uint32_t          src_size[2];
     uint64_t          src_mc_addr[2];
     uint32_t          src_pitch[2];
     uint32_t          src_width[2];
     uint32_t          src_height[2];
     uint32_t          src_bpp[2];
+    struct radeon_bo  *dst_bo;
     uint32_t          dst_size;
     uint64_t          dst_mc_addr;
     uint32_t          dst_pitch;
@@ -731,6 +735,7 @@ struct radeon_accel_state {
 
     // copy
     ExaOffscreenArea  *copy_area;
+    struct radeon_bo  *copy_area_bo;
     Bool              same_surface;
     int               rop;
     uint32_t          planemask;
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index b52f965..efc6bde 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -333,7 +333,9 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
         return FALSE;
     }
 
-    if ( (info->ChipFamily >= CHIP_FAMILY_R300) ) {
+    if ( (info->ChipFamily >= CHIP_FAMILY_R600) ) {
+        dri2_info.driverName = R600_DRIVER_NAME;
+    } else if ( (info->ChipFamily >= CHIP_FAMILY_R300) ) {
         dri2_info.driverName = R300_DRIVER_NAME;
     } else if ( info->ChipFamily >= CHIP_FAMILY_R200 ) {
         dri2_info.driverName = R200_DRIVER_NAME;
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 3f3c9ba..56e87a9 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -336,7 +336,7 @@ static void RADEONFinishAccess_BE(PixmapPtr pPix, int index)
 #endif /* X_BYTE_ORDER == X_BIG_ENDIAN */
 
 #ifdef XF86DRM_MODE
-static Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
+Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
 {
     ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
     struct radeon_exa_pixmap_priv *driver_priv;
@@ -364,7 +364,7 @@ static Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
     return TRUE;
 }
 
-static void RADEONFinishAccess_CS(PixmapPtr pPix, int index)
+void RADEONFinishAccess_CS(PixmapPtr pPix, int index)
 {
     struct radeon_exa_pixmap_priv *driver_priv;
 
@@ -456,7 +456,7 @@ void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
     return new_priv;
 }
 
-static void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
+void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
 {
     struct radeon_exa_pixmap_priv *driver_priv = driverPriv;
 
@@ -489,7 +489,7 @@ void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
     }
 }
 
-static Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix)
+Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix)
 {
     struct radeon_exa_pixmap_priv *driver_priv;
 
commit 04692f80678ffea15ac33820381ce45865e697b8
Author: Dave Airlie <airlied at linux.ie>
Date:   Wed Aug 26 05:31:56 2009 +1000

    radeon: afaics these aren't radeon regs but r128 regs.
    
    so remove them from radeon use.

diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index b6a6d8d..6387e4f 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -789,10 +789,9 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 	    R200_VAP_VF_MAX_VTX_NUM);
 	FINISH_ACCEL();
 
-	BEGIN_ACCEL(5);
+	BEGIN_ACCEL(4);
 	OUT_ACCEL_REG(R200_RE_AUX_SCISSOR_CNTL, 0);
 	OUT_ACCEL_REG(R200_RE_CNTL, 0);
-	OUT_ACCEL_REG(RADEON_AUX_SC_CNTL, 0);
 	OUT_ACCEL_REG(RADEON_RB3D_PLANEMASK, 0xffffffff);
 	OUT_ACCEL_REG(RADEON_SE_CNTL, (RADEON_DIFFUSE_SHADE_GOURAUD |
 				       RADEON_BFACE_SOLID |
@@ -813,8 +812,7 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 		      RADEON_TEX1_W_ROUTING_USE_W0);
 	FINISH_ACCEL();
 
-	BEGIN_ACCEL(3);
-	OUT_ACCEL_REG(RADEON_AUX_SC_CNTL, 0);
+	BEGIN_ACCEL(2);
 	OUT_ACCEL_REG(RADEON_RB3D_PLANEMASK, 0xffffffff);
 	OUT_ACCEL_REG(RADEON_SE_CNTL, (RADEON_DIFFUSE_SHADE_GOURAUD |
 				       RADEON_BFACE_SOLID |
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index 9df7fff..3a4eda1 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -103,28 +103,6 @@
 #define RADEON_ATTRDR                       0x03c1 /* VGA */
 #define RADEON_ATTRDW                       0x03c0 /* VGA */
 #define RADEON_ATTRX                        0x03c0 /* VGA */
-#define RADEON_AUX_SC_CNTL                  0x1660
-#       define RADEON_AUX1_SC_EN            (1 << 0)
-#       define RADEON_AUX1_SC_MODE_OR       (0 << 1)
-#       define RADEON_AUX1_SC_MODE_NAND     (1 << 1)
-#       define RADEON_AUX2_SC_EN            (1 << 2)
-#       define RADEON_AUX2_SC_MODE_OR       (0 << 3)
-#       define RADEON_AUX2_SC_MODE_NAND     (1 << 3)
-#       define RADEON_AUX3_SC_EN            (1 << 4)
-#       define RADEON_AUX3_SC_MODE_OR       (0 << 5)
-#       define RADEON_AUX3_SC_MODE_NAND     (1 << 5)
-#define RADEON_AUX1_SC_BOTTOM               0x1670
-#define RADEON_AUX1_SC_LEFT                 0x1664
-#define RADEON_AUX1_SC_RIGHT                0x1668
-#define RADEON_AUX1_SC_TOP                  0x166c
-#define RADEON_AUX2_SC_BOTTOM               0x1680
-#define RADEON_AUX2_SC_LEFT                 0x1674
-#define RADEON_AUX2_SC_RIGHT                0x1678
-#define RADEON_AUX2_SC_TOP                  0x167c
-#define RADEON_AUX3_SC_BOTTOM               0x1690
-#define RADEON_AUX3_SC_LEFT                 0x1684
-#define RADEON_AUX3_SC_RIGHT                0x1688
-#define RADEON_AUX3_SC_TOP                  0x168c
 #define RADEON_AUX_WINDOW_HORZ_CNTL         0x02d8
 #define RADEON_AUX_WINDOW_VERT_CNTL         0x02dc
 
commit 9cf965bbc977f0523437c0ecf1d7363b17de2468
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Aug 25 12:47:34 2009 -0400

    R6xx/r7xx: add begin/end batch macros

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 0a9a0c6..555748b 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -207,8 +207,10 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 	pmask |= 1; /* R */
     if (pm & 0xff000000)
 	pmask |= 8; /* A */
+    BEGIN_BATCH(6);
     EREG(accel_state->ib, CB_SHADER_MASK,                      (pmask << OUTPUT0_ENABLE_shift));
     EREG(accel_state->ib, CB_COLOR_CONTROL,                    RADEON_ROP[alu]);
+    END_BATCH();
 
     cb_conf.id = 0;
     cb_conf.w = accel_state->dst_pitch;
@@ -231,6 +233,7 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 
     /* Interpolator setup */
     /* one unused export from VS (VS_EXPORT_COUNT is zero based, count minus one) */
+    BEGIN_BATCH(18);
     EREG(accel_state->ib, SPI_VS_OUT_CONFIG, (0 << VS_EXPORT_COUNT_shift));
     EREG(accel_state->ib, SPI_VS_OUT_ID_0, (0 << SEMANTIC_0_shift));
 
@@ -245,6 +248,7 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 								  FLAT_SHADE_bit		|
 								  SEL_CENTROID_bit));
     EREG(accel_state->ib, SPI_INTERP_CONTROL_0,                FLAT_SHADE_ENA_bit);
+    END_BATCH();
 
     /* PS alu constants */
     if (pPix->drawable.bitsPerPixel == 16) {
@@ -497,8 +501,10 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
 	pmask |= 1; /* R */
     if (planemask & 0xff000000)
 	pmask |= 8; /* A */
+    BEGIN_BATCH(6);
     EREG(accel_state->ib, CB_SHADER_MASK,                      (pmask << OUTPUT0_ENABLE_shift));
     EREG(accel_state->ib, CB_COLOR_CONTROL,                    RADEON_ROP[rop]);
+    END_BATCH();
 
     accel_state->dst_size = dst_pitch * dst_height * (dst_bpp/8);
     accel_state->dst_mc_addr = dst_offset;
@@ -526,6 +532,7 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
 
     /* Interpolator setup */
     /* export tex coord from VS */
+    BEGIN_BATCH(18);
     EREG(accel_state->ib, SPI_VS_OUT_CONFIG, ((1 - 1) << VS_EXPORT_COUNT_shift));
     EREG(accel_state->ib, SPI_VS_OUT_ID_0, (0 << SEMANTIC_0_shift));
 
@@ -539,6 +546,7 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
 								(0x01 << DEFAULT_VAL_shift)	|
 								SEL_CENTROID_bit));
     EREG(accel_state->ib, SPI_INTERP_CONTROL_0,                0);
+    END_BATCH();
 }
 
 static void
@@ -1499,6 +1507,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     ps_conf.export_mode         = 2;
     ps_setup                    (pScrn, accel_state->ib, &ps_conf);
 
+    BEGIN_BATCH(12);
     EREG(accel_state->ib, CB_SHADER_MASK,                      (0xf << OUTPUT0_ENABLE_shift));
 
     blendcntl = R600GetBlendCntl(op, pMaskPicture, pDstPicture->format);
@@ -1513,6 +1522,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
 								    PER_MRT_BLEND_bit));
 	EREG(accel_state->ib, CB_BLEND0_CONTROL,                   blendcntl);
     }
+    END_BATCH();
 
     cb_conf.id = 0;
     cb_conf.w = accel_state->dst_pitch;
@@ -1540,6 +1550,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     set_render_target(pScrn, accel_state->ib, &cb_conf);
 
     /* Interpolator setup */
+    BEGIN_BATCH(21);
     if (pMask) {
 	/* export 2 tex coords from VS */
 	EREG(accel_state->ib, SPI_VS_OUT_CONFIG, ((2 - 1) << VS_EXPORT_COUNT_shift));
@@ -1566,6 +1577,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
 								(0x01 << DEFAULT_VAL_shift)	|
 								SEL_CENTROID_bit));
     EREG(accel_state->ib, SPI_INTERP_CONTROL_0,                0);
+    END_BATCH();
 
     return TRUE;
 }
diff --git a/src/r600_state.h b/src/r600_state.h
index 8f20e42..10b1022 100644
--- a/src/r600_state.h
+++ b/src/r600_state.h
@@ -170,6 +170,9 @@ typedef struct {
     uint32_t num_indices;
 } draw_config_t;
 
+#define BEGIN_BATCH(n) do {} while(0)
+#define END_BATCH() do {} while(0)
+
 #define E32(ib, dword)                                                  \
 do {                                                                    \
     uint32_t *ib_head = (pointer)(char*)(ib)->address;			\
diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index 4502ab3..6739616 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -468,8 +468,10 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     }
 
     /* Render setup */
+    BEGIN_BATCH(6);
     EREG(accel_state->ib, CB_SHADER_MASK,                      (0x0f << OUTPUT0_ENABLE_shift));
     EREG(accel_state->ib, CB_COLOR_CONTROL,                    (0xcc << ROP3_shift)); /* copy */
+    END_BATCH();
 
     cb_conf.id = 0;
 
@@ -503,6 +505,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 
     /* Interpolator setup */
     /* export tex coords from VS */
+    BEGIN_BATCH(18);
     EREG(accel_state->ib, SPI_VS_OUT_CONFIG, ((1 - 1) << VS_EXPORT_COUNT_shift));
     EREG(accel_state->ib, SPI_VS_OUT_ID_0, (0 << SEMANTIC_0_shift));
 
@@ -514,7 +517,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 								(0x03 << DEFAULT_VAL_shift)	|
 								SEL_CENTROID_bit));
     EREG(accel_state->ib, SPI_INTERP_CONTROL_0,                0);
-
+    END_BATCH();
 
     vs_alu_consts[0] = 1.0 / pPriv->w;
     vs_alu_consts[1] = 1.0 / pPriv->h;
diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index 55188a4..059c3cc 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -53,7 +53,9 @@ void R600CPFlushIndirect(ScrnInfoPtr pScrn, drmBufPtr ib)
     //       buffer->idx);
 
     while (buffer->used & 0x3c){
+	BEGIN_BATCH();
         E32(buffer, CP_PACKET2()); /* fill up to multiple of 16 dwords */
+	END_BATCH();
     }
 
     //ErrorF("buffer bytes: %d\n", buffer->used);
@@ -81,19 +83,21 @@ wait_3d_idle_clean(ScrnInfoPtr pScrn, drmBufPtr ib)
 {
 
     //flush caches, don't generate timestamp
+    BEGIN_BATCH(5);
     PACK3(ib, IT_EVENT_WRITE, 1);
     E32(ib, CACHE_FLUSH_AND_INV_EVENT);
     // wait for 3D idle clean
     EREG(ib, WAIT_UNTIL,                          (WAIT_3D_IDLE_bit |
 						   WAIT_3D_IDLECLEAN_bit));
+    END_BATCH();
 }
 
 void
 wait_3d_idle(ScrnInfoPtr pScrn, drmBufPtr ib)
 {
-
+    BEGIN_BATCH(3);
     EREG(ib, WAIT_UNTIL,                          WAIT_3D_IDLE_bit);
-
+    END_BATCH();
 }
 
 void
@@ -102,13 +106,16 @@ start_3d(ScrnInfoPtr pScrn, drmBufPtr ib)
     RADEONInfoPtr info = RADEONPTR(pScrn);
 
     if (info->ChipFamily < CHIP_FAMILY_RV770) {
+	BEGIN_BATCH(5);
 	PACK3(ib, IT_START_3D_CMDBUF, 1);
 	E32(ib, 0);
-    }
+    } else
+	BEGIN_BATCH(3);
 
     PACK3(ib, IT_CONTEXT_CONTROL, 2);
     E32(ib, 0x80000000);
     E32(ib, 0x80000000);
+    END_BATCH();
 
     wait_3d_idle_clean (pScrn, ib);
 }
@@ -158,6 +165,7 @@ sq_setup(ScrnInfoPtr pScrn, drmBufPtr ib, sq_config_t *sq_conf)
     sq_stack_resource_mgmt_2 = ((sq_conf->num_gs_stack_entries << NUM_GS_STACK_ENTRIES_shift) |
 				(sq_conf->num_es_stack_entries << NUM_ES_STACK_ENTRIES_shift));
 
+    BEGIN_BATCH(8);
     PACK0(ib, SQ_CONFIG, 6);
     E32(ib, sq_config);
     E32(ib, sq_gpr_resource_mgmt_1);
@@ -165,7 +173,7 @@ sq_setup(ScrnInfoPtr pScrn, drmBufPtr ib, sq_config_t *sq_conf)
     E32(ib, sq_thread_resource_mgmt);
     E32(ib, sq_stack_resource_mgmt_1);
     E32(ib, sq_stack_resource_mgmt_2);
-
+    END_BATCH();
 }
 
 void
@@ -204,6 +212,11 @@ set_render_target(ScrnInfoPtr pScrn, drmBufPtr ib, cb_config_t *cb_conf)
     h = (cb_conf->h + 7) & ~7;
     slice = ((cb_conf->w * h) / 64) - 1;
 
+    if ((info->ChipFamily > CHIP_FAMILY_R600) &&
+	(info->ChipFamily < CHIP_FAMILY_RV770))
+	BEGIN_BATCH(23);
+    else
+	BEGIN_BATCH(21);
     EREG(ib, (CB_COLOR0_BASE + (4 * cb_conf->id)), (cb_conf->base >> 8));
 
     // rv6xx workaround
@@ -223,6 +236,7 @@ set_render_target(ScrnInfoPtr pScrn, drmBufPtr ib, cb_config_t *cb_conf)
     EREG(ib, (CB_COLOR0_FRAG + (4 * cb_conf->id)), (0     >> 8));	// FMASK per-tile data base/256
     EREG(ib, (CB_COLOR0_MASK + (4 * cb_conf->id)), ((0    << CMASK_BLOCK_MAX_shift)	|
 						    (0    << FMASK_TILE_MAX_shift)));
+    END_BATCH();
 }
 
 void
@@ -234,11 +248,13 @@ cp_set_surface_sync(ScrnInfoPtr pScrn, drmBufPtr ib, uint32_t sync_type, uint32_
     else
 	cp_coher_size = ((size + 255) >> 8);
 
+    BEGIN_BATCH(5);
     PACK3(ib, IT_SURFACE_SYNC, 4);
     E32(ib, sync_type);
     E32(ib, cp_coher_size);
     E32(ib, (mc_addr >> 8));
     E32(ib, 10); /* poll interval */
+    END_BATCH();
 }
 
 /* inserts a wait for vline in the command stream */
@@ -278,6 +294,7 @@ void cp_wait_vline_sync(ScrnInfoPtr pScrn, drmBufPtr ib, PixmapPtr pPix,
 
     radeon_crtc = xf86_config->crtc[crtc]->driver_private;
 
+    BEGIN_BATCH(10);
     /* set the VLINE range */
     EREG(ib, AVIVO_D1MODE_VLINE_START_END + radeon_crtc->crtc_offset,
          (start << AVIVO_D1MODE_VLINE_START_SHIFT) |
@@ -291,6 +308,7 @@ void cp_wait_vline_sync(ScrnInfoPtr pScrn, drmBufPtr ib, PixmapPtr pPix,
     E32(ib, 0);                          // Ref value
     E32(ib, AVIVO_D1MODE_VLINE_STAT);    // Mask
     E32(ib, 10);                         // Wait interval
+    END_BATCH();
 }
 
 void
@@ -304,9 +322,11 @@ fs_setup(ScrnInfoPtr pScrn, drmBufPtr ib, shader_config_t *fs_conf)
     if (fs_conf->dx10_clamp)
 	sq_pgm_resources |= SQ_PGM_RESOURCES_FS__DX10_CLAMP_bit;
 
+    BEGIN_BATCH(9);
     EREG(ib, SQ_PGM_START_FS, fs_conf->shader_addr >> 8);
     EREG(ib, SQ_PGM_RESOURCES_FS, sq_pgm_resources);
     EREG(ib, SQ_PGM_CF_OFFSET_FS, 0);
+    END_BATCH();
 }
 
 void
@@ -324,9 +344,11 @@ vs_setup(ScrnInfoPtr pScrn, drmBufPtr ib, shader_config_t *vs_conf)
     if (vs_conf->uncached_first_inst)
 	sq_pgm_resources |= UNCACHED_FIRST_INST_bit;
 
+    BEGIN_BATCH(9);
     EREG(ib, SQ_PGM_START_VS, vs_conf->shader_addr >> 8);
     EREG(ib, SQ_PGM_RESOURCES_VS, sq_pgm_resources);
     EREG(ib, SQ_PGM_CF_OFFSET_VS, 0);
+    END_BATCH();
 }
 
 void
@@ -346,10 +368,12 @@ ps_setup(ScrnInfoPtr pScrn, drmBufPtr ib, shader_config_t *ps_conf)
     if (ps_conf->clamp_consts)
 	sq_pgm_resources |= CLAMP_CONSTS_bit;
 
+    BEGIN_BATCH(12);
     EREG(ib, SQ_PGM_START_PS, ps_conf->shader_addr >> 8);
     EREG(ib, SQ_PGM_RESOURCES_PS, sq_pgm_resources);
     EREG(ib, SQ_PGM_EXPORTS_PS, ps_conf->export_mode);
     EREG(ib, SQ_PGM_CF_OFFSET_PS, 0);
+    END_BATCH();
 }
 
 void
@@ -358,9 +382,11 @@ set_alu_consts(ScrnInfoPtr pScrn, drmBufPtr ib, int offset, int count, float *co
     int i;
     const int countreg = count * (SQ_ALU_CONSTANT_offset >> 2);
 
+    BEGIN_BATCH(2 + count_reg);
     PACK0(ib, SQ_ALU_CONSTANT + offset * SQ_ALU_CONSTANT_offset, countreg);
     for (i = 0; i < countreg; i++)
 	EFLOAT(ib, const_buf[i]);
+    END_BATCH();
 }
 
 void
@@ -369,7 +395,9 @@ set_bool_consts(ScrnInfoPtr pScrn, drmBufPtr ib, int offset, uint32_t val)
     /* bool register order is: ps, vs, gs; one register each
      * 1 bits per bool; 32 bools each for ps, vs, gs.
      */
+    BEGIN_BATCH(3);
     EREG(ib, SQ_BOOL_CONST + offset * SQ_BOOL_CONST_offset, val);
+    END_BATCH();
 }
 
 void
@@ -391,6 +419,7 @@ set_vtx_resource(ScrnInfoPtr pScrn, drmBufPtr ib, vtx_resource_t *res)
     if (res->srf_mode_all)
 	    sq_vtx_constant_word2 |= SQ_VTX_CONSTANT_WORD2_0__SRF_MODE_ALL_bit;
 
+    BEGIN_BATCH(9);
     PACK0(ib, SQ_VTX_RESOURCE + res->id * SQ_VTX_RESOURCE_offset, 7);
     E32(ib, res->vb_addr & 0xffffffff);				// 0: BASE_ADDRESS
     E32(ib, (res->vtx_num_entries << 2) - 1);			// 1: SIZE
@@ -399,6 +428,7 @@ set_vtx_resource(ScrnInfoPtr pScrn, drmBufPtr ib, vtx_resource_t *res)
     E32(ib, 0);							// 4: n/a
     E32(ib, 0);							// 5: n/a
     E32(ib, SQ_TEX_VTX_VALID_BUFFER << SQ_VTX_CONSTANT_WORD6_0__TYPE_shift);	// 6: TYPE
+    END_BATCH();
 }
 
 void
@@ -453,6 +483,7 @@ set_tex_resource(ScrnInfoPtr pScrn, drmBufPtr ib, tex_resource_t *tex_res)
     if (tex_res->interlaced)
 	sq_tex_resource_word6 |= INTERLACED_bit;
 
+    BEGIN_BATCH(9);
     PACK0(ib, SQ_TEX_RESOURCE + tex_res->id * SQ_TEX_RESOURCE_offset, 7);
     E32(ib, sq_tex_resource_word0);
     E32(ib, sq_tex_resource_word1);
@@ -461,6 +492,7 @@ set_tex_resource(ScrnInfoPtr pScrn, drmBufPtr ib, tex_resource_t *tex_res)
     E32(ib, sq_tex_resource_word4);
     E32(ib, sq_tex_resource_word5);
     E32(ib, sq_tex_resource_word6);
+    END_BATCH();
 }
 
 void
@@ -505,27 +537,31 @@ set_tex_sampler (ScrnInfoPtr pScrn, drmBufPtr ib, tex_sampler_t *s)
     if (s->type)
 	sq_tex_sampler_word2 |= SQ_TEX_SAMPLER_WORD2_0__TYPE_bit;
 
+    BEGIN_BATCH(5);
     PACK0(ib, SQ_TEX_SAMPLER_WORD + s->id * SQ_TEX_SAMPLER_WORD_offset, 3);
     E32(ib, sq_tex_sampler_word0);
     E32(ib, sq_tex_sampler_word1);
     E32(ib, sq_tex_sampler_word2);
+    END_BATCH();
 }
 
 //XXX deal with clip offsets in clip setup
 void
 set_screen_scissor(ScrnInfoPtr pScrn, drmBufPtr ib, int x1, int y1, int x2, int y2)
 {
-
+    BEGIN_BATCH(6);
     EREG(ib, PA_SC_SCREEN_SCISSOR_TL,              ((x1 << PA_SC_SCREEN_SCISSOR_TL__TL_X_shift) |
 						    (y1 << PA_SC_SCREEN_SCISSOR_TL__TL_Y_shift)));
     EREG(ib, PA_SC_SCREEN_SCISSOR_BR,              ((x2 << PA_SC_SCREEN_SCISSOR_BR__BR_X_shift) |
 						    (y2 << PA_SC_SCREEN_SCISSOR_BR__BR_Y_shift)));
+    END_BATCH();
 }
 
 void
 set_vport_scissor(ScrnInfoPtr pScrn, drmBufPtr ib, int id, int x1, int y1, int x2, int y2)
 {
 
+    BEGIN_BATCH(6);
     EREG(ib, PA_SC_VPORT_SCISSOR_0_TL +
 	 id * PA_SC_VPORT_SCISSOR_0_TL_offset, ((x1 << PA_SC_VPORT_SCISSOR_0_TL__TL_X_shift) |
 						(y1 << PA_SC_VPORT_SCISSOR_0_TL__TL_Y_shift) |
@@ -533,40 +569,45 @@ set_vport_scissor(ScrnInfoPtr pScrn, drmBufPtr ib, int id, int x1, int y1, int x
     EREG(ib, PA_SC_VPORT_SCISSOR_0_BR +
 	 id * PA_SC_VPORT_SCISSOR_0_BR_offset, ((x2 << PA_SC_VPORT_SCISSOR_0_BR__BR_X_shift) |
 						(y2 << PA_SC_VPORT_SCISSOR_0_BR__BR_Y_shift)));
+    END_BATCH();
 }
 
 void
 set_generic_scissor(ScrnInfoPtr pScrn, drmBufPtr ib, int x1, int y1, int x2, int y2)
 {
 
+    BEGIN_BATCH(6);
     EREG(ib, PA_SC_GENERIC_SCISSOR_TL,            ((x1 << PA_SC_GENERIC_SCISSOR_TL__TL_X_shift) |
 						   (y1 << PA_SC_GENERIC_SCISSOR_TL__TL_Y_shift) |
 						   WINDOW_OFFSET_DISABLE_bit));
     EREG(ib, PA_SC_GENERIC_SCISSOR_BR,            ((x2 << PA_SC_GENERIC_SCISSOR_BR__BR_X_shift) |
 						   (y2 << PA_SC_GENERIC_SCISSOR_TL__TL_Y_shift)));
+    END_BATCH();
 }
 
 void
 set_window_scissor(ScrnInfoPtr pScrn, drmBufPtr ib, int x1, int y1, int x2, int y2)
 {
-
+    BEGIN_BATCH(6);
     EREG(ib, PA_SC_WINDOW_SCISSOR_TL,             ((x1 << PA_SC_WINDOW_SCISSOR_TL__TL_X_shift) |
 						   (y1 << PA_SC_WINDOW_SCISSOR_TL__TL_Y_shift) |
 						   WINDOW_OFFSET_DISABLE_bit));
     EREG(ib, PA_SC_WINDOW_SCISSOR_BR,             ((x2 << PA_SC_WINDOW_SCISSOR_BR__BR_X_shift) |
 						   (y2 << PA_SC_WINDOW_SCISSOR_BR__BR_Y_shift)));
+    END_BATCH();
 }
 
 void
 set_clip_rect(ScrnInfoPtr pScrn, drmBufPtr ib, int id, int x1, int y1, int x2, int y2)
 {
-
+    BEGIN_BATCH(6);
     EREG(ib, PA_SC_CLIPRECT_0_TL +
 	 id * PA_SC_CLIPRECT_0_TL_offset,     ((x1 << PA_SC_CLIPRECT_0_TL__TL_X_shift) |
 					       (y1 << PA_SC_CLIPRECT_0_TL__TL_Y_shift)));
     EREG(ib, PA_SC_CLIPRECT_0_BR +
 	 id * PA_SC_CLIPRECT_0_BR_offset,     ((x2 << PA_SC_CLIPRECT_0_BR__BR_X_shift) |
 					       (y2 << PA_SC_CLIPRECT_0_BR__BR_Y_shift)));
+    END_BATCH();
 }
 
 /*
@@ -594,6 +635,7 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     wait_3d_idle(pScrn, ib);
 
     // ASIC specific setup, see drm
+    BEGIN_BATCH(15);
     if (info->ChipFamily < CHIP_FAMILY_RV770) {
 	EREG(ib, TA_CNTL_AUX,                     (( 3 << GRADIENT_CREDIT_shift)		|
 						   (28 << TD_FIFO_CREDIT_shift)));
@@ -619,6 +661,7 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
 						    (4  << DEPTH_CACHELINE_FREE_shift)	|
 						    0));
     }
+    END_BATCH();
 
     // SQ
     sq_conf.ps_prio = 0;
@@ -744,6 +787,7 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
 
     sq_setup(pScrn, ib, &sq_conf);
 
+    BEGIN_BATCH(59);
     EREG(ib, SQ_VTX_BASE_VTX_LOC,                 0);
     EREG(ib, SQ_VTX_START_INST_LOC,               0);
 
@@ -790,28 +834,29 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     E32(ib, 0x00000000);
     E32(ib, 0x00000000);
     E32(ib, 0x00000000);
+    END_BATCH();
 
     if (info->ChipFamily < CHIP_FAMILY_RV770) {
+	BEGIN_BATCH(11);
 	PACK0(ib, CB_FOG_RED, 3);
 	E32(ib, 0x00000000);
 	E32(ib, 0x00000000);
 	E32(ib, 0x00000000);
+	PACK0(ib, CB_CLEAR_RED, 4);
+	EFLOAT(ib, 1.0);						/* WTF? */
+	EFLOAT(ib, 0.0);
+	EFLOAT(ib, 1.0);
+	EFLOAT(ib, 1.0);
+	END_BATCH();
     }
 
+    BEGIN_BATCH(18);
     PACK0(ib, CB_CLRCMP_CONTROL, 4);
     E32(ib, 1 << CLRCMP_FCN_SEL_shift);				// CB_CLRCMP_CONTROL: use CLRCMP_FCN_SRC
     E32(ib, 0);							// CB_CLRCMP_SRC
     E32(ib, 0);							// CB_CLRCMP_DST
     E32(ib, 0);							// CB_CLRCMP_MSK
 
-
-    if (info->ChipFamily < CHIP_FAMILY_RV770) {
-	PACK0(ib, CB_CLEAR_RED, 4);
-	EFLOAT(ib, 1.0);						/* WTF? */
-	EFLOAT(ib, 0.0);
-	EFLOAT(ib, 1.0);
-	EFLOAT(ib, 1.0);
-    }
     EREG(ib, CB_TARGET_MASK,                      (0x0f << TARGET0_ENABLE_shift));
     EREG(ib, R7xx_CB_SHADER_CONTROL,              (RT0_ENABLE_bit));
 
@@ -821,23 +866,29 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
 						   (0 << WINDOW_Y_OFFSET_shift)));
 
     EREG(ib, PA_SC_CLIPRECT_RULE,                 CLIP_RULE_mask);
+    END_BATCH();
 
     /* clip boolean is set to always visible -> doesn't matter */
     for (i = 0; i < PA_SC_CLIPRECT_0_TL_num; i++)
 	set_clip_rect (pScrn, ib, i, 0, 0, 8192, 8192);
 
+    BEGIN_BATCH(3);
     if (info->ChipFamily < CHIP_FAMILY_RV770)
 	EREG(ib, R7xx_PA_SC_EDGERULE,             0x00000000);
     else
 	EREG(ib, R7xx_PA_SC_EDGERULE,             0xAAAAAAAA);
+    END_BATCH();
 
     for (i = 0; i < PA_SC_VPORT_SCISSOR_0_TL_num; i++) {
 	set_vport_scissor (pScrn, ib, i, 0, 0, 8192, 8192);
+	BEGIN_BATCH(4);
 	PACK0(ib, PA_SC_VPORT_ZMIN_0 + i * PA_SC_VPORT_ZMIN_0_offset, 2);
 	EFLOAT(ib, 0.0);
 	EFLOAT(ib, 1.0);
+	END_BATCH();
     }
 
+    BEGIN_BATCH(15);
     if (info->ChipFamily < CHIP_FAMILY_RV770)
 	EREG(ib, PA_SC_MODE_CNTL,                 (WALK_ORDER_ENABLE_bit | FORCE_EOV_CNTDWN_ENABLE_bit));
     else
@@ -852,13 +903,17 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     EREG(ib, PA_SC_LINE_CNTL,                     0);
     EREG(ib, PA_SC_AA_CONFIG,                     0);
     EREG(ib, PA_SC_AA_MASK,                       0xFFFFFFFF);
+    END_BATCH();
 
     //XXX: double check this
     if (info->ChipFamily > CHIP_FAMILY_R600) {
+	BEGIN_BATCH(6);
 	EREG(ib, PA_SC_AA_SAMPLE_LOCS_MCTX,       0);
 	EREG(ib, PA_SC_AA_SAMPLE_LOCS_8S_WD1_M,   0);
+	END_BATCH();
     }
 
+    BEGIN_BATCH(83);
     EREG(ib, PA_SC_LINE_STIPPLE,                  0);
     EREG(ib, PA_SC_MPASS_PS_CNTL,                 0);
 
@@ -908,17 +963,18 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     EREG(ib, SPI_FOG_CNTL,                        0);
     EREG(ib, SPI_FOG_FUNC_SCALE,                  0);
     EREG(ib, SPI_FOG_FUNC_BIAS,                   0);
+    END_BATCH();
 
     // clear FS
     fs_setup(pScrn, ib, &fs_conf);
 
     // VGT
+    BEGIN_BATCH(75);
     EREG(ib, VGT_MAX_VTX_INDX,                    2048); /* XXX set to a reasonably large number of indices */
     EREG(ib, VGT_MIN_VTX_INDX,                    0);
     EREG(ib, VGT_INDX_OFFSET,                     0);
     EREG(ib, VGT_INSTANCE_STEP_RATE_0,            0);
     EREG(ib, VGT_INSTANCE_STEP_RATE_1,            0);
-
     EREG(ib, VGT_MULTI_PRIM_IB_RESET_INDX,        0);
     EREG(ib, VGT_OUTPUT_PATH_CNTL,                0);
     EREG(ib, VGT_GS_MODE,                         0);
@@ -939,7 +995,7 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     EREG(ib, VGT_REUSE_OFF,                       0);
     EREG(ib, VGT_VTX_CNT_EN,                      0);
     EREG(ib, VGT_STRMOUT_BUFFER_EN,               0);
-
+    END_BATCH();
 }
 
 
@@ -952,12 +1008,6 @@ draw_immd(ScrnInfoPtr pScrn, drmBufPtr ib, draw_config_t *draw_conf, uint32_t *i
 {
     uint32_t i, count;
 
-    EREG(ib, VGT_PRIMITIVE_TYPE, draw_conf->prim_type);
-    PACK3(ib, IT_INDEX_TYPE, 1);
-    E32(ib, draw_conf->index_type);
-    PACK3(ib, IT_NUM_INSTANCES, 1);
-    E32(ib, draw_conf->num_instances);
-
     // calculate num of packets
     count = 2;
     if (draw_conf->index_type == DI_INDEX_SIZE_16_BIT)
@@ -965,6 +1015,13 @@ draw_immd(ScrnInfoPtr pScrn, drmBufPtr ib, draw_config_t *draw_conf, uint32_t *i
     else
 	count += draw_conf->num_indices;
 
+    BEGIN_BATCH(8 + count);
+    EREG(ib, VGT_PRIMITIVE_TYPE, draw_conf->prim_type);
+    PACK3(ib, IT_INDEX_TYPE, 1);
+    E32(ib, draw_conf->index_type);
+    PACK3(ib, IT_NUM_INSTANCES, 1);
+    E32(ib, draw_conf->num_instances);
+
     PACK3(ib, IT_DRAW_INDEX_IMMD, count);
     E32(ib, draw_conf->num_indices);
     E32(ib, draw_conf->vgt_draw_initiator);
@@ -980,12 +1037,13 @@ draw_immd(ScrnInfoPtr pScrn, drmBufPtr ib, draw_config_t *draw_conf, uint32_t *i
 	for (i = 0; i < draw_conf->num_indices; i++)
 	    E32(ib, indices[i]);
     }
+    END_BATCH();
 }
 
 void
 draw_auto(ScrnInfoPtr pScrn, drmBufPtr ib, draw_config_t *draw_conf)
 {
-
+    BEGIN_BATCH(10);
     EREG(ib, VGT_PRIMITIVE_TYPE, draw_conf->prim_type);
     PACK3(ib, IT_INDEX_TYPE, 1);
     E32(ib, draw_conf->index_type);
@@ -994,6 +1052,7 @@ draw_auto(ScrnInfoPtr pScrn, drmBufPtr ib, draw_config_t *draw_conf)
     PACK3(ib, IT_DRAW_INDEX_AUTO, 2);
     E32(ib, draw_conf->num_indices);
     E32(ib, draw_conf->vgt_draw_initiator);
+    END_BATCH();
 }
 
 void
commit b6368cc572c79bce9a9366242c727c13cab3f006
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Aug 25 12:14:33 2009 -0400

    r6xx/r7xx: move more common state to default state setup

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 3e77515..0a9a0c6 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -164,10 +164,6 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 
     set_default_state(pScrn, accel_state->ib);
 
-    /* Scissor / viewport */
-    EREG(accel_state->ib, PA_CL_VTE_CNTL,                      VTX_XY_FMT_bit);
-    EREG(accel_state->ib, PA_CL_CLIP_CNTL,                     CLIP_DISABLE_bit);
-
     set_generic_scissor(pScrn, accel_state->ib, 0, 0, pPix->drawable.width, pPix->drawable.height);
     set_screen_scissor(pScrn, accel_state->ib, 0, 0, pPix->drawable.width, pPix->drawable.height);
     set_window_scissor(pScrn, accel_state->ib, 0, 0, pPix->drawable.width, pPix->drawable.height);
@@ -212,7 +208,6 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     if (pm & 0xff000000)
 	pmask |= 8; /* A */
     EREG(accel_state->ib, CB_SHADER_MASK,                      (pmask << OUTPUT0_ENABLE_shift));
-    EREG(accel_state->ib, R7xx_CB_SHADER_CONTROL,              (RT0_ENABLE_bit));
     EREG(accel_state->ib, CB_COLOR_CONTROL,                    RADEON_ROP[alu]);
 
     cb_conf.id = 0;
@@ -234,12 +229,6 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     cb_conf.blend_clamp = 1;
     set_render_target(pScrn, accel_state->ib, &cb_conf);
 
-    EREG(accel_state->ib, PA_SU_SC_MODE_CNTL,                  (FACE_bit			|
-								(POLYMODE_PTYPE__TRIANGLES << POLYMODE_FRONT_PTYPE_shift)	|
-								(POLYMODE_PTYPE__TRIANGLES << POLYMODE_BACK_PTYPE_shift)));
-    EREG(accel_state->ib, DB_SHADER_CONTROL,                   ((1 << Z_ORDER_shift)		| /* EARLY_Z_THEN_LATE_Z */
-								DUAL_EXPORT_ENABLE_bit)); /* Only useful if no depth export */
-
     /* Interpolator setup */
     /* one unused export from VS (VS_EXPORT_COUNT is zero based, count minus one) */
     EREG(accel_state->ib, SPI_VS_OUT_CONFIG, (0 << VS_EXPORT_COUNT_shift));
@@ -408,10 +397,6 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
 
     set_default_state(pScrn, accel_state->ib);
 
-    /* Scissor / viewport */
-    EREG(accel_state->ib, PA_CL_VTE_CNTL,                      VTX_XY_FMT_bit);
-    EREG(accel_state->ib, PA_CL_CLIP_CNTL,                     CLIP_DISABLE_bit);
-
     set_generic_scissor(pScrn, accel_state->ib, 0, 0, dst_width, dst_height);
     set_screen_scissor(pScrn, accel_state->ib, 0, 0, dst_width, dst_height);
     set_window_scissor(pScrn, accel_state->ib, 0, 0, dst_width, dst_height);
@@ -513,7 +498,6 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
     if (planemask & 0xff000000)
 	pmask |= 8; /* A */
     EREG(accel_state->ib, CB_SHADER_MASK,                      (pmask << OUTPUT0_ENABLE_shift));
-    EREG(accel_state->ib, R7xx_CB_SHADER_CONTROL,              (RT0_ENABLE_bit));
     EREG(accel_state->ib, CB_COLOR_CONTROL,                    RADEON_ROP[rop]);
 
     accel_state->dst_size = dst_pitch * dst_height * (dst_bpp/8);
@@ -540,12 +524,6 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
     cb_conf.blend_clamp = 1;
     set_render_target(pScrn, accel_state->ib, &cb_conf);
 
-    EREG(accel_state->ib, PA_SU_SC_MODE_CNTL,                  (FACE_bit			|
-								(POLYMODE_PTYPE__TRIANGLES << POLYMODE_FRONT_PTYPE_shift)	|
-								(POLYMODE_PTYPE__TRIANGLES << POLYMODE_BACK_PTYPE_shift)));
-    EREG(accel_state->ib, DB_SHADER_CONTROL,                   ((1 << Z_ORDER_shift)		| /* EARLY_Z_THEN_LATE_Z */
-								DUAL_EXPORT_ENABLE_bit)); /* Only useful if no depth export */
-
     /* Interpolator setup */
     /* export tex coord from VS */
     EREG(accel_state->ib, SPI_VS_OUT_CONFIG, ((1 - 1) << VS_EXPORT_COUNT_shift));
@@ -1463,10 +1441,6 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
 
     set_default_state(pScrn, accel_state->ib);
 
-    /* Scissor / viewport */
-    EREG(accel_state->ib, PA_CL_VTE_CNTL,                      VTX_XY_FMT_bit);
-    EREG(accel_state->ib, PA_CL_CLIP_CNTL,                     CLIP_DISABLE_bit);
-
     set_generic_scissor(pScrn, accel_state->ib, 0, 0, pDst->drawable.width, pDst->drawable.height);
     set_screen_scissor(pScrn, accel_state->ib, 0, 0, pDst->drawable.width, pDst->drawable.height);
     set_window_scissor(pScrn, accel_state->ib, 0, 0, pDst->drawable.width, pDst->drawable.height);
@@ -1526,7 +1500,6 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     ps_setup                    (pScrn, accel_state->ib, &ps_conf);
 
     EREG(accel_state->ib, CB_SHADER_MASK,                      (0xf << OUTPUT0_ENABLE_shift));
-    EREG(accel_state->ib, R7xx_CB_SHADER_CONTROL,              (RT0_ENABLE_bit));
 
     blendcntl = R600GetBlendCntl(op, pMaskPicture, pDstPicture->format);
 
@@ -1566,12 +1539,6 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     cb_conf.blend_clamp = 1;
     set_render_target(pScrn, accel_state->ib, &cb_conf);
 
-    EREG(accel_state->ib, PA_SU_SC_MODE_CNTL,                  (FACE_bit			|
-								(POLYMODE_PTYPE__TRIANGLES << POLYMODE_FRONT_PTYPE_shift)	|
-								(POLYMODE_PTYPE__TRIANGLES << POLYMODE_BACK_PTYPE_shift)));
-    EREG(accel_state->ib, DB_SHADER_CONTROL,                   ((1 << Z_ORDER_shift)		| /* EARLY_Z_THEN_LATE_Z */
-								DUAL_EXPORT_ENABLE_bit)); /* Only useful if no depth export */
-
     /* Interpolator setup */
     if (pMask) {
 	/* export 2 tex coords from VS */
diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index 5dc79c9..4502ab3 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -241,10 +241,6 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 
     set_default_state(pScrn, accel_state->ib);
 
-    /* Scissor / viewport */
-    EREG(accel_state->ib, PA_CL_VTE_CNTL,                      VTX_XY_FMT_bit);
-    EREG(accel_state->ib, PA_CL_CLIP_CNTL,                     CLIP_DISABLE_bit);
-
     set_generic_scissor(pScrn, accel_state->ib, 0, 0, pPixmap->drawable.width, pPixmap->drawable.height);
     set_screen_scissor(pScrn, accel_state->ib, 0, 0, pPixmap->drawable.width, pPixmap->drawable.height);
     set_window_scissor(pScrn, accel_state->ib, 0, 0, pPixmap->drawable.width, pPixmap->drawable.height);
@@ -473,7 +469,6 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 
     /* Render setup */
     EREG(accel_state->ib, CB_SHADER_MASK,                      (0x0f << OUTPUT0_ENABLE_shift));
-    EREG(accel_state->ib, R7xx_CB_SHADER_CONTROL,              (RT0_ENABLE_bit));
     EREG(accel_state->ib, CB_COLOR_CONTROL,                    (0xcc << ROP3_shift)); /* copy */
 
     cb_conf.id = 0;
@@ -506,12 +501,6 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     cb_conf.blend_clamp = 1;
     set_render_target(pScrn, accel_state->ib, &cb_conf);
 
-    EREG(accel_state->ib, PA_SU_SC_MODE_CNTL,                  (FACE_bit			|
-								(POLYMODE_PTYPE__TRIANGLES << POLYMODE_FRONT_PTYPE_shift)	|
-								(POLYMODE_PTYPE__TRIANGLES << POLYMODE_BACK_PTYPE_shift)));
-    EREG(accel_state->ib, DB_SHADER_CONTROL,                   ((1 << Z_ORDER_shift)		| /* EARLY_Z_THEN_LATE_Z */
-								DUAL_EXPORT_ENABLE_bit)); /* Only useful if no depth export */
-
     /* Interpolator setup */
     /* export tex coords from VS */
     EREG(accel_state->ib, SPI_VS_OUT_CONFIG, ((1 - 1) << VS_EXPORT_COUNT_shift));
diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index 0457f7d..55188a4 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -775,6 +775,11 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
 						   (2 << ALPHA_TO_MASK_OFFSET2_shift)	|
 						   (2 << ALPHA_TO_MASK_OFFSET3_shift)));
 
+
+    EREG(ib, DB_SHADER_CONTROL, ((1 << Z_ORDER_shift) | /* EARLY_Z_THEN_LATE_Z */
+				 DUAL_EXPORT_ENABLE_bit)); /* Only useful if no depth export */
+
+
     // SX
     EREG(ib, SX_ALPHA_TEST_CONTROL,               0);
     EREG(ib, SX_ALPHA_REF,                        0);
@@ -808,6 +813,8 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
 	EFLOAT(ib, 1.0);
     }
     EREG(ib, CB_TARGET_MASK,                      (0x0f << TARGET0_ENABLE_shift));
+    EREG(ib, R7xx_CB_SHADER_CONTROL,              (RT0_ENABLE_bit));
+
 
     // SC
     EREG(ib, PA_SC_WINDOW_OFFSET,                 ((0 << WINDOW_X_OFFSET_shift) |
@@ -837,6 +844,11 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
 	EREG(ib, PA_SC_MODE_CNTL,                 (FORCE_EOV_CNTDWN_ENABLE_bit | FORCE_EOV_REZ_ENABLE_bit |
 						   0x00500000)); /* ? */
 
+    EREG(ib, PA_SU_SC_MODE_CNTL, (FACE_bit |
+				  (POLYMODE_PTYPE__TRIANGLES << POLYMODE_FRONT_PTYPE_shift) |
+				  (POLYMODE_PTYPE__TRIANGLES << POLYMODE_BACK_PTYPE_shift)));
+
+
     EREG(ib, PA_SC_LINE_CNTL,                     0);
     EREG(ib, PA_SC_AA_CONFIG,                     0);
     EREG(ib, PA_SC_AA_MASK,                       0xFFFFFFFF);
@@ -867,6 +879,10 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     EFLOAT(ib, 1.0);						// PA_CL_GB_HORZ_CLIP_ADJ
     EFLOAT(ib, 1.0);						// PA_CL_GB_HORZ_DISC_ADJ
 
+    /* Scissor / viewport */
+    EREG(ib, PA_CL_VTE_CNTL,                      VTX_XY_FMT_bit);
+    EREG(ib, PA_CL_CLIP_CNTL,                     CLIP_DISABLE_bit);
+
     // SU
     EREG(ib, PA_SU_SC_MODE_CNTL,                  FACE_bit);
     EREG(ib, PA_SU_POINT_SIZE,                    0);
commit fc74e1194c980d978667e02c60a29a761a694bde
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Aug 25 11:39:56 2009 -0400

    RV740: disable small DFS transfers
    
    Seems problematic on all rv740 chips, so until we
    can find a solution, disable them.

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 48e797f..3e77515 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -1864,6 +1864,10 @@ R600DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
     int wpass = w * (bpp/8);
     drmBufPtr scratch;
 
+    /* RV740 seems to be particularly problematic with small xfers */
+    if ((info->ChipFamily == CHIP_FAMILY_RV740) && (w < 32 || h < 32))
+	return FALSE;
+
     if (src_pitch & 7)
 	return FALSE;
 
commit 1c909ecd88e75c6e16af7aa068e32a7a60b0af37
Author: Jerome Glisse <jglisse at redhat.com>
Date:   Tue Aug 25 11:21:41 2009 +0200

    radeon: Fix X recycling with KMS
    
    On X recycling CloseScreen drop master so grab it again
    in InitScreen and avoid to reallocate buffer & various
    others cs/bo utilities on X recycling.

diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 0cabc53..cd398c6 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -507,6 +507,8 @@ static Bool RADEONCloseScreen_KMS(int scrnIndex, ScreenPtr pScreen)
     if (info->cursor) xf86DestroyCursorInfoRec(info->cursor);
     info->cursor = NULL;
 
+    radeon_dri2_close_screen(pScreen);
+
     pScrn->vtSema = FALSE;
     xf86ClearPrimInitDone(info->pEnt->index);
     pScreen->BlockHandler = info->BlockHandler;
@@ -537,6 +539,7 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
     int            subPixelOrder = SubPixelUnknown;
     char*          s;
     void *front_ptr;
+    int ret;
 
     pScrn->fbOffset = 0;
 
@@ -547,13 +550,19 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
 			  pScrn->defaultVisual)) return FALSE;
     miSetPixmapDepths ();
 
+    ret = drmSetMaster(info->dri->drmFD);
+    if (ret) {
+        ErrorF("Unable to retrieve master\n");
+        return FALSE;
+    }
     info->directRenderingEnabled = FALSE;
     if (info->r600_shadow_fb == FALSE)
         info->directRenderingEnabled = radeon_dri2_screen_init(pScreen);
 
     front_ptr = info->FB;
 
-    info->bufmgr = radeon_bo_manager_gem_ctor(info->dri->drmFD);
+    if (!info->bufmgr)
+        info->bufmgr = radeon_bo_manager_gem_ctor(info->dri->drmFD);
     if (!info->bufmgr) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "failed to initialise GEM buffer manager");
@@ -561,14 +570,16 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
     }
     drmmode_set_bufmgr(pScrn, &info->drmmode, info->bufmgr);
 
-    info->csm = radeon_cs_manager_gem_ctor(info->dri->drmFD);
+    if (!info->csm)
+        info->csm = radeon_cs_manager_gem_ctor(info->dri->drmFD);
     if (!info->csm) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "failed to initialise command submission manager");
 	return FALSE;
     }
 
-    info->cs = radeon_cs_create(info->csm, RADEON_BUFFER_SIZE/4);
+    if (!info->cs)
+        info->cs = radeon_cs_create(info->csm, RADEON_BUFFER_SIZE/4);
     if (!info->cs) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "failed to initialise command submission buffer");
@@ -732,6 +743,9 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "RADEONScreenInit finished\n");
 
+    info->accel_state->XInited3D = FALSE;
+    info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
+
     return TRUE;
 }
 
@@ -833,19 +847,22 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
 	cursor_size = RADEON_ALIGN(cursor_size, pagesize);
 	for (c = 0; c < xf86_config->num_crtc; c++) {
 	    /* cursor objects */
-	    info->cursor_bo[c] = radeon_bo_open(info->bufmgr, 0, cursor_size,
-					      0, RADEON_GEM_DOMAIN_VRAM, 0);
-	    if (!info->cursor_bo[c]) {
-		return FALSE;
-	    }
-
-	    if (radeon_bo_map(info->cursor_bo[c], 1)) {
-	      ErrorF("Failed to map cursor buffer memory\n");
-	    }
-
-	    drmmode_set_cursor(pScrn, &info->drmmode, c, info->cursor_bo[c]);
-	    total_size_bytes += cursor_size;
-	}
+            if (info->cursor_bo[c] == NULL) {
+                info->cursor_bo[c] = radeon_bo_open(info->bufmgr, 0,
+                                                    cursor_size, 0,
+                                                    RADEON_GEM_DOMAIN_VRAM, 0);
+                if (!info->cursor_bo[c]) {
+                    return FALSE;
+                }
+
+                if (radeon_bo_map(info->cursor_bo[c], 1)) {
+                    ErrorF("Failed to map cursor buffer memory\n");
+                }
+
+                drmmode_set_cursor(pScrn, &info->drmmode, c, info->cursor_bo[c]);
+                total_size_bytes += cursor_size;
+            }
+        }
     }
 
     screen_size = RADEON_ALIGN(screen_size, pagesize);
@@ -857,17 +874,19 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
 
     info->dri->textureSize = 0;
 
-    info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size,
-				    0, RADEON_GEM_DOMAIN_VRAM, 0);
-    if (info->r600_shadow_fb == TRUE) {
-        if (radeon_bo_map(info->front_bo, 1)) {
-	    ErrorF("Failed to map cursor buffer memory\n");
-	}
+    if (info->front_bo == NULL) {
+        info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size,
+                                        0, RADEON_GEM_DOMAIN_VRAM, 0);
+        if (info->r600_shadow_fb == TRUE) {
+            if (radeon_bo_map(info->front_bo, 1)) {
+                ErrorF("Failed to map cursor buffer memory\n");
+            }
+        }
+        if (info->allowColorTiling) {
+            radeon_bo_set_tiling(info->front_bo, RADEON_TILING_MACRO, stride);
+        }
     }
 
-    if (info->allowColorTiling) {
-	radeon_bo_set_tiling(info->front_bo, RADEON_TILING_MACRO, stride);
-    }
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer size: %dK\n", info->front_bo->size/1024);
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Remaining VRAM size (used for pixmaps): %dK\n", remain_size_bytes/1024);
 
commit 39aaf9addc923852598ba6fb914459671b78e492
Author: Dave Airlie <airlied at linux.ie>
Date:   Mon Aug 24 18:59:22 2009 +1000

    r600: use exa fallback code for solid/copy codepaths.
    
    Solid seem to try and handle 1bpp which really no.

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 578a473..48e797f 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -39,6 +39,21 @@
 #include "r600_reg.h"
 #include "r600_state.h"
 
+
+#define RADEON_TRACE_FALL 0
+#define RADEON_TRACE_DRAW 0
+
+#if RADEON_TRACE_FALL
+#define RADEON_FALLBACK(x)     		\
+do {					\
+	ErrorF("%s: ", __FUNCTION__);	\
+	ErrorF x;			\
+	return FALSE;			\
+} while (0)
+#else
+#define RADEON_FALLBACK(x) return FALSE
+#endif
+
 extern PixmapPtr
 RADEONGetDrawablePixmap(DrawablePtr pDrawable);
 
@@ -80,6 +95,20 @@ uint32_t RADEON_ROP[16] = {
     RADEON_ROP3_ONE,  /* GXset          */
 };
 
+static Bool R600CheckBPP(int bpp)
+{
+	switch (bpp) {
+	case 8:
+	case 16:
+	case 32:
+		return TRUE;
+	default:
+		break;
+	}
+	return FALSE;
+}
+
+
 static void
 R600DoneSolid(PixmapPtr pPix);
 
@@ -99,20 +128,22 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     uint32_t a, r, g, b;
     float ps_alu_consts[4];
 
+    if (pPix->drawable.bitsPerPixel == 24)
+        RADEON_FALLBACK(("24bpp unsupported\n"));
+    if (!R600CheckBPP(pPix->drawable.bitsPerPixel))
+        RADEON_FALLBACK(("R600CheckDatatype failed\n"));
+
     accel_state->dst_mc_addr = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset;
     accel_state->dst_size = exaGetPixmapPitch(pPix) * pPix->drawable.height;
     accel_state->dst_pitch = exaGetPixmapPitch(pPix) / (pPix->drawable.bitsPerPixel / 8);
 
     /* bad pitch */
     if (accel_state->dst_pitch & 7)
-	return FALSE;
+	RADEON_FALLBACK(("Bad pitch 0x%08x\n", accel_state->dst_pitch));
 
     /* bad offset */
     if (accel_state->dst_mc_addr & 0xff)
-	return FALSE;
-
-    if (pPix->drawable.bitsPerPixel == 24)
-	return FALSE;
+	RADEON_FALLBACK(("Bad offset 0x%08x\n", accel_state->dst_mc_addr));
 
     CLEAR (cb_conf);
     CLEAR (vs_conf);
@@ -634,6 +665,15 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
     RADEONInfoPtr info = RADEONPTR(pScrn);
     struct radeon_accel_state *accel_state = info->accel_state;
 
+    if (pSrc->drawable.bitsPerPixel == 24)
+        RADEON_FALLBACK(("24bpp unsupported\n"));
+    if (pDst->drawable.bitsPerPixel == 24)
+        RADEON_FALLBACK(("24bpp unsupported\n"));
+    if (!R600CheckBPP(pSrc->drawable.bitsPerPixel))
+        RADEON_FALLBACK(("R600CheckDatatype src failed\n"));
+    if (!R600CheckBPP(pDst->drawable.bitsPerPixel))
+        RADEON_FALLBACK(("R600CheckDatatype dst failed\n"));
+
     accel_state->dst_pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8);
     accel_state->src_pitch[0] = exaGetPixmapPitch(pSrc) / (pSrc->drawable.bitsPerPixel / 8);
 
@@ -648,20 +688,16 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
 
     /* bad pitch */
     if (accel_state->src_pitch[0] & 7)
-	return FALSE;
+	RADEON_FALLBACK(("Bad src pitch 0x%08x\n", accel_state->src_pitch[0]));
     if (accel_state->dst_pitch & 7)
-	return FALSE;
+	RADEON_FALLBACK(("Bad dst pitch 0x%08x\n", accel_state->dst_pitch));
 
     /* bad offset */
     if (accel_state->src_mc_addr[0] & 0xff)
-	return FALSE;
-    if (accel_state->dst_mc_addr & 0xff)
-	return FALSE;
+	RADEON_FALLBACK(("Bad src offset 0x%08x\n", accel_state->src_mc_addr[0]));
 
-    if (pSrc->drawable.bitsPerPixel == 24)
-	return FALSE;
-    if (pDst->drawable.bitsPerPixel == 24)
-	return FALSE;
+    if (accel_state->dst_mc_addr & 0xff)
+	RADEON_FALLBACK(("Bad dst offset 0x%08x\n", accel_state->dst_mc_addr));
 
     /* return FALSE; */
 
@@ -909,19 +945,6 @@ R600DoneCopy(PixmapPtr pDst)
 
 }
 
-#define RADEON_TRACE_FALL 0
-#define RADEON_TRACE_DRAW 0
-
-#if RADEON_TRACE_FALL
-#define RADEON_FALLBACK(x)     		\
-do {					\
-	ErrorF("%s: ", __FUNCTION__);	\
-	ErrorF x;			\
-	return FALSE;			\
-} while (0)
-#else
-#define RADEON_FALLBACK(x) return FALSE
-#endif
 
 #define xFixedToFloat(f) (((float) (f)) / 65536)
 
commit e4b2d57ddca8739ec0b452565713398d036be0d5
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Aug 24 14:11:24 2009 +1000

    r600: fix bad unit in texture setup

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 979bb73..578a473 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -1098,10 +1098,10 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
     accel_state->src_pitch[unit] = exaGetPixmapPitch(pPix) / (pPix->drawable.bitsPerPixel / 8);
     accel_state->src_size[unit] = exaGetPixmapPitch(pPix) * pPix->drawable.height;
 
-    if (accel_state->src_pitch[1] & 7)
+    if (accel_state->src_pitch[unit] & 7)
 	RADEON_FALLBACK(("Bad pitch %d 0x%x\n", (int)accel_state->src_pitch[unit], unit));
 
-    if (accel_state->src_mc_addr[1] & 0xff)
+    if (accel_state->src_mc_addr[unit] & 0xff)
 	RADEON_FALLBACK(("Bad offset %d 0x%x\n", (int)accel_state->src_mc_addr[unit], unit));
 
     for (i = 0; i < sizeof(R600TexFormats) / sizeof(R600TexFormats[0]); i++) {
commit bac224912c750dc1c85ff2d9b8526dad6c23b572
Author: Dave Airlie <airlied at redhat.com>
Date:   Sat Aug 22 21:17:59 2009 +1000

    radeon: don't spec any initial placement for pixmaps.
    
    allow the first use to decide placement.

diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index ec65722..3f3c9ba 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -391,8 +391,7 @@ void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align)
 	return new_priv;
 
     new_priv->bo = radeon_bo_open(info->bufmgr, 0, size,
-				  align, RADEON_GEM_DOMAIN_VRAM |
-				  RADEON_GEM_DOMAIN_GTT, 0);
+				  align, 0, 0);
     if (!new_priv->bo) {
 	xfree(new_priv);
 	ErrorF("Failed to alloc memory\n");
commit 77f98717d825162da106c6898cdbcbdf5c984ae6
Author: Dave Airlie <airlied at redhat.com>
Date:   Sat Aug 22 21:16:25 2009 +1000

    exa/cs: add DFS from GTT optimisation
    
    This uses the new libdrm busy interface, once I had this in place
    I added a error if this happened and it does on my desktop here,
    so may as well add the optimisation that used to be in my old KMS tree.
    
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index e48317f..f937c4e 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -507,6 +507,33 @@ out:
 }
 
 static Bool
+RADEONDownloadFromScreenGTT(PixmapPtr pSrc, int x, int y, int w,
+			    int h, char *dst, int dst_pitch)
+{
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int src_pitch = exaGetPixmapPitch(pSrc);
+    int bpp = pSrc->drawable.bitsPerPixel;
+    int src_offset;
+    int r;
+
+    driver_priv = exaGetPixmapDriverPrivate(pSrc);
+    r = radeon_bo_map(driver_priv->bo, 0);
+    if (r)
+	return FALSE;
+
+    src_offset = (x * bpp / 8) + (y * src_pitch);
+    w *= bpp / 8;
+
+    while (h--) {
+        memcpy(dst, driver_priv->bo->ptr + src_offset, w);
+        src_offset += src_pitch;
+        dst += dst_pitch;
+    }
+    radeon_bo_unmap(driver_priv->bo);
+    return TRUE;
+}
+
+static Bool
 RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
                            int h, char *dst, int dst_pitch)
 {
@@ -519,11 +546,19 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
     unsigned bpp = pSrc->drawable.bitsPerPixel;
     uint32_t scratch_pitch = (w * bpp / 8 + 63) & ~63;
     Bool r;
+    uint32_t src_domain;
+    int busy;
 
     if (bpp < 8)
 	return FALSE;
 
     driver_priv = exaGetPixmapDriverPrivate(pSrc);
+ 
+    busy = radeon_bo_is_busy(driver_priv->bo, &src_domain);
+
+    if (src_domain == RADEON_GEM_DOMAIN_GTT)
+	return RADEONDownloadFromScreenGTT(pSrc, x, y, w, h,
+					   dst, dst_pitch);
 
     size = scratch_pitch * h;
     scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0);
commit b1b77a4d6fb7404af9568644e1a8e050fdfa956e
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Aug 19 13:29:04 2009 -0400

    rs600: add support for DisplayPriority HIGH
    
    Still haven't implemented the actual watermark
    calculation, but this forces the display requests
    to urgent if the user specifies DisplayPriority HIGH.

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 176efa6..341deb4 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -767,9 +767,37 @@ RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn,
     OUTREG(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split);
 #endif
 
-    // fixme
-    if (info->ChipFamily == CHIP_FAMILY_RS600)
+    /* fixme
+     * Still need to implement the actual watermark calculation
+     * for rs600.  This just allows us to force high display
+     * priority.
+     */
+    if (info->ChipFamily == CHIP_FAMILY_RS600) {
+	if (info->DispPriority == 2) {
+	    uint32_t priority_cnt;
+
+	    if (mode1) {
+		priority_cnt = INREG(AVIVO_D1MODE_PRIORITY_A_CNT);
+		priority_cnt |= AVIVO_DxMODE_PRIORITY_ALWAYS_ON;
+		OUTREG(AVIVO_D1MODE_PRIORITY_A_CNT, priority_cnt);
+
+		priority_cnt = INREG(AVIVO_D1MODE_PRIORITY_B_CNT);
+		priority_cnt |= AVIVO_DxMODE_PRIORITY_ALWAYS_ON;
+		OUTREG(AVIVO_D1MODE_PRIORITY_B_CNT, priority_cnt);
+	    }
+
+	    if (mode2) {
+		priority_cnt = INREG(AVIVO_D2MODE_PRIORITY_A_CNT);
+		priority_cnt |= AVIVO_DxMODE_PRIORITY_ALWAYS_ON;
+		OUTREG(AVIVO_D2MODE_PRIORITY_A_CNT, priority_cnt);
+
+		priority_cnt = INREG(AVIVO_D2MODE_PRIORITY_B_CNT);
+		priority_cnt |= AVIVO_DxMODE_PRIORITY_ALWAYS_ON;
+		OUTREG(AVIVO_D2MODE_PRIORITY_B_CNT, priority_cnt);
+	    }
+	}
 	return;
+    }
 
     /* IGP bandwidth - get from integrated systems table
      * SYSTEM_MEMORY_BANDWIDTH (Mbyte/s) = SYSTEM_MEMORY_CLOCK (MHz) * (1+DDR) * 8 * EFF * Num of channels
commit 72e0d1b2cb11a67b8e4be4c74913ee44dc051c5b
Author: Dave Airlie <airlied at redhat.com>
Date:   Wed Aug 19 19:01:30 2009 +1000

    radeon/kms: add initial colortiling support (disabled by default).
    
    This requires an X server from git with createpixmap2 support fixed up in it.
    
    On 1.6 and previous it won't do any tiling, if you are running git server
    please upgrade to latest git.
    
    Option "AllowColorTiling" "true" to enable and do some testing

diff --git a/src/radeon.h b/src/radeon.h
index 6b47a6a..3a3631e 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -1620,4 +1620,9 @@ static __inline__ int radeon_timedout(const struct timeval *endtime)
         now.tv_usec > endtime->tv_usec : now.tv_sec > endtime->tv_sec;
 }
 
+enum {
+    RADEON_CREATE_PIXMAP_TILING_MACRO = 0x10000000,
+    RADEON_CREATE_PIXMAP_TILING_MICRO = 0x20000000,
+};
+
 #endif /* _RADEON_H_ */
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 9c86244..b52f965 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -64,6 +64,7 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
     PixmapPtr pixmap, depth_pixmap;
     struct radeon_exa_pixmap_priv *driver_priv;
     int i, r;
+    int flags = 0;
 
     buffers = xcalloc(count, sizeof *buffers);
     if (buffers == NULL) {
@@ -88,11 +89,22 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
             pixmap = depth_pixmap;
             pixmap->refcnt++;
         } else {
-            pixmap = (*pScreen->CreatePixmap)(pScreen,
+	    /* tile the back buffer */
+	    switch(attachments[i]) {
+	    case DRI2BufferBackLeft:
+	    case DRI2BufferBackRight:
+	    case DRI2BufferFakeFrontLeft:
+	    case DRI2BufferFakeFrontRight:
+		flags = RADEON_CREATE_PIXMAP_TILING_MACRO;
+		break;
+	    default:
+		flags = 0;
+	    }
+	    pixmap = (*pScreen->CreatePixmap)(pScreen,
                                               drawable->width,
                                               drawable->height,
                                               drawable->depth,
-                                              0);
+                                              flags);
         }
 
         if (attachments[i] == DRI2BufferDepth) {
@@ -126,6 +138,7 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
     PixmapPtr pixmap, depth_pixmap;
     struct radeon_exa_pixmap_priv *driver_priv;
     int r;
+    int flags;
 
     buffers = xcalloc(1, sizeof *buffers);
     if (buffers == NULL) {
@@ -150,11 +163,26 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
         pixmap = depth_pixmap;
         pixmap->refcnt++;
     } else {
+	/* tile the back buffer */
+	switch(attachment) {
+	case DRI2BufferDepth:
+	case DRI2BufferDepthStencil:
+	    flags = RADEON_CREATE_PIXMAP_TILING_MACRO | RADEON_CREATE_PIXMAP_TILING_MICRO;
+	    break;
+	case DRI2BufferBackLeft:
+	case DRI2BufferBackRight:
+	case DRI2BufferFakeFrontLeft:
+	case DRI2BufferFakeFrontRight:
+	    flags = RADEON_CREATE_PIXMAP_TILING_MACRO;
+	    break;
+	default:
+	    flags = 0;
+	}
         pixmap = (*pScreen->CreatePixmap)(pScreen,
                 drawable->width,
                 drawable->height,
                 (format != 0)?format:drawable->depth,
-                0);
+                flags);
     }
 
     if (attachment == DRI2BufferDepth) {
diff --git a/src/radeon_drm.h b/src/radeon_drm.h
index daa42d6..f974e19 100644
--- a/src/radeon_drm.h
+++ b/src/radeon_drm.h
@@ -503,6 +503,8 @@ typedef struct {
 #define DRM_RADEON_GEM_WAIT_IDLE	0x24
 #define DRM_RADEON_CS			0x26
 #define DRM_RADEON_INFO			0x27
+#define DRM_RADEON_GEM_SET_TILING	0x28
+#define DRM_RADEON_GEM_GET_TILING	0x29
 
 #define DRM_IOCTL_RADEON_CP_INIT    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)
 #define DRM_IOCTL_RADEON_CP_START   DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_START)
@@ -541,7 +543,8 @@ typedef struct {
 #define DRM_IOCTL_RADEON_GEM_WAIT_IDLE	DRM_IOW(DRM_COMMAND_BASE + DRM_RADEON_GEM_WAIT_IDLE, struct drm_radeon_gem_wait_idle) 
 #define DRM_IOCTL_RADEON_CS		DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs)
 #define DRM_IOCTL_RADEON_INFO		DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INFO, struct drm_radeon_info)
-
+#define DRM_IOCTL_RADEON_SET_TILING	DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_TILING, struct drm_radeon_gem_set_tiling)
+#define DRM_IOCTL_RADEON_GET_TILING	DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_GET_TILING, struct drm_radeon_gem_get_tiling)
 
 typedef struct drm_radeon_init {
 	enum {
@@ -797,6 +800,24 @@ struct drm_radeon_gem_create {
 	uint32_t	flags;
 };
 
+#define RADEON_TILING_MACRO 0x1
+#define RADEON_TILING_MICRO 0x2
+#define RADEON_TILING_SWAP  0x4
+#define RADEON_TILING_SURFACE  0x8 /* this object requires a surface
+				    * when mapped - i.e. front buffer */
+
+struct drm_radeon_gem_set_tiling {
+	uint32_t	handle;
+	uint32_t	tiling_flags;
+	uint32_t	pitch;
+};
+
+struct drm_radeon_gem_get_tiling {
+	uint32_t	handle;
+	uint32_t	tiling_flags;
+	uint32_t	pitch;
+};
+
 struct drm_radeon_gem_mmap {
 	uint32_t	handle;
 	uint32_t	pad;
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 25e3311..ec65722 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -403,6 +403,60 @@ void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align)
 
 }
 
+void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
+			     int depth, int usage_hint, int bitsPerPixel,
+			     int *new_pitch)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    struct radeon_exa_pixmap_priv *new_priv;
+    int padded_width;
+    uint32_t size;
+    uint32_t tiling = 0;
+    int pixmap_align = 0;
+    
+    if (usage_hint) {
+	if (info->allowColorTiling) {
+    	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO)
+ 	   	tiling |= RADEON_TILING_MACRO;
+    	    if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO)
+                tiling |= RADEON_TILING_MICRO;
+	}
+    }
+
+    if (tiling) {
+	height = (height + 15) & ~15;
+	pixmap_align = 255;
+    } else
+	pixmap_align = 63;
+
+    padded_width = ((width * bitsPerPixel + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
+    padded_width = (padded_width + pixmap_align) & ~pixmap_align;
+    size = height * padded_width;
+
+    new_priv = xcalloc(1, sizeof(struct radeon_exa_pixmap_priv));
+    if (!new_priv)
+	return NULL;
+
+    if (size == 0)
+	return new_priv;
+
+    *new_pitch = padded_width;
+
+    new_priv->bo = radeon_bo_open(info->bufmgr, 0, size,
+				  0, 0, 0);
+    if (!new_priv->bo) {
+	xfree(new_priv);
+	ErrorF("Failed to alloc memory\n");
+	return NULL;
+    }
+
+    if (tiling)
+	radeon_bo_set_tiling(new_priv->bo, tiling, *new_pitch);
+
+    return new_priv;
+}
+
 static void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
 {
     struct radeon_exa_pixmap_priv *driver_priv = driverPriv;
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 605e598..e48317f 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -786,6 +786,9 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen)
         info->accel_state->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen;
 	info->accel_state->exa->PrepareAccess = RADEONPrepareAccess_CS;
 	info->accel_state->exa->FinishAccess = RADEONFinishAccess_CS;
+#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 5)
+        info->accel_state->exa->CreatePixmap2 = RADEONEXACreatePixmap2;
+#endif
     }
 #endif
 #endif
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index d93a40b..0cabc53 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -386,6 +386,11 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
     if (info->IsSecondary)
 	zaphod_mask = 0x2;
 
+    info->allowColorTiling = xf86ReturnOptValBool(info->Options,
+                                        OPTION_COLOR_TILING, FALSE);
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	 "KMS Color Tiling: %sabled\n", info->allowColorTiling ? "en" : "dis");
+
     bus_id = DRICreatePCIBusID(info->PciInfo);
     if (drmmode_pre_init(pScrn, &info->drmmode, bus_id, "radeon", pScrn->bitsPerPixel / 8, zaphod_mask) == FALSE) {
 	xfree(bus_id);
@@ -860,6 +865,9 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
 	}
     }
 
+    if (info->allowColorTiling) {
+	radeon_bo_set_tiling(info->front_bo, RADEON_TILING_MACRO, stride);
+    }
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer size: %dK\n", info->front_bo->size/1024);
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Remaining VRAM size (used for pixmaps): %dK\n", remain_size_bytes/1024);
 
commit 479a6daefe46f985c415b0d000b1b1b820f3924e
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Aug 18 02:53:29 2009 -0400

    AVIVO: add support for DisplayPriority HIGH
    
    If the DisplayPriority option is set to HIGH,
    force the diplay mem requests to urgent.

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index e04b3c4..176efa6 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -807,7 +807,7 @@ RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn,
 	float consumption_time, consumption_rate;
 	int num_line_pair, request_fifo_depth, lb_request_fifo_depth;
 	int max_req;
-	uint32_t lb_max_req_outstanding;
+	uint32_t lb_max_req_outstanding, priority_cnt;
 	float line_time, active_time, chunk_time;
 	float worst_case_latency, tolerable_latency;
 	float fill_rate;
@@ -1131,16 +1131,21 @@ RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn,
 	else if (priority_mark > priority_mark_max)
 	    priority_mark = priority_mark_max;
 
+	priority_cnt = priority_mark & AVIVO_DxMODE_PRIORITY_MARK_MASK;
+
+	if (info->DispPriority == 2)
+	    priority_cnt |= AVIVO_DxMODE_PRIORITY_ALWAYS_ON;
+
 	/*ErrorF("priority_mark %d: 0x%x\n", i, priority_mark);*/
 
 	/* Determine which display to program priority mark for */
 	/* FIXME: program DxMODE_PRIORITY_B_CNT for slower sclk */
 	if (i == 0) {
-	    OUTREG(AVIVO_D1MODE_PRIORITY_A_CNT, (priority_mark & AVIVO_DxMODE_PRIORITY_MARK_MASK));
-	    OUTREG(AVIVO_D1MODE_PRIORITY_B_CNT, (priority_mark & AVIVO_DxMODE_PRIORITY_MARK_MASK));
+	    OUTREG(AVIVO_D1MODE_PRIORITY_A_CNT, priority_cnt);
+	    OUTREG(AVIVO_D1MODE_PRIORITY_B_CNT, priority_cnt);
 	} else {
-	    OUTREG(AVIVO_D2MODE_PRIORITY_A_CNT, (priority_mark & AVIVO_DxMODE_PRIORITY_MARK_MASK));
-	    OUTREG(AVIVO_D2MODE_PRIORITY_B_CNT, (priority_mark & AVIVO_DxMODE_PRIORITY_MARK_MASK));
+	    OUTREG(AVIVO_D2MODE_PRIORITY_A_CNT, priority_cnt);
+	    OUTREG(AVIVO_D2MODE_PRIORITY_B_CNT, priority_cnt);
 	}
     }
 
commit 8fd6f69c84103b277de70181988e843da23c85b0
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Aug 17 15:50:21 2009 +1000

    radeon: move detected monitor type debugging.
    
    We should print this after DAC detection to be useful for TV

diff --git a/src/radeon_output.c b/src/radeon_output.c
index f554824..30f6f3b 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -281,9 +281,6 @@ radeon_ddc_connected(xf86OutputPtr output)
     } else
 	MonType = MT_NONE;
 
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "Output: %s, Detected Monitor Type: %d\n", output->name, MonType);
-
     return MonType;
 }
 
@@ -1013,6 +1010,8 @@ radeon_detect(xf86OutputPtr output)
     }
 
 
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "Output: %s, Detected Monitor Type: %d\n", output->name, radeon_output->MonType);
     if (output->MonInfo) {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on output: %s ----------------------\n",
 		   output->name);
commit d25185f33d06a8162469e18688e95ee19a5d94d8
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Aug 17 15:31:16 2009 +1000

    atom: recall crtc source script after tv dpms on
    
    For some reason we lost the DACB source when we dpms tv back on.

diff --git a/src/atombios_output.c b/src/atombios_output.c
index 2f4338f..57345b3 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -65,6 +65,8 @@ const char *device_name[12] = {
     "DFP5",
 };
 
+static void atombios_set_output_crtc_source(xf86OutputPtr output);
+
 static int
 atombios_output_dac_setup(xf86OutputPtr output, int action)
 {
@@ -1280,6 +1282,9 @@ atombios_output_dpms(xf86OutputPtr output, int mode)
 		ErrorF("Output %s enable failed\n",
 		       device_name[radeon_get_device_index(radeon_output->active_device)]);
 	}
+	/* at least for TV atom fails to reassociate the correct crtc source at dpms on */
+	if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT))
+		atombios_set_output_crtc_source(output);
 	break;
     case DPMSModeStandby:
     case DPMSModeSuspend:
commit a971f1cfbbda1e3d16fb41f4a07f3b43fd59bc0d
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Aug 17 15:25:17 2009 +1000

    atombios: store dac detect result into save register.
    
    We end up writing back an empty save register over the dac
    detection results so the atombios table can no longer
    figure out the S-video vs composite so sets the wrong one up.
    
    this gets tv-out on my r580 with a composite connector working.

diff --git a/src/atombios_output.c b/src/atombios_output.c
index 33b1342..2f4338f 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -1609,7 +1609,7 @@ atombios_dac_detect(xf86OutputPtr output)
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
     RADEONMonitorType MonType = MT_NONE;
     AtomBiosResult ret;
-    uint32_t bios_0_scratch;
+    RADEONSavePtr save = info->ModeReg;
 
     if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) {
 	if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_TVOUT, FALSE)) {
@@ -1623,24 +1623,24 @@ atombios_dac_detect(xf86OutputPtr output)
     ret = atom_bios_dac_load_detect(info->atomBIOS, output);
     if (ret == ATOM_SUCCESS) {
 	if (info->ChipFamily >= CHIP_FAMILY_R600)
-	    bios_0_scratch = INREG(R600_BIOS_0_SCRATCH);
+	    save->bios_0_scratch = INREG(R600_BIOS_0_SCRATCH);
 	else
-	    bios_0_scratch = INREG(RADEON_BIOS_0_SCRATCH);
-	/*ErrorF("DAC connect %08X\n", (unsigned int)bios_0_scratch);*/
+	    save->bios_0_scratch = INREG(RADEON_BIOS_0_SCRATCH);
+	/*ErrorF("DAC connect %08X\n", (unsigned int)save->bios_0_scratch);*/
 
 	if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) {
-	    if (bios_0_scratch & ATOM_S0_CRT1_MASK)
+	    if (save->bios_0_scratch & ATOM_S0_CRT1_MASK)
 		MonType = MT_CRT;
 	} else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) {
-	    if (bios_0_scratch & ATOM_S0_CRT2_MASK)
+	    if (save->bios_0_scratch & ATOM_S0_CRT2_MASK)
 		MonType = MT_CRT;
 	} else if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) {
-	    if (bios_0_scratch & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A))
+	    if (save->bios_0_scratch & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A))
 		MonType = MT_CV;
 	} else if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) {
-	    if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
+	    if (save->bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
 		MonType = MT_CTV;
-	    else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
+	    else if (save->bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
 		MonType = MT_STV;
 	}
     }
commit efef7c01ad38e078de2fa3f9e528e4ef7d05d00a
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Aug 17 13:44:20 2009 +1000

    atom/tvout: set the correct scaler up for tv out
    
    If we need to use the second scaler actually set the second scaler
    up.

diff --git a/src/atombios_output.c b/src/atombios_output.c
index 00d17cb..33b1342 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -771,234 +771,238 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action)
 
 }
 
-static void atom_rv515_force_tv_scaler(ScrnInfoPtr pScrn)
+static void atom_rv515_force_tv_scaler(ScrnInfoPtr pScrn, RADEONCrtcPrivatePtr radeon_crtc)
 {
     RADEONInfoPtr info       = RADEONPTR(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
-
-    OUTREG(0x659C,0x0);
-    OUTREG(0x6594,0x705);
-    OUTREG(0x65A4,0x10001);
-    OUTREG(0x65D8,0x0);
-    OUTREG(0x65B0,0x0);
-    OUTREG(0x65C0,0x0);
-    OUTREG(0x65D4,0x0);
-    OUTREG(0x6578,0x0);
-    OUTREG(0x657C,0x841880A8);
-    OUTREG(0x6578,0x1);
-    OUTREG(0x657C,0x84208680);
-    OUTREG(0x6578,0x2);
-    OUTREG(0x657C,0xBFF880B0);
-    OUTREG(0x6578,0x100);
-    OUTREG(0x657C,0x83D88088);
-    OUTREG(0x6578,0x101);
-    OUTREG(0x657C,0x84608680);
-    OUTREG(0x6578,0x102);
-    OUTREG(0x657C,0xBFF080D0);
-    OUTREG(0x6578,0x200);
-    OUTREG(0x657C,0x83988068);
-    OUTREG(0x6578,0x201);
-    OUTREG(0x657C,0x84A08680);
-    OUTREG(0x6578,0x202);
-    OUTREG(0x657C,0xBFF080F8);
-    OUTREG(0x6578,0x300);
-    OUTREG(0x657C,0x83588058);
-    OUTREG(0x6578,0x301);
-    OUTREG(0x657C,0x84E08660);
-    OUTREG(0x6578,0x302);
-    OUTREG(0x657C,0xBFF88120);
-    OUTREG(0x6578,0x400);
-    OUTREG(0x657C,0x83188040);
-    OUTREG(0x6578,0x401);
-    OUTREG(0x657C,0x85008660);
-    OUTREG(0x6578,0x402);
-    OUTREG(0x657C,0xBFF88150);
-    OUTREG(0x6578,0x500);
-    OUTREG(0x657C,0x82D88030);
-    OUTREG(0x6578,0x501);
-    OUTREG(0x657C,0x85408640);
-    OUTREG(0x6578,0x502);
-    OUTREG(0x657C,0xBFF88180);
-    OUTREG(0x6578,0x600);
-    OUTREG(0x657C,0x82A08018);
-    OUTREG(0x6578,0x601);
-    OUTREG(0x657C,0x85808620);
-    OUTREG(0x6578,0x602);
-    OUTREG(0x657C,0xBFF081B8);
-    OUTREG(0x6578,0x700);
-    OUTREG(0x657C,0x82608010);
-    OUTREG(0x6578,0x701);
-    OUTREG(0x657C,0x85A08600);
-    OUTREG(0x6578,0x702);
-    OUTREG(0x657C,0x800081F0);
-    OUTREG(0x6578,0x800);
-    OUTREG(0x657C,0x8228BFF8);
-    OUTREG(0x6578,0x801);
-    OUTREG(0x657C,0x85E085E0);
-    OUTREG(0x6578,0x802);
-    OUTREG(0x657C,0xBFF88228);
-    OUTREG(0x6578,0x10000);
-    OUTREG(0x657C,0x82A8BF00);
-    OUTREG(0x6578,0x10001);
-    OUTREG(0x657C,0x82A08CC0);
-    OUTREG(0x6578,0x10002);
-    OUTREG(0x657C,0x8008BEF8);
-    OUTREG(0x6578,0x10100);
-    OUTREG(0x657C,0x81F0BF28);
-    OUTREG(0x6578,0x10101);
-    OUTREG(0x657C,0x83608CA0);
-    OUTREG(0x6578,0x10102);
-    OUTREG(0x657C,0x8018BED0);
-    OUTREG(0x6578,0x10200);
-    OUTREG(0x657C,0x8148BF38);
-    OUTREG(0x6578,0x10201);
-    OUTREG(0x657C,0x84408C80);
-    OUTREG(0x6578,0x10202);
-    OUTREG(0x657C,0x8008BEB8);
-    OUTREG(0x6578,0x10300);
-    OUTREG(0x657C,0x80B0BF78);
-    OUTREG(0x6578,0x10301);
-    OUTREG(0x657C,0x85008C20);
-    OUTREG(0x6578,0x10302);
-    OUTREG(0x657C,0x8020BEA0);
-    OUTREG(0x6578,0x10400);
-    OUTREG(0x657C,0x8028BF90);
-    OUTREG(0x6578,0x10401);
-    OUTREG(0x657C,0x85E08BC0);
-    OUTREG(0x6578,0x10402);
-    OUTREG(0x657C,0x8018BE90);
-    OUTREG(0x6578,0x10500);
-    OUTREG(0x657C,0xBFB8BFB0);
-    OUTREG(0x6578,0x10501);
-    OUTREG(0x657C,0x86C08B40);
-    OUTREG(0x6578,0x10502);
-    OUTREG(0x657C,0x8010BE90);
-    OUTREG(0x6578,0x10600);
-    OUTREG(0x657C,0xBF58BFC8);
-    OUTREG(0x6578,0x10601);
-    OUTREG(0x657C,0x87A08AA0);
-    OUTREG(0x6578,0x10602);
-    OUTREG(0x657C,0x8010BE98);
-    OUTREG(0x6578,0x10700);
-    OUTREG(0x657C,0xBF10BFF0);
-    OUTREG(0x6578,0x10701);
-    OUTREG(0x657C,0x886089E0);
-    OUTREG(0x6578,0x10702);
-    OUTREG(0x657C,0x8018BEB0);
-    OUTREG(0x6578,0x10800);
-    OUTREG(0x657C,0xBED8BFE8);
-    OUTREG(0x6578,0x10801);
-    OUTREG(0x657C,0x89408940);
-    OUTREG(0x6578,0x10802);
-    OUTREG(0x657C,0xBFE8BED8);
-    OUTREG(0x6578,0x20000);
-    OUTREG(0x657C,0x80008000);
-    OUTREG(0x6578,0x20001);
-    OUTREG(0x657C,0x90008000);
-    OUTREG(0x6578,0x20002);
-    OUTREG(0x657C,0x80008000);
-    OUTREG(0x6578,0x20003);
-    OUTREG(0x657C,0x80008000);
-    OUTREG(0x6578,0x20100);
-    OUTREG(0x657C,0x80108000);
-    OUTREG(0x6578,0x20101);
-    OUTREG(0x657C,0x8FE0BF70);
-    OUTREG(0x6578,0x20102);
-    OUTREG(0x657C,0xBFE880C0);
-    OUTREG(0x6578,0x20103);
-    OUTREG(0x657C,0x80008000);
-    OUTREG(0x6578,0x20200);
-    OUTREG(0x657C,0x8018BFF8);
-    OUTREG(0x6578,0x20201);
-    OUTREG(0x657C,0x8F80BF08);
-    OUTREG(0x6578,0x20202);
-    OUTREG(0x657C,0xBFD081A0);
-    OUTREG(0x6578,0x20203);
-    OUTREG(0x657C,0xBFF88000);
-    OUTREG(0x6578,0x20300);
-    OUTREG(0x657C,0x80188000);
-    OUTREG(0x6578,0x20301);
-    OUTREG(0x657C,0x8EE0BEC0);
-    OUTREG(0x6578,0x20302);
-    OUTREG(0x657C,0xBFB082A0);
-    OUTREG(0x6578,0x20303);
-    OUTREG(0x657C,0x80008000);
-    OUTREG(0x6578,0x20400);
-    OUTREG(0x657C,0x80188000);
-    OUTREG(0x6578,0x20401);
-    OUTREG(0x657C,0x8E00BEA0);
-    OUTREG(0x6578,0x20402);
-    OUTREG(0x657C,0xBF8883C0);
-    OUTREG(0x6578,0x20403);
-    OUTREG(0x657C,0x80008000);
-    OUTREG(0x6578,0x20500);
-    OUTREG(0x657C,0x80188000);
-    OUTREG(0x6578,0x20501);
-    OUTREG(0x657C,0x8D00BE90);
-    OUTREG(0x6578,0x20502);
-    OUTREG(0x657C,0xBF588500);
-    OUTREG(0x6578,0x20503);
-    OUTREG(0x657C,0x80008008);
-    OUTREG(0x6578,0x20600);
-    OUTREG(0x657C,0x80188000);
-    OUTREG(0x6578,0x20601);
-    OUTREG(0x657C,0x8BC0BE98);
-    OUTREG(0x6578,0x20602);
-    OUTREG(0x657C,0xBF308660);
-    OUTREG(0x6578,0x20603);
-    OUTREG(0x657C,0x80008008);
-    OUTREG(0x6578,0x20700);
-    OUTREG(0x657C,0x80108000);
-    OUTREG(0x6578,0x20701);
-    OUTREG(0x657C,0x8A80BEB0);
-    OUTREG(0x6578,0x20702);
-    OUTREG(0x657C,0xBF0087C0);
-    OUTREG(0x6578,0x20703);
-    OUTREG(0x657C,0x80008008);
-    OUTREG(0x6578,0x20800);
-    OUTREG(0x657C,0x80108000);
-    OUTREG(0x6578,0x20801);
-    OUTREG(0x657C,0x8920BED0);
-    OUTREG(0x6578,0x20802);
-    OUTREG(0x657C,0xBED08920);
-    OUTREG(0x6578,0x20803);
-    OUTREG(0x657C,0x80008010);
-    OUTREG(0x6578,0x30000);
-    OUTREG(0x657C,0x90008000);
-    OUTREG(0x6578,0x30001);
-    OUTREG(0x657C,0x80008000);
-    OUTREG(0x6578,0x30100);
-    OUTREG(0x657C,0x8FE0BF90);
-    OUTREG(0x6578,0x30101);
-    OUTREG(0x657C,0xBFF880A0);
-    OUTREG(0x6578,0x30200);
-    OUTREG(0x657C,0x8F60BF40);
-    OUTREG(0x6578,0x30201);
-    OUTREG(0x657C,0xBFE88180);
-    OUTREG(0x6578,0x30300);
-    OUTREG(0x657C,0x8EC0BF00);
-    OUTREG(0x6578,0x30301);
-    OUTREG(0x657C,0xBFC88280);
-    OUTREG(0x6578,0x30400);
-    OUTREG(0x657C,0x8DE0BEE0);
-    OUTREG(0x6578,0x30401);
-    OUTREG(0x657C,0xBFA083A0);
-    OUTREG(0x6578,0x30500);
-    OUTREG(0x657C,0x8CE0BED0);
-    OUTREG(0x6578,0x30501);
-    OUTREG(0x657C,0xBF7884E0);
-    OUTREG(0x6578,0x30600);
-    OUTREG(0x657C,0x8BA0BED8);
-    OUTREG(0x6578,0x30601);
-    OUTREG(0x657C,0xBF508640);
-    OUTREG(0x6578,0x30700);
-    OUTREG(0x657C,0x8A60BEE8);
-    OUTREG(0x6578,0x30701);
-    OUTREG(0x657C,0xBF2087A0);
-    OUTREG(0x6578,0x30800);
-    OUTREG(0x657C,0x8900BF00);
-    OUTREG(0x6578,0x30801);
-    OUTREG(0x657C,0xBF008900);
+    int index_reg = 0x6578, data_reg = 0x657c;
+
+    index_reg += radeon_crtc->crtc_offset;
+    data_reg += radeon_crtc->crtc_offset;
+
+    OUTREG(0x659C + radeon_crtc->crtc_offset, 0x0);
+    OUTREG(0x6594 + radeon_crtc->crtc_offset, 0x705);
+    OUTREG(0x65A4 + radeon_crtc->crtc_offset, 0x10001);
+    OUTREG(0x65D8 + radeon_crtc->crtc_offset, 0x0);
+    OUTREG(0x65B0 + radeon_crtc->crtc_offset, 0x0);
+    OUTREG(0x65C0 + radeon_crtc->crtc_offset, 0x0);
+    OUTREG(0x65D4 + radeon_crtc->crtc_offset, 0x0);
+    OUTREG(index_reg,0x0);
+    OUTREG(data_reg,0x841880A8);
+    OUTREG(index_reg,0x1);
+    OUTREG(data_reg,0x84208680);
+    OUTREG(index_reg,0x2);
+    OUTREG(data_reg,0xBFF880B0);
+    OUTREG(index_reg,0x100);
+    OUTREG(data_reg,0x83D88088);
+    OUTREG(index_reg,0x101);
+    OUTREG(data_reg,0x84608680);
+    OUTREG(index_reg,0x102);
+    OUTREG(data_reg,0xBFF080D0);
+    OUTREG(index_reg,0x200);
+    OUTREG(data_reg,0x83988068);
+    OUTREG(index_reg,0x201);
+    OUTREG(data_reg,0x84A08680);
+    OUTREG(index_reg,0x202);
+    OUTREG(data_reg,0xBFF080F8);
+    OUTREG(index_reg,0x300);
+    OUTREG(data_reg,0x83588058);
+    OUTREG(index_reg,0x301);
+    OUTREG(data_reg,0x84E08660);
+    OUTREG(index_reg,0x302);
+    OUTREG(data_reg,0xBFF88120);
+    OUTREG(index_reg,0x400);
+    OUTREG(data_reg,0x83188040);
+    OUTREG(index_reg,0x401);
+    OUTREG(data_reg,0x85008660);
+    OUTREG(index_reg,0x402);
+    OUTREG(data_reg,0xBFF88150);
+    OUTREG(index_reg,0x500);
+    OUTREG(data_reg,0x82D88030);
+    OUTREG(index_reg,0x501);
+    OUTREG(data_reg,0x85408640);
+    OUTREG(index_reg,0x502);
+    OUTREG(data_reg,0xBFF88180);
+    OUTREG(index_reg,0x600);
+    OUTREG(data_reg,0x82A08018);
+    OUTREG(index_reg,0x601);
+    OUTREG(data_reg,0x85808620);
+    OUTREG(index_reg,0x602);
+    OUTREG(data_reg,0xBFF081B8);
+    OUTREG(index_reg,0x700);
+    OUTREG(data_reg,0x82608010);
+    OUTREG(index_reg,0x701);
+    OUTREG(data_reg,0x85A08600);
+    OUTREG(index_reg,0x702);
+    OUTREG(data_reg,0x800081F0);
+    OUTREG(index_reg,0x800);
+    OUTREG(data_reg,0x8228BFF8);
+    OUTREG(index_reg,0x801);
+    OUTREG(data_reg,0x85E085E0);
+    OUTREG(index_reg,0x802);
+    OUTREG(data_reg,0xBFF88228);
+    OUTREG(index_reg,0x10000);
+    OUTREG(data_reg,0x82A8BF00);
+    OUTREG(index_reg,0x10001);
+    OUTREG(data_reg,0x82A08CC0);
+    OUTREG(index_reg,0x10002);
+    OUTREG(data_reg,0x8008BEF8);
+    OUTREG(index_reg,0x10100);
+    OUTREG(data_reg,0x81F0BF28);
+    OUTREG(index_reg,0x10101);
+    OUTREG(data_reg,0x83608CA0);
+    OUTREG(index_reg,0x10102);
+    OUTREG(data_reg,0x8018BED0);
+    OUTREG(index_reg,0x10200);
+    OUTREG(data_reg,0x8148BF38);
+    OUTREG(index_reg,0x10201);
+    OUTREG(data_reg,0x84408C80);
+    OUTREG(index_reg,0x10202);
+    OUTREG(data_reg,0x8008BEB8);
+    OUTREG(index_reg,0x10300);
+    OUTREG(data_reg,0x80B0BF78);
+    OUTREG(index_reg,0x10301);
+    OUTREG(data_reg,0x85008C20);
+    OUTREG(index_reg,0x10302);
+    OUTREG(data_reg,0x8020BEA0);
+    OUTREG(index_reg,0x10400);
+    OUTREG(data_reg,0x8028BF90);
+    OUTREG(index_reg,0x10401);
+    OUTREG(data_reg,0x85E08BC0);
+    OUTREG(index_reg,0x10402);
+    OUTREG(data_reg,0x8018BE90);
+    OUTREG(index_reg,0x10500);
+    OUTREG(data_reg,0xBFB8BFB0);
+    OUTREG(index_reg,0x10501);
+    OUTREG(data_reg,0x86C08B40);
+    OUTREG(index_reg,0x10502);
+    OUTREG(data_reg,0x8010BE90);
+    OUTREG(index_reg,0x10600);
+    OUTREG(data_reg,0xBF58BFC8);
+    OUTREG(index_reg,0x10601);
+    OUTREG(data_reg,0x87A08AA0);
+    OUTREG(index_reg,0x10602);
+    OUTREG(data_reg,0x8010BE98);
+    OUTREG(index_reg,0x10700);
+    OUTREG(data_reg,0xBF10BFF0);
+    OUTREG(index_reg,0x10701);
+    OUTREG(data_reg,0x886089E0);
+    OUTREG(index_reg,0x10702);
+    OUTREG(data_reg,0x8018BEB0);
+    OUTREG(index_reg,0x10800);
+    OUTREG(data_reg,0xBED8BFE8);
+    OUTREG(index_reg,0x10801);
+    OUTREG(data_reg,0x89408940);
+    OUTREG(index_reg,0x10802);
+    OUTREG(data_reg,0xBFE8BED8);
+    OUTREG(index_reg,0x20000);
+    OUTREG(data_reg,0x80008000);
+    OUTREG(index_reg,0x20001);
+    OUTREG(data_reg,0x90008000);
+    OUTREG(index_reg,0x20002);
+    OUTREG(data_reg,0x80008000);
+    OUTREG(index_reg,0x20003);
+    OUTREG(data_reg,0x80008000);
+    OUTREG(index_reg,0x20100);
+    OUTREG(data_reg,0x80108000);
+    OUTREG(index_reg,0x20101);
+    OUTREG(data_reg,0x8FE0BF70);
+    OUTREG(index_reg,0x20102);
+    OUTREG(data_reg,0xBFE880C0);
+    OUTREG(index_reg,0x20103);
+    OUTREG(data_reg,0x80008000);
+    OUTREG(index_reg,0x20200);
+    OUTREG(data_reg,0x8018BFF8);
+    OUTREG(index_reg,0x20201);
+    OUTREG(data_reg,0x8F80BF08);
+    OUTREG(index_reg,0x20202);
+    OUTREG(data_reg,0xBFD081A0);
+    OUTREG(index_reg,0x20203);
+    OUTREG(data_reg,0xBFF88000);
+    OUTREG(index_reg,0x20300);
+    OUTREG(data_reg,0x80188000);
+    OUTREG(index_reg,0x20301);
+    OUTREG(data_reg,0x8EE0BEC0);
+    OUTREG(index_reg,0x20302);
+    OUTREG(data_reg,0xBFB082A0);
+    OUTREG(index_reg,0x20303);
+    OUTREG(data_reg,0x80008000);
+    OUTREG(index_reg,0x20400);
+    OUTREG(data_reg,0x80188000);
+    OUTREG(index_reg,0x20401);
+    OUTREG(data_reg,0x8E00BEA0);
+    OUTREG(index_reg,0x20402);
+    OUTREG(data_reg,0xBF8883C0);
+    OUTREG(index_reg,0x20403);
+    OUTREG(data_reg,0x80008000);
+    OUTREG(index_reg,0x20500);
+    OUTREG(data_reg,0x80188000);
+    OUTREG(index_reg,0x20501);
+    OUTREG(data_reg,0x8D00BE90);
+    OUTREG(index_reg,0x20502);
+    OUTREG(data_reg,0xBF588500);
+    OUTREG(index_reg,0x20503);
+    OUTREG(data_reg,0x80008008);
+    OUTREG(index_reg,0x20600);
+    OUTREG(data_reg,0x80188000);
+    OUTREG(index_reg,0x20601);
+    OUTREG(data_reg,0x8BC0BE98);
+    OUTREG(index_reg,0x20602);
+    OUTREG(data_reg,0xBF308660);
+    OUTREG(index_reg,0x20603);
+    OUTREG(data_reg,0x80008008);
+    OUTREG(index_reg,0x20700);
+    OUTREG(data_reg,0x80108000);
+    OUTREG(index_reg,0x20701);
+    OUTREG(data_reg,0x8A80BEB0);
+    OUTREG(index_reg,0x20702);
+    OUTREG(data_reg,0xBF0087C0);
+    OUTREG(index_reg,0x20703);
+    OUTREG(data_reg,0x80008008);
+    OUTREG(index_reg,0x20800);
+    OUTREG(data_reg,0x80108000);
+    OUTREG(index_reg,0x20801);
+    OUTREG(data_reg,0x8920BED0);
+    OUTREG(index_reg,0x20802);
+    OUTREG(data_reg,0xBED08920);
+    OUTREG(index_reg,0x20803);
+    OUTREG(data_reg,0x80008010);
+    OUTREG(index_reg,0x30000);
+    OUTREG(data_reg,0x90008000);
+    OUTREG(index_reg,0x30001);
+    OUTREG(data_reg,0x80008000);
+    OUTREG(index_reg,0x30100);
+    OUTREG(data_reg,0x8FE0BF90);
+    OUTREG(index_reg,0x30101);
+    OUTREG(data_reg,0xBFF880A0);
+    OUTREG(index_reg,0x30200);
+    OUTREG(data_reg,0x8F60BF40);
+    OUTREG(index_reg,0x30201);
+    OUTREG(data_reg,0xBFE88180);
+    OUTREG(index_reg,0x30300);
+    OUTREG(data_reg,0x8EC0BF00);
+    OUTREG(index_reg,0x30301);
+    OUTREG(data_reg,0xBFC88280);
+    OUTREG(index_reg,0x30400);
+    OUTREG(data_reg,0x8DE0BEE0);
+    OUTREG(index_reg,0x30401);
+    OUTREG(data_reg,0xBFA083A0);
+    OUTREG(index_reg,0x30500);
+    OUTREG(data_reg,0x8CE0BED0);
+    OUTREG(index_reg,0x30501);
+    OUTREG(data_reg,0xBF7884E0);
+    OUTREG(index_reg,0x30600);
+    OUTREG(data_reg,0x8BA0BED8);
+    OUTREG(index_reg,0x30601);
+    OUTREG(data_reg,0xBF508640);
+    OUTREG(index_reg,0x30700);
+    OUTREG(data_reg,0x8A60BEE8);
+    OUTREG(index_reg,0x30701);
+    OUTREG(data_reg,0xBF2087A0);
+    OUTREG(index_reg,0x30800);
+    OUTREG(data_reg,0x8900BF00);
+    OUTREG(index_reg,0x30801);
+    OUTREG(data_reg,0xBF008900);
 }
 
 static int
@@ -1187,7 +1191,7 @@ atombios_output_scaler_setup(xf86OutputPtr output)
 	if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)
 	    && info->ChipFamily >= CHIP_FAMILY_RV515 && info->ChipFamily <= CHIP_FAMILY_RV570) {
 	    ErrorF("forcing TV scaler\n");
-	    atom_rv515_force_tv_scaler(output->scrn);
+	    atom_rv515_force_tv_scaler(output->scrn, radeon_crtc);
 	}
 	ErrorF("scaler %d setup success\n", radeon_crtc->crtc_id);
 	return ATOM_SUCCESS;
commit 032a8a06315d12e66240e7ef74b5b165f6d0d1a9
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Aug 17 12:18:23 2009 +1000

    kms: make tv out match the connector name

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 3f4ccfc..1b4985d 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -638,7 +638,7 @@ const char *output_names[] = { "None",
 			       "DVI",
 			       "DVI",
 			       "Composite",
-			       "TV",
+			       "S-video",
 			       "LVDS",
 			       "CTV",
 			       "DIN",
commit 36e51c4d63836863dd7a17cbf6e5a9b7c1bbd31a
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Aug 17 12:17:31 2009 +1000

    r100/r200: dont emit wrong clamp modes.
    
    for rect textures you don't want to use wrap clamping which
    is the default.

diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index c35ecba..4dbdc14 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -410,8 +410,7 @@ static Bool FUNC_NAME(R100TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 	RADEON_FALLBACK(("Bad filter 0x%x\n", pPict->filter));
     }
 
-    if (repeat) {
-	switch (pPict->repeatType) {
+    switch (pPict->repeatType) {
 	case RepeatNormal:
 	    txfilter |= RADEON_CLAMP_S_WRAP | RADEON_CLAMP_T_WRAP;
 	    break;
@@ -422,9 +421,10 @@ static Bool FUNC_NAME(R100TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 	    txfilter |= RADEON_CLAMP_S_MIRROR | RADEON_CLAMP_T_MIRROR;
 	    break;
 	case RepeatNone:
-	    /* Nothing to do */
+	    /* don't set an illegal clamp mode for rects */
+	    if (txformat & RADEON_TXFORMAT_NON_POWER2)
+		txfilter |= RADEON_CLAMP_S_CLAMP_LAST | RADEON_CLAMP_T_CLAMP_LAST;
 	    break;
-	}
     }
 
     BEGIN_ACCEL_RELOC(5, 1);
@@ -793,8 +793,7 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 	RADEON_FALLBACK(("Bad filter 0x%x\n", pPict->filter));
     }
 
-    if (repeat) {
-	switch (pPict->repeatType) {
+    switch (pPict->repeatType) {
 	case RepeatNormal:
 	    txfilter |= R200_CLAMP_S_WRAP | R200_CLAMP_T_WRAP;
 	    break;
@@ -805,9 +804,10 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 	    txfilter |= R200_CLAMP_S_MIRROR | R200_CLAMP_T_MIRROR;
 	    break;
 	case RepeatNone:
-	    /* Nothing to do */
+	    /* don't set an illegal clamp mode for rect textures */
+	    if (txformat & R200_TXFORMAT_NON_POWER2)
+		txfilter |= R200_CLAMP_S_CLAMP_LAST | R200_CLAMP_T_CLAMP_LAST;
 	    break;
-	}
     }
 
     BEGIN_ACCEL_RELOC(6, 1);
commit 595f7c3a60ca982ca2836a0174e1f36f9d1a4fec
Author: Dave Airlie <airlied at itt42.(none)>
Date:   Mon Aug 17 09:38:09 2009 +1000

    radeon/tv: fix typo in crtc register modifications

diff --git a/src/radeon_tv.c b/src/radeon_tv.c
index eef45d9..6c083ce 100644
--- a/src/radeon_tv.c
+++ b/src/radeon_tv.c
@@ -1198,7 +1198,7 @@ void RADEONAdjustCrtc2RegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save,
     save->crtc2_v_total_disp = ((constPtr->verResolution - 1) << RADEON_CRTC_V_DISP_SHIFT) |
 	((constPtr->verTotal - 1) << RADEON_CRTC_V_TOTAL_SHIFT);
 
-    save->crtc_v_sync_strt_wid = (save->crtc_v_sync_strt_wid & ~RADEON_CRTC_V_SYNC_STRT) |
+    save->crtc2_v_sync_strt_wid = (save->crtc2_v_sync_strt_wid & ~RADEON_CRTC_V_SYNC_STRT) |
 	((constPtr->verSyncStart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT);
 
 }
commit 92baeafde8f0c1eed2b6769e96f8093e3d6d7478
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Aug 11 15:29:17 2009 -0400

    RV280: add agp quirk
    
    from Hartmut Niemann

diff --git a/src/radeon_dri.c b/src/radeon_dri.c
index ed6ca9b..8a7ed83 100644
--- a/src/radeon_dri.c
+++ b/src/radeon_dri.c
@@ -777,6 +777,8 @@ static radeon_agpmode_quirk radeon_agpmode_quirk_list[] = {
 
     /* SiS Host Bridge 655 / R420 [Radeon X800] Needs AGPMode 4 (lp #371296) */
     { 0x1039,0x0655,            PCI_VENDOR_ATI,0x4a4b,  PCI_VENDOR_ATI,0x4422,   4 },
+    /* SiS Host Bridge / RV280 Needs AGPMode 4 */
+    { 0x1039,0x0741,            PCI_VENDOR_ATI,0x5964,  0x148c,0x2073,           4 },
 
     /* ASRock K7VT4A+ AGP 8x / ATI Radeon 9250 AGP Needs AGPMode 4 (lp #133192) */
     { 0x1849,0x3189,            PCI_VENDOR_ATI,0x5960,  0x1787,0x5960,           4 },
commit 04288fdb8b8c62fc2eb32fd467fdf05151ad121a
Author: Jerome Glisse <jglisse at redhat.com>
Date:   Tue Aug 11 19:32:52 2009 +0200

    radeon/r600: abstract vertex buffer for r600 & r700 hardware
    
    Abstract vertex buffer, preliminary work before others change
    to bring cs support along IB support.

diff --git a/src/r600_exa.c b/src/r600_exa.c
index d8c4de8..979bb73 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -126,6 +126,7 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 #endif
 
     accel_state->ib = RADEONCPGetBuffer(pScrn);
+    r600_vb_get(pScrn);
 
     /* Init */
     start_3d(pScrn, accel_state->ib);
@@ -253,8 +254,6 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     set_alu_consts(pScrn, accel_state->ib, SQ_ALU_CONSTANT_ps,
 		   sizeof(ps_alu_consts) / SQ_ALU_CONSTANT_offset, ps_alu_consts);
 
-    accel_state->vb_index = 0;
-
 #ifdef SHOW_VERTEXES
     ErrorF("PM: 0x%08x\n", pm);
 #endif
@@ -271,15 +270,13 @@ R600Solid(PixmapPtr pPix, int x1, int y1, int x2, int y2)
     struct radeon_accel_state *accel_state = info->accel_state;
     float *vb;
 
-    if (((accel_state->vb_index + 3) * 8) > (accel_state->ib->total / 2)) {
-	R600DoneSolid(pPix);
-	accel_state->vb_index = 0;
-	accel_state->ib = RADEONCPGetBuffer(pScrn);
+    if (((accel_state->vb_index + 3) * 8) > accel_state->vb_total) {
+        R600DoneSolid(pPix);
+        accel_state->ib = RADEONCPGetBuffer(pScrn);
+        r600_vb_get(pScrn);
     }
 
-    vb = (pointer)((char*)accel_state->ib->address +
-		   (accel_state->ib->total / 2) +
-		   accel_state->vb_index * 8);
+    vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*8);
 
     vb[0] = (float)x1;
     vb[1] = (float)y1;
@@ -307,12 +304,11 @@ R600DoneSolid(PixmapPtr pPix)
     CLEAR (vtx_res);
 
     if (accel_state->vb_index == 0) {
-	R600IBDiscard(pScrn, accel_state->ib);
-	return;
+        R600IBDiscard(pScrn, accel_state->ib);
+        r600_vb_discard(pScrn);
+        return;
     }
 
-    accel_state->vb_mc_addr = info->gartLocation + info->dri->bufStart +
-	(accel_state->ib->idx * accel_state->ib->total) + (accel_state->ib->total / 2);
     accel_state->vb_size = accel_state->vb_index * 8;
 
     /* flush vertex cache */
@@ -374,6 +370,7 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
     CLEAR (ps_conf);
 
     accel_state->ib = RADEONCPGetBuffer(pScrn);
+    r600_vb_get(pScrn);
 
     /* Init */
     start_3d(pScrn, accel_state->ib);
@@ -533,9 +530,6 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
 								(0x01 << DEFAULT_VAL_shift)	|
 								SEL_CENTROID_bit));
     EREG(accel_state->ib, SPI_INTERP_CONTROL_0,                0);
-
-    accel_state->vb_index = 0;
-
 }
 
 static void
@@ -550,12 +544,11 @@ R600DoCopy(ScrnInfoPtr pScrn)
     CLEAR (vtx_res);
 
     if (accel_state->vb_index == 0) {
-	R600IBDiscard(pScrn, accel_state->ib);
-	return;
+        R600IBDiscard(pScrn, accel_state->ib);
+        r600_vb_discard(pScrn);
+        return;
     }
 
-    accel_state->vb_mc_addr = info->gartLocation + info->dri->bufStart +
-	(accel_state->ib->idx * accel_state->ib->total) + (accel_state->ib->total / 2);
     accel_state->vb_size = accel_state->vb_index * 16;
 
     /* flush vertex cache */
@@ -605,15 +598,13 @@ R600AppendCopyVertex(ScrnInfoPtr pScrn,
     struct radeon_accel_state *accel_state = info->accel_state;
     float *vb;
 
-    if (((accel_state->vb_index + 3) * 16) > (accel_state->ib->total / 2)) {
-	R600DoCopy(pScrn);
-	accel_state->vb_index = 0;
-	accel_state->ib = RADEONCPGetBuffer(pScrn);
+    if (((accel_state->vb_index + 3) * 16) > accel_state->vb_total) {
+        R600DoCopy(pScrn);
+        accel_state->ib = RADEONCPGetBuffer(pScrn);
+        r600_vb_get(pScrn);
     }
 
-    vb = (pointer)((char*)accel_state->ib->address +
-		   (accel_state->ib->total / 2) +
-		   accel_state->vb_index * 16);
+    vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*16);
 
     vb[0] = (float)dstX;
     vb[1] = (float)dstY;
@@ -1442,6 +1433,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     CLEAR (ps_conf);
 
     accel_state->ib = RADEONCPGetBuffer(pScrn);
+    r600_vb_get(pScrn);
 
     /* Init */
     start_3d(pScrn, accel_state->ib);
@@ -1457,17 +1449,19 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     set_window_scissor(pScrn, accel_state->ib, 0, 0, pDst->drawable.width, pDst->drawable.height);
 
     if (!R600TextureSetup(pSrcPicture, pSrc, 0)) {
-	R600IBDiscard(pScrn, accel_state->ib);
-	return FALSE;
+        R600IBDiscard(pScrn, accel_state->ib);
+        r600_vb_discard(pScrn);
+        return FALSE;
     }
 
     if (pMask) {
-	if (!R600TextureSetup(pMaskPicture, pMask, 1)) {
-	    R600IBDiscard(pScrn, accel_state->ib);
-	    return FALSE;
-	}
+        if (!R600TextureSetup(pMaskPicture, pMask, 1)) {
+            R600IBDiscard(pScrn, accel_state->ib);
+            r600_vb_discard(pScrn);
+            return FALSE;
+        }
     } else
-	accel_state->is_transform[1] = FALSE;
+        accel_state->is_transform[1] = FALSE;
 
     if (pMask) {
 	set_bool_consts(pScrn, accel_state->ib, SQ_BOOL_CONST_vs, (1 << 0));
@@ -1583,8 +1577,6 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
 								SEL_CENTROID_bit));
     EREG(accel_state->ib, SPI_INTERP_CONTROL_0,                0);
 
-    accel_state->vb_index = 0;
-
     return TRUE;
 }
 
@@ -1615,15 +1607,13 @@ static void R600Composite(PixmapPtr pDst,
     if (accel_state->msk_pic) {
 	xPointFixed maskTopLeft, maskTopRight, maskBottomLeft, maskBottomRight;
 
-	if (((accel_state->vb_index + 3) * 24) > (accel_state->ib->total / 2)) {
-	    R600DoneComposite(pDst);
-	    accel_state->vb_index = 0;
-	    accel_state->ib = RADEONCPGetBuffer(pScrn);
-	}
+        if (((accel_state->vb_index + 3) * 24) > accel_state->vb_total) {
+            R600DoneComposite(pDst);
+            accel_state->ib = RADEONCPGetBuffer(pScrn);
+            r600_vb_get(pScrn);
+        }
 
-	vb = (pointer)((char*)accel_state->ib->address +
-		       (accel_state->ib->total / 2) +
-		       accel_state->vb_index * 24);
+        vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*24);
 
 	maskTopLeft.x     = IntToxFixed(maskX);
 	maskTopLeft.y     = IntToxFixed(maskY);
@@ -1656,15 +1646,13 @@ static void R600Composite(PixmapPtr pDst,
 	vb[17] = xFixedToFloat(maskBottomRight.y);
 
     } else {
-	if (((accel_state->vb_index + 3) * 16) > (accel_state->ib->total / 2)) {
-	    R600DoneComposite(pDst);
-	    accel_state->vb_index = 0;
-	    accel_state->ib = RADEONCPGetBuffer(pScrn);
-	}
+        if (((accel_state->vb_index + 3) * 16) > accel_state->vb_total) {
+            R600DoneComposite(pDst);
+            accel_state->ib = RADEONCPGetBuffer(pScrn);
+            r600_vb_get(pScrn);
+        }
 
-	vb = (pointer)((char*)accel_state->ib->address +
-		       (accel_state->ib->total / 2) +
-		       accel_state->vb_index * 16);
+        vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*16);
 
 	vb[0] = (float)dstX;
 	vb[1] = (float)dstY;
@@ -1698,14 +1686,11 @@ static void R600DoneComposite(PixmapPtr pDst)
     CLEAR (vtx_res);
 
     if (accel_state->vb_index == 0) {
-	R600IBDiscard(pScrn, accel_state->ib);
-	return;
+        R600IBDiscard(pScrn, accel_state->ib);
+        r600_vb_discard(pScrn);
+        return;
     }
 
-    accel_state->vb_mc_addr = info->gartLocation + info->dri->bufStart +
-	(accel_state->ib->idx * accel_state->ib->total) + (accel_state->ib->total / 2);
-
-
     /* Vertex buffer setup */
     if (accel_state->msk_pic) {
 	accel_state->vb_size = accel_state->vb_index * 24;
@@ -1817,6 +1802,7 @@ R600CopyToVRAM(ScrnInfoPtr pScrn,
     }
 
     R600IBDiscard(pScrn, scratch);
+    r600_vb_discard(pScrn);
 
     return TRUE;
 }
@@ -1902,6 +1888,7 @@ R600DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
     }
 
     R600IBDiscard(pScrn, scratch);
+    r600_vb_discard(pScrn);
 
     return TRUE;
 
diff --git a/src/r600_state.h b/src/r600_state.h
index 44e7600..8f20e42 100644
--- a/src/r600_state.h
+++ b/src/r600_state.h
@@ -279,4 +279,9 @@ draw_immd(ScrnInfoPtr pScrn, drmBufPtr ib, draw_config_t *draw_conf, uint32_t *i
 void
 draw_auto(ScrnInfoPtr pScrn, drmBufPtr ib, draw_config_t *draw_conf);
 
+void
+r600_vb_get(ScrnInfoPtr pScrn);
+void
+r600_vb_discard(ScrnInfoPtr pScrn);
+
 #endif
diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index 5e33191..5dc79c9 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -66,12 +66,11 @@ R600DoneTexturedVideo(ScrnInfoPtr pScrn)
     CLEAR (vtx_res);
 
     if (accel_state->vb_index == 0) {
-	R600IBDiscard(pScrn, accel_state->ib);
-	return;
+        R600IBDiscard(pScrn, accel_state->ib);
+        r600_vb_discard(pScrn);
+        return;
     }
 
-    accel_state->vb_mc_addr = info->gartLocation + info->dri->bufStart +
-	(accel_state->ib->idx * accel_state->ib->total) + (accel_state->ib->total / 2);
     accel_state->vb_size = accel_state->vb_index * 16;
 
     /* flush vertex cache */
@@ -235,6 +234,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 #endif
 
     accel_state->ib = RADEONCPGetBuffer(pScrn);
+    r600_vb_get(pScrn);
 
     /* Init */
     start_3d(pScrn, accel_state->ib);
@@ -552,22 +552,18 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	}
     }
 
-    accel_state->vb_index = 0;
-
     while (nBox--) {
 	int srcX, srcY, srcw, srch;
 	int dstX, dstY, dstw, dsth;
 	float *vb;
 
-	if (((accel_state->vb_index + 3) * 16) > (accel_state->ib->total / 2)) {
-	    R600DoneTexturedVideo(pScrn);
-	    accel_state->vb_index = 0;
-	    accel_state->ib = RADEONCPGetBuffer(pScrn);
-	}
+        if (((accel_state->vb_index + 3) * 16) > accel_state->vb_total) {
+            R600DoneTexturedVideo(pScrn);
+            accel_state->ib = RADEONCPGetBuffer(pScrn);
+            r600_vb_get(pScrn);
+        }
 
-	vb = (pointer)((char*)accel_state->ib->address +
-		       (accel_state->ib->total / 2) +
-		       accel_state->vb_index * 16);
+        vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*16);
 
 	dstX = pBox->x1 + dstxoff;
 	dstY = pBox->y1 + dstyoff;
diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index c47bdbb..0457f7d 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -979,3 +979,23 @@ draw_auto(ScrnInfoPtr pScrn, drmBufPtr ib, draw_config_t *draw_conf)
     E32(ib, draw_conf->num_indices);
     E32(ib, draw_conf->vgt_draw_initiator);
 }
+
+void
+r600_vb_get(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    struct radeon_accel_state *accel_state = info->accel_state;
+
+    accel_state->vb_mc_addr = info->gartLocation + info->dri->bufStart +
+                              (accel_state->ib->idx * accel_state->ib->total) +
+                              (accel_state->ib->total / 2);
+    accel_state->vb_total = (accel_state->ib->total / 2);
+    accel_state->vb_ptr = (pointer)((char*)accel_state->ib->address +
+                                           (accel_state->ib->total / 2));
+    accel_state->vb_index = 0;
+}
+
+void
+r600_vb_discard(ScrnInfoPtr pScrn)
+{
+}
diff --git a/src/radeon.h b/src/radeon.h
index d5402b2..6b47a6a 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -692,6 +692,10 @@ struct radeon_accel_state {
 
     drmBufPtr         ib;
     int               vb_index;
+    uint64_t          vb_mc_addr;
+    int               vb_total;
+    void              *vb_ptr;
+    uint32_t          vb_size;
 
     // shader storage
     ExaOffscreenArea  *shaders;
@@ -721,8 +725,6 @@ struct radeon_accel_state {
     uint64_t          vs_mc_addr;
     uint32_t          ps_size;
     uint64_t          ps_mc_addr;
-    uint32_t          vb_size;
-    uint64_t          vb_mc_addr;
 
     // UTS/DFS
     drmBufPtr         scratch;
commit 72daee2a18bfb809260d1bcbe80cc14afea3b0fa
Author: Adam Jackson <ajax at redhat.com>
Date:   Mon Aug 10 13:59:49 2009 -0400

    Fix misleading filenames in DRI setup failure messages

diff --git a/src/radeon_dri.c b/src/radeon_dri.c
index a359bc4..ed6ca9b 100644
--- a/src/radeon_dri.c
+++ b/src/radeon_dri.c
@@ -1389,7 +1389,7 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn)
     if (!xf86LoaderCheckSymbol("drmAvailable"))        return FALSE;
     if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		 "[dri] RADEONDRIGetVersion failed (libdri.a too old)\n"
+		 "[dri] RADEONDRIGetVersion failed (libdri too old)\n"
 		 "[dri] Disabling DRI.\n");
       return FALSE;
     }
@@ -1413,7 +1413,7 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn)
 	info->dri->pLibDRMVersion = drmGetLibVersion(info->dri->drmFD);
     if (info->dri->pLibDRMVersion == NULL) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "[dri] RADEONDRIGetVersion failed because libDRM is really "
+		   "[dri] RADEONDRIGetVersion failed because libdrm is really "
 		   "way to old to even get a version number out of it.\n"
 		   "[dri] Disabling DRI.\n");
 	return FALSE;
@@ -1424,7 +1424,7 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn)
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "[dri] RADEONDRIGetVersion failed because of a "
 		   "version mismatch.\n"
-		   "[dri] libdrm.a module version is %d.%d.%d but "
+		   "[dri] libdrm module version is %d.%d.%d but "
 		   "version 1.2.x is needed.\n"
 		   "[dri] Disabling DRI.\n",
 		   info->dri->pLibDRMVersion->version_major,
@@ -1488,7 +1488,7 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn)
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "[dri] RADEONDRIGetVersion failed because of a version "
 		   "mismatch.\n"
-		   "[dri] radeon.o kernel module version is %d.%d.%d "
+		   "[dri] radeon kernel module version is %d.%d.%d "
 		   "but version 1.%d.%d or newer is needed.\n"
 		   "[dri] Disabling DRI.\n",
 		   info->dri->pKernelDRMVersion->version_major,
commit cd99d9f0d715f1f74de4fe22f2fd30046f2c7568
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Fri Aug 7 11:56:50 2009 +0200

    Properly let radeon_cs_flush_indirect() re-emit 2D state if necessary.
    
    Also remove a superfluous assignment.

diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 599084f..605e598 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -222,7 +222,6 @@ FUNC_NAME(RADEONSolid)(PixmapPtr pPix, int x1, int y1, int x2, int y2)
     if (info->cs && CS_FULL(info->cs)) {
 	FUNC_NAME(RADEONDone2D)(info->accel_state->dst_pix);
 	radeon_cs_flush_indirect(pScrn);
-	FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_SOLID);
     }
 #endif
 
@@ -333,7 +332,6 @@ FUNC_NAME(RADEONCopy)(PixmapPtr pDst,
     if (info->cs && CS_FULL(info->cs)) {
 	FUNC_NAME(RADEONDone2D)(info->accel_state->dst_pix);
 	radeon_cs_flush_indirect(pScrn);
-	FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_COPY);
     }
 #endif
 
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 148386b..d93a40b 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -84,8 +84,8 @@ void radeon_cs_flush_indirect(ScrnInfoPtr pScrn)
     if (ret)
       ErrorF("space check failed in flush\n");
 
-    if (info->reemit_current2d)
-      info->reemit_current2d(pScrn, 0);
+    if (info->reemit_current2d && info->state_2d.op)
+      info->reemit_current2d(pScrn, info->state_2d.op);
     if (info->dri2.enabled) {
       info->accel_state->XInited3D = FALSE;
       info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
@@ -169,7 +169,6 @@ static void RADEONBlockHandler_KMS(int i, pointer blockData,
     if (info->VideoTimerCallback)
 	(*info->VideoTimerCallback)(pScrn, currentTime.milliseconds);
 
-    info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
     radeon_cs_flush_indirect(pScrn);
 }
 
commit 577ff3ce922e457cc32f80d4365cb1da81552e72
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Fri Aug 7 11:56:49 2009 +0200

    Add support for EXA_MIXED_PIXMAPS in xserver master.

diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 08da996..9c86244 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -98,6 +98,7 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
         if (attachments[i] == DRI2BufferDepth) {
             depth_pixmap = pixmap;
         }
+	exaMoveInPixmap(pixmap);
         driver_priv = exaGetPixmapDriverPrivate(pixmap);
 	r = radeon_gem_get_kernel_name(driver_priv->bo, &buffers[i].name);
 	if (r)
@@ -159,6 +160,7 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
     if (attachment == DRI2BufferDepth) {
         depth_pixmap = pixmap;
     }
+    exaMoveInPixmap(pixmap);
     driver_priv = exaGetPixmapDriverPrivate(pixmap);
     r = radeon_gem_get_kernel_name(driver_priv->bo, &buffers->name);
     if (r)
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index dc56c55..599084f 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -735,8 +735,12 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen)
     info->accel_state->exa->pixmapPitchAlign = 64;
 
 #ifdef EXA_HANDLES_PIXMAPS
-    if (info->cs)
+    if (info->cs) {
 	info->accel_state->exa->flags |= EXA_HANDLES_PIXMAPS;
+#ifdef EXA_MIXED_PIXMAPS
+	info->accel_state->exa->flags |= EXA_MIXED_PIXMAPS;
+#endif
+    }
 #endif
 
 #ifdef RENDER
commit e755fa56d03aa338d0c6345ed41e32aa3115ad4b
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Fri Aug 7 11:56:49 2009 +0200

    Minor fixes for KMS EXA DownloadFromScreen hook.
    
    Check we can handle the bpp, and remove superfluous flush.

diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 30d299f..dc56c55 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -522,11 +522,11 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
     uint32_t scratch_pitch = (w * bpp / 8 + 63) & ~63;
     Bool r;
 
+    if (bpp < 8)
+	return FALSE;
+
     driver_priv = exaGetPixmapDriverPrivate(pSrc);
-    /* if we have more refs than just the BO then flush */
-    if (driver_priv->bo->cref)
-        radeon_cs_flush_indirect(pScrn);
-    radeon_bo_wait(driver_priv->bo);
+
     size = scratch_pitch * h;
     scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0);
     if (scratch == NULL) {
commit 4cebafae81c1738a1c330d52a2c5248869f06411
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Fri Aug 7 11:56:40 2009 +0200

    Add KMS EXA UploadToScreen hook.
    
    Fixups by Michel Dänzer: Doesn't seem to be a win in terms of raw numbers, but
    should allow more pipelining and avoiding BO memory waste for small glyph
    pixmaps.

diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 145f13d..30d299f 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -447,7 +447,67 @@ RADEONBlitChunk(ScrnInfoPtr pScrn, struct radeon_bo *src_bo,
     FINISH_ACCEL();
 }
 
-#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
+#if defined(XF86DRM_MODE)
+static Bool
+RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h,
+		       char *src, int src_pitch)
+{
+    RINFO_FROM_SCREEN(pDst->drawable.pScreen);
+    struct radeon_exa_pixmap_priv *driver_priv;
+    struct radeon_bo *scratch;
+    unsigned size;
+    uint32_t datatype = 0;
+    uint32_t dst_pitch_offset;
+    unsigned bpp = pDst->drawable.bitsPerPixel;
+    uint32_t scratch_pitch = (w * bpp / 8 + 63) & ~63;
+    Bool r;
+    int i;
+
+    if (bpp < 8)
+	return FALSE;
+
+    driver_priv = exaGetPixmapDriverPrivate(pDst);
+
+    size = scratch_pitch * h;
+    scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0);
+    if (scratch == NULL) {
+	return FALSE;
+    }
+    radeon_cs_space_reset_bos(info->cs);
+    radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
+    radeon_cs_space_add_persistent_bo(info->cs, scratch, RADEON_GEM_DOMAIN_GTT, 0);
+    r = radeon_cs_space_check(info->cs);
+    if (r) {
+        r = FALSE;
+        goto out;
+    }
+
+    r = radeon_bo_map(scratch, 0);
+    if (r) {
+        r = FALSE;
+        goto out;
+    }
+    r = TRUE;
+    size = w * bpp / 8;
+    for (i = 0; i < h; i++) {
+        memcpy(scratch->ptr + i * scratch_pitch, src, size);
+        src += src_pitch;
+    }
+    radeon_bo_unmap(scratch);
+
+    RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype);
+    RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset);
+    ACCEL_PREAMBLE();
+    RADEON_SWITCH_TO_2D();
+    RADEONBlitChunk(pScrn, scratch, driver_priv->bo, datatype, scratch_pitch << 16,
+                    dst_pitch_offset, 0, 0, x, y, w, h,
+                    RADEON_GEM_DOMAIN_GTT, RADEON_GEM_DOMAIN_VRAM);
+
+out:
+    radeon_bo_unref(scratch);
+    return r;
+}
+
 static Bool
 RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
                            int h, char *dst, int dst_pitch)
@@ -460,7 +520,7 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
     uint32_t src_pitch_offset;
     unsigned bpp = pSrc->drawable.bitsPerPixel;
     uint32_t scratch_pitch = (w * bpp / 8 + 63) & ~63;
-    int r;
+    Bool r;
 
     driver_priv = exaGetPixmapDriverPrivate(pSrc);
     /* if we have more refs than just the BO then flush */
@@ -652,6 +712,7 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen)
     }
 # if defined(XF86DRM_MODE)
     else {
+	info->accel_state->exa->UploadToScreen = &RADEONUploadToScreenCS;
         info->accel_state->exa->DownloadFromScreen = &RADEONDownloadFromScreenCS;
     }
 # endif
commit 9243791322e36b9231e6a3f04024ad66325385e3
Author: Dave Airlie <airlied at redhat.com>
Date:   Fri Aug 7 14:07:32 2009 +1000

    r200: fixup scissors for DDX.
    
    a) turn of R200_RE_CNTL - SCISSOR_ENABLE - this save us emitting R200_RE_TOP_LEFT, note scissor is still enabled.
    b) disable aux scissors.

diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index 6f501a6..b6a6d8d 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -789,7 +789,9 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 	    R200_VAP_VF_MAX_VTX_NUM);
 	FINISH_ACCEL();
 
-	BEGIN_ACCEL(3);
+	BEGIN_ACCEL(5);
+	OUT_ACCEL_REG(R200_RE_AUX_SCISSOR_CNTL, 0);
+	OUT_ACCEL_REG(R200_RE_CNTL, 0);
 	OUT_ACCEL_REG(RADEON_AUX_SC_CNTL, 0);
 	OUT_ACCEL_REG(RADEON_RB3D_PLANEMASK, 0xffffffff);
 	OUT_ACCEL_REG(RADEON_SE_CNTL, (RADEON_DIFFUSE_SHADE_GOURAUD |
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 9cd70cd..c35ecba 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -968,7 +968,7 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
 	info->accel_state->is_transform[1] = FALSE;
     }
 
-    BEGIN_ACCEL_RELOC(13, 2);
+    BEGIN_ACCEL_RELOC(12, 2);
 
     OUT_ACCEL_REG(RADEON_PP_CNTL, pp_cntl);
     OUT_ACCEL_REG(RADEON_RB3D_CNTL, dst_format | RADEON_ALPHA_BLEND_ENABLE);
@@ -1031,7 +1031,6 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
     blendcntl = RADEONGetBlendCntl(op, pMaskPicture, pDstPicture->format);
     OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blendcntl);
 
-    OUT_ACCEL_REG(RADEON_RE_TOP_LEFT, 0);
     OUT_ACCEL_REG(RADEON_RE_WIDTH_HEIGHT, (((pDst->drawable.width) << RADEON_RE_WIDTH_SHIFT) |
 					   ((pDst->drawable.height) << RADEON_RE_HEIGHT_SHIFT)));
 
commit bd03977e320591ca55b1a2fbb32414c53cb3f72e
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Aug 4 15:21:44 2009 -0400

    radeon: fix compile with !kms

diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 5d2391f..145f13d 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -447,6 +447,7 @@ RADEONBlitChunk(ScrnInfoPtr pScrn, struct radeon_bo *src_bo,
     FINISH_ACCEL();
 }
 
+#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
 static Bool
 RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
                            int h, char *dst, int dst_pitch)
@@ -508,6 +509,7 @@ out:
     radeon_bo_unref(scratch);
     return r;
 }
+#endif
 
 static Bool
 RADEONDownloadFromScreenCP(PixmapPtr pSrc, int x, int y, int w, int h,
@@ -647,9 +649,12 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen)
 	info->accel_state->exa->UploadToScreen = RADEONUploadToScreenCP;
 	if (info->accelDFS)
 	    info->accel_state->exa->DownloadFromScreen = RADEONDownloadFromScreenCP;
-    } else {
+    }
+# if defined(XF86DRM_MODE)
+    else {
         info->accel_state->exa->DownloadFromScreen = &RADEONDownloadFromScreenCS;
     }
+# endif
 #endif
 
 #if X_BYTE_ORDER == X_BIG_ENDIAN
commit 4fc1e67e606daf9227e74518c54315b60cd38301
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Aug 4 15:17:39 2009 -0400

    radeon: re-add asus connector quirks
    
    fixes bug 19943

diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index bf3bfa0..b1cb559 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -1625,6 +1625,22 @@ static void RADEONApplyATOMQuirks(ScrnInfoPtr pScrn, int index)
 	}
     }
 
+    /* ASUS HD 3600 XT board lists the DVI port as HDMI */
+    if ((info->Chipset == PCI_CHIP_RV635_9598) &&
+	(PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) &&
+	(PCI_SUB_DEVICE_ID(info->PciInfo) == 0x01da)) {
+	if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A)
+	    info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_D;
+    }
+
+    /* ASUS HD 3450 board lists the DVI port as HDMI */
+    if ((info->Chipset == PCI_CHIP_RV620_95C5) &&
+	(PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) &&
+	(PCI_SUB_DEVICE_ID(info->PciInfo) == 0x01e2)) {
+	if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A)
+	    info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_D;
+    }
+
     /* some BIOSes seem to report DAC on HDMI - usually this is a board with
      * HDMI + VGA reporting as HDMI
      */
commit 22074cf0e58fddba743924532625e6fca49b6bdc
Author: Jerome Glisse <jglisse at redhat.com>
Date:   Tue Aug 4 21:09:25 2009 +0200

    radeon/kms: add simple DownloadFromScreen implementation
    
    What we want to do is add userspace object support to radeon
    kernel modesetting. Also this DFS is dumb and might endup doing
    blit from GTT to GTT.

diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 19adffb..5d2391f 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -402,14 +402,22 @@ RADEONUploadToScreenCP(PixmapPtr pDst, int x, int y, int w, int h,
 
 /* Emit blit with arbitrary source and destination offsets and pitches */
 static void
-RADEONBlitChunk(ScrnInfoPtr pScrn, uint32_t datatype, uint32_t src_pitch_offset,
-		uint32_t dst_pitch_offset, int srcX, int srcY, int dstX, int dstY,
-		int w, int h)
+RADEONBlitChunk(ScrnInfoPtr pScrn, struct radeon_bo *src_bo,
+                struct radeon_bo *dst_bo, uint32_t datatype,
+                uint32_t src_pitch_offset, uint32_t dst_pitch_offset,
+                int srcX, int srcY, int dstX, int dstY, int w, int h,
+                uint32_t src_domain, uint32_t dst_domain)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
     ACCEL_PREAMBLE();
 
-    BEGIN_ACCEL(6);
+    if (src_bo && dst_bo) {
+        BEGIN_ACCEL_RELOC(6, 2);
+    } else if (src_bo && dst_bo == NULL) {
+        BEGIN_ACCEL_RELOC(6, 1);
+    } else {
+        BEGIN_ACCEL(6);
+    }
     OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL,
 		  RADEON_GMC_DST_PITCH_OFFSET_CNTL |
 		  RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
@@ -421,7 +429,13 @@ RADEONBlitChunk(ScrnInfoPtr pScrn, uint32_t datatype, uint32_t src_pitch_offset,
 		  RADEON_GMC_CLR_CMP_CNTL_DIS |
 		  RADEON_GMC_WR_MSK_DIS);
     OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset);
+    if (src_bo) {
+	OUT_RELOC(src_bo, src_domain, 0);
+    }
     OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset);
+    if (dst_bo) {
+	OUT_RELOC(dst_bo, 0, dst_domain);
+    }
     OUT_ACCEL_REG(RADEON_SRC_Y_X, (srcY << 16) | srcX);
     OUT_ACCEL_REG(RADEON_DST_Y_X, (dstY << 16) | dstX);
     OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w);
@@ -433,6 +447,67 @@ RADEONBlitChunk(ScrnInfoPtr pScrn, uint32_t datatype, uint32_t src_pitch_offset,
     FINISH_ACCEL();
 }
 
+static Bool
+RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
+                           int h, char *dst, int dst_pitch)
+{
+    RINFO_FROM_SCREEN(pSrc->drawable.pScreen);
+    struct radeon_exa_pixmap_priv *driver_priv;
+    struct radeon_bo *scratch;
+    unsigned size;
+    uint32_t datatype = 0;
+    uint32_t src_pitch_offset;
+    unsigned bpp = pSrc->drawable.bitsPerPixel;
+    uint32_t scratch_pitch = (w * bpp / 8 + 63) & ~63;
+    int r;
+
+    driver_priv = exaGetPixmapDriverPrivate(pSrc);
+    /* if we have more refs than just the BO then flush */
+    if (driver_priv->bo->cref)
+        radeon_cs_flush_indirect(pScrn);
+    radeon_bo_wait(driver_priv->bo);
+    size = scratch_pitch * h;
+    scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0);
+    if (scratch == NULL) {
+	return FALSE;
+    }
+    radeon_cs_space_reset_bos(info->cs);
+    radeon_add_pixmap(info->cs, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+    radeon_cs_space_add_persistent_bo(info->cs, scratch, 0, RADEON_GEM_DOMAIN_GTT);
+    r = radeon_cs_space_check(info->cs);
+    if (r) {
+        r = FALSE;
+        goto out;
+    }
+    RADEONGetDatatypeBpp(pSrc->drawable.bitsPerPixel, &datatype);
+    RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset);
+    ACCEL_PREAMBLE();
+    RADEON_SWITCH_TO_2D();
+    RADEONBlitChunk(pScrn, driver_priv->bo, scratch, datatype, src_pitch_offset,
+                    scratch_pitch << 16, x, y, 0, 0, w, h,
+                    RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT,
+                    RADEON_GEM_DOMAIN_GTT);
+    FLUSH_RING();
+
+    radeon_bo_wait(scratch);
+    r = radeon_bo_map(scratch, 0);
+    if (r) {
+        r = FALSE;
+        goto out;
+    }
+    r = TRUE;
+    w *= bpp / 8;
+    size = 0;
+    while (h--) {
+        memcpy(dst, scratch->ptr + size, w);
+        size += scratch_pitch;
+        dst += dst_pitch;
+    }
+    radeon_bo_unmap(scratch);
+out:
+    radeon_bo_unref(scratch);
+    return r;
+}
 
 static Bool
 RADEONDownloadFromScreenCP(PixmapPtr pSrc, int x, int y, int w, int h,
@@ -466,8 +541,8 @@ RADEONDownloadFromScreenCP(PixmapPtr pSrc, int x, int y, int w, int h,
 	RADEON_SWITCH_TO_2D();
 
 	/* Kick the first blit as early as possible */
-	RADEONBlitChunk(pScrn, datatype, src_pitch_offset, scratch_pitch_offset,
-			x, y, 0, 0, w, hpass);
+	RADEONBlitChunk(pScrn, NULL, NULL, datatype, src_pitch_offset,
+                        scratch_pitch_offset, x, y, 0, 0, w, hpass, 0, 0);
 	FLUSH_RING();
 
 #if X_BYTE_ORDER == X_BIG_ENDIAN
@@ -493,8 +568,9 @@ RADEONDownloadFromScreenCP(PixmapPtr pSrc, int x, int y, int w, int h,
 	    /* Prepare next blit if anything's left */
 	    if (hpass) {
 		scratch_off = scratch->total/2 - scratch_off;
-		RADEONBlitChunk(pScrn, datatype, src_pitch_offset, scratch_pitch_offset + (scratch_off >> 10),
-				x, y, 0, 0, w, hpass);
+		RADEONBlitChunk(pScrn, NULL, NULL, datatype, src_pitch_offset,
+                                scratch_pitch_offset + (scratch_off >> 10),
+				x, y, 0, 0, w, hpass, 0, 0);
 	    }
 
 	    /*
@@ -571,6 +647,8 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen)
 	info->accel_state->exa->UploadToScreen = RADEONUploadToScreenCP;
 	if (info->accelDFS)
 	    info->accel_state->exa->DownloadFromScreen = RADEONDownloadFromScreenCP;
+    } else {
+        info->accel_state->exa->DownloadFromScreen = &RADEONDownloadFromScreenCS;
     }
 #endif
 
commit fce31b61a88522733863a9b4e9f1c935c439cb4e
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Aug 4 11:16:05 2009 -0400

    RS880: enable accel

diff --git a/src/pcidb/ati_pciids.csv b/src/pcidb/ati_pciids.csv
index e730228..695d9a6 100644
--- a/src/pcidb/ati_pciids.csv
+++ b/src/pcidb/ati_pciids.csv
@@ -449,8 +449,8 @@
 "0x9614","RS780_9614","RS780",,1,,,1,"ATI Radeon HD 3300 Graphics"
 "0x9615","RS780_9615","RS780",,1,,,1,"ATI Radeon HD 3200 Graphics"
 "0x9616","RS780_9616","RS780",,1,,,1,"ATI Radeon 3000 Graphics"
-"0x9710","RS880_9710","RS880",,1,,,1,"ATI Radeon HD Graphics"
-"0x9711","RS880_9711","RS880",,1,,,1,"ATI Radeon Graphics"
-"0x9712","RS880_9712","RS880",1,1,,,1,"ATI Mobility Radeon HD Graphics"
-"0x9713","RS880_9713","RS880",1,1,,,1,"ATI Mobility Radeon Graphics"
-"0x9714","RS880_9714","RS880",,1,,,1,"ATI Radeon Graphics"
+"0x9710","RS880_9710","RS880",,1,,,1,"ATI Radeon HD 4200"
+"0x9711","RS880_9711","RS880",,1,,,1,"ATI Radeon 4100"
+"0x9712","RS880_9712","RS880",1,1,,,1,"ATI Mobility Radeon HD 4200"
+"0x9713","RS880_9713","RS880",1,1,,,1,"ATI Mobility Radeon 4100"
+"0x9714","RS880_9714","RS880",,1,,,1,"ATI RS880"
diff --git a/src/r600_exa.c b/src/r600_exa.c
index 485322d..d8c4de8 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -319,6 +319,7 @@ R600DoneSolid(PixmapPtr pPix)
     if ((info->ChipFamily == CHIP_FAMILY_RV610) ||
 	(info->ChipFamily == CHIP_FAMILY_RV620) ||
 	(info->ChipFamily == CHIP_FAMILY_RS780) ||
+	(info->ChipFamily == CHIP_FAMILY_RS880) ||
 	(info->ChipFamily == CHIP_FAMILY_RV710))
 	cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit,
 			    accel_state->vb_size, accel_state->vb_mc_addr);
@@ -561,6 +562,7 @@ R600DoCopy(ScrnInfoPtr pScrn)
     if ((info->ChipFamily == CHIP_FAMILY_RV610) ||
 	(info->ChipFamily == CHIP_FAMILY_RV620) ||
 	(info->ChipFamily == CHIP_FAMILY_RS780) ||
+	(info->ChipFamily == CHIP_FAMILY_RS880) ||
 	(info->ChipFamily == CHIP_FAMILY_RV710))
 	cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit,
 			    accel_state->vb_size, accel_state->vb_mc_addr);
@@ -1724,6 +1726,7 @@ static void R600DoneComposite(PixmapPtr pDst)
     if ((info->ChipFamily == CHIP_FAMILY_RV610) ||
 	(info->ChipFamily == CHIP_FAMILY_RV620) ||
 	(info->ChipFamily == CHIP_FAMILY_RS780) ||
+	(info->ChipFamily == CHIP_FAMILY_RS880) ||
 	(info->ChipFamily == CHIP_FAMILY_RV710))
 	cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit,
 			    accel_state->vb_size, accel_state->vb_mc_addr);
diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index 2f0b6b1..5e33191 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -78,6 +78,7 @@ R600DoneTexturedVideo(ScrnInfoPtr pScrn)
     if ((info->ChipFamily == CHIP_FAMILY_RV610) ||
 	(info->ChipFamily == CHIP_FAMILY_RV620) ||
 	(info->ChipFamily == CHIP_FAMILY_RS780) ||
+	(info->ChipFamily == CHIP_FAMILY_RS880) ||
 	(info->ChipFamily == CHIP_FAMILY_RV710))
 	cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit,
 			    accel_state->vb_size, accel_state->vb_mc_addr);
diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index 6423e58..c47bdbb 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -128,6 +128,7 @@ sq_setup(ScrnInfoPtr pScrn, drmBufPtr ib, sq_config_t *sq_conf)
     if ((info->ChipFamily == CHIP_FAMILY_RV610) ||
 	(info->ChipFamily == CHIP_FAMILY_RV620) ||
 	(info->ChipFamily == CHIP_FAMILY_RS780) ||
+	(info->ChipFamily == CHIP_FAMILY_RS880) ||
 	(info->ChipFamily == CHIP_FAMILY_RV710))
 	sq_config = 0;						// no VC
     else
@@ -662,6 +663,7 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     case CHIP_FAMILY_RV610:
     case CHIP_FAMILY_RV620:
     case CHIP_FAMILY_RS780:
+    case CHIP_FAMILY_RS880:
     default:
 	sq_conf.num_ps_gprs = 84;
 	sq_conf.num_vs_gprs = 36;
diff --git a/src/radeon_chipset_gen.h b/src/radeon_chipset_gen.h
index 12dc322..fc41c3d 100644
--- a/src/radeon_chipset_gen.h
+++ b/src/radeon_chipset_gen.h
@@ -368,10 +368,10 @@ static SymTabRec RADEONChipsets[] = {
   { PCI_CHIP_RS780_9614, "ATI Radeon HD 3300 Graphics" },
   { PCI_CHIP_RS780_9615, "ATI Radeon HD 3200 Graphics" },
   { PCI_CHIP_RS780_9616, "ATI Radeon 3000 Graphics" },
-  { PCI_CHIP_RS880_9710, "ATI Radeon HD Graphics" },
-  { PCI_CHIP_RS880_9711, "ATI Radeon Graphics" },
-  { PCI_CHIP_RS880_9712, "ATI Mobility Radeon HD Graphics" },
-  { PCI_CHIP_RS880_9713, "ATI Mobility Radeon Graphics" },
-  { PCI_CHIP_RS880_9714, "ATI Radeon Graphics" },
+  { PCI_CHIP_RS880_9710, "ATI Radeon HD 4200" },
+  { PCI_CHIP_RS880_9711, "ATI Radeon 4100" },
+  { PCI_CHIP_RS880_9712, "ATI Mobility Radeon HD 4200" },
+  { PCI_CHIP_RS880_9713, "ATI Mobility Radeon 4100" },
+  { PCI_CHIP_RS880_9714, "ATI RS880" },
   { -1,                 NULL }
 };
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 29c0b11..e766093 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -2295,9 +2295,6 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn)
 	}
     }
 
-    if (info->ChipFamily == CHIP_FAMILY_RS880)
-	return FALSE;
-
     if (!xf86ReturnOptValBool(info->Options, OPTION_DRI, TRUE)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		"Direct rendering forced off\n");
commit 6b1b4b9214d58175727f7992fc42bc7244c42bf2
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Mon Aug 3 15:55:04 2009 -0400

    radeon: add some new r7xx pci ids

diff --git a/src/ati_pciids_gen.h b/src/ati_pciids_gen.h
index 92ae397..3f9691e 100644
--- a/src/ati_pciids_gen.h
+++ b/src/ati_pciids_gen.h
@@ -361,15 +361,19 @@
 #define PCI_CHIP_RV730_948F 0x948F
 #define PCI_CHIP_RV730_9490 0x9490
 #define PCI_CHIP_RV730_9491 0x9491
+#define PCI_CHIP_RV730_9495 0x9495
 #define PCI_CHIP_RV730_9498 0x9498
 #define PCI_CHIP_RV730_949C 0x949C
 #define PCI_CHIP_RV730_949E 0x949E
 #define PCI_CHIP_RV730_949F 0x949F
 #define PCI_CHIP_RV740_94A0 0x94A0
 #define PCI_CHIP_RV740_94A1 0x94A1
+#define PCI_CHIP_RV740_94A3 0x94A3
 #define PCI_CHIP_RV740_94B1 0x94B1
 #define PCI_CHIP_RV740_94B3 0x94B3
+#define PCI_CHIP_RV740_94B4 0x94B4
 #define PCI_CHIP_RV740_94B5 0x94B5
+#define PCI_CHIP_RV740_94B9 0x94B9
 #define PCI_CHIP_RV610_94C0 0x94C0
 #define PCI_CHIP_RV610_94C1 0x94C1
 #define PCI_CHIP_RV610_94C3 0x94C3
@@ -402,6 +406,7 @@
 #define PCI_CHIP_RV710_9552 0x9552
 #define PCI_CHIP_RV710_9553 0x9553
 #define PCI_CHIP_RV710_9555 0x9555
+#define PCI_CHIP_RV710_9557 0x9557
 #define PCI_CHIP_RV630_9580 0x9580
 #define PCI_CHIP_RV630_9581 0x9581
 #define PCI_CHIP_RV630_9583 0x9583
diff --git a/src/pcidb/ati_pciids.csv b/src/pcidb/ati_pciids.csv
index 5e78bda..e730228 100644
--- a/src/pcidb/ati_pciids.csv
+++ b/src/pcidb/ati_pciids.csv
@@ -362,15 +362,19 @@
 "0x948F","RV730_948F","RV730",,,,,,"ATI Radeon RV730 (AGP)"
 "0x9490","RV730_9490","RV730",,,,,,"ATI RV730XT [Radeon HD 4670]"
 "0x9491","RV730_9491","RV730",,,,,,"ATI RADEON E4600"
+"0x9495","RV730_9495","RV730",,,,,,"ATI Radeon HD 4600 Series"
 "0x9498","RV730_9498","RV730",,,,,,"ATI RV730 PRO [Radeon HD 4650]"
 "0x949C","RV730_949C","RV730",,,,,,"ATI FirePro V7750 (FireGL)"
 "0x949E","RV730_949E","RV730",,,,,,"ATI FirePro V5700 (FireGL)"
 "0x949F","RV730_949F","RV730",,,,,,"ATI FirePro V3750 (FireGL)"
 "0x94A0","RV740_94A0","RV740",1,,,,,"ATI Mobility Radeon HD 4830"
 "0x94A1","RV740_94A1","RV740",1,,,,,"ATI Mobility Radeon HD 4850"
+"0x94A3","RV740_94A3","RV740",1,,,,,"ATI FirePro M7740"
 "0x94B1","RV740_94B1","RV740",,,,,,"ATI RV740"
 "0x94B3","RV740_94B3","RV740",,,,,,"ATI Radeon HD 4770"
+"0x94B4","RV740_94B4","RV740",,,,,,"ATI Radeon HD 4700 Series"
 "0x94B5","RV740_94B5","RV740",,,,,,"ATI Radeon HD 4770"
+"0x94B9","RV740_94B9","RV740",1,,,,,"ATI FirePro M5750"
 "0x94C0","RV610_94C0","RV610",,,,,,"ATI RV610"
 "0x94C1","RV610_94C1","RV610",,,,,,"ATI Radeon HD 2400 XT"
 "0x94C3","RV610_94C3","RV610",,,,,,"ATI Radeon HD 2400 Pro"
@@ -403,6 +407,7 @@
 "0x9552","RV710_9552","RV710",1,,,,,"ATI Mobility Radeon 4300 Series"
 "0x9553","RV710_9553","RV710",1,,,,,"ATI Mobility Radeon 4500 Series"
 "0x9555","RV710_9555","RV710",1,,,,,"ATI Mobility Radeon 4500 Series"
+"0x9557","RV710_9557","RV710",1,,,,,"ATI FirePro RG220"
 "0x9580","RV630_9580","RV630",,,,,,"ATI RV630"
 "0x9581","RV630_9581","RV630",1,,,,,"ATI Mobility Radeon HD 2600"
 "0x9583","RV630_9583","RV630",1,,,,,"ATI Mobility Radeon HD 2600 XT"
diff --git a/src/radeon_chipinfo_gen.h b/src/radeon_chipinfo_gen.h
index 641361d..41144c7 100644
--- a/src/radeon_chipinfo_gen.h
+++ b/src/radeon_chipinfo_gen.h
@@ -281,15 +281,19 @@ static RADEONCardInfo RADEONCards[] = {
  { 0x948F, CHIP_FAMILY_RV730, 0, 0, 0, 0, 0 },
  { 0x9490, CHIP_FAMILY_RV730, 0, 0, 0, 0, 0 },
  { 0x9491, CHIP_FAMILY_RV730, 0, 0, 0, 0, 0 },
+ { 0x9495, CHIP_FAMILY_RV730, 0, 0, 0, 0, 0 },
  { 0x9498, CHIP_FAMILY_RV730, 0, 0, 0, 0, 0 },
  { 0x949C, CHIP_FAMILY_RV730, 0, 0, 0, 0, 0 },
  { 0x949E, CHIP_FAMILY_RV730, 0, 0, 0, 0, 0 },
  { 0x949F, CHIP_FAMILY_RV730, 0, 0, 0, 0, 0 },
  { 0x94A0, CHIP_FAMILY_RV740, 1, 0, 0, 0, 0 },
  { 0x94A1, CHIP_FAMILY_RV740, 1, 0, 0, 0, 0 },
+ { 0x94A3, CHIP_FAMILY_RV740, 1, 0, 0, 0, 0 },
  { 0x94B1, CHIP_FAMILY_RV740, 0, 0, 0, 0, 0 },
  { 0x94B3, CHIP_FAMILY_RV740, 0, 0, 0, 0, 0 },
+ { 0x94B4, CHIP_FAMILY_RV740, 0, 0, 0, 0, 0 },
  { 0x94B5, CHIP_FAMILY_RV740, 0, 0, 0, 0, 0 },
+ { 0x94B9, CHIP_FAMILY_RV740, 1, 0, 0, 0, 0 },
  { 0x94C0, CHIP_FAMILY_RV610, 0, 0, 0, 0, 0 },
  { 0x94C1, CHIP_FAMILY_RV610, 0, 0, 0, 0, 0 },
  { 0x94C3, CHIP_FAMILY_RV610, 0, 0, 0, 0, 0 },
@@ -322,6 +326,7 @@ static RADEONCardInfo RADEONCards[] = {
  { 0x9552, CHIP_FAMILY_RV710, 1, 0, 0, 0, 0 },
  { 0x9553, CHIP_FAMILY_RV710, 1, 0, 0, 0, 0 },
  { 0x9555, CHIP_FAMILY_RV710, 1, 0, 0, 0, 0 },
+ { 0x9557, CHIP_FAMILY_RV710, 1, 0, 0, 0, 0 },
  { 0x9580, CHIP_FAMILY_RV630, 0, 0, 0, 0, 0 },
  { 0x9581, CHIP_FAMILY_RV630, 1, 0, 0, 0, 0 },
  { 0x9583, CHIP_FAMILY_RV630, 1, 0, 0, 0, 0 },
diff --git a/src/radeon_chipset_gen.h b/src/radeon_chipset_gen.h
index 76966bf..12dc322 100644
--- a/src/radeon_chipset_gen.h
+++ b/src/radeon_chipset_gen.h
@@ -281,15 +281,19 @@ static SymTabRec RADEONChipsets[] = {
   { PCI_CHIP_RV730_948F, "ATI Radeon RV730 (AGP)" },
   { PCI_CHIP_RV730_9490, "ATI RV730XT [Radeon HD 4670]" },
   { PCI_CHIP_RV730_9491, "ATI RADEON E4600" },
+  { PCI_CHIP_RV730_9495, "ATI Radeon HD 4600 Series" },
   { PCI_CHIP_RV730_9498, "ATI RV730 PRO [Radeon HD 4650]" },
   { PCI_CHIP_RV730_949C, "ATI FirePro V7750 (FireGL)" },
   { PCI_CHIP_RV730_949E, "ATI FirePro V5700 (FireGL)" },
   { PCI_CHIP_RV730_949F, "ATI FirePro V3750 (FireGL)" },
   { PCI_CHIP_RV740_94A0, "ATI Mobility Radeon HD 4830" },
   { PCI_CHIP_RV740_94A1, "ATI Mobility Radeon HD 4850" },
+  { PCI_CHIP_RV740_94A3, "ATI FirePro M7740" },
   { PCI_CHIP_RV740_94B1, "ATI RV740" },
   { PCI_CHIP_RV740_94B3, "ATI Radeon HD 4770" },
+  { PCI_CHIP_RV740_94B4, "ATI Radeon HD 4700 Series" },
   { PCI_CHIP_RV740_94B5, "ATI Radeon HD 4770" },
+  { PCI_CHIP_RV740_94B9, "ATI FirePro M5750" },
   { PCI_CHIP_RV610_94C0, "ATI RV610" },
   { PCI_CHIP_RV610_94C1, "ATI Radeon HD 2400 XT" },
   { PCI_CHIP_RV610_94C3, "ATI Radeon HD 2400 Pro" },
@@ -322,6 +326,7 @@ static SymTabRec RADEONChipsets[] = {
   { PCI_CHIP_RV710_9552, "ATI Mobility Radeon 4300 Series" },
   { PCI_CHIP_RV710_9553, "ATI Mobility Radeon 4500 Series" },
   { PCI_CHIP_RV710_9555, "ATI Mobility Radeon 4500 Series" },
+  { PCI_CHIP_RV710_9557, "ATI FirePro RG220" },
   { PCI_CHIP_RV630_9580, "ATI RV630" },
   { PCI_CHIP_RV630_9581, "ATI Mobility Radeon HD 2600" },
   { PCI_CHIP_RV630_9583, "ATI Mobility Radeon HD 2600 XT" },
diff --git a/src/radeon_pci_chipset_gen.h b/src/radeon_pci_chipset_gen.h
index 4995b4b..1b85dcc 100644
--- a/src/radeon_pci_chipset_gen.h
+++ b/src/radeon_pci_chipset_gen.h
@@ -281,15 +281,19 @@ PciChipsets RADEONPciChipsets[] = {
  { PCI_CHIP_RV730_948F, PCI_CHIP_RV730_948F, RES_SHARED_VGA },
  { PCI_CHIP_RV730_9490, PCI_CHIP_RV730_9490, RES_SHARED_VGA },
  { PCI_CHIP_RV730_9491, PCI_CHIP_RV730_9491, RES_SHARED_VGA },
+ { PCI_CHIP_RV730_9495, PCI_CHIP_RV730_9495, RES_SHARED_VGA },
  { PCI_CHIP_RV730_9498, PCI_CHIP_RV730_9498, RES_SHARED_VGA },
  { PCI_CHIP_RV730_949C, PCI_CHIP_RV730_949C, RES_SHARED_VGA },
  { PCI_CHIP_RV730_949E, PCI_CHIP_RV730_949E, RES_SHARED_VGA },
  { PCI_CHIP_RV730_949F, PCI_CHIP_RV730_949F, RES_SHARED_VGA },
  { PCI_CHIP_RV740_94A0, PCI_CHIP_RV740_94A0, RES_SHARED_VGA },
  { PCI_CHIP_RV740_94A1, PCI_CHIP_RV740_94A1, RES_SHARED_VGA },
+ { PCI_CHIP_RV740_94A3, PCI_CHIP_RV740_94A3, RES_SHARED_VGA },
  { PCI_CHIP_RV740_94B1, PCI_CHIP_RV740_94B1, RES_SHARED_VGA },
  { PCI_CHIP_RV740_94B3, PCI_CHIP_RV740_94B3, RES_SHARED_VGA },
+ { PCI_CHIP_RV740_94B4, PCI_CHIP_RV740_94B4, RES_SHARED_VGA },
  { PCI_CHIP_RV740_94B5, PCI_CHIP_RV740_94B5, RES_SHARED_VGA },
+ { PCI_CHIP_RV740_94B9, PCI_CHIP_RV740_94B9, RES_SHARED_VGA },
  { PCI_CHIP_RV610_94C0, PCI_CHIP_RV610_94C0, RES_SHARED_VGA },
  { PCI_CHIP_RV610_94C1, PCI_CHIP_RV610_94C1, RES_SHARED_VGA },
  { PCI_CHIP_RV610_94C3, PCI_CHIP_RV610_94C3, RES_SHARED_VGA },
@@ -322,6 +326,7 @@ PciChipsets RADEONPciChipsets[] = {
  { PCI_CHIP_RV710_9552, PCI_CHIP_RV710_9552, RES_SHARED_VGA },
  { PCI_CHIP_RV710_9553, PCI_CHIP_RV710_9553, RES_SHARED_VGA },
  { PCI_CHIP_RV710_9555, PCI_CHIP_RV710_9555, RES_SHARED_VGA },
+ { PCI_CHIP_RV710_9557, PCI_CHIP_RV710_9557, RES_SHARED_VGA },
  { PCI_CHIP_RV630_9580, PCI_CHIP_RV630_9580, RES_SHARED_VGA },
  { PCI_CHIP_RV630_9581, PCI_CHIP_RV630_9581, RES_SHARED_VGA },
  { PCI_CHIP_RV630_9583, PCI_CHIP_RV630_9583, RES_SHARED_VGA },
diff --git a/src/radeon_pci_device_match_gen.h b/src/radeon_pci_device_match_gen.h
index b087239..64127bd 100644
--- a/src/radeon_pci_device_match_gen.h
+++ b/src/radeon_pci_device_match_gen.h
@@ -281,15 +281,19 @@ static const struct pci_id_match radeon_device_match[] = {
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_948F, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_9490, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_9491, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV730_9495, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_9498, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_949C, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_949E, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_949F, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV740_94A0, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV740_94A1, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV740_94A3, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV740_94B1, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV740_94B3, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV740_94B4, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV740_94B5, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV740_94B9, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV610_94C0, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV610_94C1, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV610_94C3, 0 ),
@@ -322,6 +326,7 @@ static const struct pci_id_match radeon_device_match[] = {
  ATI_DEVICE_MATCH( PCI_CHIP_RV710_9552, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV710_9553, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV710_9555, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV710_9557, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV630_9580, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV630_9581, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV630_9583, 0 ),
commit f564460e94c9d0f1cf3ff4b8535481b2b8b4e9c1
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Sat Aug 1 16:53:47 2009 -0400

    radeon: use XAA in some cases
    
    Use XAA in low memory situations or when the DRI is disabled.
    Using shadowfb might also be a viable option, maybe even a better option...
    fixes bug 21683

diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 3f79917..29c0b11 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -2083,6 +2083,7 @@ static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn)
 #if defined(USE_EXA) && defined(USE_XAA)
     char *optstr;
 #endif
+    int maxy = info->FbMapSize / (pScrn->displayWidth * info->CurrentLayout.pixel_bytes);
 
     if (!(info->accel_state = xcalloc(1, sizeof(struct radeon_accel_state)))) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to allocate accel_state rec!\n");
@@ -2109,7 +2110,16 @@ static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn)
 	return TRUE;
     }
 
-    info->useEXA = TRUE;
+#ifdef XF86DRI
+    if ((!info->directRenderingEnabled) ||
+	(maxy <= pScrn->virtualY * 3) ||
+	(pScrn->videoRam <= 32768))
+	info->useEXA = FALSE;
+    else
+	info->useEXA = TRUE;
+#else
+	info->useEXA = FALSE;
+#endif
 
     if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
 	int errmaj = 0, errmin = 0;
@@ -2119,9 +2129,10 @@ static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn)
 #if defined(USE_XAA)
 	optstr = (char *)xf86GetOptValString(info->Options, OPTION_ACCELMETHOD);
 	if (optstr != NULL) {
-	    if (xf86NameCmp(optstr, "EXA") == 0)
+	    if (xf86NameCmp(optstr, "EXA") == 0) {
 		from = X_CONFIG;
-	    else if (xf86NameCmp(optstr, "XAA") == 0) {
+		info->useEXA = TRUE;
+	    } else if (xf86NameCmp(optstr, "XAA") == 0) {
 		from = X_CONFIG;
 		if (info->ChipFamily < CHIP_FAMILY_R600)
 		    info->useEXA = FALSE;
commit c71b2f050e8996787eae463eddbfdb5864ffa65a
Author: Bryce Harrington <bryce at canonical.com>
Date:   Sat Aug 1 16:50:43 2009 -0400

    radeon: AGPMode quirk needed for SiS
    
    fixes bug 23065

diff --git a/src/radeon_dri.c b/src/radeon_dri.c
index a98e2ab..a359bc4 100644
--- a/src/radeon_dri.c
+++ b/src/radeon_dri.c
@@ -775,6 +775,9 @@ static radeon_agpmode_quirk radeon_agpmode_quirk_list[] = {
     /* Ali Corp M1671 Super P4 Northbridge / Mobility M6 LY Needs AGPMode 1 (lp #146303)*/
     { 0x10b9,0x1671,           PCI_VENDOR_ATI,0x4c59,   0x103c,0x0027,           1 },
 
+    /* SiS Host Bridge 655 / R420 [Radeon X800] Needs AGPMode 4 (lp #371296) */
+    { 0x1039,0x0655,            PCI_VENDOR_ATI,0x4a4b,  PCI_VENDOR_ATI,0x4422,   4 },
+
     /* ASRock K7VT4A+ AGP 8x / ATI Radeon 9250 AGP Needs AGPMode 4 (lp #133192) */
     { 0x1849,0x3189,            PCI_VENDOR_ATI,0x5960,  0x1787,0x5960,           4 },
 
commit e3659ed06fc5bb8817f1dbd7c2d6bc94c67b30f7
Author: Bryce Harrington <bryce at canonical.com>
Date:   Sat Aug 1 16:48:48 2009 -0400

    radeon: AGPMode quirk needed for IBM Thinkpad T40 with Mobility M7 LW
    
    fixes bug 23064

diff --git a/src/radeon_dri.c b/src/radeon_dri.c
index 5feb27b..a98e2ab 100644
--- a/src/radeon_dri.c
+++ b/src/radeon_dri.c
@@ -745,6 +745,8 @@ static radeon_agpmode_quirk radeon_agpmode_quirk_list[] = {
     { PCI_VENDOR_INTEL,0x2570,  PCI_VENDOR_ATI,0x4a4e,  PCI_VENDOR_DELL,0x5106,  4 },
     /* Intel 82865G/PE/P DRAM Controller/Host-Hub / RV280 [Radeon 9200 SE] Needs AGPMode 4 (lp #300304) */
     { PCI_VENDOR_INTEL,0x2570,  PCI_VENDOR_ATI,0x5964,  0x148c,0x2073,           4 },
+    /* Intel 82855PM host bridge / Mobility M7 LW Needs AGPMode 4 (lp: #353996) */
+    { PCI_VENDOR_INTEL,0x3340,  PCI_VENDOR_ATI,0x4c57, PCI_VENDOR_IBM,0x0530,    4 },
     /* Intel 82855PM Processor to I/O Controller / Mobility M6 LY Needs AGPMode 1 (deb #467235) */
     { PCI_VENDOR_INTEL,0x3340,  PCI_VENDOR_ATI,0x4c59,  PCI_VENDOR_IBM,0x052f,   1 },
     /* Intel 82855PM host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (lp #195051) */
commit 2391531ed6b7c11ddd5ab91b2369821cc5f8b8a7
Author: Bryce Harrington <bryce at canonical.com>
Date:   Sat Aug 1 16:41:41 2009 -0400

    radeon: AGPMode quirk needed for HP Omnibook 6200
    
    fixed bug 23063

diff --git a/src/radeon_dri.c b/src/radeon_dri.c
index 77a3ff7..5feb27b 100644
--- a/src/radeon_dri.c
+++ b/src/radeon_dri.c
@@ -770,6 +770,9 @@ static radeon_agpmode_quirk radeon_agpmode_quirk_list[] = {
     /* Intel 82443BX/ZX/DX Host bridge / RV280 [Radeon 9200] Needs AGPMode 1 (lp #370205) */
     { PCI_VENDOR_INTEL,0x7190,  PCI_VENDOR_ATI,0x5961,  0x174b,0x7c13,           1 },
 
+    /* Ali Corp M1671 Super P4 Northbridge / Mobility M6 LY Needs AGPMode 1 (lp #146303)*/
+    { 0x10b9,0x1671,           PCI_VENDOR_ATI,0x4c59,   0x103c,0x0027,           1 },
+
     /* ASRock K7VT4A+ AGP 8x / ATI Radeon 9250 AGP Needs AGPMode 4 (lp #133192) */
     { 0x1849,0x3189,            PCI_VENDOR_ATI,0x5960,  0x1787,0x5960,           4 },
 
commit 474eda02257152ced52364f38cbad24c20aebbc0
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Sat Aug 1 16:06:52 2009 -0400

    radeon: reload bicubic Xv texture on VT switch
    
    fixed bicubic filtering after VT switch or suspend/resume

diff --git a/src/radeon.h b/src/radeon.h
index 3c62fd9..d5402b2 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -1264,6 +1264,7 @@ extern void RADEONUpdateHVPosition(xf86OutputPtr output, DisplayModePtr mode);
 /* radeon_video.c */
 extern void RADEONInitVideo(ScreenPtr pScreen);
 extern void RADEONResetVideo(ScrnInfoPtr pScrn);
+extern Bool radeon_load_bicubic_texture(ScrnInfoPtr pScrn);
 
 /* radeon_legacy_memory.c */
 extern uint32_t
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 049047a..3f79917 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -5700,6 +5700,8 @@ Bool RADEONEnterVT(int scrnIndex, int flags)
 	DRIUnlock(pScrn->pScreen);
     }
 #endif
+    if (IS_R500_3D || IS_R300_3D)
+	radeon_load_bicubic_texture(pScrn);
 
     return TRUE;
 }
diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c
index 0f89b49..a9d6fc3 100644
--- a/src/radeon_textured_video.c
+++ b/src/radeon_textured_video.c
@@ -671,7 +671,7 @@ RADEONSetTexPortAttribute(ScrnInfoPtr  pScrn,
     return Success;
 }
 
-static Bool radeon_load_bicubic_texture(ScrnInfoPtr pScrn)
+Bool radeon_load_bicubic_texture(ScrnInfoPtr pScrn)
 {
     RADEONInfoPtr    info = RADEONPTR(pScrn);
 
@@ -706,6 +706,7 @@ static Bool radeon_load_bicubic_texture(ScrnInfoPtr pScrn)
     return TRUE;
 }
 
+#if 0
 /* XXX */
 static void radeon_unload_bicubic_texture(ScrnInfoPtr pScrn)
 {
@@ -717,6 +718,7 @@ static void radeon_unload_bicubic_texture(ScrnInfoPtr pScrn)
     }
 
 }
+#endif
 
 XF86VideoAdaptorPtr
 RADEONSetupImageTexturedVideo(ScreenPtr pScreen)
commit 447a2ce1b88aa2d6d5713e93174c4002617720f7
Author: Dave Airlie <airlied at redhat.com>
Date:   Thu Jul 30 09:54:01 2009 +1000

    radeon: fix r600 shadow fb mode with cursor allocation in wrong place
    
    From RHEL QE testing, we could end up with the cursor at 0 since
    we think EXA is in use when really it isn't. the info->useEXA = FALSe
    might be unnecessary but better to be explicit
    
    Signed-off-by: Dave Airlie <airlied at redhat.com>

diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 979b1ad..049047a 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -2103,6 +2103,12 @@ static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn)
 	info->accel_state->has_tcl = TRUE;
     }
 
+    /* if we have shadow fb bail */
+    if (info->r600_shadow_fb) {
+	info->useEXA = FALSE;
+	return TRUE;
+    }
+
     info->useEXA = TRUE;
 
     if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
commit 2b9a5be3bb22fad1d52ec9eea7733c5e956250b7
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Jul 29 03:34:11 2009 -0400

    radeon: fix typo in object header to connector type conversion
    
    Should fix bug 19943

diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index f590d5b..bf3bfa0 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -1436,11 +1436,11 @@ const int object_connector_convert[] =
       CONNECTOR_CTV,
       CONNECTOR_STV,
       CONNECTOR_NONE,
+      CONNECTOR_NONE,
       CONNECTOR_DIN,
       CONNECTOR_SCART,
       CONNECTOR_HDMI_TYPE_A,
       CONNECTOR_HDMI_TYPE_B,
-      CONNECTOR_HDMI_TYPE_B,
       CONNECTOR_LVDS,
       CONNECTOR_DIN,
       CONNECTOR_NONE,
commit 63c873cbd4d1d21d9f688028c0900c79fadc42c1
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Jul 28 15:22:40 2009 +1000

    ati: change to using ABI version check

diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 46c6451..979b1ad 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -93,7 +93,7 @@
 #include "xf86.h"
 #include "xf86_OSproc.h"
 #include "xf86RandR12.h"
-#ifndef XSERVER_LIBPCIACCESS
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
 #include "xf86RAC.h"
 #include "xf86Resources.h"
 #endif
diff --git a/src/radeon_probe.c b/src/radeon_probe.c
index d9f92fa..42e7259 100644
--- a/src/radeon_probe.c
+++ b/src/radeon_probe.c
@@ -45,7 +45,7 @@
 #include "atipcirename.h"
 
 #include "xf86.h"
-#ifndef XSERVER_LIBPCIACCESS
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
 #include "xf86Resources.h"
 #endif
 
commit 21a621c297ac71c65c239ea960c38706e718b91c
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Jul 28 13:32:28 2009 +1000

    ati: update for resources/RAC API removal

diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index bf95029..46c6451 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -92,9 +92,11 @@
 				/* X and server generic header files */
 #include "xf86.h"
 #include "xf86_OSproc.h"
-#include "xf86RAC.h"
 #include "xf86RandR12.h"
+#ifndef XSERVER_LIBPCIACCESS
+#include "xf86RAC.h"
 #include "xf86Resources.h"
+#endif
 #include "xf86cmap.h"
 #include "vbe.h"
 
@@ -2923,12 +2925,14 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
 	       PCI_DEV_DEV(info->PciInfo),
 	       PCI_DEV_FUNC(info->PciInfo));
 
+#ifndef XSERVER_LIBPCIACCESS
     if (xf86RegisterResources(info->pEnt->index, 0, ResExclusive))
 	goto fail;
 
     xf86SetOperatingState(resVga, info->pEnt->index, ResUnusedOpr);
 
     pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
+#endif
     pScrn->monitor     = pScrn->confScreen->monitor;
 
    /* Allocate an xf86CrtcConfig */
diff --git a/src/radeon_probe.c b/src/radeon_probe.c
index 78dee85..d9f92fa 100644
--- a/src/radeon_probe.c
+++ b/src/radeon_probe.c
@@ -45,7 +45,9 @@
 #include "atipcirename.h"
 
 #include "xf86.h"
+#ifndef XSERVER_LIBPCIACCESS
 #include "xf86Resources.h"
+#endif
 
 #ifdef XF86DRM_MODE
 #include "xf86drmMode.h"
@@ -56,6 +58,7 @@
 
 #include "radeon_pci_chipset_gen.h"
 
+
 #ifdef XSERVER_LIBPCIACCESS
 #include "radeon_pci_device_match_gen.h"
 #endif
commit 5ad2519c2a7c0df389b2cd7cf7151c7e4b7252a8
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Mon Jul 27 14:22:02 2009 +0200

    KMS: Explicitly specify VRAM and GTT domains when allocating BOs for pixmaps.
    
    Without this, apparently they are initially allocated in system RAM (or
    possibly GTT), so any GPU rendering to them first triggers a copy of the whole
    uninitialized data to VRAM...
    
    We may want to explore more sophisticated schemes in the future, but for now
    this seems to improve KMS 2D performance quite a bit.

diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 4f1f9ea..25e3311 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -391,7 +391,8 @@ void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align)
 	return new_priv;
 
     new_priv->bo = radeon_bo_open(info->bufmgr, 0, size,
-				  align, 0, 0);
+				  align, RADEON_GEM_DOMAIN_VRAM |
+				  RADEON_GEM_DOMAIN_GTT, 0);
     if (!new_priv->bo) {
 	xfree(new_priv);
 	ErrorF("Failed to alloc memory\n");
commit 57f2c83a22f27567506c555af431f89e6031204c
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Sat Jul 25 14:19:38 2009 -0400

    radeon: Set PCI/PCIE bus type properly per asic
    
    - r1xx-rv350 chips have the old pci gart
    - rv380+ chips have newer pcie gart
    
    Select the right kind regardless of whether the user selects
    PCI or PCIE.

diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 3791305..bf95029 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -1977,7 +1977,6 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn)
 	}
     }
 
-
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s card detected\n",
 	       (info->cardType==CARD_PCI) ? "PCI" :
 		(info->cardType==CARD_PCIE) ? "PCIE" : "AGP");
@@ -1997,12 +1996,15 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn)
 	if (strcmp(s, "AGP") == 0) {
 	    info->cardType = CARD_AGP;
 	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into AGP mode\n");
-	} else if (strcmp(s, "PCI") == 0) {
-	    info->cardType = CARD_PCI;
-	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI mode\n");
-	} else if (strcmp(s, "PCIE") == 0) {
-	    info->cardType = CARD_PCIE;
-	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI Express mode\n");
+	} else if ((strcmp(s, "PCI") == 0) ||
+		   (strcmp(s, "PCIE") == 0)) {
+	    if (info->ChipFamily >= CHIP_FAMILY_RV380) {
+		info->cardType = CARD_PCIE;
+		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI Express mode\n");
+	    } else {
+		info->cardType = CARD_PCI;
+		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI mode\n");
+	    }
 	} else {
 	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
 		       "Invalid BusType option, using detected type\n");
commit 2afc46fa74ce7730f766a3370d323c6b59694186
Author: Jerome Glisse <jglisse at redhat.com>
Date:   Thu Jul 23 20:13:15 2009 +0200

    radeon: fix KMS shadowfb for r6xx and newer hw.
    
    We need to map front buffer and also to avoid EXA initialization
    when falling back to shadowfb on newer r6xx/r7xx when KMS is enabled.

diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 8a14f88..148386b 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -543,7 +543,9 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
 			  pScrn->defaultVisual)) return FALSE;
     miSetPixmapDepths ();
 
-    info->directRenderingEnabled = radeon_dri2_screen_init(pScreen);
+    info->directRenderingEnabled = FALSE;
+    if (info->r600_shadow_fb == FALSE)
+        info->directRenderingEnabled = radeon_dri2_screen_init(pScreen);
 
     front_ptr = info->FB;
 
@@ -689,6 +691,8 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
 
     if (info->r600_shadow_fb == TRUE) {
         if (!shadowSetup(pScreen)) {
+	    xf86DrvMsg(scrnIndex, X_ERROR,
+		       "Shadowfb initialization failed\n");
             return FALSE;
         }
     }
@@ -811,9 +815,11 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
 	xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n");
 	return FALSE;
     }
-    info->accel_state->exa = exaDriverAlloc();
-    if (info->accel_state->exa == NULL)
-	return FALSE;
+    if (info->r600_shadow_fb == FALSE) {
+        info->accel_state->exa = exaDriverAlloc();
+        if (info->accel_state->exa == NULL)
+	    return FALSE;
+    }
 
     screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * stride;
     {
@@ -849,6 +855,11 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
 
     info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size,
 				    0, RADEON_GEM_DOMAIN_VRAM, 0);
+    if (info->r600_shadow_fb == TRUE) {
+        if (radeon_bo_map(info->front_bo, 1)) {
+	    ErrorF("Failed to map cursor buffer memory\n");
+	}
+    }
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer size: %dK\n", info->front_bo->size/1024);
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Remaining VRAM size (used for pixmaps): %dK\n", remain_size_bytes/1024);
commit 328e4c816348b6f867df30b39856dbe78c8e0dcc
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Jul 23 13:28:36 2009 -0400

    RS780: fill in MC access functions
    
    Also, r6xx/r7xx don't have indirect MC space, so
    don't try to access it.

diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 535b316..3791305 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -621,6 +621,12 @@ unsigned RADEONINMC(ScrnInfoPtr pScrn, int addr)
     } else if (info->ChipFamily == CHIP_FAMILY_RS600) {
 	OUTREG(RS600_MC_INDEX, ((addr & RS600_MC_ADDR_MASK) | RS600_MC_IND_CITF_ARB0));
 	data = INREG(RS600_MC_DATA);
+    } else if ((info->ChipFamily == CHIP_FAMILY_RS780) ||
+	       (info->ChipFamily == CHIP_FAMILY_RS880)) {
+	OUTREG(RS780_MC_INDEX, (addr & RS780_MC_INDEX_MASK));
+	data = INREG(RS780_MC_DATA);
+    } else if (info->ChipFamily >= CHIP_FAMILY_R600) {
+	data = 0;
     } else if (IS_AVIVO_VARIANT) {
 	OUTREG(AVIVO_MC_INDEX, (addr & 0xff) | 0x7f0000);
 	(void)INREG(AVIVO_MC_INDEX);
@@ -657,6 +663,13 @@ void RADEONOUTMC(ScrnInfoPtr pScrn, int addr, uint32_t data)
 				RS600_MC_IND_CITF_ARB0 |
 				RS600_MC_IND_WR_EN));
 	OUTREG(RS600_MC_DATA, data);
+    } else if ((info->ChipFamily == CHIP_FAMILY_RS780) ||
+	       (info->ChipFamily == CHIP_FAMILY_RS880)) {
+	OUTREG(RS780_MC_INDEX, ((addr & RS780_MC_INDEX_MASK) |
+				      RS780_MC_INDEX_WR_EN));
+	OUTREG(RS780_MC_DATA, data);
+    } else if (info->ChipFamily >= CHIP_FAMILY_R600) {
+	// do nothing
     } else if (IS_AVIVO_VARIANT) {
 	OUTREG(AVIVO_MC_INDEX, (addr & 0xff) | 0xff0000);
 	(void)INREG(AVIVO_MC_INDEX);
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index 1db7c67..9df7fff 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -3549,6 +3549,11 @@
 #	define R520_MEM_NUM_CHANNELS_SHIFT  24
 #	define R520_MC_CHANNEL_SIZE  (1 << 23)
 
+#define RS780_MC_INDEX				0x28f8
+#	define RS780_MC_INDEX_MASK		0x1ff
+#	define RS780_MC_INDEX_WR_EN		(1 << 9)
+#define RS780_MC_DATA				0x28fc
+
 #define R600_RAMCFG				       0x2408
 #       define R600_CHANSIZE                           (1 << 7)
 #       define R600_CHANSIZE_OVERRIDE                  (1 << 10)
commit f96d5b255425fbd02be2cad26edb590d474a5640
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Jul 23 13:25:04 2009 -0400

    R6xx/R7xx: clip rendering to destination surface dimensions

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 34dbbb2..485322d 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -136,6 +136,10 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     EREG(accel_state->ib, PA_CL_VTE_CNTL,                      VTX_XY_FMT_bit);
     EREG(accel_state->ib, PA_CL_CLIP_CNTL,                     CLIP_DISABLE_bit);
 
+    set_generic_scissor(pScrn, accel_state->ib, 0, 0, pPix->drawable.width, pPix->drawable.height);
+    set_screen_scissor(pScrn, accel_state->ib, 0, 0, pPix->drawable.width, pPix->drawable.height);
+    set_window_scissor(pScrn, accel_state->ib, 0, 0, pPix->drawable.width, pPix->drawable.height);
+
     accel_state->vs_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
 	accel_state->solid_vs_offset;
     accel_state->ps_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
@@ -351,7 +355,7 @@ R600DoneSolid(PixmapPtr pPix)
 static void
 R600DoPrepareCopy(ScrnInfoPtr pScrn,
 		  int src_pitch, int src_width, int src_height, uint32_t src_offset, int src_bpp,
-		  int dst_pitch, int dst_height, uint32_t dst_offset, int dst_bpp,
+		  int dst_pitch, int dst_width, int dst_height, uint32_t dst_offset, int dst_bpp,
 		  int rop, Pixel planemask)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
@@ -379,6 +383,10 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn,
     EREG(accel_state->ib, PA_CL_VTE_CNTL,                      VTX_XY_FMT_bit);
     EREG(accel_state->ib, PA_CL_CLIP_CNTL,                     CLIP_DISABLE_bit);
 
+    set_generic_scissor(pScrn, accel_state->ib, 0, 0, dst_width, dst_height);
+    set_screen_scissor(pScrn, accel_state->ib, 0, 0, dst_width, dst_height);
+    set_window_scissor(pScrn, accel_state->ib, 0, 0, dst_width, dst_height);
+
     accel_state->vs_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
 	accel_state->copy_vs_offset;
     accel_state->ps_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
@@ -689,7 +697,7 @@ R600PrepareCopy(PixmapPtr pSrc,   PixmapPtr pDst,
 	R600DoPrepareCopy(pScrn,
 			  accel_state->src_pitch[0], pSrc->drawable.width, pSrc->drawable.height,
 			  accel_state->src_mc_addr[0], pSrc->drawable.bitsPerPixel,
-			  accel_state->dst_pitch, pDst->drawable.height,
+			  accel_state->dst_pitch, pDst->drawable.width, pDst->drawable.height,
 			  accel_state->dst_mc_addr, pDst->drawable.bitsPerPixel,
 			  rop, planemask);
 
@@ -738,7 +746,7 @@ R600OverlapCopy(PixmapPtr pDst,
                 if (srcY > dstY ) { /* diagonal up */
                     R600DoPrepareCopy(pScrn,
                                       dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-                                      dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
                                       accel_state->rop, accel_state->planemask);
                     R600AppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, w, vchunk);
                     R600DoCopy(pScrn);
@@ -748,7 +756,7 @@ R600OverlapCopy(PixmapPtr pDst,
                 } else { /* diagonal down */
                     R600DoPrepareCopy(pScrn,
                                       dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-                                      dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
                                       accel_state->rop, accel_state->planemask);
                     R600AppendCopyVertex(pScrn, srcX, srcY + h - vchunk, dstX, dstY + h - vchunk, w, vchunk);
                     R600DoCopy(pScrn);
@@ -759,7 +767,7 @@ R600OverlapCopy(PixmapPtr pDst,
                 if (srcX > dstX ) { /* diagonal left */
                     R600DoPrepareCopy(pScrn,
                                       dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-                                      dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
                                       accel_state->rop, accel_state->planemask);
                     R600AppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, hchunk, h);
                     R600DoCopy(pScrn);
@@ -769,7 +777,7 @@ R600OverlapCopy(PixmapPtr pDst,
                 } else { /* diagonal right */
                     R600DoPrepareCopy(pScrn,
                                       dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-                                      dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
                                       accel_state->rop, accel_state->planemask);
                     R600AppendCopyVertex(pScrn, srcX + w - hchunk, srcY, dstX + w - hchunk, dstY, hchunk, h);
                     R600DoCopy(pScrn);
@@ -785,7 +793,7 @@ R600OverlapCopy(PixmapPtr pDst,
 		for (i = w; i > 0; i -= hchunk) {
 		    R600DoPrepareCopy(pScrn,
 				      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-				      dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+				      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
 				      accel_state->rop, accel_state->planemask);
 		    R600AppendCopyVertex(pScrn, srcX + i - hchunk, srcY, dstX + i - hchunk, dstY, hchunk, h);
 		    R600DoCopy(pScrn);
@@ -795,7 +803,7 @@ R600OverlapCopy(PixmapPtr pDst,
 		for (i = 0; i < w; i += hchunk) {
 		    R600DoPrepareCopy(pScrn,
 				      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-				      dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+				      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
 				      accel_state->rop, accel_state->planemask);
 
 		    R600AppendCopyVertex(pScrn, srcX + i, srcY, dstX + i, dstY, hchunk, h);
@@ -808,7 +816,7 @@ R600OverlapCopy(PixmapPtr pDst,
                 for (i = 0; i < h; i += vchunk) {
                     R600DoPrepareCopy(pScrn,
                                       dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-                                      dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
                                       accel_state->rop, accel_state->planemask);
 
                     if (vchunk > h - i) vchunk = h - i;
@@ -820,7 +828,7 @@ R600OverlapCopy(PixmapPtr pDst,
                 for (i = h; i > 0; i -= vchunk) {
                     R600DoPrepareCopy(pScrn,
                                       dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-                                      dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+                                      dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
                                       accel_state->rop, accel_state->planemask);
 
                     if (vchunk > i) vchunk = i;
@@ -832,7 +840,7 @@ R600OverlapCopy(PixmapPtr pDst,
     } else {
 	R600DoPrepareCopy(pScrn,
 			  dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
-			  dst_pitch, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
+			  dst_pitch, pDst->drawable.width, pDst->drawable.height, dst_offset, pDst->drawable.bitsPerPixel,
 			  accel_state->rop, accel_state->planemask);
 
 	R600AppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, w, h);
@@ -863,13 +871,13 @@ R600Copy(PixmapPtr pDst,
 
 	    R600DoPrepareCopy(pScrn,
 			      pitch, pDst->drawable.width, pDst->drawable.height, orig_offset, pDst->drawable.bitsPerPixel,
-			      pitch,                       pDst->drawable.height, tmp_offset, pDst->drawable.bitsPerPixel,
+			      pitch, pDst->drawable.width, pDst->drawable.height, tmp_offset, pDst->drawable.bitsPerPixel,
 			      accel_state->rop, accel_state->planemask);
 	    R600AppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, w, h);
 	    R600DoCopy(pScrn);
 	    R600DoPrepareCopy(pScrn,
 			      pitch, pDst->drawable.width, pDst->drawable.height, tmp_offset, pDst->drawable.bitsPerPixel,
-			      pitch,                       pDst->drawable.height, orig_offset, pDst->drawable.bitsPerPixel,
+			      pitch, pDst->drawable.width, pDst->drawable.height, orig_offset, pDst->drawable.bitsPerPixel,
 			      accel_state->rop, accel_state->planemask);
 	    R600AppendCopyVertex(pScrn, dstX, dstY, dstX, dstY, w, h);
 	    R600DoCopy(pScrn);
@@ -881,7 +889,7 @@ R600Copy(PixmapPtr pDst,
 
 	R600DoPrepareCopy(pScrn,
 			  pitch, pDst->drawable.width, pDst->drawable.height, offset, pDst->drawable.bitsPerPixel,
-			  pitch,                       pDst->drawable.height, offset, pDst->drawable.bitsPerPixel,
+			  pitch, pDst->drawable.width, pDst->drawable.height, offset, pDst->drawable.bitsPerPixel,
 			  accel_state->rop, accel_state->planemask);
 	R600AppendCopyVertex(pScrn, srcX, srcY, dstX, dstY, w, h);
 	R600DoCopy(pScrn);
@@ -1442,6 +1450,10 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     EREG(accel_state->ib, PA_CL_VTE_CNTL,                      VTX_XY_FMT_bit);
     EREG(accel_state->ib, PA_CL_CLIP_CNTL,                     CLIP_DISABLE_bit);
 
+    set_generic_scissor(pScrn, accel_state->ib, 0, 0, pDst->drawable.width, pDst->drawable.height);
+    set_screen_scissor(pScrn, accel_state->ib, 0, 0, pDst->drawable.width, pDst->drawable.height);
+    set_window_scissor(pScrn, accel_state->ib, 0, 0, pDst->drawable.width, pDst->drawable.height);
+
     if (!R600TextureSetup(pSrcPicture, pSrc, 0)) {
 	R600IBDiscard(pScrn, accel_state->ib);
 	return FALSE;
@@ -1740,7 +1752,7 @@ static void R600DoneComposite(PixmapPtr pDst)
 Bool
 R600CopyToVRAM(ScrnInfoPtr pScrn,
 	       char *src, int src_pitch,
-	       uint32_t dst_pitch, uint32_t dst_mc_addr, uint32_t dst_height, int bpp,
+	       uint32_t dst_pitch, uint32_t dst_mc_addr, uint32_t dst_width, uint32_t dst_height, int bpp,
 	       int x, int y, int w, int h)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
@@ -1794,7 +1806,7 @@ R600CopyToVRAM(ScrnInfoPtr pScrn,
 	/* blit from scratch to vram */
 	R600DoPrepareCopy(pScrn,
 			  scratch_pitch, w, oldhpass, offset, bpp,
-			  dst_pitch, dst_height, dst_mc_addr, bpp,
+			  dst_pitch, dst_width, dst_height, dst_mc_addr, bpp,
 			  3, 0xffffffff);
 	R600AppendCopyVertex(pScrn, 0, 0, x, y, w, oldhpass);
 	R600DoCopy(pScrn);
@@ -1814,12 +1826,11 @@ R600UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
     RADEONInfoPtr info = RADEONPTR(pScrn);
     uint32_t dst_pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8);
     uint32_t dst_mc_addr = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
-    uint32_t dst_height = pDst->drawable.height;
     int bpp = pDst->drawable.bitsPerPixel;
 
     return R600CopyToVRAM(pScrn,
 			  src, src_pitch,
-			  dst_pitch, dst_mc_addr, dst_height, bpp,
+			  dst_pitch, dst_mc_addr, pDst->drawable.width, pDst->drawable.height, bpp,
 			  x, y, w, h);
 }
 
@@ -1854,7 +1865,7 @@ R600DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
     /* blit from vram to scratch */
     R600DoPrepareCopy(pScrn,
 		      src_pitch, src_width, src_height, src_mc_addr, bpp,
-		      scratch_pitch, hpass, scratch_mc_addr, bpp,
+		      scratch_pitch, src_width, hpass, scratch_mc_addr, bpp,
 		      3, 0xffffffff);
     R600AppendCopyVertex(pScrn, x, y, 0, 0, w, hpass);
     R600DoCopy(pScrn);
@@ -1871,7 +1882,7 @@ R600DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
 	    /* blit from vram to scratch */
 	    R600DoPrepareCopy(pScrn,
 			      src_pitch, src_width, src_height, src_mc_addr, bpp,
-			      scratch_pitch, hpass, scratch_mc_addr + scratch_offset, bpp,
+			      scratch_pitch, src_width, hpass, scratch_mc_addr + scratch_offset, bpp,
 			      3, 0xffffffff);
 	    R600AppendCopyVertex(pScrn, x, y, 0, 0, w, hpass);
 	    R600DoCopy(pScrn);
diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index 7c91a06..2f0b6b1 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -244,6 +244,10 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     EREG(accel_state->ib, PA_CL_VTE_CNTL,                      VTX_XY_FMT_bit);
     EREG(accel_state->ib, PA_CL_CLIP_CNTL,                     CLIP_DISABLE_bit);
 
+    set_generic_scissor(pScrn, accel_state->ib, 0, 0, pPixmap->drawable.width, pPixmap->drawable.height);
+    set_screen_scissor(pScrn, accel_state->ib, 0, 0, pPixmap->drawable.width, pPixmap->drawable.height);
+    set_window_scissor(pScrn, accel_state->ib, 0, 0, pPixmap->drawable.width, pPixmap->drawable.height);
+
     accel_state->vs_mc_addr = info->fbLocation + pScrn->fbOffset + accel_state->shaders->offset +
 	accel_state->xv_vs_offset;
 
diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index 7f2d54c..6423e58 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -808,11 +808,8 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     EREG(ib, CB_TARGET_MASK,                      (0x0f << TARGET0_ENABLE_shift));
 
     // SC
-    set_generic_scissor(pScrn, ib, 0, 0, 8192, 8192);
-    set_screen_scissor(pScrn, ib, 0, 0, 8192, 8192);
     EREG(ib, PA_SC_WINDOW_OFFSET,                 ((0 << WINDOW_X_OFFSET_shift) |
 						   (0 << WINDOW_Y_OFFSET_shift)));
-    set_window_scissor(pScrn, ib, 0, 0, 8192, 8192);
 
     EREG(ib, PA_SC_CLIPRECT_RULE,                 CLIP_RULE_mask);
 
diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c
index d034c33..0f89b49 100644
--- a/src/radeon_textured_video.c
+++ b/src/radeon_textured_video.c
@@ -50,7 +50,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv);
 extern Bool
 R600CopyToVRAM(ScrnInfoPtr pScrn,
 	       char *src, int src_pitch,
-	       uint32_t dst_pitch, uint32_t dst_mc_addr, uint32_t dst_height, int bpp,
+	       uint32_t dst_pitch, uint32_t dst_mc_addr, uint32_t dst_width, uint32_t dst_height, int bpp,
 	       int x, int y, int w, int h);
 
 #define IMAGE_MAX_WIDTH		2048
@@ -203,7 +203,7 @@ R600CopyData(
 
 	R600CopyToVRAM(pScrn,
 		       (char *)src, srcPitch,
-		       dstPitch, dst_mc_addr, h, cpp * 8,
+		       dstPitch, dst_mc_addr, w, h, cpp * 8,
 		       0, 0, w, h);
     } else {
 	if (srcPitch == dstPitch)
commit e372f845b0defaf2d2c9ef3cbbf7498e09d9372e
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Sun Jul 19 16:05:29 2009 +0200

    Guard reference to CRTC active field.
    
    Fixes build against older xserver.

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 42b0b15..3f4ccfc 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -323,8 +323,11 @@ done:
 		crtc->y = saved_y;
 		crtc->rotation = saved_rotation;
 		crtc->mode = saved_mode;
-	} else
+	}
+#if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3
+	else
 		crtc->active = TRUE;
+#endif
 
 	return ret;
 }
commit e38305aebdc95f80f5b4b3e5ba541ea67dc05f01
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Sat Jul 18 22:23:45 2009 +0200

    Also drop DRM master in KMS CloseScreen.
    
    The LeaveVT hook isn't always called when the server dies, e.g. when quitting
    from the GDM greeter. This may cause existing servers to fall over if the dying
    server process still exists when they try to re-acquire master and set a mode.
    
    Also use drmSet/DropMaster() rather than ioctl() directly.

diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 59a654f..8a14f88 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -498,6 +498,8 @@ static Bool RADEONCloseScreen_KMS(int scrnIndex, ScreenPtr pScreen)
 	info->accel_state->exa = NULL;
     }
 
+    drmDropMaster(info->dri->drmFD);
+
     if (info->cursor) xf86DestroyCursorInfoRec(info->cursor);
     info->cursor = NULL;
 
@@ -735,8 +737,8 @@ Bool RADEONEnterVT_KMS(int scrnIndex, int flags)
 		   "RADEONEnterVT_KMS\n");
 
 
-    ret = ioctl(info->dri->drmFD, DRM_IOCTL_SET_MASTER, NULL);
-    if (ret == -EINVAL)
+    ret = drmSetMaster(info->dri->drmFD);
+    if (ret)
 	ErrorF("Unable to retrieve master\n");
 
     info->accel_state->XInited3D = FALSE;
@@ -762,7 +764,7 @@ void RADEONLeaveVT_KMS(int scrnIndex, int flags)
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "RADEONLeaveVT_KMS\n");
 
-    ioctl(info->dri->drmFD, DRM_IOCTL_DROP_MASTER, NULL);
+    drmDropMaster(info->dri->drmFD);
 
 #ifdef HAVE_FREE_SHADOW
     xf86RotateFreeShadow(pScrn);
commit a43c660a00147bfae5ca601f4720b2680b75211f
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Sat Jul 18 22:21:59 2009 +0200

    Set CRTC active flag to TRUE after a successful KMS mode set.
    
    Otherwise some things like changing the colour map won't work properly.

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index ea2f71f..42b0b15 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -323,7 +323,9 @@ done:
 		crtc->y = saved_y;
 		crtc->rotation = saved_rotation;
 		crtc->mode = saved_mode;
-	}
+	} else
+		crtc->active = TRUE;
+
 	return ret;
 }
 
commit f32069f42b3e4643f15148d0b96164def00dcc74
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Sat Jul 18 22:20:08 2009 +0200

    Set the STALL bit in the CRTC_GUI_TRIG_VLINE registers.
    
    As recommended by the register reference when using the WAIT_CRTC_VLINE bit in
    the WAIT_UNTIL register, as we are.

diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index 3df7daf..6f501a6 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -846,7 +846,8 @@ void drmmode_wait_for_vline(ScrnInfoPtr pScrn, PixmapPtr pPix,
 	OUT_ACCEL_REG(RADEON_CRTC_GUI_TRIG_VLINE, /* another placeholder */
 		      ((start << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
 		      (stop << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
-		      RADEON_CRTC_GUI_TRIG_VLINE_INV));
+		      RADEON_CRTC_GUI_TRIG_VLINE_INV |
+		      RADEON_CRTC_GUI_TRIG_VLINE_STALL));
     }
     OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
 				      RADEON_ENG_DISPLAY_SELECT_CRTC0));
@@ -918,12 +919,14 @@ void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix,
 	    OUT_ACCEL_REG(RADEON_CRTC_GUI_TRIG_VLINE,
 			  ((start << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
 			   (stop << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
-			   RADEON_CRTC_GUI_TRIG_VLINE_INV));
+			   RADEON_CRTC_GUI_TRIG_VLINE_INV |
+			   RADEON_CRTC_GUI_TRIG_VLINE_STALL));
 	else
 	    OUT_ACCEL_REG(RADEON_CRTC2_GUI_TRIG_VLINE,
 			  ((start << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
 			   (stop << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
-			   RADEON_CRTC_GUI_TRIG_VLINE_INV));
+			   RADEON_CRTC_GUI_TRIG_VLINE_INV |
+			   RADEON_CRTC_GUI_TRIG_VLINE_STALL));
     }
 
     if (crtc == 0)
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index 8da513b..1db7c67 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -445,8 +445,9 @@
 #       define RADEON_CRTC_V_CUTOFF_ACTIVE_EN (1<<5)
 #define RADEON_CRTC_GUI_TRIG_VLINE          0x0218
 #       define RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT  0
-#       define RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT    16
 #       define RADEON_CRTC_GUI_TRIG_VLINE_INV          (1 << 15)
+#       define RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT    16
+#       define RADEON_CRTC_GUI_TRIG_VLINE_STALL        (1 << 30)
 #define RADEON_CRTC_H_SYNC_STRT_WID         0x0204
 #       define RADEON_CRTC_H_SYNC_STRT_PIX        (0x07  <<  0)
 #       define RADEON_CRTC_H_SYNC_STRT_CHAR       (0x3ff <<  3)
commit 27bd9fc9b2c0eeff488c1f26f1355a7fa3655520
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Sat Jul 18 22:14:27 2009 +0200

    Enable vsync for DRI2 region copies.

diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 4770ba3..08da996 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -228,6 +228,8 @@ radeon_dri2_copy_region(DrawablePtr drawable,
     PixmapPtr dst_pixmap;
     RegionPtr copy_clip;
     GCPtr gc;
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    Bool vsync;
 
     src_pixmap = src_private->pixmap;
     dst_pixmap = dst_private->pixmap;
@@ -242,8 +244,15 @@ radeon_dri2_copy_region(DrawablePtr drawable,
     REGION_COPY(pScreen, copy_clip, region);
     (*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0);
     ValidateGC(&dst_pixmap->drawable, gc);
+
+    vsync = info->accel_state->vsync;
+    info->accel_state->vsync = TRUE;
+
     (*gc->ops->CopyArea)(&src_pixmap->drawable, &dst_pixmap->drawable, gc,
                          0, 0, drawable->width, drawable->height, 0, 0);
+
+    info->accel_state->vsync = vsync;
+
     FreeScratchGC(gc);
     radeon_cs_flush_indirect(pScrn);
 }
commit 4b1b28865ffb17f58a70d955212fd51cb1fb55ab
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Jul 16 17:09:33 2009 -0400

    R6xx/r7xx: reduce the amount of default state setup
    
    Most of the default state setup was extraneous or duplicated
    in the accel ops.  There's no need to reset all the consts
    everytime you reset the default state for example.  This leads
    to a 10x reduction in default state.

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 3673064..34dbbb2 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -219,7 +219,7 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 								  (0x03 << DEFAULT_VAL_shift)	|
 								  FLAT_SHADE_bit		|
 								  SEL_CENTROID_bit));
-    EREG(accel_state->ib, SPI_INTERP_CONTROL_0,                FLAT_SHADE_ENA_bit | 0);
+    EREG(accel_state->ib, SPI_INTERP_CONTROL_0,                FLAT_SHADE_ENA_bit);
 
     /* PS alu constants */
     if (pPix->drawable.bitsPerPixel == 16) {
diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index 65834bf..7f2d54c 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -96,75 +96,6 @@ wait_3d_idle(ScrnInfoPtr pScrn, drmBufPtr ib)
 
 }
 
-static void
-reset_cb(ScrnInfoPtr pScrn, drmBufPtr ib)
-{
-    int i;
-
-    PACK0(ib, CB_COLOR0_INFO, 8);
-    for (i = 0; i < 8; i++)
-	E32(ib, 0);
-}
-
-static void
-reset_td_samplers(ScrnInfoPtr pScrn, drmBufPtr ib)
-{
-    int i;
-
-    wait_3d_idle(pScrn, ib);
-
-    PACK0(ib, TD_PS_SAMPLER0_BORDER_RED, 4*TD_PS_SAMPLER0_BORDER_RED_num);
-    for (i = 0; i < 4*TD_PS_SAMPLER0_BORDER_RED_num; i++)
-	E32(ib, 0);
-    PACK0(ib, TD_VS_SAMPLER0_BORDER_RED, 4*TD_VS_SAMPLER0_BORDER_RED_num);
-    for (i = 0; i < 4*TD_VS_SAMPLER0_BORDER_RED_num; i++)
-	E32(ib, 0);
-
-    wait_3d_idle(pScrn, ib);
-}
-
-static void
-reset_sampler_const (ScrnInfoPtr pScrn, drmBufPtr ib)
-{
-    int i;
-
-    for (i = 0; i < SQ_TEX_SAMPLER_WORD_all_num; i++) {
-	PACK0(ib, SQ_TEX_SAMPLER_WORD + i * SQ_TEX_SAMPLER_WORD_offset, 3);
-	E32(ib, SQ_TEX_DEPTH_COMPARE_LESSEQUAL << DEPTH_COMPARE_FUNCTION_shift);
-	E32(ib, MAX_LOD_mask);
-	E32(ib, 0);
-    }
-}
-
-static void
-reset_dx9_alu_consts(ScrnInfoPtr pScrn, drmBufPtr ib)
-{
-    int i;
-
-    const int count = SQ_ALU_CONSTANT_all_num * (SQ_ALU_CONSTANT_offset >> 2);
-
-    PACK0(ib, SQ_ALU_CONSTANT, count);
-    for (i = 0; i < count; i++)
-	EFLOAT(ib, 0.0);
-}
-
-static void
-reset_bool_loop_const(ScrnInfoPtr pScrn, drmBufPtr ib)
-{
-    int i;
-
-
-    PACK0(ib, SQ_BOOL_CONST, SQ_BOOL_CONST_all_num);
-    for (i = 0; i < SQ_BOOL_CONST_all_num; i++)
-	E32(ib, 0);
-
-    PACK0(ib, SQ_LOOP_CONST, SQ_LOOP_CONST_all_num);
-
-    for (i = 0; i < SQ_LOOP_CONST_all_num; i++)
-	E32(ib, 0);
-
-}
-
 void
 start_3d(ScrnInfoPtr pScrn, drmBufPtr ib)
 {
@@ -654,10 +585,8 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     memset(&tex_res, 0, sizeof(tex_resource_t));
     memset(&fs_conf, 0, sizeof(shader_config_t));
 
-#if 1
     if (accel_state->XInited3D)
 	return;
-#endif
 
     accel_state->XInited3D = TRUE;
 
@@ -690,11 +619,6 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
 						    0));
     }
 
-    reset_td_samplers(pScrn, ib);
-    reset_dx9_alu_consts(pScrn, ib);
-    reset_bool_loop_const (pScrn, ib);
-    reset_sampler_const (pScrn, ib);
-
     // SQ
     sq_conf.ps_prio = 0;
     sq_conf.vs_prio = 1;
@@ -854,24 +778,12 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     EREG(ib, SX_ALPHA_REF,                        0);
 
     // CB
-    reset_cb(pScrn, ib);
-
     PACK0(ib, CB_BLEND_RED, 4);
     E32(ib, 0x00000000);
     E32(ib, 0x00000000);
     E32(ib, 0x00000000);
     E32(ib, 0x00000000);
 
-    /* CB_COLOR_CONTROL.PER_MRT_BLEND is off */
-    // RV6xx+ have per-MRT blend
-    if (info->ChipFamily > CHIP_FAMILY_R600) {
-	PACK0(ib, CB_BLEND0_CONTROL, CB_BLEND0_CONTROL_num);
-	for (i = 0; i < CB_BLEND0_CONTROL_num; i++)
-	    E32(ib, 0);
-    }
-
-    EREG(ib, CB_BLEND_CONTROL,                    0);
-
     if (info->ChipFamily < CHIP_FAMILY_RV770) {
 	PACK0(ib, CB_FOG_RED, 3);
 	E32(ib, 0x00000000);
@@ -879,7 +791,6 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
 	E32(ib, 0x00000000);
     }
 
-    EREG(ib, CB_COLOR_CONTROL,                    0);
     PACK0(ib, CB_CLRCMP_CONTROL, 4);
     E32(ib, 1 << CLRCMP_FCN_SEL_shift);				// CB_CLRCMP_CONTROL: use CLRCMP_FCN_SRC
     E32(ib, 0);							// CB_CLRCMP_SRC
@@ -948,7 +859,6 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     EFLOAT(ib, 0.0f);						// PA_CL_VPORT_YOFFSET
     EFLOAT(ib, 0.0f);						// PA_CL_VPORT_ZSCALE
     EFLOAT(ib, 0.0f);						// PA_CL_VPORT_ZOFFSET
-    EREG(ib, PA_CL_CLIP_CNTL,                     (CLIP_DISABLE_bit | DX_CLIP_SPACE_DEF_bit));
     EREG(ib, PA_CL_VTE_CNTL,                      0);
     EREG(ib, PA_CL_VS_OUT_CNTL,                   0);
     EREG(ib, PA_CL_NANINF_CNTL,                   0);
@@ -958,11 +868,6 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     EFLOAT(ib, 1.0);						// PA_CL_GB_HORZ_CLIP_ADJ
     EFLOAT(ib, 1.0);						// PA_CL_GB_HORZ_DISC_ADJ
 
-    /* user clipping planes are disabled by default */
-    PACK0(ib, PA_CL_UCP_0_X, 24);
-    for (i = 0; i < 24; i++)
-	EFLOAT(ib, 0.0);
-
     // SU
     EREG(ib, PA_SU_SC_MODE_CNTL,                  FACE_bit);
     EREG(ib, PA_SU_POINT_SIZE,                    0);
@@ -984,20 +889,11 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     else
 	EREG(ib, R7xx_SPI_THREAD_GROUPING,        (1 << PS_GROUPING_shift));
 
-    EREG(ib, SPI_INTERP_CONTROL_0,                ((2 << PNT_SPRITE_OVRD_X_shift)		|
-						   (3 << PNT_SPRITE_OVRD_Y_shift)		|
-						   (0 << PNT_SPRITE_OVRD_Z_shift)		|
-						   (1 << PNT_SPRITE_OVRD_W_shift))); /* s,t,0,1 */
     EREG(ib, SPI_INPUT_Z,                         0);
     EREG(ib, SPI_FOG_CNTL,                        0);
     EREG(ib, SPI_FOG_FUNC_SCALE,                  0);
     EREG(ib, SPI_FOG_FUNC_BIAS,                   0);
 
-    PACK0(ib, SPI_VS_OUT_ID_0, SPI_VS_OUT_ID_0_num);
-    for (i = 0; i < SPI_VS_OUT_ID_0_num; i++)		/* identity mapping */
-	E32(ib, 0x03020100 + i*0x04040404);
-    EREG(ib, SPI_VS_OUT_CONFIG,                   0);
-
     // clear FS
     fs_setup(pScrn, ib, &fs_conf);
 
@@ -1029,24 +925,6 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     EREG(ib, VGT_VTX_CNT_EN,                      0);
     EREG(ib, VGT_STRMOUT_BUFFER_EN,               0);
 
-    // clear tex resources - PS
-    for (i = 0; i < 16; i++) {
-	tex_res.id = i;
-	set_tex_resource(pScrn, ib, &tex_res);
-    }
-
-    // clear tex resources - VS
-    for (i = 160; i < 164; i++) {
-	tex_res.id = i;
-	set_tex_resource(pScrn, ib, &tex_res);
-    }
-
-    // clear tex resources - FS
-    for (i = 320; i < 335; i++) {
-	tex_res.id = i;
-	set_tex_resource(pScrn, ib, &tex_res);
-    }
-
 }
 
 
commit 7e6557b81026d8a4d6c837839e68c28b151f8a97
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Jul 16 11:33:57 2009 +1000

    Update to xextproto 7.1 support.
    
    DPMS header was split into dpms.h (client) and dpmsconst.h (server). Drivers
    need to include dpmsconst.h if xextproto 7.1 is available.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/configure.ac b/configure.ac
index 39018b8..48375ee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -90,6 +90,10 @@ XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto)
 
 # Checks for pkg-config packages
 PKG_CHECK_MODULES(XORG, [xorg-server >= 1.2 xproto fontsproto $REQUIRED_MODULES])
+PKG_CHECK_MODULES(XEXT, [xextproto >= 7.0.99.1],
+                  HAVE_XEXTPROTO_71="yes"; AC_DEFINE(HAVE_XEXTPROTO_71, 1, [xextproto 7.1 available]),
+                  HAVE_XEXTPROTO_71="no")
+AM_CONDITIONAL(HAVE_XEXTPROTO_71, [ test "$HAVE_XEXTPROTO_71" = "yes" ])
 sdkdir=$(pkg-config --variable=sdkdir xorg-server)
 
 # Checks for libraries.
diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 6d24c2b..e04b3c4 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -33,8 +33,13 @@
 #include "config.h"
 #endif
 /* DPMS */
+#ifdef HAVE_XEXTPROTO_71
+#include <X11/extensions/dpmsconst.h>
+#else
 #define DPMS_SERVER
 #include <X11/extensions/dpms.h>
+#endif
+
 
 #include "radeon.h"
 #include "radeon_reg.h"
diff --git a/src/atombios_output.c b/src/atombios_output.c
index 158e76f..00d17cb 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -34,8 +34,13 @@
 #include "config.h"
 #endif
 /* DPMS */
+#ifdef HAVE_XEXTPROTO_71
+#include <X11/extensions/dpmsconst.h>
+#else
 #define DPMS_SERVER
 #include <X11/extensions/dpms.h>
+#endif
+
 #include <unistd.h>
 
 #include "radeon.h"
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index b5846df..ea2f71f 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -41,8 +41,13 @@
 #include "drmmode_display.h"
 
 /* DPMS */
+#ifdef HAVE_XEXTPROTO_71
+#include <X11/extensions/dpmsconst.h>
+#else
 #define DPMS_SERVER
 #include <X11/extensions/dpms.h>
+#endif
+
 
 static void
 drmmode_ConvertFromKMode(ScrnInfoPtr	scrn,
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 317612d..535b316 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -104,8 +104,13 @@
 #include "vgaHW.h"
 #endif
 
+#ifdef HAVE_XEXTPROTO_71
+#include <X11/extensions/dpmsconst.h>
+#else
 #define DPMS_SERVER
 #include <X11/extensions/dpms.h>
+#endif
+
 
 #include "atipciids.h"
 #include "radeon_chipset_gen.h"
commit 95d431e8b260dd43cf6d93b90eecab1dc0ec7c26
Author: Dave Airlie <airlied at redhat.com>
Date:   Wed Jul 15 12:07:01 2009 +1000

    radeon: emit colorpitch relocs.
    
    This causes relocs to be emitted for the colorpitch.
    
    Shouldn't have no effect on current kernels, but will keep DDX
    going on kms kernels when tiling lands
    
    Also contains a missing reloc space for r200

diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 641ea1f..9cd70cd 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -639,11 +639,11 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
 	info->accel_state->is_transform[1] = FALSE;
     }
 
-    BEGIN_ACCEL_RELOC(10, 1);
+    BEGIN_ACCEL_RELOC(10, 2);
     OUT_ACCEL_REG(RADEON_PP_CNTL, pp_cntl);
     OUT_ACCEL_REG(RADEON_RB3D_CNTL, dst_format | RADEON_ALPHA_BLEND_ENABLE);
     EMIT_WRITE_OFFSET(RADEON_RB3D_COLOROFFSET, 0, pDst);
-    OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, colorpitch);
+    EMIT_COLORPITCH(RADEON_RB3D_COLORPITCH, colorpitch, pDst);
 
     /* IN operator: Multiply src by mask components or mask alpha.
      * BLEND_CTL_ADD is A * B + C.
@@ -968,12 +968,13 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
 	info->accel_state->is_transform[1] = FALSE;
     }
 
-    BEGIN_ACCEL_RELOC(13, 1);
+    BEGIN_ACCEL_RELOC(13, 2);
 
     OUT_ACCEL_REG(RADEON_PP_CNTL, pp_cntl);
     OUT_ACCEL_REG(RADEON_RB3D_CNTL, dst_format | RADEON_ALPHA_BLEND_ENABLE);
 
     EMIT_WRITE_OFFSET(RADEON_RB3D_COLOROFFSET, 0, pDst);
+    EMIT_COLORPITCH(RADEON_RB3D_COLORPITCH, colorpitch, pDst);
 
     OUT_ACCEL_REG(R200_SE_VTX_FMT_0, R200_VTX_XY);
     if (pMask)
@@ -984,7 +985,7 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
 	OUT_ACCEL_REG(R200_SE_VTX_FMT_1,
 		      (2 << R200_VTX_TEX0_COMP_CNT_SHIFT));
 
-    OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, colorpitch);
+
 
     /* IN operator: Multiply src by mask components or mask alpha.
      * BLEND_CTL_ADD is A * B + C.
@@ -2003,9 +2004,9 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
     FINISH_ACCEL();
 
     
-    BEGIN_ACCEL_RELOC(3, 1);
+    BEGIN_ACCEL_RELOC(3, 2);
     EMIT_WRITE_OFFSET(R300_RB3D_COLOROFFSET0, 0, pDst);
-    OUT_ACCEL_REG(R300_RB3D_COLORPITCH0, colorpitch);
+    EMIT_COLORPITCH(R300_RB3D_COLORPITCH0, colorpitch, pDst);
 
     blendcntl = RADEONGetBlendCntl(op, pMaskPicture, pDstPicture->format);
     OUT_ACCEL_REG(R300_RB3D_BLENDCNTL, blendcntl | R300_ALPHA_BLEND_ENABLE | R300_READ_ENABLE);
diff --git a/src/radeon_macros.h b/src/radeon_macros.h
index ae8d950..26d9825 100644
--- a/src/radeon_macros.h
+++ b/src/radeon_macros.h
@@ -196,5 +196,14 @@ do {									\
       OUT_ACCEL_REG((reg), (offset) + info->fbLocation + pScrn->fbOffset);} \
   } while(0)
 
+#define EMIT_COLORPITCH(reg, value, pPix) do {			\
+    if (info->cs) {						\
+	driver_priv = exaGetPixmapDriverPrivate(pPix);			\
+	OUT_ACCEL_REG((reg), value);					\
+	OUT_RELOC(driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);		\
+    } else {								\
+	OUT_ACCEL_REG((reg), value);					\
+    }									\
+}while(0)
 
 #endif
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index 95db7d5..1d6b2e7 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -197,11 +197,11 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 
     txoffset = info->cs ? 0 : pPriv->src_offset;
 
-    BEGIN_ACCEL_RELOC(4,1);
+    BEGIN_ACCEL_RELOC(4,2);
 
     OUT_ACCEL_REG(RADEON_RB3D_CNTL, dst_format);
     EMIT_WRITE_OFFSET(RADEON_RB3D_COLOROFFSET, 0, pPixmap);
-    OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, colorpitch);
+    EMIT_COLORPITCH(RADEON_RB3D_COLORPITCH, colorpitch, pPixmap);
     OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL,
 		  RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO);
 
@@ -583,11 +583,11 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     if (RADEONTilingEnabled(pScrn, pPixmap))
 	colorpitch |= RADEON_COLOR_TILE_ENABLE;
 
-    BEGIN_ACCEL(4);
+    BEGIN_ACCEL_RELOC(4,2);
 
     OUT_ACCEL_REG(RADEON_RB3D_CNTL, dst_format);
     EMIT_WRITE_OFFSET(RADEON_RB3D_COLOROFFSET, 0, pPixmap);
-    OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, colorpitch);
+    EMIT_COLORPITCH(RADEON_RB3D_COLORPITCH, colorpitch, pPixmap);
 
     OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL,
 		  RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO);
@@ -2271,12 +2271,12 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	FINISH_ACCEL();
     }
 
-    BEGIN_ACCEL_RELOC(6, 1);
+    BEGIN_ACCEL_RELOC(6, 2);
     OUT_ACCEL_REG(R300_TX_INVALTAGS, 0);
     OUT_ACCEL_REG(R300_TX_ENABLE, txenable);
 
     EMIT_WRITE_OFFSET(R300_RB3D_COLOROFFSET0, 0, pPixmap);
-    OUT_ACCEL_REG(R300_RB3D_COLORPITCH0, colorpitch);
+    EMIT_COLORPITCH(R300_RB3D_COLORPITCH0, colorpitch, pPixmap);
 
     /* no need to enable blending */
     OUT_ACCEL_REG(R300_RB3D_BLENDCNTL, RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO);
@@ -3848,12 +3848,12 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	FINISH_ACCEL();
     }
 
-    BEGIN_ACCEL_RELOC(6, 1);
+    BEGIN_ACCEL_RELOC(6, 2);
     OUT_ACCEL_REG(R300_TX_INVALTAGS, 0);
     OUT_ACCEL_REG(R300_TX_ENABLE, txenable);
 
     EMIT_WRITE_OFFSET(R300_RB3D_COLOROFFSET0, 0, pPixmap);
-    OUT_ACCEL_REG(R300_RB3D_COLORPITCH0, colorpitch);
+    EMIT_COLORPITCH(R300_RB3D_COLORPITCH0, colorpitch, pPixmap);
 
     /* no need to enable blending */
     OUT_ACCEL_REG(R300_RB3D_BLENDCNTL, RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO);
commit 8312763977b22e108b7d003cbf3256e0165e4439
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Jul 14 18:13:27 2009 -0400

    Add an r420 AGP quirk
    
    fixes bug 22726

diff --git a/src/radeon_dri.c b/src/radeon_dri.c
index d37e0ae..77a3ff7 100644
--- a/src/radeon_dri.c
+++ b/src/radeon_dri.c
@@ -798,6 +798,9 @@ static radeon_agpmode_quirk radeon_agpmode_quirk_list[] = {
     /* HP Host Bridge / R300 [FireGL X1] Needs AGPMode 2 (fdo #7770) */
     { PCI_VENDOR_HP,0x122e,    PCI_VENDOR_ATI,0x4e47,  PCI_VENDOR_ATI,0x0152,    2 },
 
+    /* nVidia Host Bridge / R420 [X800 Pro] Needs AGPMode 4 (fdo #22726) */
+    { 0x10de,0x00e1,           PCI_VENDOR_ATI,0x4a49,  PCI_VENDOR_ATI,0x0002,    4 },
+
     { 0, 0, 0, 0, 0, 0, 0 },
 };
 
commit 5473eeeb45468fd200fec49a8506281628a5e4b5
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Jul 14 14:05:13 2009 -0400

    R3/4/5xx: only upload the bicubic texture once
    
    Upload the bicubic texture once during textured video init
    rather than once per frame.  Suggested by Michel Daenzer on
    IRC.

diff --git a/src/radeon.h b/src/radeon.h
index ad9a908..3c62fd9 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -999,6 +999,10 @@ typedef struct {
     Bool cs;
 #endif
 
+    /* Xv bicubic filtering */
+    struct radeon_bo *bicubic_bo;
+    void             *bicubic_memory;
+    int               bicubic_offset;
 } RADEONInfoRec, *RADEONInfoPtr;
 
 #define RADEONWaitForFifo(pScrn, entries)				\
diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c
index 617f359..d034c33 100644
--- a/src/radeon_textured_video.c
+++ b/src/radeon_textured_video.c
@@ -332,16 +332,10 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
     }
 
     /* Bicubic filter loading */
-    if (pPriv->bicubic_memory == NULL && pPriv->bicubic_enabled) {
-	pPriv->bicubic_offset = radeon_legacy_allocate_memory(pScrn,
-						              &pPriv->bicubic_memory,
-						              sizeof(bicubic_tex_512), 64);
-	pPriv->bicubic_src_offset = pPriv->bicubic_offset;
-	if (pPriv->bicubic_offset == 0)
-		pPriv->bicubic_enabled = FALSE;
-
-	if (info->cs)
-	    pPriv->bicubic_bo = pPriv->bicubic_memory;
+    if (pPriv->bicubic_enabled) {
+	if (info->bicubic_offset == 0)
+	    pPriv->bicubic_enabled = FALSE;
+	pPriv->bicubic_src_offset = info->bicubic_offset;
     }
 
     if (pDraw->type == DRAWABLE_WINDOW)
@@ -375,9 +369,9 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
 	int ret;
 	radeon_bo_wait(pPriv->src_bo);
 	ret = radeon_bo_map(pPriv->src_bo, 1);
-	if (ret) 
+	if (ret)
 	    return BadAlloc;
-	
+
 	pPriv->src_addr = pPriv->src_bo->ptr;
     } else {
 	pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset);
@@ -448,27 +442,6 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
 	break;
     }
 
-    /* Upload bicubic filter tex */
-    if (pPriv->bicubic_enabled) {
-	if (info->ChipFamily < CHIP_FAMILY_R600) {
-	    uint8_t *bicubic_addr;
-	    int ret;
-	    if (info->cs) {
-		radeon_bo_wait(pPriv->bicubic_bo);
-		ret = radeon_bo_map(pPriv->bicubic_bo, 1);
-		if (ret)
-		    return BadAlloc;
-
-		bicubic_addr = pPriv->bicubic_bo->ptr;
-	    } else
-		bicubic_addr = (uint8_t *)(info->FB + pPriv->bicubic_offset);
-
-	    RADEONCopyData(pScrn, (uint8_t *)bicubic_tex_512, bicubic_addr, 1024, 1024, 1, 512, 2);
-	   if (info->cs)
-	       radeon_bo_unmap(pPriv->bicubic_bo);
-	}
-    }
-
     /* update cliplist */
     if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
 	REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
@@ -698,6 +671,53 @@ RADEONSetTexPortAttribute(ScrnInfoPtr  pScrn,
     return Success;
 }
 
+static Bool radeon_load_bicubic_texture(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr    info = RADEONPTR(pScrn);
+
+    /* Bicubic filter loading */
+    info->bicubic_offset = radeon_legacy_allocate_memory(pScrn,
+							 &info->bicubic_memory,
+							 sizeof(bicubic_tex_512), 64);
+    if (info->bicubic_offset == 0)
+	return FALSE;
+
+    if (info->cs)
+	info->bicubic_bo = info->bicubic_memory;
+
+    /* Upload bicubic filter tex */
+    if (info->ChipFamily < CHIP_FAMILY_R600) {
+	uint8_t *bicubic_addr;
+	int ret;
+	if (info->cs) {
+	    radeon_bo_wait(info->bicubic_bo);
+	    ret = radeon_bo_map(info->bicubic_bo, 1);
+	    if (ret)
+		return FALSE;
+
+	    bicubic_addr = info->bicubic_bo->ptr;
+	} else
+	    bicubic_addr = (uint8_t *)(info->FB + info->bicubic_offset);
+
+	RADEONCopyData(pScrn, (uint8_t *)bicubic_tex_512, bicubic_addr, 1024, 1024, 1, 512, 2);
+	if (info->cs)
+	    radeon_bo_unmap(info->bicubic_bo);
+    }
+    return TRUE;
+}
+
+/* XXX */
+static void radeon_unload_bicubic_texture(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr    info = RADEONPTR(pScrn);
+
+    if (info->bicubic_memory != NULL) {
+	radeon_legacy_free_memory(pScrn, info->bicubic_memory);
+	info->bicubic_memory = NULL;
+    }
+
+}
+
 XF86VideoAdaptorPtr
 RADEONSetupImageTexturedVideo(ScreenPtr pScreen)
 {
@@ -795,6 +815,9 @@ RADEONSetupImageTexturedVideo(ScreenPtr pScreen)
 	adapt->pPortPrivates[i].ptr = (pointer) (pPriv);
     }
 
+    if (IS_R500_3D || IS_R300_3D)
+	radeon_load_bicubic_texture(pScrn);
+
     return adapt;
 }
 
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index 280a799..95db7d5 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -110,7 +110,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
         radeon_cs_space_add_persistent_bo(info->cs, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	if (pPriv->bicubic_enabled)
-	    radeon_cs_space_add_persistent_bo(info->cs, pPriv->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	    radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	driver_priv = exaGetPixmapDriverPrivate(pPixmap);
 	radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
@@ -499,7 +499,7 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
         radeon_cs_space_add_persistent_bo(info->cs, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	if (pPriv->bicubic_enabled)
-	    radeon_cs_space_add_persistent_bo(info->cs, pPriv->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	    radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	driver_priv = exaGetPixmapDriverPrivate(pPixmap);
 	radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
@@ -1041,7 +1041,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	radeon_cs_space_add_persistent_bo(info->cs, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	if (pPriv->bicubic_enabled)
-	  radeon_cs_space_add_persistent_bo(info->cs, pPriv->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	  radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	driver_priv = exaGetPixmapDriverPrivate(pPixmap);
 	radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
@@ -1227,7 +1227,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	OUT_ACCEL_REG(R300_TX_FORMAT0_1, txformat0);
 	OUT_ACCEL_REG(R300_TX_FORMAT1_1, txformat1);
 	OUT_ACCEL_REG(R300_TX_FORMAT2_1, txpitch);
-	OUT_TEXTURE_REG(R300_TX_OFFSET_1, bicubic_offset, pPriv->bicubic_bo);
+	OUT_TEXTURE_REG(R300_TX_OFFSET_1, bicubic_offset, info->bicubic_bo);
 	FINISH_ACCEL();
 
 	/* Enable tex 1 */
@@ -2492,7 +2492,7 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	radeon_cs_space_add_persistent_bo(info->cs, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	if (pPriv->bicubic_enabled)
-	    radeon_cs_space_add_persistent_bo(info->cs, pPriv->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	    radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	driver_priv = exaGetPixmapDriverPrivate(pPixmap);
 	radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
@@ -2681,7 +2681,7 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	OUT_ACCEL_REG(R300_TX_FORMAT0_1, txformat0);
 	OUT_ACCEL_REG(R300_TX_FORMAT1_1, txformat1);
 	OUT_ACCEL_REG(R300_TX_FORMAT2_1, txpitch);
-	OUT_TEXTURE_REG(R300_TX_OFFSET_1, bicubic_offset, pPriv->bicubic_bo);
+	OUT_TEXTURE_REG(R300_TX_OFFSET_1, bicubic_offset, info->bicubic_bo);
 	FINISH_ACCEL();
 
 	/* Enable tex 1 */
diff --git a/src/radeon_video.c b/src/radeon_video.c
index 58b9d46..f1fe72b 100644
--- a/src/radeon_video.c
+++ b/src/radeon_video.c
@@ -1648,10 +1648,6 @@ RADEONStopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
 
   if (pPriv->textured) {
       if (cleanup) {
-	  if (pPriv->bicubic_memory != NULL) {
-	      radeon_legacy_free_memory(pScrn, pPriv->bicubic_memory);
-	      pPriv->bicubic_memory = NULL;
-	  }
 	  if (pPriv->video_memory != NULL) {
 	      radeon_legacy_free_memory(pScrn, pPriv->video_memory);
 	      pPriv->video_memory = NULL;
diff --git a/src/radeon_video.h b/src/radeon_video.h
index aeb6441..989942c 100644
--- a/src/radeon_video.h
+++ b/src/radeon_video.h
@@ -94,8 +94,6 @@ typedef struct {
    int           planev_offset;
 
    /* bicubic filtering */
-   void         *bicubic_memory;
-   int           bicubic_offset;
    Bool          bicubic_enabled;
    uint32_t      bicubic_src_offset;
    int           bicubic_state;
@@ -122,7 +120,6 @@ typedef struct {
     int vsync;
 
     struct radeon_bo *src_bo;
-    struct radeon_bo *bicubic_bo;
 } RADEONPortPrivRec, *RADEONPortPrivPtr;
 
 /* Reference color space transform data */
commit 0485f27bc3d75cb6ab320e8164dbe6ea2713c78e
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Jul 14 13:11:12 2009 -0400

    R3/4/5xx: fix bicubic Xv filtering with KMS changes
    
    fixes bug 22730

diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c
index 10414b9..617f359 100644
--- a/src/radeon_textured_video.c
+++ b/src/radeon_textured_video.c
@@ -336,7 +336,7 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
 	pPriv->bicubic_offset = radeon_legacy_allocate_memory(pScrn,
 						              &pPriv->bicubic_memory,
 						              sizeof(bicubic_tex_512), 64);
-	pPriv->bicubic_src_offset = pPriv->bicubic_offset + info->fbLocation + pScrn->fbOffset;
+	pPriv->bicubic_src_offset = pPriv->bicubic_offset;
 	if (pPriv->bicubic_offset == 0)
 		pPriv->bicubic_enabled = FALSE;
 
@@ -458,7 +458,7 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
 		ret = radeon_bo_map(pPriv->bicubic_bo, 1);
 		if (ret)
 		    return BadAlloc;
-		
+
 		bicubic_addr = pPriv->bicubic_bo->ptr;
 	    } else
 		bicubic_addr = (uint8_t *)(info->FB + pPriv->bicubic_offset);
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index 6e8b3f9..280a799 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -1220,7 +1220,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	    bicubic_offset = 0;
 	else
 	    bicubic_offset = pPriv->bicubic_src_offset;
-       
+
 	BEGIN_ACCEL_RELOC(6, 1);
 	OUT_ACCEL_REG(R300_TX_FILTER0_1, txfilter);
 	OUT_ACCEL_REG(R300_TX_FILTER1_1, 0);
commit ca4a9efef987108266ae59afbb5142d4d2000c8e
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Mon Jul 13 11:28:41 2009 -0400

    Add configure option to disable kms support
    
    Useful to building with mixed kms/non-kms setups

diff --git a/configure.ac b/configure.ac
index 12be307..39018b8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -70,6 +70,12 @@ AC_ARG_ENABLE(exa,
               [EXA="$enableval"],
               [EXA=yes])
 
+AC_ARG_ENABLE(kms,
+              AC_HELP_STRING([--disable-kms],
+                             [Disable KMS support [[default=enabled]]]),
+              [DRM_MODE="$enableval"],
+              [DRM_MODE=yes])
+
 AC_ARG_WITH(xserver-source,AC_HELP_STRING([--with-xserver-source=XSERVER_SOURCE],
                                           [Path to X server source tree]),
                            [ XSERVER_SOURCE="$withval" ],
@@ -125,17 +131,20 @@ if test "$DRI" = yes; then
 
         save_CFLAGS="$CFLAGS"
         CFLAGS="$XORG_CFLAGS $DRI_CFLAGS $CFLAGS"
-	AC_CHECK_HEADER(xf86drmMode.h,[DRM_MODE=yes],[DRM_MODE=no],[#include <stdint.h>
+	AM_CONDITIONAL(DRM_MODE, test x$DRM_MODE = xyes)
+	if test "$DRM_MODE" = yes; then
+	   	AC_CHECK_HEADER(xf86drmMode.h,[DRM_MODE=yes],[DRM_MODE=no],[#include <stdint.h>
 #include <stdlib.h>])
-	if test "x$DRM_MODE" = xyes; then
-		PKG_CHECK_MODULES(LIBDRM_RADEON, [xorg-server >= 1.6 libdrm_radeon],
-		[LIBDRM_RADEON=yes], [LIBDRM_RADEON=no])
-
-		if test "x$LIBDRM_RADEON" = xyes; then
-			AC_DEFINE(XF86DRM_MODE,1,[DRM kernel modesetting])
-			AC_DEFINE(RADEON_DRI2, 1,[Enable DRI2 code])
-		fi
-        fi
+		if test "x$DRM_MODE" = xyes; then
+		   	PKG_CHECK_MODULES(LIBDRM_RADEON, [xorg-server >= 1.6 libdrm_radeon],
+			[LIBDRM_RADEON=yes], [LIBDRM_RADEON=no])
+
+			if test "x$LIBDRM_RADEON" = xyes; then
+			   	AC_DEFINE(XF86DRM_MODE,1,[DRM kernel modesetting])
+				AC_DEFINE(RADEON_DRI2, 1,[Enable DRI2 code])
+			fi
+        	fi
+	fi
 	CFLAGS="$save_CFLAGS"
 fi
 
commit 035e8d1d5593c12828bb079de4e663cf1b1f1674
Author: Edward O'Callaghan <eocallaghan at auroraux.org>
Date:   Sun Jul 12 13:45:29 2009 +0200

    Fix a warning
    
    Signed-off-by: Nicolai Hähnle <nhaehnle at gmail.com>

diff --git a/src/radeon_drm.h b/src/radeon_drm.h
index dd0087a..daa42d6 100644
--- a/src/radeon_drm.h
+++ b/src/radeon_drm.h
@@ -549,7 +549,7 @@ typedef struct drm_radeon_init {
 		RADEON_CLEANUP_CP = 0x02,
 		RADEON_INIT_R200_CP = 0x03,
 		RADEON_INIT_R300_CP = 0x04,
-		RADEON_INIT_R600_CP = 0x05,
+		RADEON_INIT_R600_CP = 0x05
 	} func;
 	unsigned long sarea_priv_offset;
 	int is_pci; /* for overriding only */
commit 76af48c43f829e7aebacc9f2a623823fa26ee22b
Author: Gaetan Nadon <memsize at videotron.ca>
Date:   Wed Jul 8 09:58:56 2009 -0400

    xf86-video-ati: use XORG_CHANGELOG macro to create ChangeLog. #22611
    
    Build break: Makefile.am: command not found: git-log
    Adding the macro in configure.ac and use it in Makefile.am
    Refer to: https://bugs.freedesktop.org/show_bug.cgi?id=22611
    Tested: running autogen.sh, make and 'make dist'
    
    Signed-off-by: Gaetan Nadon <memsize at videotron.ca>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/Makefile.am b/Makefile.am
index 242f5b4..e76bf11 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -27,6 +27,6 @@ CLEANFILES = ChangeLog
 .PHONY: ChangeLog
 
 ChangeLog:
-	(GIT_DIR=$(top_srcdir)/.git git log > .changelog.tmp && mv .changelog.tmp ChangeLog; rm -f .changelog.tmp) || (touch ChangeLog; echo 'git directory not found: installing possibly empty changelog.' >&2)
+	$(CHANGELOG_CMD)
 
 dist-hook: ChangeLog
diff --git a/configure.ac b/configure.ac
index 1b7353f..12be307 100644
--- a/configure.ac
+++ b/configure.ac
@@ -28,6 +28,11 @@ AC_INIT([xf86-video-ati],
 
 AC_CONFIG_SRCDIR([Makefile.am])
 AM_CONFIG_HEADER([config.h])
+
+# Require xorg-macros: XORG_RELEASE_VERSION XORG_CHANGELOG
+m4_ifndef([XORG_MACROS_VERSION], [AC_FATAL([must install xorg-macros 1.2 or later before running autoconf/autogen])])
+XORG_MACROS_VERSION(1.2)
+
 AC_CONFIG_AUX_DIR(.)
 
 AM_INIT_AUTOMAKE([dist-bzip2])
@@ -340,6 +345,7 @@ AC_SUBST([DRIVER_NAME])
 XORG_MANPAGE_SECTIONS
 XORG_RELEASE_VERSION
 XORG_CHECK_LINUXDOC
+XORG_CHANGELOG
 
 AC_MSG_NOTICE(
 [The atimisc sub-driver has been split out to xf86-video-mach64:]
commit 43db263d301082e84e9bc304816bcbb206fe280e
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Jul 9 12:48:06 2009 -0400

    RV280: another AGP quirk
    
    fdo bug 12544

diff --git a/src/radeon_dri.c b/src/radeon_dri.c
index af56d9f..d37e0ae 100644
--- a/src/radeon_dri.c
+++ b/src/radeon_dri.c
@@ -789,6 +789,8 @@ static radeon_agpmode_quirk radeon_agpmode_quirk_list[] = {
     { PCI_VENDOR_VIA,0x3189,    PCI_VENDOR_ATI,0x5960,  0x1462,0x0380,           4 },
     /* VIA VT8377 Host Bridge / RV280 Needs AGPMode 4 (ati ML) */
     { PCI_VENDOR_VIA,0x3189,    PCI_VENDOR_ATI,0x5964,  0x148c,0x2073,           4 },
+    /* VIA VT8377 Host Bridge / RV280 Needs AGPMode 4 (fdo #12544) */
+    { PCI_VENDOR_VIA,0x3189,    PCI_VENDOR_ATI,0x5964,  0x1043,0xc008,           4 },
 
     /* ATI Host Bridge / RV280 [M9+] Needs AGPMode 1 (phoronix forum) */
     { PCI_VENDOR_ATI,0xcbb2,    PCI_VENDOR_ATI,0x5c61,  PCI_VENDOR_SONY,0x8175,  1 },
commit 69b5e5496f10a9f566d2e563862c96cb41952eb6
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Jul 9 12:42:45 2009 -0400

    RV280: Add an AGP quirk
    
    lp bug 370205 via fdo bug 12544

diff --git a/src/radeon_dri.c b/src/radeon_dri.c
index 19f7abe..af56d9f 100644
--- a/src/radeon_dri.c
+++ b/src/radeon_dri.c
@@ -767,6 +767,8 @@ static radeon_agpmode_quirk radeon_agpmode_quirk_list[] = {
     { PCI_VENDOR_INTEL,0x3580,  PCI_VENDOR_ATI,0x4e50,  PCI_VENDOR_ASUS,0x1942,  1 },
     /* Intel 82852/82855 host bridge / Mobility 9600/9700 Needs AGPMode 1 (deb #510208) */
     { PCI_VENDOR_INTEL,0x3580,  PCI_VENDOR_ATI,0x4e50,  0x10cf,0x127f,           1 },
+    /* Intel 82443BX/ZX/DX Host bridge / RV280 [Radeon 9200] Needs AGPMode 1 (lp #370205) */
+    { PCI_VENDOR_INTEL,0x7190,  PCI_VENDOR_ATI,0x5961,  0x174b,0x7c13,           1 },
 
     /* ASRock K7VT4A+ AGP 8x / ATI Radeon 9250 AGP Needs AGPMode 4 (lp #133192) */
     { 0x1849,0x3189,            PCI_VENDOR_ATI,0x5960,  0x1787,0x5960,           4 },
commit a6d6c900e60a3685ee9e93c34eb7f6d237c45fd8
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu Jul 9 11:30:57 2009 -0400

    RS740: fixup display latency setting as per rs690
    
    Both chips program the same in this regard

diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index d3fb62b..6d24c2b 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -693,7 +693,8 @@ RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn,
 	uint32_t mc_init_misc_lat_timer = 0;
 	if (info->ChipFamily == CHIP_FAMILY_RV515)
 	    mc_init_misc_lat_timer = INMC(pScrn, RV515_MC_INIT_MISC_LAT_TIMER);
-	else if (info->ChipFamily == CHIP_FAMILY_RS690)
+	else if ((info->ChipFamily == CHIP_FAMILY_RS690) ||
+		 (info->ChipFamily == CHIP_FAMILY_RS740))
 	    mc_init_misc_lat_timer = INMC(pScrn, RS690_MC_INIT_MISC_LAT_TIMER);
 
 	mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT);
@@ -706,7 +707,8 @@ RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn,
 
 	if (info->ChipFamily == CHIP_FAMILY_RV515)
 	    OUTMC(pScrn, RV515_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
-	else if (info->ChipFamily == CHIP_FAMILY_RS690)
+	else if ((info->ChipFamily == CHIP_FAMILY_RS690) ||
+		 (info->ChipFamily == CHIP_FAMILY_RS740))
 	    OUTMC(pScrn, RS690_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
     }
 
commit ea407570d39ace3162d372eda56bf791bfd80c24
Author: Dave Airlie <airlied at redhat.com>
Date:   Thu Jul 9 10:46:23 2009 +1000

    radeon: add shave support.
    
    clean up output a lot

diff --git a/.gitignore b/.gitignore
index ddc5574..45acc17 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,3 +32,5 @@ radeon.4
 radeon.4x
 stamp-h1
 *cscope*
+shave
+shave-libtool
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644
index 0000000..0a3509e
--- /dev/null
+++ b/acinclude.m4
@@ -0,0 +1,77 @@
+dnl Make automake/libtool output more friendly to humans
+dnl  Damien Lespiau <damien.lespiau at gmail.com>
+dnl
+dnl SHAVE_INIT([shavedir],[default_mode])
+dnl
+dnl shavedir: the directory where the shave scripts are, it defaults to
+dnl           $(top_builddir)
+dnl default_mode: (enable|disable) default shave mode.  This parameter
+dnl               controls shave's behaviour when no option has been
+dnl               given to configure.  It defaults to disable.
+dnl
+dnl * SHAVE_INIT should be called late in your configure.(ac|in) file (just
+dnl   before AC_CONFIG_FILE/AC_OUTPUT is perfect.  This macro rewrites CC and
+dnl   LIBTOOL, you don't want the configure tests to have these variables
+dnl   re-defined.
+dnl * This macro requires GNU make's -s option.
+
+AC_DEFUN([_SHAVE_ARG_ENABLE],
+[
+  AC_ARG_ENABLE([shave],
+    AS_HELP_STRING(
+      [--enable-shave],
+      [use shave to make the build pretty [[default=$1]]]),,
+      [enable_shave=$1]
+    )
+])
+
+AC_DEFUN([SHAVE_INIT],
+[
+  dnl you can tweak the default value of enable_shave
+  m4_if([$2], [enable], [_SHAVE_ARG_ENABLE(yes)], [_SHAVE_ARG_ENABLE(no)])
+
+  if test x"$enable_shave" = xyes; then
+    dnl where can we find the shave scripts?
+    m4_if([$1],,
+      [shavedir="$ac_pwd"],
+      [shavedir="$ac_pwd/$1"])
+    AC_SUBST(shavedir)
+
+    dnl make is now quiet
+    AC_SUBST([MAKEFLAGS], [-s])
+    AC_SUBST([AM_MAKEFLAGS], ['`test -z $V && echo -s`'])
+
+    dnl we need sed
+    AC_CHECK_PROG(SED,sed,sed,false)
+
+    dnl substitute libtool
+    SHAVE_SAVED_LIBTOOL=$LIBTOOL
+    LIBTOOL="${SHELL} ${shavedir}/shave-libtool '${SHAVE_SAVED_LIBTOOL}'"
+    AC_SUBST(LIBTOOL)
+
+    dnl substitute cc/cxx
+    SHAVE_SAVED_CC=$CC
+    SHAVE_SAVED_CXX=$CXX
+    SHAVE_SAVED_FC=$FC
+    SHAVE_SAVED_F77=$F77
+    SHAVE_SAVED_OBJC=$OBJC
+    CC="${SHELL} ${shavedir}/shave cc ${SHAVE_SAVED_CC}"
+    CXX="${SHELL} ${shavedir}/shave cxx ${SHAVE_SAVED_CXX}"
+    FC="${SHELL} ${shavedir}/shave fc ${SHAVE_SAVED_FC}"
+    F77="${SHELL} ${shavedir}/shave f77 ${SHAVE_SAVED_F77}"
+    OBJC="${SHELL} ${shavedir}/shave objc ${SHAVE_SAVED_OBJC}"
+    AC_SUBST(CC)
+    AC_SUBST(CXX)
+    AC_SUBST(FC)
+    AC_SUBST(F77)
+    AC_SUBST(OBJC)
+
+    V=@
+  else
+    V=1
+  fi
+  Q='$(V:1=)'
+  AC_SUBST(V)
+  AC_SUBST(Q)
+])
+
diff --git a/configure.ac b/configure.ac
index 8cf69c1..1b7353f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -35,6 +35,8 @@ AC_SYS_LARGEFILE
 
 AM_MAINTAINER_MODE
 
+AC_CONFIG_FILES([shave shave-libtool])
+
 # Checks for programs.
 AC_DISABLE_STATIC
 AC_PROG_LIBTOOL
@@ -351,6 +353,8 @@ AC_MSG_NOTICE(
 [Please install that driver as well for rage128-based cards.]
 )
 
+SHAVE_INIT(.,enable)
+
 AC_OUTPUT([
 	Makefile
 	src/Makefile
diff --git a/shave-libtool.in b/shave-libtool.in
new file mode 100644
index 0000000..1f3a720
--- /dev/null
+++ b/shave-libtool.in
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+# we need sed
+SED=@SED@
+if test -z "$SED" ; then
+SED=sed
+fi
+
+lt_unmangle ()
+{
+   last_result=`echo $1 | $SED -e 's#.libs/##' -e 's#[0-9a-zA-Z_\-\.]*_la-##'`
+}
+
+# the real libtool to use
+LIBTOOL="$1"
+shift
+
+# if 1, don't print anything, the underlaying wrapper will do it
+pass_though=0
+
+# scan the arguments, keep the right ones for libtool, and discover the mode
+preserved_args=
+while test "$#" -gt 0; do
+    opt="$1"
+    shift
+
+    case $opt in
+    --mode=*)
+        mode=`echo $opt | $SED -e 's/[-_a-zA-Z0-9]*=//'`
+        preserved_args="$preserved_args $opt"
+        ;;
+    -o)
+        lt_output="$1"
+        preserved_args="$preserved_args $opt"
+	;;
+    *)
+        preserved_args="$preserved_args $opt"
+        ;;
+      esac
+done
+
+case "$mode" in
+compile)
+    # shave will be called and print the actual CC/CXX/LINK line
+    preserved_args="$preserved_args --shave-mode=$mode"
+    pass_though=1
+    ;;
+link)
+    preserved_args="$preserved_args --shave-mode=$mode"
+    Q="  LINK  "
+    ;;
+*)
+    # let's u
+    # echo "*** libtool: Unimplemented mode: $mode, fill a bug report"
+    ;;
+esac
+
+lt_unmangle "$lt_output"
+output=$last_result
+
+if test -z $V; then
+    if test $pass_though -eq 0; then
+        echo "$Q$output"
+    fi
+    $LIBTOOL --silent $preserved_args
+else
+    echo $LIBTOOL $preserved_args
+    $LIBTOOL $preserved_args
+fi
diff --git a/shave.in b/shave.in
new file mode 100644
index 0000000..5c16f27
--- /dev/null
+++ b/shave.in
@@ -0,0 +1,79 @@
+#!/bin/sh
+
+# we need sed
+SED=@SED@
+if test -z "$SED" ; then
+SED=sed
+fi
+
+lt_unmangle ()
+{
+   last_result=`echo $1 | $SED -e 's#.libs/##' -e 's#[0-9a-zA-Z_\-\.]*_la-##'`
+}
+
+# the tool to wrap (cc, cxx, ar, ranlib, ..)
+tool="$1"
+shift
+
+# the reel tool (to call)
+REEL_TOOL="$1"
+shift
+
+pass_through=0
+preserved_args=
+while test "$#" -gt 0; do
+    opt="$1"
+    shift
+
+    case $opt in
+    --shave-mode=*)
+        mode=`echo $opt | $SED -e 's/[-_a-zA-Z0-9]*=//'`
+	;;
+    -o)
+        lt_output="$1"
+        preserved_args="$preserved_args $opt"
+	;;
+    *)
+        preserved_args="$preserved_args $opt"
+        ;;
+      esac
+done
+
+# mode=link is handled in the libtool wrapper
+case "$mode,$tool" in
+link,*)
+    pass_through=1
+    ;;
+*,cxx)
+    Q="  CXX   "
+    ;;
+*,cc)
+    Q="  CC    "
+    ;;
+*,fc)
+    Q="  FC    "
+    ;;
+*,f77)
+    Q="  F77   "
+    ;;
+*,objc)
+    Q="  OBJC   "
+    ;;
+*,*)
+    # should not happen
+    Q="  CC    "
+    ;;
+esac
+
+lt_unmangle "$lt_output"
+output=$last_result
+
+if test -z $V; then
+    if test $pass_through -eq 0; then
+        echo "$Q$output"
+    fi
+    $REEL_TOOL $preserved_args
+else
+    echo $REEL_TOOL $preserved_args
+    $REEL_TOOL $preserved_args
+fi
commit 8c03c1fdb5ea35570064946557050c87ca30582a
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Jul 8 18:34:57 2009 -0400

    R6xx/R7xx: fix hangs on x2 cards with PM options
    
    Changing the PCIE lanes on x2 cards results in a hang,
    so for now, disable it.
    
    Fixes fdo bug 22669

diff --git a/src/radeon_pm.c b/src/radeon_pm.c
index 131a9fd..fe8f214 100644
--- a/src/radeon_pm.c
+++ b/src/radeon_pm.c
@@ -38,6 +38,8 @@
 #include "radeon_macros.h"
 #include "radeon_atombios.h"
 
+#include "ati_pciids_gen.h"
+
 /* 10 khz */
 static uint32_t calc_eng_mem_clock(ScrnInfoPtr pScrn,
 				   uint32_t req_clock,
@@ -629,6 +631,15 @@ RADEONSetPCIELanes(ScrnInfoPtr pScrn, int lanes)
     if (info->IsIGP)
 	return;
 
+    /* don't change lanes on multi-gpu cards for now */
+    if ((info->Chipset == PCI_CHIP_RV770_9441) ||
+	(info->Chipset == PCI_CHIP_RV770_9443) ||
+	(info->Chipset == PCI_CHIP_RV770_944B) ||
+	(info->Chipset == PCI_CHIP_RV670_9506) ||
+	(info->Chipset == PCI_CHIP_RV670_9509) ||
+	(info->Chipset == PCI_CHIP_RV670_950F))
+	return;
+
     RADEONWaitForIdleMMIO(pScrn);
 
     switch (lanes) {
commit 9645838c57f6b40837fdce23ce7f9faefb3d9966
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Wed Jul 8 19:18:02 2009 +0200

    Further non-KMS fixes / cleanups.
    
    Only compile tested.

diff --git a/src/radeon.h b/src/radeon.h
index c5b2cc2..ad9a908 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -1519,6 +1519,13 @@ do {									\
 #endif /* XF86DRI */
 
 #if defined(XF86DRI) && defined(USE_EXA)
+
+#ifdef XF86DRM_MODE
+#define CS_FULL(cs) ((cs)->cdw > 15 * 1024)
+#else
+#define CS_FULL(cs) FALSE
+#endif
+
 #define RADEON_SWITCH_TO_2D()						\
 do {									\
 	uint32_t flush = 0;                                             \
@@ -1537,7 +1544,7 @@ do {									\
 	}								\
         info->accel_state->engineMode = EXA_ENGINEMODE_2D;              \
 } while (0);
-# ifdef XF86DRM_MODE
+
 #define RADEON_SWITCH_TO_3D()						\
 do {									\
 	uint32_t flush = 0;						\
@@ -1546,7 +1553,7 @@ do {									\
 	    flush = 1;                                                  \
 	    break;							\
 	case EXA_ENGINEMODE_2D:						\
-	    flush = !info->cs || info->cs->cdw > 15 * 1024;		\
+	    flush = !info->cs || CS_FULL(info->cs);			\
 	case EXA_ENGINEMODE_3D:						\
 	    break;							\
 	}								\
@@ -1560,29 +1567,6 @@ do {									\
 	    RADEONInit3DEngine(pScrn);                                  \
         info->accel_state->engineMode = EXA_ENGINEMODE_3D;              \
 } while (0);
-# else
-#define RADEON_SWITCH_TO_3D()						\
-do {									\
-	uint32_t flush = 0;						\
-	switch (info->accel_state->engineMode) {			\
-	case EXA_ENGINEMODE_UNKNOWN:					\
-	case EXA_ENGINEMODE_2D:						\
-	    flush = 1;                                                  \
-	    break;							\
-	case EXA_ENGINEMODE_3D:						\
-	    break;							\
-	}								\
-	if (flush) {							\
-	    if (info->cs)						\
-		radeon_cs_flush_indirect(pScrn);			\
-	    else if (info->directRenderingEnabled)			\
-		RADEONCPFlushIndirect(pScrn, 1);                        \
-	}                                                               \
-	if (!info->accel_state->XInited3D)				\
-	    RADEONInit3DEngine(pScrn);                                  \
-	info->accel_state->engineMode = EXA_ENGINEMODE_3D;              \
-} while (0);
-# endif
 #else
 #define RADEON_SWITCH_TO_2D()
 #define RADEON_SWITCH_TO_3D()
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index e7f1e9c..4f1f9ea 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -120,6 +120,9 @@ static __inline__ uint32_t F_TO_DW(float val)
     return tmp.l;
 }
 
+
+#ifdef XF86DRM_MODE
+
 static inline void radeon_add_pixmap(struct radeon_cs *cs, PixmapPtr pPix, int read_domains, int write_domain)
 {
     struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix);
@@ -127,6 +130,9 @@ static inline void radeon_add_pixmap(struct radeon_cs *cs, PixmapPtr pPix, int r
     radeon_cs_space_add_persistent_bo(cs, driver_priv->bo, read_domains, write_domain);
 }
 
+#endif /* XF86DRM_MODE */
+
+
 /* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we
  * require src and dest datatypes to be equal.
  */
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 4b75299..19adffb 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -152,8 +152,6 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 {
     RINFO_FROM_SCREEN(pPix->drawable.pScreen);
     uint32_t datatype, dst_pitch_offset;
-    struct radeon_exa_pixmap_priv *driver_priv;
-    int ret;
 
     TRACE;
 
@@ -166,7 +164,10 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 
     RADEON_SWITCH_TO_2D();
 
+#ifdef XF86DRM_MODE
     if (info->cs) {
+	struct radeon_exa_pixmap_priv *driver_priv;
+	int ret;
       
 	radeon_cs_space_reset_bos(info->cs);
 
@@ -176,8 +177,12 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 	ret = radeon_cs_space_check(info->cs);
 	if (ret)
 	    RADEON_FALLBACK(("Not enough RAM to hw accel solid operation\n"));
-    }
 
+	driver_priv = exaGetPixmapDriverPrivate(pPix);
+	if (driver_priv)
+	    info->state_2d.dst_bo = driver_priv->bo;
+    }
+#endif
 
     info->state_2d.default_sc_bottom_right = (RADEON_DEFAULT_SC_RIGHT_MAX |
 					       RADEON_DEFAULT_SC_BOTTOM_MAX);
@@ -197,10 +202,6 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     info->state_2d.src_pitch_offset = 0;
     info->state_2d.src_bo = NULL;
 
-    driver_priv = exaGetPixmapDriverPrivate(pPix);
-    if (driver_priv)
-      info->state_2d.dst_bo = driver_priv->bo;
-
     info->accel_state->dst_pix = pPix;
 
     FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_SOLID);
@@ -217,12 +218,8 @@ FUNC_NAME(RADEONSolid)(PixmapPtr pPix, int x1, int y1, int x2, int y2)
 
     TRACE;
 
-#ifdef ACCEL_CP
-    if (info->cs
-#ifdef XF86DRM_MODE
-	&& info->cs->cdw > 15 * 1024
-#endif
-	) {
+#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
+    if (info->cs && CS_FULL(info->cs)) {
 	FUNC_NAME(RADEONDone2D)(info->accel_state->dst_pix);
 	radeon_cs_flush_indirect(pScrn);
 	FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_SOLID);
@@ -277,13 +274,14 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc,   PixmapPtr pDst,
 {
     RINFO_FROM_SCREEN(pDst->drawable.pScreen);
     uint32_t datatype, src_pitch_offset, dst_pitch_offset;
-    struct radeon_exa_pixmap_priv *driver_priv;
-    int ret;
     TRACE;
 
     RADEON_SWITCH_TO_2D();
 
+#ifdef XF86DRM_MODE
     if (info->cs) {
+	struct radeon_exa_pixmap_priv *driver_priv;
+	int ret;
       
 	radeon_cs_space_reset_bos(info->cs);
 
@@ -299,6 +297,7 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc,   PixmapPtr pDst,
 	if (ret)
 	    RADEON_FALLBACK(("Not enough RAM to hw accel copy operation\n"));
     }
+#endif
 
     info->accel_state->xdir = xdir;
     info->accel_state->ydir = ydir;
@@ -330,12 +329,8 @@ FUNC_NAME(RADEONCopy)(PixmapPtr pDst,
 
     TRACE;
 
-#ifdef ACCEL_CP
-    if (info->cs
-#ifdef XF86DRM_MODE
-	&& info->cs->cdw > 15 * 1024
-#endif
-	) {
+#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
+    if (info->cs && CS_FULL(info->cs)) {
 	FUNC_NAME(RADEONDone2D)(info->accel_state->dst_pix);
 	radeon_cs_flush_indirect(pScrn);
 	FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_COPY);
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 73f8ee9..641ea1f 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -2115,12 +2115,8 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
     /* ErrorF("RadeonComposite (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n",
        srcX, srcY, maskX, maskY,dstX, dstY, w, h); */
 
-#ifdef ACCEL_CP
-    if (info->cs
-#ifdef XF86DRM_MODE
-	&& info->cs->cdw > 15 * 1024
-#endif
-	) {
+#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
+    if (info->cs && CS_FULL(info->cs)) {
 	FUNC_NAME(RadeonDoneComposite)(info->accel_state->dst_pix);
 	radeon_cs_flush_indirect(pScrn);
 	info->accel_state->exa->PrepareComposite(info->accel_state->composite_op,
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index b814921..6e8b3f9 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -100,10 +100,12 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
     int dstxoff, dstyoff, pixel_shift, vtx_count;
     BoxPtr pBox = REGION_RECTS(&pPriv->clip);
     int nBox = REGION_NUM_RECTS(&pPriv->clip);
-    int ret;
     ACCEL_PREAMBLE();
 
+#ifdef XF86DRM_MODE
     if (info->cs) {
+	int ret;
+
 	radeon_cs_space_reset_bos(info->cs);
         radeon_cs_space_add_persistent_bo(info->cs, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
@@ -119,6 +121,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	    return;
 	}
     }
+#endif
 
     pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
 
@@ -486,10 +489,12 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     int ref = pPriv->transform_index;
     float ucscale = 0.25, vcscale = 0.25;
     Bool needux8 = FALSE, needvx8 = FALSE;
-    int ret;
     ACCEL_PREAMBLE();
 
+#ifdef XF86DRM_MODE
     if (info->cs) {
+	int ret;
+
 	radeon_cs_space_reset_bos(info->cs);
         radeon_cs_space_add_persistent_bo(info->cs, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
@@ -505,6 +510,7 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	    return;
 	}
     }
+#endif
 
     pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
 
@@ -1025,10 +1031,12 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     int dstxoff, dstyoff, pixel_shift, vtx_count;
     BoxPtr pBox = REGION_RECTS(&pPriv->clip);
     int nBox = REGION_NUM_RECTS(&pPriv->clip);
-    int ret;
     ACCEL_PREAMBLE();
 
+#ifdef XF86DRM_MODE
     if (info->cs) {
+	int ret;
+
 	radeon_cs_space_reset_bos(info->cs);
 	radeon_cs_space_add_persistent_bo(info->cs, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
@@ -1044,6 +1052,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	    return;
 	}
     }
+#endif
 
     pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
 
@@ -2473,10 +2482,12 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     int dstxoff, dstyoff, pixel_shift, vtx_count;
     BoxPtr pBox = REGION_RECTS(&pPriv->clip);
     int nBox = REGION_NUM_RECTS(&pPriv->clip);
-    int ret;
     ACCEL_PREAMBLE();
 
+#ifdef XF86DRM_MODE
     if (info->cs) {
+	int ret;
+
 	radeon_cs_space_reset_bos(info->cs);
 	radeon_cs_space_add_persistent_bo(info->cs, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
@@ -2492,6 +2503,7 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	    return;
 	}
     }
+#endif
 
     pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
 
commit 2d86ec4ddb1fb83be95ed9cdcbabf4d568a6d7b6
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Wed Jul 8 12:33:34 2009 -0400

    Fix the build for the !XF86DRM_MODE case
    
    compile tested only.

diff --git a/src/radeon.h b/src/radeon.h
index d4e89d4..c5b2cc2 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -1537,7 +1537,7 @@ do {									\
 	}								\
         info->accel_state->engineMode = EXA_ENGINEMODE_2D;              \
 } while (0);
-
+# ifdef XF86DRM_MODE
 #define RADEON_SWITCH_TO_3D()						\
 do {									\
 	uint32_t flush = 0;						\
@@ -1560,6 +1560,29 @@ do {									\
 	    RADEONInit3DEngine(pScrn);                                  \
         info->accel_state->engineMode = EXA_ENGINEMODE_3D;              \
 } while (0);
+# else
+#define RADEON_SWITCH_TO_3D()						\
+do {									\
+	uint32_t flush = 0;						\
+	switch (info->accel_state->engineMode) {			\
+	case EXA_ENGINEMODE_UNKNOWN:					\
+	case EXA_ENGINEMODE_2D:						\
+	    flush = 1;                                                  \
+	    break;							\
+	case EXA_ENGINEMODE_3D:						\
+	    break;							\
+	}								\
+	if (flush) {							\
+	    if (info->cs)						\
+		radeon_cs_flush_indirect(pScrn);			\
+	    else if (info->directRenderingEnabled)			\
+		RADEONCPFlushIndirect(pScrn, 1);                        \
+	}                                                               \
+	if (!info->accel_state->XInited3D)				\
+	    RADEONInit3DEngine(pScrn);                                  \
+	info->accel_state->engineMode = EXA_ENGINEMODE_3D;              \
+} while (0);
+# endif
 #else
 #define RADEON_SWITCH_TO_2D()
 #define RADEON_SWITCH_TO_3D()
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index d215228..4b75299 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -218,7 +218,11 @@ FUNC_NAME(RADEONSolid)(PixmapPtr pPix, int x1, int y1, int x2, int y2)
     TRACE;
 
 #ifdef ACCEL_CP
-    if (info->cs && info->cs->cdw > 15 * 1024) {
+    if (info->cs
+#ifdef XF86DRM_MODE
+	&& info->cs->cdw > 15 * 1024
+#endif
+	) {
 	FUNC_NAME(RADEONDone2D)(info->accel_state->dst_pix);
 	radeon_cs_flush_indirect(pScrn);
 	FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_SOLID);
@@ -327,7 +331,11 @@ FUNC_NAME(RADEONCopy)(PixmapPtr pDst,
     TRACE;
 
 #ifdef ACCEL_CP
-    if (info->cs && info->cs->cdw > 15 * 1024) {
+    if (info->cs
+#ifdef XF86DRM_MODE
+	&& info->cs->cdw > 15 * 1024
+#endif
+	) {
 	FUNC_NAME(RADEONDone2D)(info->accel_state->dst_pix);
 	radeon_cs_flush_indirect(pScrn);
 	FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_COPY);
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 10144a6..73f8ee9 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -2116,7 +2116,11 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
        srcX, srcY, maskX, maskY,dstX, dstY, w, h); */
 
 #ifdef ACCEL_CP
-    if (info->cs && info->cs->cdw > 15 * 1024) {
+    if (info->cs
+#ifdef XF86DRM_MODE
+	&& info->cs->cdw > 15 * 1024
+#endif
+	) {
 	FUNC_NAME(RadeonDoneComposite)(info->accel_state->dst_pix);
 	radeon_cs_flush_indirect(pScrn);
 	info->accel_state->exa->PrepareComposite(info->accel_state->composite_op,
commit a68afc2a80b8581cc3d67e9b5a95a10b0d4ead0e
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Wed Jul 8 09:15:28 2009 +0200

    Fix RADEON_TRACE_FALL build.

diff --git a/src/radeon_macros.h b/src/radeon_macros.h
index b3b740f..ae8d950 100644
--- a/src/radeon_macros.h
+++ b/src/radeon_macros.h
@@ -169,7 +169,7 @@ do {									\
     if (!info->cs) {			       \
 	uint32_t _pix_offset = radeonGetPixmapOffset(pPix);	\
 	if ((_pix_offset & mask) != 0)					\
-	    RADEON_FALLBACK(("Bad %s offset 0x%x\n", type, (int)pix_offset)); \
+	    RADEON_FALLBACK(("Bad %s offset 0x%x\n", type, (int)_pix_offset)); \
     }									\
     } while(0)
 
commit 9ca0aeaad01b7c682396b30af48668f287a59d6e
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Wed Jul 8 09:13:36 2009 +0200

    Pass on CS relocation offset values.
    
    Not actually used ATM, but just in case...

diff --git a/src/radeon_macros.h b/src/radeon_macros.h
index 15d9d73..b3b740f 100644
--- a/src/radeon_macros.h
+++ b/src/radeon_macros.h
@@ -176,7 +176,7 @@ do {									\
 #define EMIT_OFFSET(reg, value, pPix, rd, wd) do {		\
     if (info->cs) {						\
 	driver_priv = exaGetPixmapDriverPrivate(pPix);		\
-	OUT_ACCEL_REG((reg), 0);				\
+	OUT_ACCEL_REG((reg), (value));				\
 	OUT_RELOC(driver_priv->bo, (rd), (wd));			\
     } else {							\
 	uint32_t _pix_offset;					\
commit f718dd794477fbdd5eeb4183f43ff25517c63034
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Wed Jul 8 09:11:18 2009 +0200

    Don't set EXA UploadTo/DownloadFromScreen hooks when they'd always return FALSE.

diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 11dde5a..d215228 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -368,9 +368,6 @@ RADEONUploadToScreenCP(PixmapPtr pDst, int x, int y, int w, int h,
 
     TRACE;
 
-    if (info->kms_enabled)
-	return FALSE;
-
     if (bpp < 8)
 	return FALSE;
 
@@ -446,9 +443,6 @@ RADEONDownloadFromScreenCP(PixmapPtr pSrc, int x, int y, int w, int h,
 
     TRACE;
 
-    if (info->kms_enabled)
-      return FALSE;
-
     /*
      * Try to accelerate download. Use an indirect buffer as scratch space,
      * blitting the bits to one half while copying them out of the other one and
@@ -570,9 +564,11 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen)
     info->accel_state->exa->MarkSync = FUNC_NAME(RADEONMarkSync);
     info->accel_state->exa->WaitMarker = FUNC_NAME(RADEONSync);
 #ifdef ACCEL_CP
-    info->accel_state->exa->UploadToScreen = RADEONUploadToScreenCP;
-    if (info->accelDFS)
-	info->accel_state->exa->DownloadFromScreen = RADEONDownloadFromScreenCP;
+    if (!info->kms_enabled) {
+	info->accel_state->exa->UploadToScreen = RADEONUploadToScreenCP;
+	if (info->accelDFS)
+	    info->accel_state->exa->DownloadFromScreen = RADEONDownloadFromScreenCP;
+    }
 #endif
 
 #if X_BYTE_ORDER == X_BIG_ENDIAN
commit 42e76d0b24b76fbcc6b08a4ea5003dbec368645c
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Wed Jul 8 08:51:10 2009 +0200

    Don't always flush CS when switching from 2D to 3D.
    
    This works fine here and doubles x11perf -aa10text scores, but may cause
    problems on other setups according to Dave. Let's see...

diff --git a/src/radeon.h b/src/radeon.h
index 5d5d5e1..d4e89d4 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -1543,8 +1543,10 @@ do {									\
 	uint32_t flush = 0;						\
 	switch (info->accel_state->engineMode) {			\
 	case EXA_ENGINEMODE_UNKNOWN:					\
-	case EXA_ENGINEMODE_2D:						\
 	    flush = 1;                                                  \
+	    break;							\
+	case EXA_ENGINEMODE_2D:						\
+	    flush = !info->cs || info->cs->cdw > 15 * 1024;		\
 	case EXA_ENGINEMODE_3D:						\
 	    break;							\
 	}								\
commit 94fe049c35187ddc3ec0472e9309c3a22879f415
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Wed Jul 8 08:36:22 2009 +0200

    KMS CS fixes, take two.
    
    Avoid flushing CS in the middle of (setting up state for) an operation,
    properly finish/restart the operation.

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 18831f7..3673064 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -1166,7 +1166,7 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
     }
 
     if (unit == 0) {
-	if (!accel_state->has_mask) {
+	if (!accel_state->msk_pic) {
 	    if (PICT_FORMAT_RGB(pPict->format) == 0) {
 		pix_r = SQ_SEL_0;
 		pix_g = SQ_SEL_0;
@@ -1397,7 +1397,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     /* return FALSE; */
 
     if (pMask) {
-	accel_state->has_mask = TRUE;
+	accel_state->msk_pic = pMaskPicture;
 	if (pMaskPicture->componentAlpha) {
 	    accel_state->component_alpha = TRUE;
 	    if (R600BlendOp[op].src_alpha)
@@ -1409,7 +1409,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
 	    accel_state->src_alpha = FALSE;
 	}
     } else {
-	accel_state->has_mask = FALSE;
+	accel_state->msk_pic = NULL;
 	accel_state->component_alpha = FALSE;
 	accel_state->src_alpha = FALSE;
     }
@@ -1598,7 +1598,7 @@ static void R600Composite(PixmapPtr pDst,
     srcBottomRight.x = IntToxFixed(srcX + w);
     srcBottomRight.y = IntToxFixed(srcY + h);
 
-    if (accel_state->has_mask) {
+    if (accel_state->msk_pic) {
 	xPointFixed maskTopLeft, maskTopRight, maskBottomLeft, maskBottomRight;
 
 	if (((accel_state->vb_index + 3) * 24) > (accel_state->ib->total / 2)) {
@@ -1693,7 +1693,7 @@ static void R600DoneComposite(PixmapPtr pDst)
 
 
     /* Vertex buffer setup */
-    if (accel_state->has_mask) {
+    if (accel_state->msk_pic) {
 	accel_state->vb_size = accel_state->vb_index * 24;
 	vtx_res.id              = SQ_VTX_RESOURCE_vs;
 	vtx_res.vtx_size_dw     = 24 / 4;
diff --git a/src/radeon.h b/src/radeon.h
index c030034..5d5d5e1 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -672,9 +672,15 @@ struct radeon_accel_state {
 #define EXA_ENGINEMODE_2D      1
 #define EXA_ENGINEMODE_3D      2
 
+    int               composite_op;
+    PicturePtr        dst_pic;
+    PicturePtr        msk_pic;
+    PicturePtr        src_pic;
+    PixmapPtr         dst_pix;
+    PixmapPtr         msk_pix;
+    PixmapPtr         src_pix;
     Bool              is_transform[2];
     PictTransform     *transform[2];
-    Bool              has_mask;
     /* Whether we are tiling horizontally and vertically */
     Bool              need_src_tile_x;
     Bool              need_src_tile_y;
@@ -1547,8 +1553,9 @@ do {									\
 	        radeon_cs_flush_indirect(pScrn);			\
 	    else if (info->directRenderingEnabled)				\
 	        RADEONCPFlushIndirect(pScrn, 1);                        \
-	    RADEONInit3DEngine(pScrn);                                  \
 	}                                                               \
+	if (!info->accel_state->XInited3D)				\
+	    RADEONInit3DEngine(pScrn);                                  \
         info->accel_state->engineMode = EXA_ENGINEMODE_3D;              \
 } while (0);
 #else
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 460824d..11dde5a 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -131,6 +131,22 @@ static void FUNC_NAME(Emit2DState)(ScrnInfoPtr pScrn, int op)
 	info->reemit_current2d = FUNC_NAME(Emit2DState);
 }
 
+static void
+FUNC_NAME(RADEONDone2D)(PixmapPtr pPix)
+{
+    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
+    ACCEL_PREAMBLE();
+
+    TRACE;
+
+    info->state_2d.op = 0;
+    BEGIN_ACCEL(2);
+    OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
+    OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
+                  RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
+    FINISH_ACCEL();
+}
+
 static Bool
 FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 {
@@ -185,6 +201,8 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     if (driver_priv)
       info->state_2d.dst_bo = driver_priv->bo;
 
+    info->accel_state->dst_pix = pPix;
+
     FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_SOLID);
 
     return TRUE;
@@ -199,6 +217,14 @@ FUNC_NAME(RADEONSolid)(PixmapPtr pPix, int x1, int y1, int x2, int y2)
 
     TRACE;
 
+#ifdef ACCEL_CP
+    if (info->cs && info->cs->cdw > 15 * 1024) {
+	FUNC_NAME(RADEONDone2D)(info->accel_state->dst_pix);
+	radeon_cs_flush_indirect(pScrn);
+	FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_SOLID);
+    }
+#endif
+
     if (info->accel_state->vsync)
 	FUNC_NAME(RADEONWaitForVLine)(pScrn, pPix, RADEONBiggerCrtcArea(pPix), y1, y2);
 
@@ -208,22 +234,6 @@ FUNC_NAME(RADEONSolid)(PixmapPtr pPix, int x1, int y1, int x2, int y2)
     FINISH_ACCEL();
 }
 
-static void
-FUNC_NAME(RADEONDone2D)(PixmapPtr pPix)
-{
-    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
-    ACCEL_PREAMBLE();
-
-    TRACE;
-
-    info->state_2d.op = 0;
-    BEGIN_ACCEL(2);
-    OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
-    OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
-                  RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
-    FINISH_ACCEL();
-}
-
 void
 FUNC_NAME(RADEONDoPrepareCopy)(ScrnInfoPtr pScrn, uint32_t src_pitch_offset,
 			       uint32_t dst_pitch_offset, uint32_t datatype, int rop,
@@ -288,6 +298,7 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc,   PixmapPtr pDst,
 
     info->accel_state->xdir = xdir;
     info->accel_state->ydir = ydir;
+    info->accel_state->dst_pix = pDst;
 
     if (pDst->drawable.bitsPerPixel == 24)
 	RADEON_FALLBACK(("24bpp unsupported"));
@@ -315,6 +326,14 @@ FUNC_NAME(RADEONCopy)(PixmapPtr pDst,
 
     TRACE;
 
+#ifdef ACCEL_CP
+    if (info->cs && info->cs->cdw > 15 * 1024) {
+	FUNC_NAME(RADEONDone2D)(info->accel_state->dst_pix);
+	radeon_cs_flush_indirect(pScrn);
+	FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_COPY);
+    }
+#endif
+
     if (info->accel_state->xdir < 0) {
 	srcX += w - 1;
 	dstX += w - 1;
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 1e07408..10144a6 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -542,6 +542,45 @@ static Bool R100CheckComposite(int op, PicturePtr pSrcPicture,
 
     return TRUE;
 }
+
+static Bool
+RADEONPrepareCompositeCS(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+			    PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask,
+			    PixmapPtr pDst)
+{
+    RINFO_FROM_SCREEN(pDst->drawable.pScreen);
+
+    info->accel_state->composite_op = op;
+    info->accel_state->dst_pic = pDstPicture;
+    info->accel_state->msk_pic = pMaskPicture;
+    info->accel_state->src_pic = pSrcPicture;
+    info->accel_state->dst_pix = pDst;
+    info->accel_state->msk_pix = pMask;
+    info->accel_state->src_pix = pSrc;
+
+#ifdef XF86DRM_MODE
+    if (info->cs) {
+	int ret;
+
+	radeon_cs_space_reset_bos(info->cs);
+
+	radeon_add_pixmap(info->cs, pSrc,
+			  RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	if (pMask)
+	    radeon_add_pixmap(info->cs, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
+
+	ret = radeon_cs_space_check(info->cs);
+	if (ret)
+	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
+    }
+#endif
+
+    return TRUE;
+}
+
 #endif /* ONLY_ONCE */
 
 static Bool FUNC_NAME(R100PrepareComposite)(int op,
@@ -557,7 +596,6 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
     uint32_t pp_cntl, blendcntl, cblend, ablend;
     int pixel_shift;
     struct radeon_exa_pixmap_priv *driver_priv;
-    int ret;
     ACCEL_PREAMBLE();
 
     TRACE;
@@ -568,11 +606,6 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
     if (pDstPicture->format == PICT_a8 && RadeonBlendOp[op].dst_alpha)
 	RADEON_FALLBACK(("Can't dst alpha blend A8\n"));
 
-    if (pMask)
-	info->accel_state->has_mask = TRUE;
-    else
-	info->accel_state->has_mask = FALSE;
-
     pixel_shift = pDst->drawable.bitsPerPixel >> 4;
 
     dst_pitch = exaGetPixmapPitch(pDst);
@@ -585,28 +618,15 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
 
-    /* switch to 3D before doing buffer space checks as it may flush */
-    RADEON_SWITCH_TO_3D();
-
-    if (info->cs) {
-	radeon_cs_space_reset_bos(info->cs);
-
-	radeon_add_pixmap(info->cs, pSrc,
-			  RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
-
-	if (pMask)
-	    radeon_add_pixmap(info->cs, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
-
-	radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
-
-	ret = radeon_cs_space_check(info->cs);
-	if (ret)
-	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
-    }
-
     if (!RADEONSetupSourceTile(pSrcPicture, pSrc, FALSE, TRUE))
 	return FALSE;
 
+    RADEONPrepareCompositeCS(op, pSrcPicture, pMaskPicture, pDstPicture,
+			     pSrc, pMask, pDst);
+
+    /* switch to 3D after doing buffer space checks as the latter may flush */
+    RADEON_SWITCH_TO_3D();
+
     if (!FUNC_NAME(R100TextureSetup)(pSrcPicture, pSrc, 0))
 	return FALSE;
     pp_cntl = RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE;
@@ -905,7 +925,6 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
     uint32_t pp_cntl, blendcntl, cblend, ablend, colorpitch;
     int pixel_shift;
     struct radeon_exa_pixmap_priv *driver_priv;
-    int ret;
     ACCEL_PREAMBLE();
 
     TRACE;
@@ -916,11 +935,6 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
     if (pDstPicture->format == PICT_a8 && RadeonBlendOp[op].dst_alpha)
 	RADEON_FALLBACK(("Can't dst alpha blend A8\n"));
 
-    if (pMask)
-	info->accel_state->has_mask = TRUE;
-    else
-	info->accel_state->has_mask = FALSE;
-
     pixel_shift = pDst->drawable.bitsPerPixel >> 4;
 
     dst_pitch = exaGetPixmapPitch(pDst);
@@ -933,26 +947,15 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
 
-    /* switch to 3D before doing buffer space checks as it may flush */
-    RADEON_SWITCH_TO_3D();
-
-    if (info->cs) {
-	radeon_cs_space_reset_bos(info->cs);
-        radeon_add_pixmap(info->cs, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
-
-	if (pMask)
-	    radeon_add_pixmap(info->cs, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
-
-	radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
-
-	ret = radeon_cs_space_check(info->cs);
-	if (ret)
- 	  RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
-    }
-
     if (!RADEONSetupSourceTile(pSrcPicture, pSrc, FALSE, TRUE))
 	return FALSE;
 
+    RADEONPrepareCompositeCS(op, pSrcPicture, pMaskPicture, pDstPicture,
+			     pSrc, pMask, pDst);
+
+    /* switch to 3D after doing buffer space checks as it may flush */
+    RADEON_SWITCH_TO_3D();
+
     if (!FUNC_NAME(R200TextureSetup)(pSrcPicture, pSrc, 0))
 	return FALSE;
     pp_cntl = RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE;
@@ -1145,7 +1148,7 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
     txformat1 = R300TexFormats[i].card_fmt;
 
     if (IS_R300_3D) {
-	if ((unit == 0) && info->accel_state->has_mask)
+	if ((unit == 0) && info->accel_state->msk_pic)
 	    txformat1 |= R300_TX_FORMAT_CACHE_HALF_REGION_0;
 	else if (unit == 1)
 	    txformat1 |= R300_TX_FORMAT_CACHE_HALF_REGION_1;
@@ -1383,7 +1386,6 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
     uint32_t src_color, src_alpha;
     uint32_t mask_color, mask_alpha;
     int pixel_shift;
-    int ret;
     struct radeon_exa_pixmap_priv *driver_priv;
     ACCEL_PREAMBLE();
     TRACE;
@@ -1391,11 +1393,6 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
     if (!R300GetDestFormat(pDstPicture, &dst_format))
 	return FALSE;
 
-    if (pMask)
-	info->accel_state->has_mask = TRUE;
-    else
-	info->accel_state->has_mask = FALSE;
-
     pixel_shift = pDst->drawable.bitsPerPixel >> 4;
 
     dst_pitch = exaGetPixmapPitch(pDst);
@@ -1411,26 +1408,15 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
 
-    /* have to execute switch before doing buffer sizing check as it flushes */
-    RADEON_SWITCH_TO_3D();
-
-    if (info->cs) {
-      	radeon_cs_space_reset_bos(info->cs);
-	radeon_add_pixmap(info->cs, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
-
-	if (pMask)
-	  radeon_add_pixmap(info->cs, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
-
-	radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
-
-	ret = radeon_cs_space_check(info->cs);
-	if (ret)
-	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
-    }
-
     if (!RADEONSetupSourceTile(pSrcPicture, pSrc, TRUE, FALSE))
 	return FALSE;
 
+    RADEONPrepareCompositeCS(op, pSrcPicture, pMaskPicture, pDstPicture,
+			     pSrc, pMask, pDst);
+
+    /* have to execute switch after doing buffer sizing check as the latter flushes */
+    RADEON_SWITCH_TO_3D();
+
     if (!FUNC_NAME(R300TextureSetup)(pSrcPicture, pSrc, 0))
 	return FALSE;
     txenable = R300_TEX_0_ENABLE;
@@ -2027,7 +2013,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
     FINISH_ACCEL();
 
     BEGIN_ACCEL(1);
-    if (info->accel_state->has_mask)
+    if (pMask)
 	OUT_ACCEL_REG(R300_VAP_VTX_SIZE, 6);
     else
 	OUT_ACCEL_REG(R300_VAP_VTX_SIZE, 4);
@@ -2036,6 +2022,25 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
     return TRUE;
 }
 
+static void FUNC_NAME(RadeonDoneComposite)(PixmapPtr pDst)
+{
+    RINFO_FROM_SCREEN(pDst->drawable.pScreen);
+    ACCEL_PREAMBLE();
+
+    ENTER_DRAW(0);
+
+    if (IS_R300_3D || IS_R500_3D) {
+	BEGIN_ACCEL(3);
+	OUT_ACCEL_REG(R300_SC_CLIP_RULE, 0xAAAA);
+	OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_RB3D_DC_FLUSH_ALL);
+    } else
+	BEGIN_ACCEL(1);
+    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
+    FINISH_ACCEL();
+
+    LEAVE_DRAW(0);
+}
+
 
 #ifdef ACCEL_CP
 
@@ -2110,6 +2115,20 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
     /* ErrorF("RadeonComposite (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n",
        srcX, srcY, maskX, maskY,dstX, dstY, w, h); */
 
+#ifdef ACCEL_CP
+    if (info->cs && info->cs->cdw > 15 * 1024) {
+	FUNC_NAME(RadeonDoneComposite)(info->accel_state->dst_pix);
+	radeon_cs_flush_indirect(pScrn);
+	info->accel_state->exa->PrepareComposite(info->accel_state->composite_op,
+						 info->accel_state->dst_pic,
+						 info->accel_state->msk_pic,
+						 info->accel_state->src_pic,
+						 info->accel_state->dst_pix,
+						 info->accel_state->msk_pix,
+						 info->accel_state->src_pix);
+    }
+#endif
+
     srcTopLeft.x     = IntToxFixed(srcX);
     srcTopLeft.y     = IntToxFixed(srcY);
     srcTopRight.x    = IntToxFixed(srcX + w);
@@ -2128,7 +2147,7 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
 	}
     }
 
-    if (info->accel_state->has_mask) {
+    if (info->accel_state->msk_pic) {
 	maskTopLeft.x     = IntToxFixed(maskX);
 	maskTopLeft.y     = IntToxFixed(maskY);
 	maskTopRight.x    = IntToxFixed(maskX + w);
@@ -2159,7 +2178,7 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
 	BEGIN_RING(3 * vtx_count + 3);
 	OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD,
 			    3 * vtx_count + 1));
-	if (info->accel_state->has_mask)
+	if (info->accel_state->msk_pic)
 	    OUT_RING(RADEON_CP_VC_FRMT_XY |
 		     RADEON_CP_VC_FRMT_ST0 |
 		     RADEON_CP_VC_FRMT_ST1);
@@ -2209,7 +2228,7 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
 
 #endif
 
-    if (info->accel_state->has_mask) {
+    if (info->accel_state->msk_pic) {
 	if (IS_R300_3D || IS_R500_3D) {
 	    VTX_OUT_MASK((float)dstX,                                      (float)dstY,
 			 xFixedToFloat(srcTopLeft.x) / info->accel_state->texW[0],      xFixedToFloat(srcTopLeft.y) / info->accel_state->texH[0],
@@ -2317,24 +2336,5 @@ static void FUNC_NAME(RadeonComposite)(PixmapPtr pDst,
     }
 }
 
-static void FUNC_NAME(RadeonDoneComposite)(PixmapPtr pDst)
-{
-    RINFO_FROM_SCREEN(pDst->drawable.pScreen);
-    ACCEL_PREAMBLE();
-
-    ENTER_DRAW(0);
-
-    if (IS_R300_3D || IS_R500_3D) {
-	BEGIN_ACCEL(3);
-	OUT_ACCEL_REG(R300_SC_CLIP_RULE, 0xAAAA);
-	OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_RB3D_DC_FLUSH_ALL);
-    } else
-	BEGIN_ACCEL(1);
-    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
-    FINISH_ACCEL();
-
-    LEAVE_DRAW(0);
-}
-
 #undef ONLY_ONCE
 #undef FUNC_NAME
commit 0519f15af2fe5e7e5a6c94e7203a96fe363c643e
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Tue Jul 7 10:04:09 2009 +0200

    Fix DRI2 with current xserver Git.

diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 37b47fe..4770ba3 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -308,7 +308,7 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
     dri2_info.CreateBuffers = radeon_dri2_create_buffers;
     dri2_info.DestroyBuffers = radeon_dri2_destroy_buffers;
 #else
-    dri2_info.version = 2;
+    dri2_info.version = DRI2INFOREC_VERSION;
     dri2_info.CreateBuffer = radeon_dri2_create_buffer;
     dri2_info.DestroyBuffer = radeon_dri2_destroy_buffer;
 #endif
commit 7ad11fec2579807371360cb680e593f723ebaa1a
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Jul 6 18:43:08 2009 +1000

    radeon: add make dist headers

diff --git a/src/Makefile.am b/src/Makefile.am
index 421d163..57a365b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -169,4 +169,6 @@ EXTRA_DIST = \
 	radeon_pci_device_match_gen.h \
 	pcidb/ati_pciids.csv \
 	pcidb/parse_pci_ids.pl \
-	radeon_atombios.h
+	radeon_atombios.h \
+	radeon_dri2.h \
+	drmmode_display.h
commit e68fbf743ec88e0fa3a9f1ffe83daf251e250b21
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Jul 6 18:32:32 2009 +1000

    git: fix git-log to git log

diff --git a/Makefile.am b/Makefile.am
index 87e90ba..242f5b4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -27,6 +27,6 @@ CLEANFILES = ChangeLog
 .PHONY: ChangeLog
 
 ChangeLog:
-	(GIT_DIR=$(top_srcdir)/.git git-log > .changelog.tmp && mv .changelog.tmp ChangeLog; rm -f .changelog.tmp) || (touch ChangeLog; echo 'git directory not found: installing possibly empty changelog.' >&2)
+	(GIT_DIR=$(top_srcdir)/.git git log > .changelog.tmp && mv .changelog.tmp ChangeLog; rm -f .changelog.tmp) || (touch ChangeLog; echo 'git directory not found: installing possibly empty changelog.' >&2)
 
 dist-hook: ChangeLog
commit 5eeb1fd19c6797cc76ce308570dffe34cb82b24d
Author: Dave Airlie <airlied at linux.ie>
Date:   Mon Jul 6 17:45:50 2009 +1000

    radeon: oops fix compile without libdrm

diff --git a/src/radeon_dummy_bufmgr.h b/src/radeon_dummy_bufmgr.h
index b3ff991..e08e656 100644
--- a/src/radeon_dummy_bufmgr.h
+++ b/src/radeon_dummy_bufmgr.h
@@ -55,7 +55,7 @@ static inline void radeon_cs_flush_indirect(ScrnInfoPtr pScrn)
 }
 
 static inline void radeon_ddx_cs_start(ScrnInfoPtr pScrn, int n,
-				       const char *file, const char *func, int line);
+				       const char *file, const char *func, int line)
 {
 }
 
commit 98824f37fc74dc1fec2677515d0dc3cfc263f00a
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Jul 6 15:29:53 2009 +1000

    radeon: move state changes into flush function

diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 4ff1c6a..59a654f 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -73,12 +73,17 @@ const OptionInfoRec RADEONOptions_KMS[] = {
 void radeon_cs_flush_indirect(ScrnInfoPtr pScrn)
 {
     RADEONInfoPtr  info = RADEONPTR(pScrn);
+    int ret;
 
     if (!info->cs->cdw)
 	return;
     radeon_cs_emit(info->cs);
     radeon_cs_erase(info->cs);
 
+    ret = radeon_cs_space_check(info->cs);
+    if (ret)
+      ErrorF("space check failed in flush\n");
+
     if (info->reemit_current2d)
       info->reemit_current2d(pScrn, 0);
     if (info->dri2.enabled) {
@@ -92,14 +97,10 @@ void radeon_ddx_cs_start(ScrnInfoPtr pScrn,
 			 const char *func, int line)
 {
     RADEONInfoPtr  info = RADEONPTR(pScrn);
-    int ret;
 
     if (info->cs->cdw + n > info->cs->ndw) {
 	radeon_cs_flush_indirect(pScrn);
-	ret = radeon_cs_space_check(info->cs);
-	if (ret)
-	    ErrorF("space check failed in DDX CS start %s:%s:%d\n",
-		   file, func, line);
+
     }
     radeon_cs_begin(info->cs, n, file, func, line);
 }
commit 503b51343267248b4c6994b88238dd5384528f03
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Jul 6 15:20:13 2009 +1000

    radeon: taken from kms-support + CS fixes commit.
    
    re-emit 2D state and reset 3D state emit on flush

diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 7ecfe88..4ff1c6a 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -78,6 +78,13 @@ void radeon_cs_flush_indirect(ScrnInfoPtr pScrn)
 	return;
     radeon_cs_emit(info->cs);
     radeon_cs_erase(info->cs);
+
+    if (info->reemit_current2d)
+      info->reemit_current2d(pScrn, 0);
+    if (info->dri2.enabled) {
+      info->accel_state->XInited3D = FALSE;
+      info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
+    }
 }
 
 void radeon_ddx_cs_start(ScrnInfoPtr pScrn,
commit d78d50591851d14543f0935d051a59ef29751bbc
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Jul 6 14:45:07 2009 +1000

    radeon: port to new space checking in libdrm interface
    
    This uses a new libdrm interface which shares code with mesa.
    
    It also fixes the bo to flush when full instead of never flushing.
    
    It survives gtkperf -a here which the driver didn't before now

diff --git a/src/radeon.h b/src/radeon.h
index 82136c8..c030034 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -1069,7 +1069,6 @@ extern void RADEONWaitForFifoFunction(ScrnInfoPtr pScrn, int entries);
 #ifdef XF86DRI
 extern drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn);
 extern void RADEONCPFlushIndirect(ScrnInfoPtr pScrn, int discard);
-extern void radeon_cs_flush_indirect(ScrnInfoPtr pScrn);
 extern void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn);
 extern int RADEONCPStop(ScrnInfoPtr pScrn,  RADEONInfoPtr info);
 #  ifdef USE_XAA
@@ -1266,6 +1265,12 @@ extern void
 radeon_legacy_free_memory(ScrnInfoPtr pScrn,
 		          void *mem_struct);
 
+#ifdef XF86DRM_MODE
+extern void radeon_cs_flush_indirect(ScrnInfoPtr pScrn);
+extern void radeon_ddx_cs_start(ScrnInfoPtr pScrn,
+				int num, const char *file,
+				const char *func, int line);
+#endif
 struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix);
 void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo);
 
@@ -1355,7 +1360,7 @@ do {									\
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,				\
 		   "BEGIN_RING(%d) in %s\n", (unsigned int)n, __FUNCTION__);\
     }									\
-    if (info->cs) radeon_cs_begin(info->cs, n, __FILE__, __func__, __LINE__); else { \
+    if (info->cs) { radeon_ddx_cs_start(pScrn, n, __FILE__, __func__, __LINE__); } else { \
       if (++info->cp->dma_begin_count != 1) {				\
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,				\
 		   "BEGIN_RING without end at %s:%d\n",			\
diff --git a/src/radeon_accel.c b/src/radeon_accel.c
index 79052a1..02905dd 100644
--- a/src/radeon_accel.c
+++ b/src/radeon_accel.c
@@ -658,18 +658,6 @@ int RADEONCPStop(ScrnInfoPtr pScrn, RADEONInfoPtr info)
 
 #define RADEON_IB_RESERVE (16 * sizeof(uint32_t))
 
-void radeon_cs_flush_indirect(ScrnInfoPtr pScrn)
-{
-#ifdef XF86DRM_MODE
-    RADEONInfoPtr  info = RADEONPTR(pScrn);
-
-    if (!info->cs->cdw)
-	return;
-    radeon_cs_emit(info->cs);
-    radeon_cs_erase(info->cs);
-#endif
-}
-
 /* Get an indirect buffer for the CP 2D acceleration commands  */
 drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn)
 {
diff --git a/src/radeon_dummy_bufmgr.h b/src/radeon_dummy_bufmgr.h
index bf89292..b3ff991 100644
--- a/src/radeon_dummy_bufmgr.h
+++ b/src/radeon_dummy_bufmgr.h
@@ -39,19 +39,24 @@ static inline struct radeon_bo *radeon_bo_unref(struct radeon_bo *bo) {return NU
 static inline void radeon_bo_unmap(struct radeon_bo *bo) {return;}
 static inline int radeon_bo_wait(struct radeon_bo *bo) {return 0;}
 
+static inline int radeon_cs_space_add_persistent_bo(Bool cs, struct radeon_bo *bo,
+						    uint32_t read_domains, uint32_t write_domain)
+{
+  return 0;
+}
 
-struct radeon_cs_space_check {
-  struct radeon_bo *bo;
-  int read_domains;
-  int write_domain;
-  int new_accounted;
-};
-
-static inline int radeon_cs_space_check(Bool cs, struct radeon_cs_space_check *bos, int num)
+static inline int radeon_cs_space_check(Bool cs)
 {
   return 0;
 }
-#define RADEON_CS_SPACE_OP_TO_BIG 0
-#define RADEON_CS_SPACE_FLUSH 1
+
+static inline void radeon_cs_flush_indirect(ScrnInfoPtr pScrn)
+{
+}
+
+static inline void radeon_ddx_cs_start(ScrnInfoPtr pScrn, int n,
+				       const char *file, const char *func, int line);
+{
+}
 
 #endif
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index ca4eda0..e7f1e9c 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -120,13 +120,11 @@ static __inline__ uint32_t F_TO_DW(float val)
     return tmp.l;
 }
 
-static inline void radeon_add_pixmap(struct radeon_cs_space_check *bos, int index, PixmapPtr pPix, int read_domains, int write_domain)
+static inline void radeon_add_pixmap(struct radeon_cs *cs, PixmapPtr pPix, int read_domains, int write_domain)
 {
     struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix);
-    bos[index].bo = driver_priv->bo;
-    bos[index].read_domains = read_domains;
-    bos[index].write_domain = write_domain;
-    bos[index].new_accounted = 0;
+
+    radeon_cs_space_add_persistent_bo(cs, driver_priv->bo, read_domains, write_domain);
 }
 
 /* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we
@@ -344,7 +342,7 @@ static Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
 
     /* if we have more refs than just the BO then flush */
     if (driver_priv->bo->cref > 1)
-      radeon_cs_flush_indirect(pScrn);
+        radeon_cs_flush_indirect(pScrn);
     
     radeon_bo_wait(driver_priv->bo);
 
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 5b72360..460824d 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -138,9 +138,6 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     uint32_t datatype, dst_pitch_offset;
     struct radeon_exa_pixmap_priv *driver_priv;
     int ret;
-    int retry_count = 0;
-    struct radeon_cs_space_check bos[1];
-    int i;
 
     TRACE;
 
@@ -152,28 +149,17 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 	RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch failed\n"));
 
     RADEON_SWITCH_TO_2D();
- retry:
+
     if (info->cs) {
       
-	i = 0;
+	radeon_cs_space_reset_bos(info->cs);
+
 	driver_priv = exaGetPixmapDriverPrivate(pPix);
-	bos[i].bo = driver_priv->bo;
-	bos[i].read_domains = 0;
-	bos[i].write_domain = RADEON_GEM_DOMAIN_VRAM;;
-	bos[i].new_accounted = 0;
-	i++;
-
-	ret = radeon_cs_space_check(info->cs, bos, i);
-	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
-	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
-	}
-	if (ret == RADEON_CS_SPACE_FLUSH) {
-	    radeon_cs_flush_indirect(pScrn);
-	    retry_count++;
-	    if (retry_count == 2)
-	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
-	    goto retry;
-	}
+	radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
+
+	ret = radeon_cs_space_check(info->cs);
+	if (ret)
+	    RADEON_FALLBACK(("Not enough RAM to hw accel solid operation\n"));
     }
 
 
@@ -279,40 +265,27 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc,   PixmapPtr pDst,
     uint32_t datatype, src_pitch_offset, dst_pitch_offset;
     struct radeon_exa_pixmap_priv *driver_priv;
     int ret;
-    int retry_count = 0;
-    struct radeon_cs_space_check bos[2];
-    int i;
     TRACE;
 
     RADEON_SWITCH_TO_2D();
-retry:
+
     if (info->cs) {
       
+	radeon_cs_space_reset_bos(info->cs);
+
 	driver_priv = exaGetPixmapDriverPrivate(pSrc);
+	radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 	info->state_2d.src_bo = driver_priv->bo;
 
 	driver_priv = exaGetPixmapDriverPrivate(pDst);
+	radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
 	info->state_2d.dst_bo = driver_priv->bo;
 
-	i = 0;
-	radeon_add_pixmap(bos, i++, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
-
-	radeon_add_pixmap(bos, i++, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
-
-	ret = radeon_cs_space_check(info->cs, bos, i);
-	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
-	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
-	}
-	if (ret == RADEON_CS_SPACE_FLUSH) {
-	    radeon_cs_flush_indirect(pScrn);
-	    retry_count++;
-	    if (retry_count == 2)
-	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
-	    goto retry;
-	}
+	ret = radeon_cs_space_check(info->cs);
+	if (ret)
+	    RADEON_FALLBACK(("Not enough RAM to hw accel copy operation\n"));
     }
 
-
     info->accel_state->xdir = xdir;
     info->accel_state->ydir = ydir;
 
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 60c40a2..1e07408 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -557,9 +557,7 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
     uint32_t pp_cntl, blendcntl, cblend, ablend;
     int pixel_shift;
     struct radeon_exa_pixmap_priv *driver_priv;
-    int retry_count = 0;
-    struct radeon_cs_space_check bos[3];
-    int i, ret;
+    int ret;
     ACCEL_PREAMBLE();
 
     TRACE;
@@ -589,28 +587,21 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
 
     /* switch to 3D before doing buffer space checks as it may flush */
     RADEON_SWITCH_TO_3D();
- retry:
+
     if (info->cs) {
-      
-	i = 0;
-	radeon_add_pixmap(bos, i++, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_reset_bos(info->cs);
+
+	radeon_add_pixmap(info->cs, pSrc,
+			  RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	if (pMask)
-	    radeon_add_pixmap(bos, i++, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	    radeon_add_pixmap(info->cs, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
-	radeon_add_pixmap(bos, i++, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
+	radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
 
-	ret = radeon_cs_space_check(info->cs, bos, i);
-	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	ret = radeon_cs_space_check(info->cs);
+	if (ret)
 	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
-	}
-	if (ret == RADEON_CS_SPACE_FLUSH) {
-	    radeon_cs_flush_indirect(pScrn);
-	    retry_count++;
-	    if (retry_count == 2)
-	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
-	    goto retry;
-	}
     }
 
     if (!RADEONSetupSourceTile(pSrcPicture, pSrc, FALSE, TRUE))
@@ -914,9 +905,7 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
     uint32_t pp_cntl, blendcntl, cblend, ablend, colorpitch;
     int pixel_shift;
     struct radeon_exa_pixmap_priv *driver_priv;
-    int retry_count = 0;
-    struct radeon_cs_space_check bos[3];
-    int i, ret;
+    int ret;
     ACCEL_PREAMBLE();
 
     TRACE;
@@ -947,29 +936,20 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
     /* switch to 3D before doing buffer space checks as it may flush */
     RADEON_SWITCH_TO_3D();
 
- retry:
     if (info->cs) {
-      
-	i = 0;
-	radeon_add_pixmap(bos, i++, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_reset_bos(info->cs);
+        radeon_add_pixmap(info->cs, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	if (pMask)
-	    radeon_add_pixmap(bos, i++, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	    radeon_add_pixmap(info->cs, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
-	radeon_add_pixmap(bos, i++, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
+	radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
 
-	ret = radeon_cs_space_check(info->cs, bos, i);
-	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
-	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
-	}
-	if (ret == RADEON_CS_SPACE_FLUSH) {
-	    radeon_cs_flush_indirect(pScrn);
-	    retry_count++;
-	    if (retry_count == 2)
-	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
-	    goto retry;
-	}
+	ret = radeon_cs_space_check(info->cs);
+	if (ret)
+ 	  RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
     }
+
     if (!RADEONSetupSourceTile(pSrcPicture, pSrc, FALSE, TRUE))
 	return FALSE;
 
@@ -1404,10 +1384,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
     uint32_t mask_color, mask_alpha;
     int pixel_shift;
     int ret;
-    int retry_count = 0;
     struct radeon_exa_pixmap_priv *driver_priv;
-    struct radeon_cs_space_check bos[3];
-    int i;
     ACCEL_PREAMBLE();
     TRACE;
 
@@ -1436,29 +1413,19 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 
     /* have to execute switch before doing buffer sizing check as it flushes */
     RADEON_SWITCH_TO_3D();
- retry:
+
     if (info->cs) {
-      
-	i = 0;
-	driver_priv = exaGetPixmapDriverPrivate(pSrc);
-	radeon_add_pixmap(bos, i++, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+      	radeon_cs_space_reset_bos(info->cs);
+	radeon_add_pixmap(info->cs, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	if (pMask)
-	    radeon_add_pixmap(bos, i++, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	  radeon_add_pixmap(info->cs, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
-	radeon_add_pixmap(bos, i++, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
+	radeon_add_pixmap(info->cs, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
 
-	ret = radeon_cs_space_check(info->cs, bos, i);
-	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	ret = radeon_cs_space_check(info->cs);
+	if (ret)
 	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
-	}
-	if (ret == RADEON_CS_SPACE_FLUSH) {
-            radeon_cs_flush_indirect(pScrn);
-	    retry_count++;
-	    if (retry_count == 2)
-	        RADEON_FALLBACK(("Not enough Video RAM - this really shouldn't happen\nm"));
-	    goto retry;
-	}
     }
 
     if (!RADEONSetupSourceTile(pSrcPicture, pSrc, TRUE, FALSE))
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index cd3ec9a..7ecfe88 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -70,6 +70,34 @@ const OptionInfoRec RADEONOptions_KMS[] = {
     { -1,                    NULL,               OPTV_NONE,    {0}, FALSE }
 };
 
+void radeon_cs_flush_indirect(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+
+    if (!info->cs->cdw)
+	return;
+    radeon_cs_emit(info->cs);
+    radeon_cs_erase(info->cs);
+}
+
+void radeon_ddx_cs_start(ScrnInfoPtr pScrn,
+			 int n, const char *file,
+			 const char *func, int line)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+    int ret;
+
+    if (info->cs->cdw + n > info->cs->ndw) {
+	radeon_cs_flush_indirect(pScrn);
+	ret = radeon_cs_space_check(info->cs);
+	if (ret)
+	    ErrorF("space check failed in DDX CS start %s:%s:%d\n",
+		   file, func, line);
+    }
+    radeon_cs_begin(info->cs, n, file, func, line);
+}
+
+
 extern _X_EXPORT int gRADEONEntityIndex;
 
 static int getRADEONEntityIndex(void)
@@ -532,6 +560,7 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
     }
 
     radeon_cs_set_limit(info->cs, RADEON_GEM_DOMAIN_GTT, info->gart_size);
+    radeon_cs_space_set_flush(info->cs, (void(*)(void *))radeon_cs_flush_indirect, pScrn); 
 
     radeon_setup_kernel_mem(pScreen);
     front_ptr = info->front_bo->ptr;
diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c
index 184258c..10414b9 100644
--- a/src/radeon_textured_video.c
+++ b/src/radeon_textured_video.c
@@ -137,14 +137,6 @@ static REF_TRANSFORM trans[2] =
     {1.1643, 0.0, 1.7927, -0.2132, -0.5329, 2.1124, 0.0}  /* BT.709 */
 };
 
-static inline void radeon_add_bo(struct radeon_cs_space_check *bos, int index, struct radeon_bo *bo, int read_domains, int write_domain)
-{
-    bos[index].bo = bo;
-    bos[index].read_domains = read_domains;
-    bos[index].write_domain = write_domain;
-    bos[index].new_accounted = 0;
-}
-
 #define ACCEL_MMIO
 #define ACCEL_PREAMBLE()	unsigned char *RADEONMMIO = info->MMIO
 #define BEGIN_ACCEL(n)		RADEONWaitForFifo(pScrn, (n))
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index 2efe449..b814921 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -93,7 +93,6 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
     RADEONInfoPtr info = RADEONPTR(pScrn);
     PixmapPtr pPixmap = pPriv->pPixmap;
     struct radeon_exa_pixmap_priv *driver_priv;
-    struct radeon_cs_space_check bos[3];
     uint32_t txformat, txsize, txpitch, txoffset;
     uint32_t dst_pitch, dst_format;
     uint32_t colorpitch;
@@ -101,34 +100,24 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
     int dstxoff, dstyoff, pixel_shift, vtx_count;
     BoxPtr pBox = REGION_RECTS(&pPriv->clip);
     int nBox = REGION_NUM_RECTS(&pPriv->clip);
-    int i, ret, retry_count = 0;
+    int ret;
     ACCEL_PREAMBLE();
 
- retry:
     if (info->cs) {
-	i = 0;
-	radeon_add_bo(bos, i++, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_reset_bos(info->cs);
+        radeon_cs_space_add_persistent_bo(info->cs, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	if (pPriv->bicubic_enabled)
-	    radeon_add_bo(bos, i++, pPriv->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	    radeon_cs_space_add_persistent_bo(info->cs, pPriv->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	driver_priv = exaGetPixmapDriverPrivate(pPixmap);
-	radeon_add_bo(bos, i++, driver_priv->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
 
-	ret = radeon_cs_space_check(info->cs, bos, i);
-	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	ret = radeon_cs_space_check(info->cs);
+	if (ret) {
 	    ErrorF("Not enough RAM to hw accel xv operation\n");
 	    return;
 	}
-	if (ret == RADEON_CS_SPACE_FLUSH) {
-	    radeon_cs_flush_indirect(pScrn);
-	    retry_count++;
-	    if (retry_count == 2) {
-	        ErrorF("Not enough RAM to hw accel xv operation\n");
-	        return;
-	    }
-	    goto retry;
-	}
     }
 
     pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
@@ -497,35 +486,24 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     int ref = pPriv->transform_index;
     float ucscale = 0.25, vcscale = 0.25;
     Bool needux8 = FALSE, needvx8 = FALSE;
-    struct radeon_cs_space_check bos[3];
-    int i, ret, retry_count = 0;
+    int ret;
     ACCEL_PREAMBLE();
 
- retry:
     if (info->cs) {
-	i = 0;
-	radeon_add_bo(bos, i++, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_reset_bos(info->cs);
+        radeon_cs_space_add_persistent_bo(info->cs, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	if (pPriv->bicubic_enabled)
-	    radeon_add_bo(bos, i++, pPriv->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	    radeon_cs_space_add_persistent_bo(info->cs, pPriv->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	driver_priv = exaGetPixmapDriverPrivate(pPixmap);
-	radeon_add_bo(bos, i++, driver_priv->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
 
-	ret = radeon_cs_space_check(info->cs, bos, i);
-	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	ret = radeon_cs_space_check(info->cs);
+	if (ret) {
 	    ErrorF("Not enough RAM to hw accel xv operation\n");
 	    return;
 	}
-	if (ret == RADEON_CS_SPACE_FLUSH) {
-	    radeon_cs_flush_indirect(pScrn);
-	    retry_count++;
-	    if (retry_count == 2) {
-	        ErrorF("Not enough RAM to hw accel xv operation\n");
-	        return;
-	    }
-	    goto retry;
-	}
     }
 
     pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
@@ -1047,35 +1025,24 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     int dstxoff, dstyoff, pixel_shift, vtx_count;
     BoxPtr pBox = REGION_RECTS(&pPriv->clip);
     int nBox = REGION_NUM_RECTS(&pPriv->clip);
-    struct radeon_cs_space_check bos[3];
-    int i, ret, retry_count = 0;
+    int ret;
     ACCEL_PREAMBLE();
 
- retry:
     if (info->cs) {
-	i = 0;
-	radeon_add_bo(bos, i++, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_reset_bos(info->cs);
+	radeon_cs_space_add_persistent_bo(info->cs, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	if (pPriv->bicubic_enabled)
-	    radeon_add_bo(bos, i++, pPriv->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	  radeon_cs_space_add_persistent_bo(info->cs, pPriv->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	driver_priv = exaGetPixmapDriverPrivate(pPixmap);
-	radeon_add_bo(bos, i++, driver_priv->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
 
-	ret = radeon_cs_space_check(info->cs, bos, i);
-	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	ret = radeon_cs_space_check(info->cs);
+	if (ret) {
 	    ErrorF("Not enough RAM to hw accel xv operation\n");
 	    return;
 	}
-	if (ret == RADEON_CS_SPACE_FLUSH) {
-	    radeon_cs_flush_indirect(pScrn);
-	    retry_count++;
-	    if (retry_count == 2) {
-	        ErrorF("Not enough RAM to hw accel xv operation\n");
-	        return;
-	    }
-	    goto retry;
-	}
     }
 
     pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
@@ -2500,41 +2467,30 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     struct radeon_exa_pixmap_priv *driver_priv;
     uint32_t txfilter, txformat0, txformat1, txoffset, txpitch;
     uint32_t dst_pitch, dst_format;
-    uint32_t txenable, colorpitch;
+    uint32_t txenable, colorpitch, bicubic_offset;
     uint32_t output_fmt;
     Bool isplanar = FALSE;
     int dstxoff, dstyoff, pixel_shift, vtx_count;
     BoxPtr pBox = REGION_RECTS(&pPriv->clip);
     int nBox = REGION_NUM_RECTS(&pPriv->clip);
-    struct radeon_cs_space_check bos[3];
-    int i, ret, retry_count = 0;
+    int ret;
     ACCEL_PREAMBLE();
 
- retry:
     if (info->cs) {
-	i = 0;
-	radeon_add_bo(bos, i++, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_reset_bos(info->cs);
+	radeon_cs_space_add_persistent_bo(info->cs, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	if (pPriv->bicubic_enabled)
-	    radeon_add_bo(bos, i++, pPriv->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	    radeon_cs_space_add_persistent_bo(info->cs, pPriv->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	driver_priv = exaGetPixmapDriverPrivate(pPixmap);
-	radeon_add_bo(bos, i++, driver_priv->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+	radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
 
-	ret = radeon_cs_space_check(info->cs, bos, i);
-	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	ret = radeon_cs_space_check(info->cs);
+	if (ret) {
 	    ErrorF("Not enough RAM to hw accel xv operation\n");
 	    return;
 	}
-	if (ret == RADEON_CS_SPACE_FLUSH) {
-	    radeon_cs_flush_indirect(pScrn);
-	    retry_count++;
-	    if (retry_count == 2) {
-	        ErrorF("Not enough RAM to hw accel xv operation\n");
-	        return;
-	    }
-	    goto retry;
-	}
     }
 
     pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
@@ -2702,13 +2658,18 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 		    R300_TX_MAG_FILTER_NEAREST |
 		    (1 << R300_TX_ID_SHIFT));
 
+	if (info->cs)
+	    bicubic_offset = 0;
+	else
+	    bicubic_offset = pPriv->bicubic_src_offset;
+
 	BEGIN_ACCEL(6);
 	OUT_ACCEL_REG(R300_TX_FILTER0_1, txfilter);
 	OUT_ACCEL_REG(R300_TX_FILTER1_1, 0);
 	OUT_ACCEL_REG(R300_TX_FORMAT0_1, txformat0);
 	OUT_ACCEL_REG(R300_TX_FORMAT1_1, txformat1);
 	OUT_ACCEL_REG(R300_TX_FORMAT2_1, txpitch);
-	OUT_ACCEL_REG(R300_TX_OFFSET_1, pPriv->bicubic_src_offset);
+	OUT_TEXTURE_REG(R300_TX_OFFSET_1, bicubic_offset, pPriv->bicubic_bo);
 	FINISH_ACCEL();
 
 	/* Enable tex 1 */
commit e1200cb89218930d01330ba0114e013438655cce
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon Jul 6 15:10:29 2009 +1000

    Revert "KMS CS fixes."
    
    This reverts commit 11cf8a28eb46f48d101888552266921bee8b63fc.
    
    I'll bring this back in a few minutes, I've got a big change introducing
    a new cs space accounting scheme which this messes up and I think
    probably conflicts with what I've done.
    
    I promise i'll go over this and pick the bits that are still useful :)

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 3673064..18831f7 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -1166,7 +1166,7 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
     }
 
     if (unit == 0) {
-	if (!accel_state->msk_pic) {
+	if (!accel_state->has_mask) {
 	    if (PICT_FORMAT_RGB(pPict->format) == 0) {
 		pix_r = SQ_SEL_0;
 		pix_g = SQ_SEL_0;
@@ -1397,7 +1397,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     /* return FALSE; */
 
     if (pMask) {
-	accel_state->msk_pic = pMaskPicture;
+	accel_state->has_mask = TRUE;
 	if (pMaskPicture->componentAlpha) {
 	    accel_state->component_alpha = TRUE;
 	    if (R600BlendOp[op].src_alpha)
@@ -1409,7 +1409,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
 	    accel_state->src_alpha = FALSE;
 	}
     } else {
-	accel_state->msk_pic = NULL;
+	accel_state->has_mask = FALSE;
 	accel_state->component_alpha = FALSE;
 	accel_state->src_alpha = FALSE;
     }
@@ -1598,7 +1598,7 @@ static void R600Composite(PixmapPtr pDst,
     srcBottomRight.x = IntToxFixed(srcX + w);
     srcBottomRight.y = IntToxFixed(srcY + h);
 
-    if (accel_state->msk_pic) {
+    if (accel_state->has_mask) {
 	xPointFixed maskTopLeft, maskTopRight, maskBottomLeft, maskBottomRight;
 
 	if (((accel_state->vb_index + 3) * 24) > (accel_state->ib->total / 2)) {
@@ -1693,7 +1693,7 @@ static void R600DoneComposite(PixmapPtr pDst)
 
 
     /* Vertex buffer setup */
-    if (accel_state->msk_pic) {
+    if (accel_state->has_mask) {
 	accel_state->vb_size = accel_state->vb_index * 24;
 	vtx_res.id              = SQ_VTX_RESOURCE_vs;
 	vtx_res.vtx_size_dw     = 24 / 4;
diff --git a/src/radeon.h b/src/radeon.h
index ad62a61..82136c8 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -672,15 +672,9 @@ struct radeon_accel_state {
 #define EXA_ENGINEMODE_2D      1
 #define EXA_ENGINEMODE_3D      2
 
-    int               composite_op;
-    PicturePtr        dst_pic;
-    PicturePtr        msk_pic;
-    PicturePtr        src_pic;
-    PixmapPtr         dst_pix;
-    PixmapPtr         msk_pix;
-    PixmapPtr         src_pix;
     Bool              is_transform[2];
     PictTransform     *transform[2];
+    Bool              has_mask;
     /* Whether we are tiling horizontally and vertically */
     Bool              need_src_tile_x;
     Bool              need_src_tile_y;
@@ -1519,10 +1513,8 @@ do {									\
 	uint32_t flush = 0;                                             \
 	switch (info->accel_state->engineMode) {			\
 	case EXA_ENGINEMODE_UNKNOWN:					\
-	    flush = 1;                                                  \
-	    break;							\
 	case EXA_ENGINEMODE_3D:						\
-	    flush = info->cs == NULL || info->cs->cdw > 15 * 1024;      \
+	    flush = 1;                                                  \
 	case EXA_ENGINEMODE_2D:						\
 	    break;							\
 	}								\
@@ -1540,10 +1532,8 @@ do {									\
 	uint32_t flush = 0;						\
 	switch (info->accel_state->engineMode) {			\
 	case EXA_ENGINEMODE_UNKNOWN:					\
-	    flush = 1;                                                  \
-	    break;							\
 	case EXA_ENGINEMODE_2D:						\
-	    flush = info->cs == NULL || info->cs->cdw > 15 * 1024;      \
+	    flush = 1;                                                  \
 	case EXA_ENGINEMODE_3D:						\
 	    break;							\
 	}								\
@@ -1552,9 +1542,8 @@ do {									\
 	        radeon_cs_flush_indirect(pScrn);			\
 	    else if (info->directRenderingEnabled)				\
 	        RADEONCPFlushIndirect(pScrn, 1);                        \
-	}                                                               \
-	if (!info->accel_state->XInited3D)				\
 	    RADEONInit3DEngine(pScrn);                                  \
+	}                                                               \
         info->accel_state->engineMode = EXA_ENGINEMODE_3D;              \
 } while (0);
 #else
diff --git a/src/radeon_accel.c b/src/radeon_accel.c
index 16d88e4..79052a1 100644
--- a/src/radeon_accel.c
+++ b/src/radeon_accel.c
@@ -667,13 +667,6 @@ void radeon_cs_flush_indirect(ScrnInfoPtr pScrn)
 	return;
     radeon_cs_emit(info->cs);
     radeon_cs_erase(info->cs);
-
-    /* Need to re-initialize 3D state in each CS */
-    info->accel_state->XInited3D = FALSE;
-
-#ifdef USE_EXA
-    info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
-#endif
 #endif
 }
 
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index fb33b6f..5b72360 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -213,17 +213,6 @@ FUNC_NAME(RADEONSolid)(PixmapPtr pPix, int x1, int y1, int x2, int y2)
 
     TRACE;
 
-#ifdef ACCEL_CP
-    if (info->cs && info->cs->cdw > 15 * 1024) {
-	struct radeon_cs_space_check bos[1];
-
-	radeon_cs_flush_indirect(pScrn);
-	radeon_add_pixmap(bos, 0, pPix, 0, RADEON_GEM_DOMAIN_VRAM);
-	radeon_cs_space_check(info->cs, bos, 1);
-	FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_SOLID);
-    }
-#endif
-
     if (info->accel_state->vsync)
 	FUNC_NAME(RADEONWaitForVLine)(pScrn, pPix, RADEONBiggerCrtcArea(pPix), y1, y2);
 
@@ -353,21 +342,6 @@ FUNC_NAME(RADEONCopy)(PixmapPtr pDst,
 
     TRACE;
 
-#ifdef ACCEL_CP
-    if (info->cs && info->cs->cdw > 15 * 1024) {
-	struct radeon_cs_space_check bos[2];
-
-	radeon_cs_flush_indirect(pScrn);
-	bos[0].bo = info->state_2d.src_bo;
-	bos[0].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
-	bos[0].write_domain = 0;
-	bos[0].new_accounted = 0;
-	radeon_add_pixmap(bos, 1, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
-	radeon_cs_space_check(info->cs, bos, 2);
-	FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_COPY);
-    }
-#endif
-
     if (info->accel_state->xdir < 0) {
 	srcX += w - 1;
 	dstX += w - 1;
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index ee82d85..60c40a2 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -542,55 +542,6 @@ static Bool R100CheckComposite(int op, PicturePtr pSrcPicture,
 
     return TRUE;
 }
-
-static Bool
-RADEONPrepareCompositeState(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
-			    PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask,
-			    PixmapPtr pDst)
-{
-    RINFO_FROM_SCREEN(pDst->drawable.pScreen);
-    struct radeon_cs_space_check bos[3];
-    int i, ret, retry_count = 0;
-
-    /* switch to 3D before doing buffer space checks as it may flush */
-    RADEON_SWITCH_TO_3D();
-
- retry:
-    if (info->cs) {
-      
-	i = 0;
-	radeon_add_pixmap(bos, i++, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
-
-	if (pMask)
-	    radeon_add_pixmap(bos, i++, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
-
-	radeon_add_pixmap(bos, i++, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
-
-	ret = radeon_cs_space_check(info->cs, bos, i);
-	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
-	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
-	}
-	if (ret == RADEON_CS_SPACE_FLUSH) {
-	    radeon_cs_flush_indirect(pScrn);
-	    retry_count++;
-	    if (retry_count == 2)
-	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
-	    RADEON_SWITCH_TO_3D();
-	    goto retry;
-	}
-    }
-
-    info->accel_state->composite_op = op;
-    info->accel_state->dst_pic = pDstPicture;
-    info->accel_state->msk_pic = pMaskPicture;
-    info->accel_state->src_pic = pSrcPicture;
-    info->accel_state->dst_pix = pDst;
-    info->accel_state->msk_pix = pMask;
-    info->accel_state->src_pix = pSrc;
-
-    return TRUE;
-}
-
 #endif /* ONLY_ONCE */
 
 static Bool FUNC_NAME(R100PrepareComposite)(int op,
@@ -606,6 +557,9 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
     uint32_t pp_cntl, blendcntl, cblend, ablend;
     int pixel_shift;
     struct radeon_exa_pixmap_priv *driver_priv;
+    int retry_count = 0;
+    struct radeon_cs_space_check bos[3];
+    int i, ret;
     ACCEL_PREAMBLE();
 
     TRACE;
@@ -616,6 +570,11 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
     if (pDstPicture->format == PICT_a8 && RadeonBlendOp[op].dst_alpha)
 	RADEON_FALLBACK(("Can't dst alpha blend A8\n"));
 
+    if (pMask)
+	info->accel_state->has_mask = TRUE;
+    else
+	info->accel_state->has_mask = FALSE;
+
     pixel_shift = pDst->drawable.bitsPerPixel >> 4;
 
     dst_pitch = exaGetPixmapPitch(pDst);
@@ -628,11 +587,33 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
 
-    if (!RADEONSetupSourceTile(pSrcPicture, pSrc, FALSE, TRUE))
-	return FALSE;
+    /* switch to 3D before doing buffer space checks as it may flush */
+    RADEON_SWITCH_TO_3D();
+ retry:
+    if (info->cs) {
+      
+	i = 0;
+	radeon_add_pixmap(bos, i++, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	if (pMask)
+	    radeon_add_pixmap(bos, i++, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	radeon_add_pixmap(bos, i++, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
 
-    if (!RADEONPrepareCompositeState(op, pSrcPicture, pMaskPicture, pDstPicture,
-				     pSrc, pMask, pDst))
+	ret = radeon_cs_space_check(info->cs, bos, i);
+	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
+	}
+	if (ret == RADEON_CS_SPACE_FLUSH) {
+	    radeon_cs_flush_indirect(pScrn);
+	    retry_count++;
+	    if (retry_count == 2)
+	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
+	    goto retry;
+	}
+    }
+
+    if (!RADEONSetupSourceTile(pSrcPicture, pSrc, FALSE, TRUE))
 	return FALSE;
 
     if (!FUNC_NAME(R100TextureSetup)(pSrcPicture, pSrc, 0))
@@ -933,6 +914,9 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
     uint32_t pp_cntl, blendcntl, cblend, ablend, colorpitch;
     int pixel_shift;
     struct radeon_exa_pixmap_priv *driver_priv;
+    int retry_count = 0;
+    struct radeon_cs_space_check bos[3];
+    int i, ret;
     ACCEL_PREAMBLE();
 
     TRACE;
@@ -943,6 +927,11 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
     if (pDstPicture->format == PICT_a8 && RadeonBlendOp[op].dst_alpha)
 	RADEON_FALLBACK(("Can't dst alpha blend A8\n"));
 
+    if (pMask)
+	info->accel_state->has_mask = TRUE;
+    else
+	info->accel_state->has_mask = FALSE;
+
     pixel_shift = pDst->drawable.bitsPerPixel >> 4;
 
     dst_pitch = exaGetPixmapPitch(pDst);
@@ -955,11 +944,33 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
 
-    if (!RADEONSetupSourceTile(pSrcPicture, pSrc, FALSE, TRUE))
-	return FALSE;
+    /* switch to 3D before doing buffer space checks as it may flush */
+    RADEON_SWITCH_TO_3D();
+
+ retry:
+    if (info->cs) {
+      
+	i = 0;
+	radeon_add_pixmap(bos, i++, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	if (pMask)
+	    radeon_add_pixmap(bos, i++, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
-    if (!RADEONPrepareCompositeState(op, pSrcPicture, pMaskPicture, pDstPicture,
-				     pSrc, pMask, pDst))
+	radeon_add_pixmap(bos, i++, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
+
+	ret = radeon_cs_space_check(info->cs, bos, i);
+	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
+	}
+	if (ret == RADEON_CS_SPACE_FLUSH) {
+	    radeon_cs_flush_indirect(pScrn);
+	    retry_count++;
+	    if (retry_count == 2)
+	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
+	    goto retry;
+	}
+    }
+    if (!RADEONSetupSourceTile(pSrcPicture, pSrc, FALSE, TRUE))
 	return FALSE;
 
     if (!FUNC_NAME(R200TextureSetup)(pSrcPicture, pSrc, 0))
@@ -1154,7 +1165,7 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
     txformat1 = R300TexFormats[i].card_fmt;
 
     if (IS_R300_3D) {
-	if ((unit == 0) && info->accel_state->msk_pic)
+	if ((unit == 0) && info->accel_state->has_mask)
 	    txformat1 |= R300_TX_FORMAT_CACHE_HALF_REGION_0;
 	else if (unit == 1)
 	    txformat1 |= R300_TX_FORMAT_CACHE_HALF_REGION_1;
@@ -1392,13 +1403,22 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
     uint32_t src_color, src_alpha;
     uint32_t mask_color, mask_alpha;
     int pixel_shift;
+    int ret;
+    int retry_count = 0;
     struct radeon_exa_pixmap_priv *driver_priv;
+    struct radeon_cs_space_check bos[3];
+    int i;
     ACCEL_PREAMBLE();
     TRACE;
 
     if (!R300GetDestFormat(pDstPicture, &dst_format))
 	return FALSE;
 
+    if (pMask)
+	info->accel_state->has_mask = TRUE;
+    else
+	info->accel_state->has_mask = FALSE;
+
     pixel_shift = pDst->drawable.bitsPerPixel >> 4;
 
     dst_pitch = exaGetPixmapPitch(pDst);
@@ -1414,11 +1434,34 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
 
-    if (!RADEONSetupSourceTile(pSrcPicture, pSrc, TRUE, FALSE))
-	return FALSE;
+    /* have to execute switch before doing buffer sizing check as it flushes */
+    RADEON_SWITCH_TO_3D();
+ retry:
+    if (info->cs) {
+      
+	i = 0;
+	driver_priv = exaGetPixmapDriverPrivate(pSrc);
+	radeon_add_pixmap(bos, i++, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	if (pMask)
+	    radeon_add_pixmap(bos, i++, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	radeon_add_pixmap(bos, i++, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
 
-    if (!RADEONPrepareCompositeState(op, pSrcPicture, pMaskPicture, pDstPicture,
-				     pSrc, pMask, pDst))
+	ret = radeon_cs_space_check(info->cs, bos, i);
+	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
+	}
+	if (ret == RADEON_CS_SPACE_FLUSH) {
+            radeon_cs_flush_indirect(pScrn);
+	    retry_count++;
+	    if (retry_count == 2)
+	        RADEON_FALLBACK(("Not enough Video RAM - this really shouldn't happen\nm"));
+	    goto retry;
+	}
+    }
+
+    if (!RADEONSetupSourceTile(pSrcPicture, pSrc, TRUE, FALSE))
 	return FALSE;
 
     if (!FUNC_NAME(R300TextureSetup)(pSrcPicture, pSrc, 0))
@@ -2017,7 +2060,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
     FINISH_ACCEL();
 
     BEGIN_ACCEL(1);
-    if (pMask)
+    if (info->accel_state->has_mask)
 	OUT_ACCEL_REG(R300_VAP_VTX_SIZE, 6);
     else
 	OUT_ACCEL_REG(R300_VAP_VTX_SIZE, 4);
@@ -2100,19 +2143,6 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
     /* ErrorF("RadeonComposite (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n",
        srcX, srcY, maskX, maskY,dstX, dstY, w, h); */
 
-#ifdef ACCEL_CP
-    if (info->cs && info->cs->cdw > 15 * 1024) {
-	radeon_cs_flush_indirect(pScrn);
-	info->accel_state->exa->PrepareComposite(info->accel_state->composite_op,
-						 info->accel_state->dst_pic,
-						 info->accel_state->msk_pic,
-						 info->accel_state->src_pic,
-						 info->accel_state->dst_pix,
-						 info->accel_state->msk_pix,
-						 info->accel_state->src_pix);
-    }
-#endif
-
     srcTopLeft.x     = IntToxFixed(srcX);
     srcTopLeft.y     = IntToxFixed(srcY);
     srcTopRight.x    = IntToxFixed(srcX + w);
@@ -2131,7 +2161,7 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
 	}
     }
 
-    if (info->accel_state->msk_pic) {
+    if (info->accel_state->has_mask) {
 	maskTopLeft.x     = IntToxFixed(maskX);
 	maskTopLeft.y     = IntToxFixed(maskY);
 	maskTopRight.x    = IntToxFixed(maskX + w);
@@ -2162,7 +2192,7 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
 	BEGIN_RING(3 * vtx_count + 3);
 	OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD,
 			    3 * vtx_count + 1));
-	if (info->accel_state->msk_pic)
+	if (info->accel_state->has_mask)
 	    OUT_RING(RADEON_CP_VC_FRMT_XY |
 		     RADEON_CP_VC_FRMT_ST0 |
 		     RADEON_CP_VC_FRMT_ST1);
@@ -2212,7 +2242,7 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
 
 #endif
 
-    if (info->accel_state->msk_pic) {
+    if (info->accel_state->has_mask) {
 	if (IS_R300_3D || IS_R500_3D) {
 	    VTX_OUT_MASK((float)dstX,                                      (float)dstY,
 			 xFixedToFloat(srcTopLeft.x) / info->accel_state->texW[0],      xFixedToFloat(srcTopLeft.y) / info->accel_state->texH[0],
commit 11cf8a28eb46f48d101888552266921bee8b63fc
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Sun Jul 5 15:14:59 2009 +0200

    KMS CS fixes.
    
    * Flush CS before running out of space.
    * Don't flush CS every time when switching between 2D and 3D engine, but make
      sure to re-initialize 2D/3D state after flushing.
    
    Doesn't seem quite perfect yet (some rendering seems to get dropped on the floor
    sometimes), but this should fix a lot of CS failures people have been seeing.

diff --git a/src/r600_exa.c b/src/r600_exa.c
index 18831f7..3673064 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -1166,7 +1166,7 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
     }
 
     if (unit == 0) {
-	if (!accel_state->has_mask) {
+	if (!accel_state->msk_pic) {
 	    if (PICT_FORMAT_RGB(pPict->format) == 0) {
 		pix_r = SQ_SEL_0;
 		pix_g = SQ_SEL_0;
@@ -1397,7 +1397,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
     /* return FALSE; */
 
     if (pMask) {
-	accel_state->has_mask = TRUE;
+	accel_state->msk_pic = pMaskPicture;
 	if (pMaskPicture->componentAlpha) {
 	    accel_state->component_alpha = TRUE;
 	    if (R600BlendOp[op].src_alpha)
@@ -1409,7 +1409,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
 	    accel_state->src_alpha = FALSE;
 	}
     } else {
-	accel_state->has_mask = FALSE;
+	accel_state->msk_pic = NULL;
 	accel_state->component_alpha = FALSE;
 	accel_state->src_alpha = FALSE;
     }
@@ -1598,7 +1598,7 @@ static void R600Composite(PixmapPtr pDst,
     srcBottomRight.x = IntToxFixed(srcX + w);
     srcBottomRight.y = IntToxFixed(srcY + h);
 
-    if (accel_state->has_mask) {
+    if (accel_state->msk_pic) {
 	xPointFixed maskTopLeft, maskTopRight, maskBottomLeft, maskBottomRight;
 
 	if (((accel_state->vb_index + 3) * 24) > (accel_state->ib->total / 2)) {
@@ -1693,7 +1693,7 @@ static void R600DoneComposite(PixmapPtr pDst)
 
 
     /* Vertex buffer setup */
-    if (accel_state->has_mask) {
+    if (accel_state->msk_pic) {
 	accel_state->vb_size = accel_state->vb_index * 24;
 	vtx_res.id              = SQ_VTX_RESOURCE_vs;
 	vtx_res.vtx_size_dw     = 24 / 4;
diff --git a/src/radeon.h b/src/radeon.h
index 82136c8..ad62a61 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -672,9 +672,15 @@ struct radeon_accel_state {
 #define EXA_ENGINEMODE_2D      1
 #define EXA_ENGINEMODE_3D      2
 
+    int               composite_op;
+    PicturePtr        dst_pic;
+    PicturePtr        msk_pic;
+    PicturePtr        src_pic;
+    PixmapPtr         dst_pix;
+    PixmapPtr         msk_pix;
+    PixmapPtr         src_pix;
     Bool              is_transform[2];
     PictTransform     *transform[2];
-    Bool              has_mask;
     /* Whether we are tiling horizontally and vertically */
     Bool              need_src_tile_x;
     Bool              need_src_tile_y;
@@ -1513,8 +1519,10 @@ do {									\
 	uint32_t flush = 0;                                             \
 	switch (info->accel_state->engineMode) {			\
 	case EXA_ENGINEMODE_UNKNOWN:					\
-	case EXA_ENGINEMODE_3D:						\
 	    flush = 1;                                                  \
+	    break;							\
+	case EXA_ENGINEMODE_3D:						\
+	    flush = info->cs == NULL || info->cs->cdw > 15 * 1024;      \
 	case EXA_ENGINEMODE_2D:						\
 	    break;							\
 	}								\
@@ -1532,8 +1540,10 @@ do {									\
 	uint32_t flush = 0;						\
 	switch (info->accel_state->engineMode) {			\
 	case EXA_ENGINEMODE_UNKNOWN:					\
-	case EXA_ENGINEMODE_2D:						\
 	    flush = 1;                                                  \
+	    break;							\
+	case EXA_ENGINEMODE_2D:						\
+	    flush = info->cs == NULL || info->cs->cdw > 15 * 1024;      \
 	case EXA_ENGINEMODE_3D:						\
 	    break;							\
 	}								\
@@ -1542,8 +1552,9 @@ do {									\
 	        radeon_cs_flush_indirect(pScrn);			\
 	    else if (info->directRenderingEnabled)				\
 	        RADEONCPFlushIndirect(pScrn, 1);                        \
-	    RADEONInit3DEngine(pScrn);                                  \
 	}                                                               \
+	if (!info->accel_state->XInited3D)				\
+	    RADEONInit3DEngine(pScrn);                                  \
         info->accel_state->engineMode = EXA_ENGINEMODE_3D;              \
 } while (0);
 #else
diff --git a/src/radeon_accel.c b/src/radeon_accel.c
index 79052a1..16d88e4 100644
--- a/src/radeon_accel.c
+++ b/src/radeon_accel.c
@@ -667,6 +667,13 @@ void radeon_cs_flush_indirect(ScrnInfoPtr pScrn)
 	return;
     radeon_cs_emit(info->cs);
     radeon_cs_erase(info->cs);
+
+    /* Need to re-initialize 3D state in each CS */
+    info->accel_state->XInited3D = FALSE;
+
+#ifdef USE_EXA
+    info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
+#endif
 #endif
 }
 
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 5b72360..fb33b6f 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -213,6 +213,17 @@ FUNC_NAME(RADEONSolid)(PixmapPtr pPix, int x1, int y1, int x2, int y2)
 
     TRACE;
 
+#ifdef ACCEL_CP
+    if (info->cs && info->cs->cdw > 15 * 1024) {
+	struct radeon_cs_space_check bos[1];
+
+	radeon_cs_flush_indirect(pScrn);
+	radeon_add_pixmap(bos, 0, pPix, 0, RADEON_GEM_DOMAIN_VRAM);
+	radeon_cs_space_check(info->cs, bos, 1);
+	FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_SOLID);
+    }
+#endif
+
     if (info->accel_state->vsync)
 	FUNC_NAME(RADEONWaitForVLine)(pScrn, pPix, RADEONBiggerCrtcArea(pPix), y1, y2);
 
@@ -342,6 +353,21 @@ FUNC_NAME(RADEONCopy)(PixmapPtr pDst,
 
     TRACE;
 
+#ifdef ACCEL_CP
+    if (info->cs && info->cs->cdw > 15 * 1024) {
+	struct radeon_cs_space_check bos[2];
+
+	radeon_cs_flush_indirect(pScrn);
+	bos[0].bo = info->state_2d.src_bo;
+	bos[0].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
+	bos[0].write_domain = 0;
+	bos[0].new_accounted = 0;
+	radeon_add_pixmap(bos, 1, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
+	radeon_cs_space_check(info->cs, bos, 2);
+	FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_COPY);
+    }
+#endif
+
     if (info->accel_state->xdir < 0) {
 	srcX += w - 1;
 	dstX += w - 1;
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 60c40a2..ee82d85 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -542,6 +542,55 @@ static Bool R100CheckComposite(int op, PicturePtr pSrcPicture,
 
     return TRUE;
 }
+
+static Bool
+RADEONPrepareCompositeState(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+			    PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask,
+			    PixmapPtr pDst)
+{
+    RINFO_FROM_SCREEN(pDst->drawable.pScreen);
+    struct radeon_cs_space_check bos[3];
+    int i, ret, retry_count = 0;
+
+    /* switch to 3D before doing buffer space checks as it may flush */
+    RADEON_SWITCH_TO_3D();
+
+ retry:
+    if (info->cs) {
+      
+	i = 0;
+	radeon_add_pixmap(bos, i++, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	if (pMask)
+	    radeon_add_pixmap(bos, i++, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	radeon_add_pixmap(bos, i++, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
+
+	ret = radeon_cs_space_check(info->cs, bos, i);
+	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
+	}
+	if (ret == RADEON_CS_SPACE_FLUSH) {
+	    radeon_cs_flush_indirect(pScrn);
+	    retry_count++;
+	    if (retry_count == 2)
+	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
+	    RADEON_SWITCH_TO_3D();
+	    goto retry;
+	}
+    }
+
+    info->accel_state->composite_op = op;
+    info->accel_state->dst_pic = pDstPicture;
+    info->accel_state->msk_pic = pMaskPicture;
+    info->accel_state->src_pic = pSrcPicture;
+    info->accel_state->dst_pix = pDst;
+    info->accel_state->msk_pix = pMask;
+    info->accel_state->src_pix = pSrc;
+
+    return TRUE;
+}
+
 #endif /* ONLY_ONCE */
 
 static Bool FUNC_NAME(R100PrepareComposite)(int op,
@@ -557,9 +606,6 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
     uint32_t pp_cntl, blendcntl, cblend, ablend;
     int pixel_shift;
     struct radeon_exa_pixmap_priv *driver_priv;
-    int retry_count = 0;
-    struct radeon_cs_space_check bos[3];
-    int i, ret;
     ACCEL_PREAMBLE();
 
     TRACE;
@@ -570,11 +616,6 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
     if (pDstPicture->format == PICT_a8 && RadeonBlendOp[op].dst_alpha)
 	RADEON_FALLBACK(("Can't dst alpha blend A8\n"));
 
-    if (pMask)
-	info->accel_state->has_mask = TRUE;
-    else
-	info->accel_state->has_mask = FALSE;
-
     pixel_shift = pDst->drawable.bitsPerPixel >> 4;
 
     dst_pitch = exaGetPixmapPitch(pDst);
@@ -587,35 +628,13 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
 
-    /* switch to 3D before doing buffer space checks as it may flush */
-    RADEON_SWITCH_TO_3D();
- retry:
-    if (info->cs) {
-      
-	i = 0;
-	radeon_add_pixmap(bos, i++, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
-
-	if (pMask)
-	    radeon_add_pixmap(bos, i++, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
-
-	radeon_add_pixmap(bos, i++, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
-
-	ret = radeon_cs_space_check(info->cs, bos, i);
-	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
-	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
-	}
-	if (ret == RADEON_CS_SPACE_FLUSH) {
-	    radeon_cs_flush_indirect(pScrn);
-	    retry_count++;
-	    if (retry_count == 2)
-	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
-	    goto retry;
-	}
-    }
-
     if (!RADEONSetupSourceTile(pSrcPicture, pSrc, FALSE, TRUE))
 	return FALSE;
 
+    if (!RADEONPrepareCompositeState(op, pSrcPicture, pMaskPicture, pDstPicture,
+				     pSrc, pMask, pDst))
+	return FALSE;
+
     if (!FUNC_NAME(R100TextureSetup)(pSrcPicture, pSrc, 0))
 	return FALSE;
     pp_cntl = RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE;
@@ -914,9 +933,6 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
     uint32_t pp_cntl, blendcntl, cblend, ablend, colorpitch;
     int pixel_shift;
     struct radeon_exa_pixmap_priv *driver_priv;
-    int retry_count = 0;
-    struct radeon_cs_space_check bos[3];
-    int i, ret;
     ACCEL_PREAMBLE();
 
     TRACE;
@@ -927,11 +943,6 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
     if (pDstPicture->format == PICT_a8 && RadeonBlendOp[op].dst_alpha)
 	RADEON_FALLBACK(("Can't dst alpha blend A8\n"));
 
-    if (pMask)
-	info->accel_state->has_mask = TRUE;
-    else
-	info->accel_state->has_mask = FALSE;
-
     pixel_shift = pDst->drawable.bitsPerPixel >> 4;
 
     dst_pitch = exaGetPixmapPitch(pDst);
@@ -944,35 +955,13 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
 
-    /* switch to 3D before doing buffer space checks as it may flush */
-    RADEON_SWITCH_TO_3D();
-
- retry:
-    if (info->cs) {
-      
-	i = 0;
-	radeon_add_pixmap(bos, i++, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
-
-	if (pMask)
-	    radeon_add_pixmap(bos, i++, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
-
-	radeon_add_pixmap(bos, i++, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
-
-	ret = radeon_cs_space_check(info->cs, bos, i);
-	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
-	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
-	}
-	if (ret == RADEON_CS_SPACE_FLUSH) {
-	    radeon_cs_flush_indirect(pScrn);
-	    retry_count++;
-	    if (retry_count == 2)
-	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
-	    goto retry;
-	}
-    }
     if (!RADEONSetupSourceTile(pSrcPicture, pSrc, FALSE, TRUE))
 	return FALSE;
 
+    if (!RADEONPrepareCompositeState(op, pSrcPicture, pMaskPicture, pDstPicture,
+				     pSrc, pMask, pDst))
+	return FALSE;
+
     if (!FUNC_NAME(R200TextureSetup)(pSrcPicture, pSrc, 0))
 	return FALSE;
     pp_cntl = RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE;
@@ -1165,7 +1154,7 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
     txformat1 = R300TexFormats[i].card_fmt;
 
     if (IS_R300_3D) {
-	if ((unit == 0) && info->accel_state->has_mask)
+	if ((unit == 0) && info->accel_state->msk_pic)
 	    txformat1 |= R300_TX_FORMAT_CACHE_HALF_REGION_0;
 	else if (unit == 1)
 	    txformat1 |= R300_TX_FORMAT_CACHE_HALF_REGION_1;
@@ -1403,22 +1392,13 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
     uint32_t src_color, src_alpha;
     uint32_t mask_color, mask_alpha;
     int pixel_shift;
-    int ret;
-    int retry_count = 0;
     struct radeon_exa_pixmap_priv *driver_priv;
-    struct radeon_cs_space_check bos[3];
-    int i;
     ACCEL_PREAMBLE();
     TRACE;
 
     if (!R300GetDestFormat(pDstPicture, &dst_format))
 	return FALSE;
 
-    if (pMask)
-	info->accel_state->has_mask = TRUE;
-    else
-	info->accel_state->has_mask = FALSE;
-
     pixel_shift = pDst->drawable.bitsPerPixel >> 4;
 
     dst_pitch = exaGetPixmapPitch(pDst);
@@ -1434,36 +1414,13 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
 
-    /* have to execute switch before doing buffer sizing check as it flushes */
-    RADEON_SWITCH_TO_3D();
- retry:
-    if (info->cs) {
-      
-	i = 0;
-	driver_priv = exaGetPixmapDriverPrivate(pSrc);
-	radeon_add_pixmap(bos, i++, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
-
-	if (pMask)
-	    radeon_add_pixmap(bos, i++, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
-
-	radeon_add_pixmap(bos, i++, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
-
-	ret = radeon_cs_space_check(info->cs, bos, i);
-	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
-	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
-	}
-	if (ret == RADEON_CS_SPACE_FLUSH) {
-            radeon_cs_flush_indirect(pScrn);
-	    retry_count++;
-	    if (retry_count == 2)
-	        RADEON_FALLBACK(("Not enough Video RAM - this really shouldn't happen\nm"));
-	    goto retry;
-	}
-    }
-
     if (!RADEONSetupSourceTile(pSrcPicture, pSrc, TRUE, FALSE))
 	return FALSE;
 
+    if (!RADEONPrepareCompositeState(op, pSrcPicture, pMaskPicture, pDstPicture,
+				     pSrc, pMask, pDst))
+	return FALSE;
+
     if (!FUNC_NAME(R300TextureSetup)(pSrcPicture, pSrc, 0))
 	return FALSE;
     txenable = R300_TEX_0_ENABLE;
@@ -2060,7 +2017,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
     FINISH_ACCEL();
 
     BEGIN_ACCEL(1);
-    if (info->accel_state->has_mask)
+    if (pMask)
 	OUT_ACCEL_REG(R300_VAP_VTX_SIZE, 6);
     else
 	OUT_ACCEL_REG(R300_VAP_VTX_SIZE, 4);
@@ -2143,6 +2100,19 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
     /* ErrorF("RadeonComposite (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n",
        srcX, srcY, maskX, maskY,dstX, dstY, w, h); */
 
+#ifdef ACCEL_CP
+    if (info->cs && info->cs->cdw > 15 * 1024) {
+	radeon_cs_flush_indirect(pScrn);
+	info->accel_state->exa->PrepareComposite(info->accel_state->composite_op,
+						 info->accel_state->dst_pic,
+						 info->accel_state->msk_pic,
+						 info->accel_state->src_pic,
+						 info->accel_state->dst_pix,
+						 info->accel_state->msk_pix,
+						 info->accel_state->src_pix);
+    }
+#endif
+
     srcTopLeft.x     = IntToxFixed(srcX);
     srcTopLeft.y     = IntToxFixed(srcY);
     srcTopRight.x    = IntToxFixed(srcX + w);
@@ -2161,7 +2131,7 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
 	}
     }
 
-    if (info->accel_state->has_mask) {
+    if (info->accel_state->msk_pic) {
 	maskTopLeft.x     = IntToxFixed(maskX);
 	maskTopLeft.y     = IntToxFixed(maskY);
 	maskTopRight.x    = IntToxFixed(maskX + w);
@@ -2192,7 +2162,7 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
 	BEGIN_RING(3 * vtx_count + 3);
 	OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD,
 			    3 * vtx_count + 1));
-	if (info->accel_state->has_mask)
+	if (info->accel_state->msk_pic)
 	    OUT_RING(RADEON_CP_VC_FRMT_XY |
 		     RADEON_CP_VC_FRMT_ST0 |
 		     RADEON_CP_VC_FRMT_ST1);
@@ -2242,7 +2212,7 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
 
 #endif
 
-    if (info->accel_state->has_mask) {
+    if (info->accel_state->msk_pic) {
 	if (IS_R300_3D || IS_R500_3D) {
 	    VTX_OUT_MASK((float)dstX,                                      (float)dstY,
 			 xFixedToFloat(srcTopLeft.x) / info->accel_state->texW[0],      xFixedToFloat(srcTopLeft.y) / info->accel_state->texH[0],
commit 8d2f712eaf1e569fd92bbe2db5aceb43b7b367d1
Author: Dave Airlie <airlied at linux.ie>
Date:   Fri Jul 3 10:40:59 2009 +1000

    radeon: don't set up overlay under KMS until we figure out how.

diff --git a/src/radeon_video.c b/src/radeon_video.c
index a14f44c..58b9d46 100644
--- a/src/radeon_video.c
+++ b/src/radeon_video.c
@@ -284,7 +284,7 @@ void RADEONInitVideo(ScreenPtr pScreen)
     memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
     adaptors = newAdaptors;
 
-    if (!IS_AVIVO_VARIANT) {
+    if (!IS_AVIVO_VARIANT && !info->kms_enabled) {
 	overlayAdaptor = RADEONSetupImageVideo(pScreen);
 	if (overlayAdaptor != NULL) {
 	    adaptors[num_adaptors++] = overlayAdaptor;
commit 2a622168606d98c404708b879e6417c8f7d7305c
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Thu Jul 2 15:03:53 2009 +0200

    Test BO pointer before passing it to radeon_bo_unref().

diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index b28f726..ca4eda0 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -405,7 +405,8 @@ static void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
     if (!driverPriv)
       return;
 
-    radeon_bo_unref(driver_priv->bo);
+    if (driver_priv->bo)
+	radeon_bo_unref(driver_priv->bo);
     xfree(driverPriv);
 }
 
commit 36a4ea5a9c7062f4c8aa7480bb7488ce2062390f
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Thu Jul 2 14:52:44 2009 +0200

    Warning fixes.

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 644727d..b5846df 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -302,7 +302,6 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 		/* go through all the outputs and force DPMS them back on? */
 		for (i = 0; i < xf86_config->num_output; i++) {
 			xf86OutputPtr output = xf86_config->output[i];
-			drmmode_output_private_ptr drmmode_output;
 
 			if (output->crtc != crtc)
 				continue;
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index b8f921d..2713bab 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -35,7 +35,7 @@
 
 typedef struct {
   int fd;
-  int fb_id;
+  unsigned fb_id;
   drmModeResPtr mode_res;
   drmModeFBPtr mode_fb;
   int cpp;
@@ -48,7 +48,7 @@ typedef struct {
     drmModeCrtcPtr mode_crtc;
     struct radeon_bo *cursor_bo;
     struct radeon_bo *rotate_bo;
-    int rotate_fb_id;
+    unsigned rotate_fb_id;
     uint16_t lut_r[256], lut_g[256], lut_b[256];
 } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
 
diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index f2554bb..3df7daf 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -831,7 +831,6 @@ void drmmode_wait_for_vline(ScrnInfoPtr pScrn, PixmapPtr pPix,
 {
     RADEONInfoPtr  info = RADEONPTR(pScrn);
     xf86CrtcConfigPtr  xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    uint32_t offset;
     drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[crtc]->driver_private;
     ACCEL_PREAMBLE();
 
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index f43490e..37b47fe 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -40,6 +40,8 @@
 
 #ifdef RADEON_DRI2
 
+#include "radeon_bo_gem.h"
+
 #if DRI2INFOREC_VERSION >= 1
 #define USE_DRI2_1_1_0
 #endif
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 9444da3..b28f726 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -334,7 +334,7 @@ static void RADEONFinishAccess_BE(PixmapPtr pPix, int index)
 #ifdef XF86DRM_MODE
 static Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
 {
-    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
+    ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
     struct radeon_exa_pixmap_priv *driver_priv;
     int ret;
 
@@ -400,8 +400,6 @@ void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align)
 
 static void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
 {
-    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-    RADEONInfoPtr info = RADEONPTR(pScrn);
     struct radeon_exa_pixmap_priv *driver_priv = driverPriv;
 
     if (!driverPriv)
@@ -413,8 +411,6 @@ static void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
 
 struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
 {
-    ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
-    RADEONInfoPtr info = RADEONPTR(pScrn);
     struct radeon_exa_pixmap_priv *driver_priv;
     driver_priv = exaGetPixmapDriverPrivate(pPix);
     return driver_priv->bo;
@@ -422,9 +418,6 @@ struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
 
 void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
 {
-    ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
-    RADEONInfoPtr info = RADEONPTR(pScrn);
-
     struct radeon_exa_pixmap_priv *driver_priv;
 
     driver_priv = exaGetPixmapDriverPrivate(pPix);
diff --git a/src/radeon_probe.c b/src/radeon_probe.c
index cf7981f..78dee85 100644
--- a/src/radeon_probe.c
+++ b/src/radeon_probe.c
@@ -47,6 +47,11 @@
 #include "xf86.h"
 #include "xf86Resources.h"
 
+#ifdef XF86DRM_MODE
+#include "xf86drmMode.h"
+#include "dri.h"
+#endif
+
 #include "radeon_chipset_gen.h"
 
 #include "radeon_pci_chipset_gen.h"
commit 65465d56c1bf943113518a5b2f57b3170213bab9
Author: Dave Airlie <airlied at linux.ie>
Date:   Thu Jul 2 18:38:38 2009 +1000

    radeon: fix up configure check better

diff --git a/configure.ac b/configure.ac
index 7535625..8cf69c1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -120,7 +120,6 @@ if test "$DRI" = yes; then
         CFLAGS="$XORG_CFLAGS $DRI_CFLAGS $CFLAGS"
 	AC_CHECK_HEADER(xf86drmMode.h,[DRM_MODE=yes],[DRM_MODE=no],[#include <stdint.h>
 #include <stdlib.h>])
-#	DRM_MODE = no
 	if test "x$DRM_MODE" = xyes; then
 		PKG_CHECK_MODULES(LIBDRM_RADEON, [xorg-server >= 1.6 libdrm_radeon],
 		[LIBDRM_RADEON=yes], [LIBDRM_RADEON=no])
@@ -254,7 +253,7 @@ CPPFLAGS="$SAVE_CPPFLAGS"
 
 AM_CONDITIONAL(USE_EXA, test "x$USE_EXA" = xyes)
 
-AM_CONDITIONAL(XF86DRM_MODE, test "x$DRM_MODE" = xyes)
+AM_CONDITIONAL(XF86DRM_MODE, test "x$LIBDRM_RADEON" = xyes)
 
 if test "x$XSERVER_LIBPCIACCESS" = xyes; then
     PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.8.0])
commit ad17108b72c9adf773a122b4c054c7b92e6a8b9d
Author: Dave Airlie <airlied at linux.ie>
Date:   Thu Jul 2 17:25:57 2009 +1000

    radeon: fix it properly.
    
    I blame the flu

diff --git a/src/radeon_probe.c b/src/radeon_probe.c
index 4f7d494..cf7981f 100644
--- a/src/radeon_probe.c
+++ b/src/radeon_probe.c
@@ -146,7 +146,8 @@ radeon_get_scrninfo(int entity_num, void *pci_dev)
       pScrn->FreeScreen    = RADEONFreeScreen_KMS;
       pScrn->ValidMode     = RADEONValidMode;
     } else 
-#endif {
+#endif 
+    {
       pScrn->PreInit       = RADEONPreInit;
       pScrn->ScreenInit    = RADEONScreenInit;
       pScrn->SwitchMode    = RADEONSwitchMode;
commit e1b9cb9ea665eaa84e64a386299efa0819d55df4
Author: Dave Airlie <airlied at redhat.com>
Date:   Thu Jul 2 17:18:47 2009 +1000

    radeon: fix compile without kms

diff --git a/src/radeon_probe.c b/src/radeon_probe.c
index 38fe0b0..4f7d494 100644
--- a/src/radeon_probe.c
+++ b/src/radeon_probe.c
@@ -135,6 +135,7 @@ radeon_get_scrninfo(int entity_num, void *pci_dev)
     pScrn->Probe         = RADEONProbe;
 #endif
 
+#ifdef XF86DRM_MODE
     if (kms == 1) {
       pScrn->PreInit       = RADEONPreInit_KMS;
       pScrn->ScreenInit    = RADEONScreenInit_KMS;
@@ -144,7 +145,8 @@ radeon_get_scrninfo(int entity_num, void *pci_dev)
       pScrn->LeaveVT       = RADEONLeaveVT_KMS;
       pScrn->FreeScreen    = RADEONFreeScreen_KMS;
       pScrn->ValidMode     = RADEONValidMode;
-    } else {
+    } else 
+#endif {
       pScrn->PreInit       = RADEONPreInit;
       pScrn->ScreenInit    = RADEONScreenInit;
       pScrn->SwitchMode    = RADEONSwitchMode;
commit de427fac6912a625f7e4d8b982a1f7a1ba80dfbe
Author: Dave Airlie <airlied at redhat.com>
Date:   Thu Jul 2 15:41:43 2009 +1000

    radeon/dri2: fix dri2 - needs newest libdrm_radeon

diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 133859f..f43490e 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -97,7 +97,9 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
             depth_pixmap = pixmap;
         }
         driver_priv = exaGetPixmapDriverPrivate(pixmap);
-	buffers[i].name = radeon_gem_name_bo(driver_priv->bo);
+	r = radeon_gem_get_kernel_name(driver_priv->bo, &buffers[i].name);
+	if (r)
+		return r;
 
         buffers[i].attachment = attachments[i];
         buffers[i].pitch = pixmap->devKind;
@@ -156,7 +158,10 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
         depth_pixmap = pixmap;
     }
     driver_priv = exaGetPixmapDriverPrivate(pixmap);
-    buffers->name = radeon_gem_name_bo(driver_priv->bo);
+    r = radeon_gem_get_kernel_name(driver_priv->bo, &buffers->name);
+    if (r)
+	    return NULL;
+
     buffers->attachment = attachment;
     buffers->pitch = pixmap->devKind;
     buffers->cpp = pixmap->drawable.bitsPerPixel / 8;
commit 2b671adba54ebff1756dd990123f4bade6e35d61
Author: Dave Airlie <airlied at redhat.com>
Date:   Thu Jul 2 15:25:19 2009 +1000

    radeon/dri2: call proper gem bo function

diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 0a30f8f..133859f 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -156,7 +156,7 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
         depth_pixmap = pixmap;
     }
     driver_priv = exaGetPixmapDriverPrivate(pixmap);
-    buffers->name = radeon_bo_name_bo(driver_priv->bo);
+    buffers->name = radeon_gem_name_bo(driver_priv->bo);
     buffers->attachment = attachment;
     buffers->pitch = pixmap->devKind;
     buffers->cpp = pixmap->drawable.bitsPerPixel / 8;
commit 851b2b8cab883e4422745cca1827aa8ac9f193a3
Author: Dave Airlie <airlied at redhat.com>
Date:   Thu Jul 2 15:17:13 2009 +1000

    radeon/kms: add textured video BO size checks

diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c
index 10414b9..184258c 100644
--- a/src/radeon_textured_video.c
+++ b/src/radeon_textured_video.c
@@ -137,6 +137,14 @@ static REF_TRANSFORM trans[2] =
     {1.1643, 0.0, 1.7927, -0.2132, -0.5329, 2.1124, 0.0}  /* BT.709 */
 };
 
+static inline void radeon_add_bo(struct radeon_cs_space_check *bos, int index, struct radeon_bo *bo, int read_domains, int write_domain)
+{
+    bos[index].bo = bo;
+    bos[index].read_domains = read_domains;
+    bos[index].write_domain = write_domain;
+    bos[index].new_accounted = 0;
+}
+
 #define ACCEL_MMIO
 #define ACCEL_PREAMBLE()	unsigned char *RADEONMMIO = info->MMIO
 #define BEGIN_ACCEL(n)		RADEONWaitForFifo(pScrn, (n))
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index b9930c7..2efe449 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -106,39 +106,25 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 
  retry:
     if (info->cs) {
-      
 	i = 0;
-	bos[i].bo = pPriv->src_bo;
-	bos[i].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
-	bos[i].write_domain = 0;
-	bos[i].new_accounted = 0;
-	i++;
+	radeon_add_bo(bos, i++, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
-	if (pPriv->bicubic_enabled) {
-	    bos[i].bo = pPriv->bicubic_bo;
-	    bos[i].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
-	    bos[i].write_domain = 0;
-	    bos[i].new_accounted = 0;
-	    i++;
-	}
+	if (pPriv->bicubic_enabled)
+	    radeon_add_bo(bos, i++, pPriv->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	driver_priv = exaGetPixmapDriverPrivate(pPixmap);
-	bos[i].bo = driver_priv->bo;
-	bos[i].read_domains = 0;
-	bos[i].write_domain = RADEON_GEM_DOMAIN_VRAM;
-	bos[i].new_accounted = 0;
-	i++;
+	radeon_add_bo(bos, i++, driver_priv->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
 
 	ret = radeon_cs_space_check(info->cs, bos, i);
 	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
-	    ErrorF("Not enough RAM to hw accel composite operation\n");
+	    ErrorF("Not enough RAM to hw accel xv operation\n");
 	    return;
 	}
 	if (ret == RADEON_CS_SPACE_FLUSH) {
 	    radeon_cs_flush_indirect(pScrn);
 	    retry_count++;
 	    if (retry_count == 2) {
-	        ErrorF("Not enough RAM to hw accel composite operation\n");
+	        ErrorF("Not enough RAM to hw accel xv operation\n");
 	        return;
 	    }
 	    goto retry;
@@ -511,9 +497,37 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     int ref = pPriv->transform_index;
     float ucscale = 0.25, vcscale = 0.25;
     Bool needux8 = FALSE, needvx8 = FALSE;
-
+    struct radeon_cs_space_check bos[3];
+    int i, ret, retry_count = 0;
     ACCEL_PREAMBLE();
 
+ retry:
+    if (info->cs) {
+	i = 0;
+	radeon_add_bo(bos, i++, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	if (pPriv->bicubic_enabled)
+	    radeon_add_bo(bos, i++, pPriv->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	driver_priv = exaGetPixmapDriverPrivate(pPixmap);
+	radeon_add_bo(bos, i++, driver_priv->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	ret = radeon_cs_space_check(info->cs, bos, i);
+	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	    ErrorF("Not enough RAM to hw accel xv operation\n");
+	    return;
+	}
+	if (ret == RADEON_CS_SPACE_FLUSH) {
+	    radeon_cs_flush_indirect(pScrn);
+	    retry_count++;
+	    if (retry_count == 2) {
+	        ErrorF("Not enough RAM to hw accel xv operation\n");
+	        return;
+	    }
+	    goto retry;
+	}
+    }
+
     pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
 
 #ifdef USE_EXA
@@ -1033,8 +1047,37 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     int dstxoff, dstyoff, pixel_shift, vtx_count;
     BoxPtr pBox = REGION_RECTS(&pPriv->clip);
     int nBox = REGION_NUM_RECTS(&pPriv->clip);
+    struct radeon_cs_space_check bos[3];
+    int i, ret, retry_count = 0;
     ACCEL_PREAMBLE();
 
+ retry:
+    if (info->cs) {
+	i = 0;
+	radeon_add_bo(bos, i++, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	if (pPriv->bicubic_enabled)
+	    radeon_add_bo(bos, i++, pPriv->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	driver_priv = exaGetPixmapDriverPrivate(pPixmap);
+	radeon_add_bo(bos, i++, driver_priv->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	ret = radeon_cs_space_check(info->cs, bos, i);
+	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	    ErrorF("Not enough RAM to hw accel xv operation\n");
+	    return;
+	}
+	if (ret == RADEON_CS_SPACE_FLUSH) {
+	    radeon_cs_flush_indirect(pScrn);
+	    retry_count++;
+	    if (retry_count == 2) {
+	        ErrorF("Not enough RAM to hw accel xv operation\n");
+	        return;
+	    }
+	    goto retry;
+	}
+    }
+
     pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
 
 #ifdef USE_EXA
@@ -2463,8 +2506,37 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     int dstxoff, dstyoff, pixel_shift, vtx_count;
     BoxPtr pBox = REGION_RECTS(&pPriv->clip);
     int nBox = REGION_NUM_RECTS(&pPriv->clip);
+    struct radeon_cs_space_check bos[3];
+    int i, ret, retry_count = 0;
     ACCEL_PREAMBLE();
 
+ retry:
+    if (info->cs) {
+	i = 0;
+	radeon_add_bo(bos, i++, pPriv->src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	if (pPriv->bicubic_enabled)
+	    radeon_add_bo(bos, i++, pPriv->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	driver_priv = exaGetPixmapDriverPrivate(pPixmap);
+	radeon_add_bo(bos, i++, driver_priv->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	ret = radeon_cs_space_check(info->cs, bos, i);
+	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	    ErrorF("Not enough RAM to hw accel xv operation\n");
+	    return;
+	}
+	if (ret == RADEON_CS_SPACE_FLUSH) {
+	    radeon_cs_flush_indirect(pScrn);
+	    retry_count++;
+	    if (retry_count == 2) {
+	        ErrorF("Not enough RAM to hw accel xv operation\n");
+	        return;
+	    }
+	    goto retry;
+	}
+    }
+
     pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
 
 #ifdef USE_EXA
commit 9d092060236e8587697fdd57a7a01f3c0dddd680
Author: Dave Airlie <airlied at redhat.com>
Date:   Thu Jul 2 15:17:03 2009 +1000

    kms: drop DGA

diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 5c570ac..cd3ec9a 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -465,13 +465,6 @@ static Bool RADEONCloseScreen_KMS(int scrnIndex, ScreenPtr pScreen)
     if (info->cursor) xf86DestroyCursorInfoRec(info->cursor);
     info->cursor = NULL;
 
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Disposing DGA\n");
-    if (info->DGAModes) xfree(info->DGAModes);
-    info->DGAModes = NULL;
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Unmapping memory\n");
-
     pScrn->vtSema = FALSE;
     xf86ClearPrimInitDone(info->pEnt->index);
     pScreen->BlockHandler = info->BlockHandler;
@@ -650,11 +643,6 @@ Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
 	}
     }
 
-    /* DGA setup */
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "Initializing DGA\n");
-    RADEONDGAInit(pScreen);
-
     /* Init Xv */
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "Initializing Xv\n");
commit 207174ea964c561076bdd5297a2fb6f136b4b645
Author: Dave Airlie <airlied at redhat.com>
Date:   Thu Jul 2 15:16:47 2009 +1000

    radeon: fix CS imbalance

diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index 96c84e8..f2554bb 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -110,7 +110,7 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 	OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
 	FINISH_ACCEL();
 
-	BEGIN_ACCEL(5);
+	BEGIN_ACCEL(3);
 	OUT_ACCEL_REG(R300_GB_AA_CONFIG, 0);
 	OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D | R300_DC_FREE_3D);
 	OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, R300_ZC_FLUSH | R300_ZC_FREE);
commit 4d24a9d2c0be0c025266cc8cdf7e8d7bb065cdb1
Author: Dave Airlie <airlied at redhat.com>
Date:   Thu Jul 2 14:55:45 2009 +1000

    radeon: enable KMS build

diff --git a/configure.ac b/configure.ac
index 2d3ac4b..7535625 100644
--- a/configure.ac
+++ b/configure.ac
@@ -118,13 +118,13 @@ if test "$DRI" = yes; then
 
         save_CFLAGS="$CFLAGS"
         CFLAGS="$XORG_CFLAGS $DRI_CFLAGS $CFLAGS"
-#AC_CHECK_HEADER(xf86drmMode.h,[DRM_MODE=yes],[DRM_MODE=no],[#include <stdint.h>
+	AC_CHECK_HEADER(xf86drmMode.h,[DRM_MODE=yes],[DRM_MODE=no],[#include <stdint.h>
 #include <stdlib.h>])
-	DRM_MODE = no
+#	DRM_MODE = no
 	if test "x$DRM_MODE" = xyes; then
 		PKG_CHECK_MODULES(LIBDRM_RADEON, [xorg-server >= 1.6 libdrm_radeon],
 		[LIBDRM_RADEON=yes], [LIBDRM_RADEON=no])
-		
+
 		if test "x$LIBDRM_RADEON" = xyes; then
 			AC_DEFINE(XF86DRM_MODE,1,[DRM kernel modesetting])
 			AC_DEFINE(RADEON_DRI2, 1,[Enable DRI2 code])
commit 9bcd3ae7966eb7a17b922bcd33e0d6f016245614
Author: Dave Airlie <airlied at redhat.com>
Date:   Thu Jul 2 14:55:18 2009 +1000

    radeon/kms: fixup 3d state emission for KMS
    
    This fixes font rendering under KMS (should have looked at dmesg)

diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index a947143..96c84e8 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -56,6 +56,7 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 {
     RADEONInfoPtr  info       = RADEONPTR(pScrn);
     uint32_t gb_tile_config, su_reg_dest, vap_cntl;
+    int size;
     ACCEL_PREAMBLE();
 
     info->accel_state->texW[0] = info->accel_state->texH[0] =
@@ -63,11 +64,13 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 
     if (IS_R300_3D || IS_R500_3D) {
 
-	BEGIN_ACCEL(3);
-	OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D | R300_DC_FREE_3D);
-	OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, R300_ZC_FLUSH | R300_ZC_FREE);
-	OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
-	FINISH_ACCEL();
+	if (!info->cs) {
+	    BEGIN_ACCEL(3);
+	    OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D | R300_DC_FREE_3D);
+	    OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, R300_ZC_FLUSH | R300_ZC_FREE);
+	    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
+	    FINISH_ACCEL();
+	}
 
 	gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16);
 
@@ -79,20 +82,26 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 	case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break;
 	}
 
-	BEGIN_ACCEL(5);
-	OUT_ACCEL_REG(R300_GB_TILE_CONFIG, gb_tile_config);
-	OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
-	OUT_ACCEL_REG(R300_DST_PIPE_CONFIG, R300_PIPE_AUTO_CONFIG);
-	OUT_ACCEL_REG(R300_GB_SELECT, 0);
-	OUT_ACCEL_REG(R300_GB_ENABLE, 0);
-	FINISH_ACCEL();
+	if (info->dri->pKernelDRMVersion->version_major < 2) {
+	    size = (info->ChipFamily >= CHIP_FAMILY_R420) ? 5 : 4;
+	    BEGIN_ACCEL(size);
+	    OUT_ACCEL_REG(R300_GB_TILE_CONFIG, gb_tile_config);
+	    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
+	    if (info->ChipFamily >= CHIP_FAMILY_R420)
+		OUT_ACCEL_REG(R300_DST_PIPE_CONFIG, R300_PIPE_AUTO_CONFIG);
+	    OUT_ACCEL_REG(R300_GB_SELECT, 0);
+	    OUT_ACCEL_REG(R300_GB_ENABLE, 0);
+	    FINISH_ACCEL();
+	}
 
 	if (IS_R500_3D) {
 	    su_reg_dest = ((1 << info->accel_state->num_gb_pipes) - 1);
-	    BEGIN_ACCEL(2);
-	    OUT_ACCEL_REG(R500_SU_REG_DEST, su_reg_dest);
-	    OUT_ACCEL_REG(R500_VAP_INDEX_OFFSET, 0);
-	    FINISH_ACCEL();
+	    if (info->dri->pKernelDRMVersion->version_major < 2) {
+		BEGIN_ACCEL(2);
+		OUT_ACCEL_REG(R500_SU_REG_DEST, su_reg_dest);
+		OUT_ACCEL_REG(R500_VAP_INDEX_OFFSET, 0);
+		FINISH_ACCEL();
+	    }
 	}
 
 	BEGIN_ACCEL(3);
@@ -105,25 +114,30 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 	OUT_ACCEL_REG(R300_GB_AA_CONFIG, 0);
 	OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D | R300_DC_FREE_3D);
 	OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, R300_ZC_FLUSH | R300_ZC_FREE);
-	OUT_ACCEL_REG(R300_GB_MSPOS0, ((6 << R300_MS_X0_SHIFT) |
-				       (6 << R300_MS_Y0_SHIFT) |
-				       (6 << R300_MS_X1_SHIFT) |
-				       (6 << R300_MS_Y1_SHIFT) |
-				       (6 << R300_MS_X2_SHIFT) |
-				       (6 << R300_MS_Y2_SHIFT) |
-				       (6 << R300_MSBD0_Y_SHIFT) |
-				       (6 << R300_MSBD0_X_SHIFT)));
-	OUT_ACCEL_REG(R300_GB_MSPOS1, ((6 << R300_MS_X3_SHIFT) |
-				       (6 << R300_MS_Y3_SHIFT) |
-				       (6 << R300_MS_X4_SHIFT) |
-				       (6 << R300_MS_Y4_SHIFT) |
-				       (6 << R300_MS_X5_SHIFT) |
-				       (6 << R300_MS_Y5_SHIFT) |
-				       (6 << R300_MSBD1_SHIFT)));
 	FINISH_ACCEL();
 
-	BEGIN_ACCEL(5);
-	OUT_ACCEL_REG(R300_GA_ENHANCE, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL);
+	if (info->dri->pKernelDRMVersion->version_major < 2) {
+	    BEGIN_ACCEL(3);
+	    OUT_ACCEL_REG(R300_GB_MSPOS0, ((6 << R300_MS_X0_SHIFT) |
+					   (6 << R300_MS_Y0_SHIFT) |
+					   (6 << R300_MS_X1_SHIFT) |
+					   (6 << R300_MS_Y1_SHIFT) |
+					   (6 << R300_MS_X2_SHIFT) |
+					   (6 << R300_MS_Y2_SHIFT) |
+					   (6 << R300_MSBD0_Y_SHIFT) |
+					   (6 << R300_MSBD0_X_SHIFT)));
+	    OUT_ACCEL_REG(R300_GB_MSPOS1, ((6 << R300_MS_X3_SHIFT) |
+					   (6 << R300_MS_Y3_SHIFT) |
+					   (6 << R300_MS_X4_SHIFT) |
+					   (6 << R300_MS_Y4_SHIFT) |
+					   (6 << R300_MS_X5_SHIFT) |
+					   (6 << R300_MS_Y5_SHIFT) |
+					   (6 << R300_MSBD1_SHIFT)));
+	    OUT_ACCEL_REG(R300_GA_ENHANCE, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL);
+	    FINISH_ACCEL();
+	}
+
+	BEGIN_ACCEL(4);
 	OUT_ACCEL_REG(R300_GA_POLY_MODE, R300_FRONT_PTYPE_TRIANGE | R300_BACK_PTYPE_TRIANGE);
 	OUT_ACCEL_REG(R300_GA_ROUND_MODE, (R300_GEOMETRY_ROUND_NEAREST |
 					   R300_COLOR_ROUND_NEAREST));
commit ac1607bb23f0c7584648407a3ac3fb27142e186e
Author: Dave Airlie <airlied at redhat.com>
Date:   Thu Jul 2 14:55:05 2009 +1000

    kms: no need to reference fifo slots

diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 9fc6643..5c570ac 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -145,7 +145,6 @@ static Bool RADEONPreInitAccel_KMS(ScrnInfoPtr pScrn)
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to allocate accel_state rec!\n");
 	return FALSE;
     }
-    info->accel_state->fifo_slots                 = 0;
 
     if (info->ChipFamily >= CHIP_FAMILY_R600) {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
commit 1782ce28953184776c90eb1255208a3e0ad245f0
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Jun 30 16:55:26 2009 +1000

    radeon: add KMS support (still disabled)
    
    This adds DRI2 + KMS + driver pixmaps support to the driver.
    
    I've decided to just do a completely separate KMS driver file
    instead of hacking the crap out of radeon_driver.c. So now
    I do the KMS check in radeon_probe.c time and set the DDX
    pointed up to a completely different set at this stage.
    
    This avoids a lot of if (kms) type crap in the code at
    the expense of making sure we make changes to both files
    if necessary.
    
    This code is still disabled in configure.ac as I broke EXA composite
    rendering somehow in KMS mode

diff --git a/configure.ac b/configure.ac
index 0cf24e6..2d3ac4b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -118,16 +118,16 @@ if test "$DRI" = yes; then
 
         save_CFLAGS="$CFLAGS"
         CFLAGS="$XORG_CFLAGS $DRI_CFLAGS $CFLAGS"
-#	AC_CHECK_HEADER(xf86drmMode.h,[DRM_MODE=yes],[DRM_MODE=no],[#include <stdint.h>
-	DRM_MODE=no
+#AC_CHECK_HEADER(xf86drmMode.h,[DRM_MODE=yes],[DRM_MODE=no],[#include <stdint.h>
 #include <stdlib.h>])
-	 if test "x$DRM_MODE" = xyes; then
+	DRM_MODE = no
+	if test "x$DRM_MODE" = xyes; then
 		PKG_CHECK_MODULES(LIBDRM_RADEON, [xorg-server >= 1.6 libdrm_radeon],
 		[LIBDRM_RADEON=yes], [LIBDRM_RADEON=no])
 		
 		if test "x$LIBDRM_RADEON" = xyes; then
 			AC_DEFINE(XF86DRM_MODE,1,[DRM kernel modesetting])
-			AC_DEFINE(DRI2, 1,[Enable DRI2 code])
+			AC_DEFINE(RADEON_DRI2, 1,[Enable DRI2 code])
 		fi
         fi
 	CFLAGS="$save_CFLAGS"
@@ -254,6 +254,8 @@ CPPFLAGS="$SAVE_CPPFLAGS"
 
 AM_CONDITIONAL(USE_EXA, test "x$USE_EXA" = xyes)
 
+AM_CONDITIONAL(XF86DRM_MODE, test "x$DRM_MODE" = xyes)
+
 if test "x$XSERVER_LIBPCIACCESS" = xyes; then
     PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.8.0])
     XORG_CFLAGS="$XORG_CFLAGS $PCIACCESS_CFLAGS"
diff --git a/src/Makefile.am b/src/Makefile.am
index 1864f96..421d163 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -26,7 +26,7 @@
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
 
-radeon_drv_la_LIBADD =
+radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS)
 
 if DRI
 RADEON_DRI_SRCS = radeon_dri.c
@@ -65,6 +65,10 @@ XMODE_SRCS=\
         modes/xf86Rotate.c \
         modes/xf86DiDGA.c
 
+if XF86DRM_MODE
+RADEON_KMS_SRCS=radeon_dri2.c radeon_kms.c drmmode_display.c
+endif
+
 if USE_EXA
 RADEON_EXA_SOURCES = radeon_exa.c r600_exa.c r6xx_accel.c r600_textured_videofuncs.c r600_shader.c
 endif
@@ -95,7 +99,8 @@ radeon_drv_la_SOURCES = \
 	radeon_textured_video.c radeon_pm.c \
 	radeon_crtc.c radeon_output.c radeon_modes.c radeon_tv.c \
 	$(RADEON_ATOMBIOS_SOURCES) radeon_atombios.c radeon_atomwrapper.c \
-	$(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) atombios_output.c atombios_crtc.c
+	$(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) atombios_output.c atombios_crtc.c \
+	$(RADEON_KMS_SRCS)
 
 if XMODES
 radeon_drv_la_SOURCES += \
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
new file mode 100644
index 0000000..644727d
--- /dev/null
+++ b/src/drmmode_display.c
@@ -0,0 +1,1035 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Dave Airlie <airlied at redhat.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef XF86DRM_MODE
+#include <sys/ioctl.h>
+#include "micmap.h"
+#include "xf86cmap.h"
+#include "radeon.h"
+#include "radeon_reg.h"
+#include "radeon_drm.h"
+#include "sarea.h"
+
+#include "drmmode_display.h"
+
+/* DPMS */
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
+static void
+drmmode_ConvertFromKMode(ScrnInfoPtr	scrn,
+		     drmModeModeInfo *kmode,
+		     DisplayModePtr	mode)
+{
+	memset(mode, 0, sizeof(DisplayModeRec));
+	mode->status = MODE_OK;
+
+	mode->Clock = kmode->clock;
+
+	mode->HDisplay = kmode->hdisplay;
+	mode->HSyncStart = kmode->hsync_start;
+	mode->HSyncEnd = kmode->hsync_end;
+	mode->HTotal = kmode->htotal;
+	mode->HSkew = kmode->hskew;
+
+	mode->VDisplay = kmode->vdisplay;
+	mode->VSyncStart = kmode->vsync_start;
+	mode->VSyncEnd = kmode->vsync_end;
+	mode->VTotal = kmode->vtotal;
+	mode->VScan = kmode->vscan;
+
+	mode->Flags = kmode->flags; //& FLAG_BITS;
+	mode->name = strdup(kmode->name);
+
+	if (kmode->type & DRM_MODE_TYPE_DRIVER)
+		mode->type = M_T_DRIVER;
+	if (kmode->type & DRM_MODE_TYPE_PREFERRED)
+		mode->type |= M_T_PREFERRED;
+	xf86SetModeCrtc (mode, scrn->adjustFlags);
+}
+
+static void
+drmmode_ConvertToKMode(ScrnInfoPtr	scrn,
+		     drmModeModeInfo *kmode,
+		     DisplayModePtr	mode)
+{
+	memset(kmode, 0, sizeof(*kmode));
+
+	kmode->clock = mode->Clock;
+	kmode->hdisplay = mode->HDisplay;
+	kmode->hsync_start = mode->HSyncStart;
+	kmode->hsync_end = mode->HSyncEnd;
+	kmode->htotal = mode->HTotal;
+	kmode->hskew = mode->HSkew;
+
+	kmode->vdisplay = mode->VDisplay;
+	kmode->vsync_start = mode->VSyncStart;
+	kmode->vsync_end = mode->VSyncEnd;
+	kmode->vtotal = mode->VTotal;
+	kmode->vscan = mode->VScan;
+
+	kmode->flags = mode->Flags; //& FLAG_BITS;
+	if (mode->name)
+		strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
+	kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
+
+}
+
+static void
+drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
+{
+#if 0
+	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+//	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+//	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+	/* bonghits in the randr 1.2 - uses dpms to disable crtc - bad buzz */
+	if (mode == DPMSModeOff) {
+//		drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+//			       0, 0, 0, NULL, 0, NULL);
+	}
+#endif
+}
+
+static PixmapPtr
+create_pixmap_for_fbcon(drmmode_ptr drmmode,
+			ScrnInfoPtr pScrn, int crtc_id)
+{
+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+	drmmode_crtc_private_ptr drmmode_crtc;
+	ScreenPtr pScreen = pScrn->pScreen;
+	PixmapPtr pixmap;
+	struct radeon_bo *bo;
+	drmModeFBPtr fbcon;
+	struct drm_gem_flink flink;
+
+	drmmode_crtc = xf86_config->crtc[crtc_id]->driver_private;
+
+	fbcon = drmModeGetFB(drmmode->fd, drmmode_crtc->mode_crtc->buffer_id);
+	if (fbcon == NULL)
+		return NULL;
+
+	flink.handle = fbcon->handle;
+	if (ioctl(drmmode->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Couldn't flink fbcon handle\n");
+		return NULL;
+	}
+
+	bo = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0);
+	if (bo == NULL) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Couldn't allocate bo for fbcon handle\n");
+		return NULL;
+	}
+
+	pixmap = GetScratchPixmapHeader(pScreen,
+					fbcon->width, fbcon->height,
+					fbcon->depth, fbcon->bpp,
+					fbcon->pitch, NULL);
+	if (pixmap == NULL) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Couldn't allocate pixmap fbcon contents\n");
+		return NULL;
+	}
+
+	radeon_set_pixmap_bo(pixmap, bo);
+
+	radeon_bo_unref(bo);
+	drmModeFreeFB(fbcon);
+	return pixmap;
+}
+
+void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
+{
+	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+	RADEONInfoPtr info = RADEONPTR(pScrn);
+	PixmapPtr src, dst;
+	ScreenPtr pScreen = pScrn->pScreen;
+	int crtc_id = 0;
+	int i;
+	int pitch = pScrn->displayWidth * info->CurrentLayout.pixel_bytes;
+
+	if (info->ChipFamily >= CHIP_FAMILY_R600)
+		return;
+
+	for (i = 0; i < xf86_config->num_crtc; i++) {
+		xf86CrtcPtr crtc = xf86_config->crtc[i];
+		drmmode_crtc_private_ptr drmmode_crtc;
+
+		drmmode_crtc = crtc->driver_private;
+		if (drmmode_crtc->mode_crtc->buffer_id)
+			crtc_id = i;
+	}
+
+	src = create_pixmap_for_fbcon(drmmode, pScrn, crtc_id);
+	if (!src)
+		return;
+
+	dst = GetScratchPixmapHeader(pScreen,
+				     pScrn->virtualX, pScrn->virtualY,
+				     pScrn->depth, pScrn->bitsPerPixel,
+				     pitch, NULL);
+	radeon_set_pixmap_bo(dst, info->front_bo);
+	info->accel_state->exa->PrepareCopy (src, dst,
+					     -1, -1, GXcopy, FB_ALLONES);
+	info->accel_state->exa->Copy (dst, 0, 0, 0, 0,
+				      pScrn->virtualX, pScrn->virtualY);
+	info->accel_state->exa->DoneCopy (dst);
+	radeon_cs_flush_indirect(pScrn);
+
+	(*pScreen->DestroyPixmap)(dst);
+	(*pScreen->DestroyPixmap)(src);
+
+}
+
+static Bool
+drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
+		     Rotation rotation, int x, int y)
+{
+	ScrnInfoPtr pScrn = crtc->scrn;
+	RADEONInfoPtr info = RADEONPTR(pScrn);
+	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+	int saved_x, saved_y;
+	Rotation saved_rotation;
+	DisplayModeRec saved_mode;
+	uint32_t *output_ids;
+	int output_count = 0;
+	Bool ret = TRUE;
+	int i;
+	int fb_id;
+	drmModeModeInfo kmode;
+	int pitch = pScrn->displayWidth * info->CurrentLayout.pixel_bytes;
+
+	if (drmmode->fb_id == 0) {
+		ret = drmModeAddFB(drmmode->fd,
+				   pScrn->virtualX, pScrn->virtualY,
+                                   pScrn->depth, pScrn->bitsPerPixel,
+				   pitch,
+				   info->front_bo->handle,
+                                   &drmmode->fb_id);
+                if (ret < 0) {
+                        ErrorF("failed to add fb\n");
+                        return FALSE;
+                }
+        }
+
+	saved_mode = crtc->mode;
+	saved_x = crtc->x;
+	saved_y = crtc->y;
+	saved_rotation = crtc->rotation;
+
+	if (mode) {
+		crtc->mode = *mode;
+		crtc->x = x;
+		crtc->y = y;
+		crtc->rotation = rotation;
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,5,99,0,0)
+		crtc->transformPresent = FALSE;
+#endif
+	}
+
+	output_ids = xcalloc(sizeof(uint32_t), xf86_config->num_output);
+	if (!output_ids) {
+		ret = FALSE;
+		goto done;
+	}
+
+	if (mode) {
+		for (i = 0; i < xf86_config->num_output; i++) {
+			xf86OutputPtr output = xf86_config->output[i];
+			drmmode_output_private_ptr drmmode_output;
+
+			if (output->crtc != crtc)
+				continue;
+
+			drmmode_output = output->driver_private;
+			output_ids[output_count] = drmmode_output->mode_output->connector_id;
+			output_count++;
+		}
+
+		if (!xf86CrtcRotate(crtc)) {
+			goto done;
+		}
+
+		drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
+
+		fb_id = drmmode->fb_id;
+		if (drmmode_crtc->rotate_fb_id) {
+			fb_id = drmmode_crtc->rotate_fb_id;
+			x = y = 0;
+		}
+		ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+				     fb_id, x, y, output_ids, output_count, &kmode);
+		if (ret)
+			xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+				   "failed to set mode: %s", strerror(-ret));
+		else
+			ret = TRUE;
+
+		if (crtc->scrn->pScreen)
+			xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
+		/* go through all the outputs and force DPMS them back on? */
+		for (i = 0; i < xf86_config->num_output; i++) {
+			xf86OutputPtr output = xf86_config->output[i];
+			drmmode_output_private_ptr drmmode_output;
+
+			if (output->crtc != crtc)
+				continue;
+
+			output->funcs->dpms(output, DPMSModeOn);
+		}
+	}
+
+
+
+done:
+	if (!ret) {
+		crtc->x = saved_x;
+		crtc->y = saved_y;
+		crtc->rotation = saved_rotation;
+		crtc->mode = saved_mode;
+	}
+	return ret;
+}
+
+static void
+drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
+{
+
+}
+
+static void
+drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+	drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
+}
+
+static void
+drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	void *ptr;
+
+	/* cursor should be mapped already */
+	ptr = drmmode_crtc->cursor_bo->ptr;
+
+	memcpy (ptr, image, 64 * 64 * 4);
+
+	return;
+}
+
+
+static void
+drmmode_hide_cursor (xf86CrtcPtr crtc)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+	drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 64, 64);
+
+}
+
+static void
+drmmode_show_cursor (xf86CrtcPtr crtc)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+	uint32_t handle = drmmode_crtc->cursor_bo->handle;
+
+	drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 64, 64);
+}
+
+static void *
+drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+	int size;
+	struct radeon_bo *rotate_bo;
+	int ret;
+	unsigned long rotate_pitch;
+
+	width = RADEON_ALIGN(width, 63);
+	rotate_pitch = width * drmmode->cpp;
+
+	size = rotate_pitch * height;
+
+	rotate_bo = radeon_bo_open(drmmode->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+	if (rotate_bo == NULL)
+		return NULL;
+
+	radeon_bo_map(rotate_bo, 1);
+
+	ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth,
+			   crtc->scrn->bitsPerPixel, rotate_pitch,
+			   rotate_bo->handle,
+			   &drmmode_crtc->rotate_fb_id);
+	if (ret) {
+		ErrorF("failed to add rotate fb\n");
+	}
+
+	drmmode_crtc->rotate_bo = rotate_bo;
+	return drmmode_crtc->rotate_bo->ptr;
+}
+
+static PixmapPtr
+drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
+{
+	ScrnInfoPtr pScrn = crtc->scrn;
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+	unsigned long rotate_pitch;
+	PixmapPtr rotate_pixmap;
+
+	if (!data)
+		data = drmmode_crtc_shadow_allocate (crtc, width, height);
+
+	rotate_pitch = RADEON_ALIGN(width, 63) * drmmode->cpp;
+
+	rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
+					       width, height,
+					       pScrn->depth,
+					       pScrn->bitsPerPixel,
+					       rotate_pitch,
+					       data);
+
+	if (rotate_pixmap == NULL) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Couldn't allocate shadow pixmap for rotated CRTC\n");
+	}
+
+	if (drmmode_crtc->rotate_bo)
+		radeon_set_pixmap_bo(rotate_pixmap, drmmode_crtc->rotate_bo);
+	return rotate_pixmap;
+
+}
+
+static void
+drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+	if (rotate_pixmap)
+	    FreeScratchPixmapHeader(rotate_pixmap);
+
+	if (data) {
+		drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id);
+		drmmode_crtc->rotate_fb_id = 0;
+		radeon_bo_unmap(drmmode_crtc->rotate_bo);
+		radeon_bo_unref(drmmode_crtc->rotate_bo);
+		drmmode_crtc->rotate_bo = NULL;
+	}
+
+}
+
+static void
+drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
+                      uint16_t *blue, int size)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+	drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+			    size, red, green, blue);
+}
+
+static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
+    .dpms = drmmode_crtc_dpms,
+    .set_mode_major = drmmode_set_mode_major,
+    .set_cursor_colors = drmmode_set_cursor_colors,
+    .set_cursor_position = drmmode_set_cursor_position,
+    .show_cursor = drmmode_show_cursor,
+    .hide_cursor = drmmode_hide_cursor,
+    .load_cursor_argb = drmmode_load_cursor_argb,
+
+    .gamma_set = drmmode_crtc_gamma_set,
+    .shadow_create = drmmode_crtc_shadow_create,
+    .shadow_allocate = drmmode_crtc_shadow_allocate,
+    .shadow_destroy = drmmode_crtc_shadow_destroy,
+    .destroy = NULL, /* XXX */
+};
+
+
+static void
+drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
+{
+	xf86CrtcPtr crtc;
+	drmmode_crtc_private_ptr drmmode_crtc;
+
+	crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
+	if (crtc == NULL)
+		return;
+
+	drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
+	drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]);
+	drmmode_crtc->drmmode = drmmode;
+	crtc->driver_private = drmmode_crtc;
+
+	return;
+}
+
+static xf86OutputStatus
+drmmode_output_detect(xf86OutputPtr output)
+{
+	/* go to the hw and retrieve a new output struct */
+	drmmode_output_private_ptr drmmode_output = output->driver_private;
+	drmmode_ptr drmmode = drmmode_output->drmmode;
+	xf86OutputStatus status;
+	drmModeFreeConnector(drmmode_output->mode_output);
+
+	drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
+
+	switch (drmmode_output->mode_output->connection) {
+	case DRM_MODE_CONNECTED:
+		status = XF86OutputStatusConnected;
+		break;
+	case DRM_MODE_DISCONNECTED:
+		status = XF86OutputStatusDisconnected;
+		break;
+	default:
+	case DRM_MODE_UNKNOWNCONNECTION:
+		status = XF86OutputStatusUnknown;
+		break;
+	}
+	return status;
+}
+
+static Bool
+drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
+{
+	return MODE_OK;
+}
+
+static DisplayModePtr
+drmmode_output_get_modes(xf86OutputPtr output)
+{
+	drmmode_output_private_ptr drmmode_output = output->driver_private;
+	drmModeConnectorPtr koutput = drmmode_output->mode_output;
+	drmmode_ptr drmmode = drmmode_output->drmmode;
+	int i;
+	DisplayModePtr Modes = NULL, Mode;
+	drmModePropertyPtr props;
+
+	/* look for an EDID property */
+	for (i = 0; i < koutput->count_props; i++) {
+		props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
+		if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
+			if (!strcmp(props->name, "EDID")) {
+				if (drmmode_output->edid_blob)
+					drmModeFreePropertyBlob(drmmode_output->edid_blob);
+				drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]);
+			}
+			drmModeFreeProperty(props);
+		}
+	}
+
+	if (drmmode_output->edid_blob)
+		xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, drmmode_output->edid_blob->data));
+	else
+		xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, NULL));
+
+	/* modes should already be available */
+	for (i = 0; i < koutput->count_modes; i++) {
+		Mode = xnfalloc(sizeof(DisplayModeRec));
+
+		drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode);
+		Modes = xf86ModesAdd(Modes, Mode);
+
+	}
+	return Modes;
+}
+
+static void
+drmmode_output_destroy(xf86OutputPtr output)
+{
+	drmmode_output_private_ptr drmmode_output = output->driver_private;
+
+	if (drmmode_output->edid_blob)
+		drmModeFreePropertyBlob(drmmode_output->edid_blob);
+	drmModeFreeConnector(drmmode_output->mode_output);
+	xfree(drmmode_output);
+	output->driver_private = NULL;
+}
+
+static void
+drmmode_output_dpms(xf86OutputPtr output, int mode)
+{
+	drmmode_output_private_ptr drmmode_output = output->driver_private;
+	drmModeConnectorPtr koutput = drmmode_output->mode_output;
+	drmmode_ptr drmmode = drmmode_output->drmmode;
+
+	drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
+				    drmmode_output->dpms_enum_id, mode);
+	return;
+}
+
+static const xf86OutputFuncsRec drmmode_output_funcs = {
+    .dpms = drmmode_output_dpms,
+#if 0
+
+    .save = drmmode_crt_save,
+    .restore = drmmode_crt_restore,
+    .mode_fixup = drmmode_crt_mode_fixup,
+    .prepare = drmmode_output_prepare,
+    .mode_set = drmmode_crt_mode_set,
+    .commit = drmmode_output_commit,
+#endif
+    .detect = drmmode_output_detect,
+    .mode_valid = drmmode_output_mode_valid,
+
+    .get_modes = drmmode_output_get_modes,
+    .destroy = drmmode_output_destroy
+};
+
+static int subpixel_conv_table[7] = { 0, SubPixelUnknown,
+				      SubPixelHorizontalRGB,
+				      SubPixelHorizontalBGR,
+				      SubPixelVerticalRGB,
+				      SubPixelVerticalBGR,
+				      SubPixelNone };
+
+const char *output_names[] = { "None",
+			       "VGA",
+			       "DVI",
+			       "DVI",
+			       "DVI",
+			       "Composite",
+			       "TV",
+			       "LVDS",
+			       "CTV",
+			       "DIN",
+			       "DP",
+			       "HDMI",
+			       "HDMI",
+};
+
+static void
+drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
+{
+	xf86OutputPtr output;
+	drmModeConnectorPtr koutput;
+	drmModeEncoderPtr kencoder;
+	drmmode_output_private_ptr drmmode_output;
+	drmModePropertyPtr props;
+	char name[32];
+	int i;
+
+	koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]);
+	if (!koutput)
+		return;
+
+	kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]);
+	if (!kencoder) {
+		drmModeFreeConnector(koutput);
+		return;
+	}
+
+	/* need to do smart conversion here for compat with non-kms ATI driver */
+	if (koutput->connector_type_id == 1) {
+	    switch(koutput->connector_type) {
+	    case DRM_MODE_CONNECTOR_VGA:
+	    case DRM_MODE_CONNECTOR_DVII:
+	    case DRM_MODE_CONNECTOR_DVID:
+	    case DRM_MODE_CONNECTOR_DVIA:
+	    case DRM_MODE_CONNECTOR_HDMIA:
+	    case DRM_MODE_CONNECTOR_HDMIB:
+		snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1);
+		break;
+	    default:
+		snprintf(name, 32, "%s", output_names[koutput->connector_type]);
+		break;
+	    }
+	} else {
+	    snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1);
+	}
+
+	output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
+	if (!output) {
+		drmModeFreeEncoder(kencoder);
+		drmModeFreeConnector(koutput);
+		return;
+	}
+
+	drmmode_output = xcalloc(sizeof(drmmode_output_private_rec), 1);
+	if (!drmmode_output) {
+		xf86OutputDestroy(output);
+		drmModeFreeConnector(koutput);
+		drmModeFreeEncoder(kencoder);
+		return;
+	}
+
+	drmmode_output->output_id = drmmode->mode_res->connectors[num];
+	drmmode_output->mode_output = koutput;
+	drmmode_output->mode_encoder = kencoder;
+	drmmode_output->drmmode = drmmode;
+	output->mm_width = koutput->mmWidth;
+	output->mm_height = koutput->mmHeight;
+
+	output->subpixel_order = subpixel_conv_table[koutput->subpixel];
+	output->driver_private = drmmode_output;
+
+	output->possible_crtcs = kencoder->possible_crtcs;
+	output->possible_clones = kencoder->possible_clones;
+
+	for (i = 0; i < koutput->count_props; i++) {
+		props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
+		if (props && (props->flags && DRM_MODE_PROP_ENUM)) {
+			if (!strcmp(props->name, "DPMS")) {
+				drmmode_output->dpms_enum_id = koutput->props[i];
+				drmModeFreeProperty(props);
+				break;
+			}
+			drmModeFreeProperty(props);
+		}
+	}
+
+	return;
+}
+
+static Bool
+drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
+{
+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+	drmmode_crtc_private_ptr
+		    drmmode_crtc = xf86_config->crtc[0]->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+	RADEONInfoPtr info = RADEONPTR(scrn);
+	struct radeon_bo *old_front = NULL;
+	Bool	    ret;
+	ScreenPtr   screen = screenInfo.screens[scrn->scrnIndex];
+	uint32_t    old_fb_id;
+	int	    i, pitch, old_width, old_height, old_pitch;
+	int screen_size;
+	int cpp = info->CurrentLayout.pixel_bytes;
+	struct radeon_bo *front_bo;
+
+	if (scrn->virtualX == width && scrn->virtualY == height)
+		return TRUE;
+
+	front_bo = radeon_get_pixmap_bo(screen->GetScreenPixmap(screen));
+	radeon_cs_flush_indirect(scrn);
+
+	if (front_bo)
+		radeon_bo_wait(front_bo);
+
+	pitch = RADEON_ALIGN(width, 63);
+	height = RADEON_ALIGN(height, 16);
+
+	screen_size = pitch * height * cpp;
+
+	xf86DrvMsg(scrn->scrnIndex, X_INFO,
+		   "Allocate new frame buffer %dx%d stride %d\n",
+		   width, height, pitch);
+
+	old_width = scrn->virtualX;
+	old_height = scrn->virtualY;
+	old_pitch = scrn->displayWidth;
+	old_fb_id = drmmode->fb_id;
+	old_front = info->front_bo;
+
+	scrn->virtualX = width;
+	scrn->virtualY = height;
+	scrn->displayWidth = pitch;
+
+	info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+	if (!info->front_bo)
+		goto fail;
+
+	ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
+			   scrn->bitsPerPixel, pitch * cpp,
+			   info->front_bo->handle,
+			   &drmmode->fb_id);
+	if (ret)
+		goto fail;
+
+	radeon_set_pixmap_bo(screen->GetScreenPixmap(screen), info->front_bo);
+	screen->ModifyPixmapHeader(screen->GetScreenPixmap(screen),
+				   width, height, -1, -1, pitch * cpp, NULL);
+
+	//	xf86DrvMsg(scrn->scrnIndex, X_INFO, "New front buffer at 0x%lx\n",
+	//		   info->front_bo-);
+
+	for (i = 0; i < xf86_config->num_crtc; i++) {
+		xf86CrtcPtr crtc = xf86_config->crtc[i];
+
+		if (!crtc->enabled)
+			continue;
+
+		drmmode_set_mode_major(crtc, &crtc->mode,
+				       crtc->rotation, crtc->x, crtc->y);
+	}
+
+	if (old_fb_id)
+		drmModeRmFB(drmmode->fd, old_fb_id);
+	if (old_front)
+		radeon_bo_unref(old_front);
+
+	return TRUE;
+
+ fail:
+	if (info->front_bo)
+		radeon_bo_unref(info->front_bo);
+	info->front_bo = old_front;
+	scrn->virtualX = old_width;
+	scrn->virtualY = old_height;
+	scrn->displayWidth = old_pitch;
+	drmmode->fb_id = old_fb_id;
+
+	return FALSE;
+}
+
+static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
+	drmmode_xf86crtc_resize
+};
+
+
+Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, char *busId, char *driver_name, int cpp, int zaphod_mask)
+{
+	xf86CrtcConfigPtr   xf86_config;
+	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+	int i;
+	Bool ret;
+
+	/* Create a bus Id */
+	/* Low level DRM open */
+	if (!pRADEONEnt->fd) {
+		ret = DRIOpenDRMMaster(pScrn, SAREA_MAX, busId, driver_name);
+		if (!ret) {
+			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+				   "[dri] DRIGetVersion failed to open the DRM\n"
+				   "[dri] Disabling DRI.\n");
+			return FALSE;
+		}
+
+		drmmode->fd = DRIMasterFD(pScrn);
+		pRADEONEnt->fd = drmmode->fd;
+	} else {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+				" reusing fd for second head\n");
+		drmmode->fd = pRADEONEnt->fd;
+	}
+	xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
+	xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+
+	drmmode->cpp = cpp;
+	drmmode->mode_res = drmModeGetResources(drmmode->fd);
+	if (!drmmode->mode_res)
+		return FALSE;
+
+	xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height);
+	for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
+		if (zaphod_mask & (1 << i))
+			drmmode_crtc_init(pScrn, drmmode, i);
+
+	for (i = 0; i < drmmode->mode_res->count_connectors; i++)
+		if (zaphod_mask & (1 << i))
+			drmmode_output_init(pScrn, drmmode, i);
+
+	xf86InitialConfiguration(pScrn, TRUE);
+
+	return TRUE;
+}
+
+Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr)
+{
+	drmmode->bufmgr = bufmgr;
+	return TRUE;
+}
+
+
+
+void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo)
+{
+	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+	xf86CrtcPtr crtc = xf86_config->crtc[id];
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+	drmmode_crtc->cursor_bo = bo;
+}
+
+void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags)
+{
+	xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+	xf86OutputPtr  output = config->output[config->compat_output];
+	xf86CrtcPtr	crtc = output->crtc;
+
+	if (crtc && crtc->enabled) {
+		drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
+				       x, y);
+	}
+}
+
+Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
+{
+	xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+	int c;
+
+	drmmode_copy_fb(pScrn, drmmode);
+
+	for (c = 0; c < config->num_crtc; c++) {
+		xf86CrtcPtr	crtc = config->crtc[c];
+		drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+		xf86OutputPtr	output = NULL;
+		int		o;
+
+		/* Skip disabled CRTCs */
+		if (!crtc->enabled) {
+			drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+				       0, 0, 0, NULL, 0, NULL);
+			continue;
+		}
+
+		if (config->output[config->compat_output]->crtc == crtc)
+			output = config->output[config->compat_output];
+		else
+		{
+			for (o = 0; o < config->num_output; o++)
+				if (config->output[o]->crtc == crtc)
+				{
+					output = config->output[o];
+					break;
+				}
+		}
+		/* paranoia */
+		if (!output)
+			continue;
+
+		/* Mark that we'll need to re-set the mode for sure */
+		memset(&crtc->mode, 0, sizeof(crtc->mode));
+		if (!crtc->desiredMode.CrtcHDisplay)
+		{
+			DisplayModePtr  mode = xf86OutputFindClosestMode (output, pScrn->currentMode);
+
+			if (!mode)
+				return FALSE;
+			crtc->desiredMode = *mode;
+			crtc->desiredRotation = RR_Rotate_0;
+			crtc->desiredX = 0;
+			crtc->desiredY = 0;
+		}
+
+		if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation,
+						 crtc->desiredX, crtc->desiredY))
+			return FALSE;
+	}
+	return TRUE;
+}
+
+static void drmmode_load_palette(ScrnInfoPtr pScrn, int numColors,
+                                 int *indices, LOCO *colors, VisualPtr pVisual)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    uint16_t       lut_r[256], lut_g[256], lut_b[256];
+    int index, j, i;
+    int c;
+
+    for (c = 0; c < xf86_config->num_crtc; c++) {
+        xf86CrtcPtr crtc = xf86_config->crtc[c];
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+        for (i = 0 ; i < 256; i++) {
+            lut_r[i] = drmmode_crtc->lut_r[i] << 6;
+            lut_g[i] = drmmode_crtc->lut_g[i] << 6;
+            lut_b[i] = drmmode_crtc->lut_b[i] << 6;
+        }
+
+        switch(pScrn->depth) {
+        case 15:
+            for (i = 0; i < numColors; i++) {
+                index = indices[i];
+                for (j = 0; j < 8; j++) {
+                    lut_r[index * 8 + j] = colors[index].red << 6;
+                    lut_g[index * 8 + j] = colors[index].green << 6;
+                    lut_b[index * 8 + j] = colors[index].blue << 6;
+                }
+            }
+         break;
+         case 16:
+             for (i = 0; i < numColors; i++) {
+                 index = indices[i];
+
+                  if (i <= 31) {
+                      for (j = 0; j < 8; j++) {
+                          lut_r[index * 8 + j] = colors[index].red << 6;
+                          lut_b[index * 8 + j] = colors[index].blue << 6;
+                      }
+                  }
+
+                  for (j = 0; j < 4; j++) {
+                      lut_g[index * 4 + j] = colors[index].green << 6;
+                  }
+              }
+	  break;
+          default:
+              for (i = 0; i < numColors; i++) {
+                  index = indices[i];
+                  lut_r[index] = colors[index].red << 6;
+                  lut_g[index] = colors[index].green << 6;
+                  lut_b[index] = colors[index].blue << 6;
+              }
+              break;
+          }
+
+    /* Make the change through RandR */
+#ifdef RANDR_12_INTERFACE
+        if (crtc->randr_crtc)
+            RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
+        else
+#endif
+            crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
+     }
+}
+
+Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
+{
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+                  "Initializing kms color map\n");
+    if (!miCreateDefColormap(pScreen))
+        return FALSE;
+    /* all radeons support 10 bit CLUTs */
+    if (!xf86HandleColormaps(pScreen, 256, 10,
+                             drmmode_load_palette, NULL,
+                             CMAP_PALETTED_TRUECOLOR
+#if 0 /* This option messes up text mode! (eich at suse.de) */
+                             | CMAP_LOAD_EVEN_IF_OFFSCREEN
+#endif
+                             | CMAP_RELOAD_ON_MODE_SWITCH))
+         return FALSE;
+    return TRUE;
+}
+#endif
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
new file mode 100644
index 0000000..b8f921d
--- /dev/null
+++ b/src/drmmode_display.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *     Dave Airlie <airlied at redhat.com>
+ *
+ */
+#ifndef DRMMODE_DISPLAY_H
+#define DRMMODE_DISPLAY_H
+
+#ifdef XF86DRM_MODE
+
+#include "xf86drmMode.h"
+
+#include "radeon_probe.h"
+
+typedef struct {
+  int fd;
+  int fb_id;
+  drmModeResPtr mode_res;
+  drmModeFBPtr mode_fb;
+  int cpp;
+  struct radeon_bo_manager *bufmgr;
+} drmmode_rec, *drmmode_ptr;
+
+typedef struct {
+
+    drmmode_ptr drmmode;
+    drmModeCrtcPtr mode_crtc;
+    struct radeon_bo *cursor_bo;
+    struct radeon_bo *rotate_bo;
+    int rotate_fb_id;
+    uint16_t lut_r[256], lut_g[256], lut_b[256];
+} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
+
+typedef struct {
+    drmmode_ptr drmmode;
+    int output_id;
+    drmModeConnectorPtr mode_output;
+    drmModeEncoderPtr mode_encoder;
+    drmModePropertyBlobPtr edid_blob;
+    int dpms_enum_id;
+} drmmode_output_private_rec, *drmmode_output_private_ptr;
+
+
+extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, char *busId, char *driver_name, int cpp, int zaphod_mask);
+extern Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr);
+extern void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo);
+void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags);
+extern Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
+extern void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
+extern Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn);
+#endif
+
+#endif
diff --git a/src/pcidb/parse_pci_ids.pl b/src/pcidb/parse_pci_ids.pl
index a3a8af8..d1900a4 100755
--- a/src/pcidb/parse_pci_ids.pl
+++ b/src/pcidb/parse_pci_ids.pl
@@ -33,7 +33,7 @@ print PCICHIPSET "PciChipsets RADEONPciChipsets[] = {\n";
 print PCIDEVICEMATCH "/* This file is autogenerated please do not edit */\n";
 print PCIDEVICEMATCH "static const struct pci_id_match radeon_device_match[] = {\n";
 print RADEONCHIPINFO "/* This file is autogenerated please do not edit */\n";
-print RADEONCHIPINFO "RADEONCardInfo RADEONCards[] = {\n";
+print RADEONCHIPINFO "static RADEONCardInfo RADEONCards[] = {\n";
 while (<CSV>) {
   if ($csv->parse($_)) {
     my @columns = $csv->fields();
diff --git a/src/radeon.h b/src/radeon.h
index 0dce081..82136c8 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -89,6 +89,8 @@
 #ifdef XF86DRM_MODE
 #include "radeon_bo.h"
 #include "radeon_cs.h"
+#include "radeon_dri2.h"
+#include "drmmode_display.h"
 #else
 #include "radeon_dummy_bufmgr.h"
 #endif
@@ -857,6 +859,9 @@ typedef struct {
     RADEONCardType    cardType;            /* Current card is a PCI card */
     struct radeon_cp  *cp;
     struct radeon_dri  *dri;
+#ifdef XF86DRM_MODE
+    struct radeon_dri2  dri2;
+#endif
 #ifdef USE_EXA
     Bool              accelDFS;
 #endif
@@ -972,10 +977,17 @@ typedef struct {
     int can_resize;
     void (*reemit_current2d)(ScrnInfoPtr pScrn, int op); // emit the current 2D state into the IB 
     struct radeon_2d_state state_2d;
+    Bool kms_enabled;
+    struct radeon_bo *front_bo;
 #ifdef XF86DRM_MODE
     struct radeon_bo_manager *bufmgr;
     struct radeon_cs_manager *csm;
     struct radeon_cs *cs;
+
+    struct radeon_bo *cursor_bo[2];
+    uint64_t vram_size;
+    uint64_t gart_size;
+    drmmode_rec drmmode;
 #else
     /* fake bool */
     Bool cs;
@@ -1163,6 +1175,12 @@ extern void RADEONInitMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
 extern void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn,
 					 RADEONSavePtr restore);
 
+Bool RADEONGetRec(ScrnInfoPtr pScrn);
+void RADEONFreeRec(ScrnInfoPtr pScrn);
+Bool RADEONPreInitVisual(ScrnInfoPtr pScrn);
+Bool RADEONPreInitWeight(ScrnInfoPtr pScrn);
+
+
 /* radeon_pm.c */
 extern void RADEONPMInit(ScrnInfoPtr pScrn);
 extern void RADEONPMBlockHandler(ScrnInfoPtr pScrn);
diff --git a/src/radeon_accel.c b/src/radeon_accel.c
index 5e24683..79052a1 100644
--- a/src/radeon_accel.c
+++ b/src/radeon_accel.c
@@ -1131,8 +1131,10 @@ void RADEONInit3DEngine(ScrnInfoPtr pScrn)
     if (info->directRenderingEnabled) {
 	drm_radeon_sarea_t *pSAREAPriv;
 
-	pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
-	pSAREAPriv->ctx_owner = DRIGetContext(pScrn->pScreen);
+	if (!info->kms_enabled) {
+	    pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+	    pSAREAPriv->ctx_owner = DRIGetContext(pScrn->pScreen);
+	}
 	RADEONInit3DEngineCP(pScrn);
     } else
 #endif
diff --git a/src/radeon_chipinfo_gen.h b/src/radeon_chipinfo_gen.h
index bffe88e..641361d 100644
--- a/src/radeon_chipinfo_gen.h
+++ b/src/radeon_chipinfo_gen.h
@@ -1,5 +1,5 @@
 /* This file is autogenerated please do not edit */
-RADEONCardInfo RADEONCards[] = {
+static RADEONCardInfo RADEONCards[] = {
  { 0x3150, CHIP_FAMILY_RV380, 1, 0, 0, 0, 0 },
  { 0x3151, CHIP_FAMILY_RV380, 0, 0, 0, 0, 0 },
  { 0x3152, CHIP_FAMILY_RV380, 1, 0, 0, 0, 0 },
diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index 6ea0513..a947143 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -811,6 +811,39 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 
 }
 
+#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
+void drmmode_wait_for_vline(ScrnInfoPtr pScrn, PixmapPtr pPix,
+			    int crtc, int start, int stop)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+    xf86CrtcConfigPtr  xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    uint32_t offset;
+    drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[crtc]->driver_private;
+    ACCEL_PREAMBLE();
+
+    BEGIN_ACCEL(3);
+
+    if (IS_AVIVO_VARIANT) {
+	uint32_t reg = AVIVO_D1MODE_VLINE_START_END; /* this is just a marker */
+	OUT_ACCEL_REG(reg,
+		      ((start << AVIVO_D1MODE_VLINE_START_SHIFT) |
+		       (stop << AVIVO_D1MODE_VLINE_END_SHIFT) |
+		       AVIVO_D1MODE_VLINE_INV));
+    } else {
+	OUT_ACCEL_REG(RADEON_CRTC_GUI_TRIG_VLINE, /* another placeholder */
+		      ((start << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
+		      (stop << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
+		      RADEON_CRTC_GUI_TRIG_VLINE_INV));
+    }
+    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
+				      RADEON_ENG_DISPLAY_SELECT_CRTC0));
+
+    OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_NOP, 0));
+    OUT_RING(drmmode_crtc->mode_crtc->crtc_id);
+    FINISH_ACCEL();
+}
+#endif
+
 /* inserts a wait for vline in the command stream */
 void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix,
 	int crtc, int start, int stop)
@@ -829,16 +862,21 @@ void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix,
     if (!xf86_config->crtc[crtc]->enabled)
 	return;
 
+    if (info->cs) {
+        if (pPix != pScrn->pScreen->GetScreenPixmap(pScrn->pScreen))
+	    return;
+    } else {
 #ifdef USE_EXA
-    if (info->useEXA)
-	offset = exaGetPixmapOffset(pPix);
-    else
+	if (info->useEXA)
+	    offset = exaGetPixmapOffset(pPix);
+	else
 #endif
-	offset = pPix->devPrivate.ptr - info->FB;
+	    offset = pPix->devPrivate.ptr - info->FB;
 
-    /* if drawing to front buffer */
-    if (offset != 0)
-	return;
+	/* if drawing to front buffer */
+	if (offset != 0)
+	    return;
+    }
 
     start = max(start, 0);
     stop = min(stop, xf86_config->crtc[crtc]->mode.VDisplay);
@@ -846,6 +884,13 @@ void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix,
     if (start > xf86_config->crtc[crtc]->mode.VDisplay)
 	return;
 
+#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
+    if (info->kms_enabled) {
+	drmmode_wait_for_vline(pScrn, pPix, crtc, start, stop);
+	return;
+    }
+#endif
+
     BEGIN_ACCEL(2);
 
     if (IS_AVIVO_VARIANT) {
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
new file mode 100644
index 0000000..0a30f8f
--- /dev/null
+++ b/src/radeon_dri2.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright 2008 Kristian Høgsberg 
+ * Copyright 2008 Jérôme Glisse
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "radeon.h"
+#include "radeon_dri2.h"
+#include "radeon_version.h"
+
+#ifdef RADEON_DRI2
+
+#if DRI2INFOREC_VERSION >= 1
+#define USE_DRI2_1_1_0
+#endif
+
+struct dri2_buffer_priv {
+    PixmapPtr   pixmap;
+    unsigned int attachment;
+};
+
+
+#ifndef USE_DRI2_1_1_0
+static DRI2BufferPtr
+radeon_dri2_create_buffers(DrawablePtr drawable,
+                           unsigned int *attachments,
+                           int count)
+{
+    ScreenPtr pScreen = drawable->pScreen;
+    DRI2BufferPtr buffers;
+    struct dri2_buffer_priv *privates;
+    PixmapPtr pixmap, depth_pixmap;
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int i, r;
+
+    buffers = xcalloc(count, sizeof *buffers);
+    if (buffers == NULL) {
+        return NULL;
+    }
+    privates = xcalloc(count, sizeof(struct dri2_buffer_priv));
+    if (privates == NULL) {
+        xfree(buffers);
+        return NULL;
+    }
+
+    depth_pixmap = NULL;
+    for (i = 0; i < count; i++) {
+        if (attachments[i] == DRI2BufferFrontLeft) {
+            if (drawable->type == DRAWABLE_PIXMAP) {
+                pixmap = (Pixmap*)drawable;
+            } else {
+                pixmap = (*pScreen->GetWindowPixmap)((WindowPtr)drawable);
+            }
+            pixmap->refcnt++;
+        } else if (attachments[i] == DRI2BufferStencil && depth_pixmap) {
+            pixmap = depth_pixmap;
+            pixmap->refcnt++;
+        } else {
+            pixmap = (*pScreen->CreatePixmap)(pScreen,
+                                              drawable->width,
+                                              drawable->height,
+                                              drawable->depth,
+                                              0);
+        }
+
+        if (attachments[i] == DRI2BufferDepth) {
+            depth_pixmap = pixmap;
+        }
+        driver_priv = exaGetPixmapDriverPrivate(pixmap);
+	buffers[i].name = radeon_gem_name_bo(driver_priv->bo);
+
+        buffers[i].attachment = attachments[i];
+        buffers[i].pitch = pixmap->devKind;
+        buffers[i].cpp = pixmap->drawable.bitsPerPixel / 8;
+        buffers[i].driverPrivate = &privates[i];
+        buffers[i].flags = 0;
+        privates[i].pixmap = pixmap;
+        privates[i].attachment = attachments[i];
+    }
+    return buffers;
+}
+#else
+static DRI2BufferPtr
+radeon_dri2_create_buffer(DrawablePtr drawable,
+                          unsigned int attachment,
+                          unsigned int format)
+{
+    ScreenPtr pScreen = drawable->pScreen;
+    DRI2BufferPtr buffers;
+    struct dri2_buffer_priv *privates;
+    PixmapPtr pixmap, depth_pixmap;
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int r;
+
+    buffers = xcalloc(1, sizeof *buffers);
+    if (buffers == NULL) {
+        return NULL;
+    }
+    privates = xcalloc(1, sizeof(struct dri2_buffer_priv));
+    if (privates == NULL) {
+        xfree(buffers);
+        return NULL;
+    }
+
+    depth_pixmap = NULL;
+
+    if (attachment == DRI2BufferFrontLeft) {
+        if (drawable->type == DRAWABLE_PIXMAP) {
+            pixmap = (PixmapPtr)drawable;
+        } else {
+            pixmap = (*pScreen->GetWindowPixmap)((WindowPtr)drawable);
+        }
+        pixmap->refcnt++;
+    } else if (attachment == DRI2BufferStencil && depth_pixmap) {
+        pixmap = depth_pixmap;
+        pixmap->refcnt++;
+    } else {
+        pixmap = (*pScreen->CreatePixmap)(pScreen,
+                drawable->width,
+                drawable->height,
+                (format != 0)?format:drawable->depth,
+                0);
+    }
+
+    if (attachment == DRI2BufferDepth) {
+        depth_pixmap = pixmap;
+    }
+    driver_priv = exaGetPixmapDriverPrivate(pixmap);
+    buffers->name = radeon_bo_name_bo(driver_priv->bo);
+    buffers->attachment = attachment;
+    buffers->pitch = pixmap->devKind;
+    buffers->cpp = pixmap->drawable.bitsPerPixel / 8;
+    buffers->driverPrivate = privates;
+    buffers->format = format;
+    buffers->flags = 0; /* not tiled */
+    privates->pixmap = pixmap;
+    privates->attachment = attachment;
+
+    return buffers;
+}
+#endif
+
+#ifndef USE_DRI2_1_1_0
+static void
+radeon_dri2_destroy_buffers(DrawablePtr drawable,
+                            DRI2BufferPtr buffers,
+                            int count)
+{
+    ScreenPtr pScreen = drawable->pScreen;
+    struct dri2_buffer_priv *private;
+    int i;
+
+    for (i = 0; i < count; i++) {
+        private = buffers[i].driverPrivate;
+        (*pScreen->DestroyPixmap)(private->pixmap);
+    }
+    if (buffers) {
+        xfree(buffers[0].driverPrivate);
+        xfree(buffers);
+    }
+}
+#else
+static void
+radeon_dri2_destroy_buffer(DrawablePtr drawable, DRI2BufferPtr buffers)
+{
+    if(buffers)
+    {
+        ScreenPtr pScreen = drawable->pScreen;
+        struct dri2_buffer_priv *private;
+
+        private = buffers->driverPrivate;
+        (*pScreen->DestroyPixmap)(private->pixmap);
+
+        xfree(buffers->driverPrivate);
+        xfree(buffers);
+    }
+}
+#endif
+
+static void
+radeon_dri2_copy_region(DrawablePtr drawable,
+                        RegionPtr region,
+                        DRI2BufferPtr dest_buffer,
+                        DRI2BufferPtr src_buffer)
+{
+    struct dri2_buffer_priv *src_private = src_buffer->driverPrivate;
+    struct dri2_buffer_priv *dst_private = dest_buffer->driverPrivate;
+    ScreenPtr pScreen = drawable->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    PixmapPtr src_pixmap;
+    PixmapPtr dst_pixmap;
+    RegionPtr copy_clip;
+    GCPtr gc;
+
+    src_pixmap = src_private->pixmap;
+    dst_pixmap = dst_private->pixmap;
+    if (src_private->attachment == DRI2BufferFrontLeft) {
+        src_pixmap = (PixmapPtr)drawable;
+    }
+    if (dst_private->attachment == DRI2BufferFrontLeft) {
+        dst_pixmap = (PixmapPtr)drawable;
+    }
+    gc = GetScratchGC(drawable->depth, pScreen);
+    copy_clip = REGION_CREATE(pScreen, NULL, 0);
+    REGION_COPY(pScreen, copy_clip, region);
+    (*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0);
+    ValidateGC(&dst_pixmap->drawable, gc);
+    (*gc->ops->CopyArea)(&src_pixmap->drawable, &dst_pixmap->drawable, gc,
+                         0, 0, drawable->width, drawable->height, 0, 0);
+    FreeScratchGC(gc);
+    radeon_cs_flush_indirect(pScrn);
+}
+
+Bool
+radeon_dri2_screen_init(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    DRI2InfoRec dri2_info;
+    int fd;
+    char *bus_id;
+    char *tmp_bus_id;
+    int cmp;
+    int i;
+
+    if (!info->useEXA) {
+        xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI2 requires EXA\n");
+        return FALSE;
+    }
+
+    /* The whole drmOpen thing is a fiasco and we need to find a way
+     * back to just using open(2).  For now, however, lets just make
+     * things worse with even more ad hoc directory walking code to
+     * discover the device file name. */
+    bus_id = DRICreatePCIBusID(info->PciInfo);
+    for (i = 0; i < DRM_MAX_MINOR; i++) {
+        sprintf(info->dri2.device_name, DRM_DEV_NAME, DRM_DIR_NAME, i);
+        fd = open(info->dri2.device_name, O_RDWR);
+        if (fd < 0)
+            continue;
+
+        tmp_bus_id = drmGetBusid(fd);
+        close(fd);
+        if (tmp_bus_id == NULL)
+            continue;
+
+        cmp = strcmp(tmp_bus_id, bus_id);
+        drmFree(tmp_bus_id);
+        if (cmp == 0)
+            break;
+    }
+    xfree(bus_id);
+
+    if (i == DRM_MAX_MINOR) {
+        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+                   "DRI2: failed to open drm device\n");
+        return FALSE;
+    }
+
+    if ( (info->ChipFamily >= CHIP_FAMILY_R300) ) {
+        dri2_info.driverName = R300_DRIVER_NAME;
+    } else if ( info->ChipFamily >= CHIP_FAMILY_R200 ) {
+        dri2_info.driverName = R200_DRIVER_NAME;
+    } else {
+        dri2_info.driverName = RADEON_DRIVER_NAME;
+    }
+    dri2_info.fd = info->dri2.drm_fd;
+    dri2_info.deviceName = info->dri2.device_name;
+#ifndef USE_DRI2_1_1_0
+    dri2_info.version = 1;
+    dri2_info.CreateBuffers = radeon_dri2_create_buffers;
+    dri2_info.DestroyBuffers = radeon_dri2_destroy_buffers;
+#else
+    dri2_info.version = 2;
+    dri2_info.CreateBuffer = radeon_dri2_create_buffer;
+    dri2_info.DestroyBuffer = radeon_dri2_destroy_buffer;
+#endif
+    dri2_info.CopyRegion = radeon_dri2_copy_region;
+    info->dri2.enabled = DRI2ScreenInit(pScreen, &dri2_info);
+    return info->dri2.enabled;
+}
+
+void radeon_dri2_close_screen(ScreenPtr pScreen)
+{
+    DRI2CloseScreen(pScreen);
+}
+
+#endif
diff --git a/src/radeon_dri2.h b/src/radeon_dri2.h
new file mode 100644
index 0000000..899a626
--- /dev/null
+++ b/src/radeon_dri2.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2008 Jerome Glisse
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#ifndef RADEON_DRI2_H
+#define RADEON_DRI2_H
+
+struct radeon_dri2 {
+    int         drm_fd;
+    Bool        enabled;
+    char        device_name[64];
+};
+
+#ifdef RADEON_DRI2
+#include "dri2.h"
+Bool radeon_dri2_screen_init(ScreenPtr pScreen);
+void radeon_dri2_close_screen(ScreenPtr pScreen);
+#endif
+
+#endif
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 9a1d4d7..317612d 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -340,7 +340,7 @@ RADEONPostInt10Check(ScrnInfoPtr pScrn, void *ptr)
 }
 
 /* Allocate our private RADEONInfoRec */
-static Bool RADEONGetRec(ScrnInfoPtr pScrn)
+Bool RADEONGetRec(ScrnInfoPtr pScrn)
 {
     if (pScrn->driverPrivate) return TRUE;
 
@@ -349,7 +349,7 @@ static Bool RADEONGetRec(ScrnInfoPtr pScrn)
 }
 
 /* Free our private RADEONInfoRec */
-static void RADEONFreeRec(ScrnInfoPtr pScrn)
+void RADEONFreeRec(ScrnInfoPtr pScrn)
 {
     RADEONInfoPtr  info;
     int i;
@@ -1251,7 +1251,7 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn)
 
 
 /* This is called by RADEONPreInit to set up the default visual */
-static Bool RADEONPreInitVisual(ScrnInfoPtr pScrn)
+Bool RADEONPreInitVisual(ScrnInfoPtr pScrn)
 {
     RADEONInfoPtr  info = RADEONPTR(pScrn);
 
@@ -1308,7 +1308,7 @@ static Bool RADEONPreInitVisual(ScrnInfoPtr pScrn)
 }
 
 /* This is called by RADEONPreInit to handle all color weight issues */
-static Bool RADEONPreInitWeight(ScrnInfoPtr pScrn)
+Bool RADEONPreInitWeight(ScrnInfoPtr pScrn)
 {
     RADEONInfoPtr  info = RADEONPTR(pScrn);
 
@@ -2813,6 +2813,7 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
 
     info->IsSecondary  = FALSE;
     info->IsPrimary = FALSE;
+    info->kms_enabled = FALSE;
 
     info->pEnt         = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
     if (info->pEnt->location.type != BUS_PCI) goto fail;
@@ -5627,7 +5628,7 @@ Bool RADEONEnterVT(int scrnIndex, int flags)
         RADEONRestoreSurfaces(pScrn, info->ModeReg);
 #ifdef XF86DRI
     if (info->directRenderingEnabled) {
-    	if (info->cardType == CARD_PCIE &&
+	if (info->cardType == CARD_PCIE &&
 	    info->dri->pKernelDRMVersion->version_minor >= 19 &&
 	    info->FbSecureSize) {
 #if X_BYTE_ORDER == X_BIG_ENDIAN
@@ -5641,7 +5642,7 @@ Bool RADEONEnterVT(int scrnIndex, int flags)
 #if X_BYTE_ORDER == X_BIG_ENDIAN
 	    OUTREG(RADEON_SURFACE_CNTL, sctrl);
 #endif
-    	}
+	}
 
 	/* get the DRI back into shape after resume */
 	RADEONDRISetVBlankInterrupt (pScrn, TRUE);
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 5b20eca..9444da3 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -344,7 +344,7 @@ static Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
 
     /* if we have more refs than just the BO then flush */
     if (driver_priv->bo->cref > 1)
-      RADEONCPFlushIndirect(pScrn, 0);
+      radeon_cs_flush_indirect(pScrn);
     
     radeon_bo_wait(driver_priv->bo);
 
@@ -387,7 +387,7 @@ void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align)
 	return new_priv;
 
     new_priv->bo = radeon_bo_open(info->bufmgr, 0, size,
-				align, 0, 0);
+				  align, 0, 0);
     if (!new_priv->bo) {
 	xfree(new_priv);
 	ErrorF("Failed to alloc memory\n");
@@ -404,6 +404,9 @@ static void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
     RADEONInfoPtr info = RADEONPTR(pScrn);
     struct radeon_exa_pixmap_priv *driver_priv = driverPriv;
 
+    if (!driverPriv)
+      return;
+
     radeon_bo_unref(driver_priv->bo);
     xfree(driverPriv);
 }
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 42a5ebc..5b72360 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -376,7 +376,7 @@ RADEONUploadToScreenCP(PixmapPtr pDst, int x, int y, int w, int h,
 
     TRACE;
 
-    if (info->cs)
+    if (info->kms_enabled)
 	return FALSE;
 
     if (bpp < 8)
@@ -454,6 +454,9 @@ RADEONDownloadFromScreenCP(PixmapPtr pSrc, int x, int y, int w, int h,
 
     TRACE;
 
+    if (info->kms_enabled)
+      return FALSE;
+
     /*
      * Try to accelerate download. Use an indirect buffer as scratch space,
      * blitting the bits to one half while copying them out of the other one and
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
new file mode 100644
index 0000000..9fc6643
--- /dev/null
+++ b/src/radeon_kms.c
@@ -0,0 +1,837 @@
+/*
+ * Copyright © 2009 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Dave Airlie <airlied at redhat.com>
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <sys/ioctl.h>
+/* Driver data structures */
+#include "radeon.h"
+#include "radeon_reg.h"
+#include "radeon_probe.h"
+#include "micmap.h"
+
+#include "shadow.h"
+
+#include "atipciids.h"
+
+
+
+#ifdef XF86DRM_MODE
+
+#include "radeon_chipset_gen.h"
+#include "radeon_chipinfo_gen.h"
+
+#define CURSOR_WIDTH	64
+#define CURSOR_HEIGHT	64
+
+#include "radeon_bo_gem.h"
+#include "radeon_cs_gem.h"
+static Bool radeon_setup_kernel_mem(ScreenPtr pScreen);
+
+const OptionInfoRec RADEONOptions_KMS[] = {
+    { OPTION_NOACCEL,        "NoAccel",          OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_SW_CURSOR,      "SWcursor",         OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_PAGE_FLIP,      "EnablePageFlip",   OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_ACCEL_DFS,      "AccelDFS",         OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_IGNORE_EDID,    "IgnoreEDID",       OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_COLOR_TILING,   "ColorTiling",      OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_RENDER_ACCEL,   "RenderAccel",      OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_SUBPIXEL_ORDER, "SubPixelOrder",    OPTV_ANYSTR,  {0}, FALSE },
+    { OPTION_ACCELMETHOD,    "AccelMethod",      OPTV_STRING,  {0}, FALSE },
+    { OPTION_DRI,            "DRI",       	 OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_TVSTD,          "TVStandard",         OPTV_STRING,  {0}, FALSE },
+    { OPTION_EXA_VSYNC,         "EXAVSync",        OPTV_BOOLEAN, {0}, FALSE },
+    { -1,                    NULL,               OPTV_NONE,    {0}, FALSE }
+};
+
+extern _X_EXPORT int gRADEONEntityIndex;
+
+static int getRADEONEntityIndex(void)
+{
+    return gRADEONEntityIndex;
+}
+
+static void *
+radeonShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode,
+		   CARD32 *size, void *closure)
+{
+    ScrnInfoPtr pScrn = xf86Screens[screen->myNum];
+    RADEONInfoPtr  info   = RADEONPTR(pScrn);
+    int stride;
+
+    stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8;
+    *size = stride;
+
+    return ((uint8_t *)info->front_bo->ptr + row * stride + offset);
+}
+
+static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr  info   = RADEONPTR(pScrn);
+    PixmapPtr pixmap;
+
+    pScreen->CreateScreenResources = info->CreateScreenResources;
+    if (!(*pScreen->CreateScreenResources)(pScreen))
+	return FALSE;
+    pScreen->CreateScreenResources = RADEONCreateScreenResources_KMS;
+
+    if (info->r600_shadow_fb) {
+	pixmap = pScreen->GetScreenPixmap(pScreen);
+
+	if (!shadowAdd(pScreen, pixmap, shadowUpdatePackedWeak(),
+		       radeonShadowWindow, 0, NULL))
+	    return FALSE;
+    }
+
+    if (info->dri2.enabled) {
+	if (info->front_bo) {
+	    PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
+	    radeon_set_pixmap_bo(pPix, info->front_bo);
+	}
+    }
+    return TRUE;
+}
+
+static void RADEONBlockHandler_KMS(int i, pointer blockData,
+				   pointer pTimeout, pointer pReadmask)
+{
+    ScreenPtr      pScreen = screenInfo.screens[i];
+    ScrnInfoPtr    pScrn   = xf86Screens[i];
+    RADEONInfoPtr  info    = RADEONPTR(pScrn);
+
+    pScreen->BlockHandler = info->BlockHandler;
+    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+    pScreen->BlockHandler = RADEONBlockHandler_KMS;
+
+    if (info->VideoTimerCallback)
+	(*info->VideoTimerCallback)(pScrn, currentTime.milliseconds);
+
+    info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
+    radeon_cs_flush_indirect(pScrn);
+}
+
+static Bool RADEONPreInitAccel_KMS(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+
+    if (!(info->accel_state = xcalloc(1, sizeof(struct radeon_accel_state)))) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to allocate accel_state rec!\n");
+	return FALSE;
+    }
+    info->accel_state->fifo_slots                 = 0;
+
+    if (info->ChipFamily >= CHIP_FAMILY_R600) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Using shadowfb for KMS on R600+\n");
+	info->r600_shadow_fb = TRUE;
+	if (!xf86LoadSubModule(pScrn, "shadow"))
+	    info->r600_shadow_fb = FALSE;
+	return TRUE;
+    }
+
+
+    if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
+	(info->ChipFamily == CHIP_FAMILY_RS200) ||
+	(info->ChipFamily == CHIP_FAMILY_RS300) ||
+	(info->ChipFamily == CHIP_FAMILY_RS400) ||
+	(info->ChipFamily == CHIP_FAMILY_RS480) ||
+	(info->ChipFamily == CHIP_FAMILY_RS600) ||
+	(info->ChipFamily == CHIP_FAMILY_RS690) ||
+	(info->ChipFamily == CHIP_FAMILY_RS740))
+	info->accel_state->has_tcl = FALSE;
+    else {
+	info->accel_state->has_tcl = TRUE;
+    }
+
+    info->useEXA = TRUE;
+
+    if (info->useEXA) {
+	int errmaj = 0, errmin = 0;
+	info->exaReq.majorversion = EXA_VERSION_MAJOR;
+	info->exaReq.minorversion = EXA_VERSION_MINOR;
+	if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL,
+			   &info->exaReq, &errmaj, &errmin)) {
+	    LoaderErrorMsg(NULL, "exa", errmaj, errmin);
+	    return FALSE;
+	}
+    }
+
+    return TRUE;
+}
+
+static Bool RADEONPreInitChipType_KMS(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info   = RADEONPTR(pScrn);
+    uint32_t cmd_stat;
+    int i;
+
+    info->Chipset = PCI_DEV_DEVICE_ID(info->PciInfo);
+    pScrn->chipset = (char *)xf86TokenToString(RADEONChipsets, info->Chipset);
+    if (!pScrn->chipset) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "ChipID 0x%04x is not recognized\n", info->Chipset);
+	return FALSE;
+    }
+
+    if (info->Chipset < 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Chipset \"%s\" is not recognized\n", pScrn->chipset);
+	return FALSE;
+    }
+    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+	       "Chipset: \"%s\" (ChipID = 0x%04x)\n",
+	       pScrn->chipset,
+	       info->Chipset);
+
+    for (i = 0; i < sizeof(RADEONCards) / sizeof(RADEONCardInfo); i++) {
+	if (info->Chipset == RADEONCards[i].pci_device_id) {
+	    RADEONCardInfo *card = &RADEONCards[i];
+	    info->ChipFamily = card->chip_family;
+	    info->IsMobility = card->mobility;
+	    info->IsIGP = card->igp;
+	    break;
+	}
+    }
+
+    info->cardType = CARD_PCI;
+
+    PCI_READ_LONG(info->PciInfo, &cmd_stat, PCI_CMD_STAT_REG);
+    if (cmd_stat & RADEON_CAP_LIST) {
+	uint32_t cap_ptr, cap_id;
+
+	PCI_READ_LONG(info->PciInfo, &cap_ptr, RADEON_CAPABILITIES_PTR_PCI_CONFIG);
+	cap_ptr &= RADEON_CAP_PTR_MASK;
+
+	while(cap_ptr != RADEON_CAP_ID_NULL) {
+	    PCI_READ_LONG(info->PciInfo, &cap_id, cap_ptr);
+	    if ((cap_id & 0xff)== RADEON_CAP_ID_AGP) {
+		info->cardType = CARD_AGP;
+		break;
+	    }
+	    if ((cap_id & 0xff)== RADEON_CAP_ID_EXP) {
+		info->cardType = CARD_PCIE;
+		break;
+	    }
+	    cap_ptr = (cap_id >> 8) & RADEON_CAP_PTR_MASK;
+	}
+    }
+
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s card detected\n",
+	       (info->cardType==CARD_PCI) ? "PCI" :
+		(info->cardType==CARD_PCIE) ? "PCIE" : "AGP");
+
+    /* treat PCIE IGP cards as PCI */
+    if (info->cardType == CARD_PCIE && info->IsIGP)
+	info->cardType = CARD_PCI;
+
+    if ((info->ChipFamily >= CHIP_FAMILY_R600) && info->IsIGP)
+	info->cardType = CARD_PCIE;
+
+    /* not sure about gart table requirements */
+    if ((info->ChipFamily == CHIP_FAMILY_RS600) && info->IsIGP)
+	info->cardType = CARD_PCIE;
+
+#ifdef RENDER
+    info->RenderAccel = xf86ReturnOptValBool(info->Options, OPTION_RENDER_ACCEL,
+					     info->Chipset != PCI_CHIP_RN50_515E &&
+					     info->Chipset != PCI_CHIP_RN50_5969);
+#endif
+    return TRUE;
+}
+
+static Bool radeon_alloc_dri(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info   = RADEONPTR(pScrn);
+    if (!(info->dri = xcalloc(1, sizeof(struct radeon_dri)))) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Unable to allocate dri rec!\n");
+	return FALSE;
+    }
+
+    if (!(info->cp = xcalloc(1, sizeof(struct radeon_cp)))) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Unable to allocate cp rec!\n");
+	return FALSE;
+    }
+    return TRUE;
+}
+
+Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
+{
+    RADEONInfoPtr     info;
+    RADEONEntPtr pRADEONEnt;
+    DevUnion* pPriv;
+    int zaphod_mask = 0;
+    char *bus_id;
+    Gamma  zeros = { 0.0, 0.0, 0.0 };
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "RADEONPreInit_KMS\n");
+    if (pScrn->numEntities != 1) return FALSE;
+    if (!RADEONGetRec(pScrn)) return FALSE;
+
+    info               = RADEONPTR(pScrn);
+    info->MMIO         = NULL;
+    info->IsSecondary  = FALSE;
+    info->IsPrimary = FALSE;
+    info->kms_enabled = TRUE;
+    info->pEnt         = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
+    if (info->pEnt->location.type != BUS_PCI) goto fail;
+
+    pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
+				 getRADEONEntityIndex());
+    pRADEONEnt = pPriv->ptr;
+
+    if(xf86IsEntityShared(pScrn->entityList[0]))
+    {
+        if(xf86IsPrimInitDone(pScrn->entityList[0]))
+        {
+            info->IsSecondary = TRUE;
+            pRADEONEnt->pSecondaryScrn = pScrn;
+        }
+        else
+        {
+	    info->IsPrimary = TRUE;
+            xf86SetPrimInitDone(pScrn->entityList[0]);
+            pRADEONEnt->pPrimaryScrn = pScrn;
+            pRADEONEnt->HasSecondary = FALSE;
+        }
+    }
+
+    info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index);
+    pScrn->monitor     = pScrn->confScreen->monitor;
+
+    if (!RADEONPreInitVisual(pScrn))
+	goto fail;
+
+    xf86CollectOptions(pScrn, NULL);
+    if (!(info->Options = xalloc(sizeof(RADEONOptions_KMS))))
+	goto fail;
+
+    memcpy(info->Options, RADEONOptions_KMS, sizeof(RADEONOptions_KMS));
+    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
+
+    if (!RADEONPreInitWeight(pScrn))
+	goto fail;
+
+    if (!RADEONPreInitChipType_KMS(pScrn))
+        goto fail;
+
+    if (!radeon_alloc_dri(pScrn))
+	return FALSE;
+
+    zaphod_mask = 0xf;
+    if (info->IsPrimary)
+	zaphod_mask = 0xd;
+    if (info->IsSecondary)
+	zaphod_mask = 0x2;
+
+    bus_id = DRICreatePCIBusID(info->PciInfo);
+    if (drmmode_pre_init(pScrn, &info->drmmode, bus_id, "radeon", pScrn->bitsPerPixel / 8, zaphod_mask) == FALSE) {
+	xfree(bus_id);
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n");
+	goto fail;
+    }
+
+    info->dri->drmFD = info->drmmode.fd;
+    info->dri2.drm_fd = info->drmmode.fd;
+    info->dri2.enabled = FALSE;
+    xfree(bus_id);
+    info->dri->pKernelDRMVersion = drmGetVersion(info->dri->drmFD);
+    if (info->dri->pKernelDRMVersion == NULL) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "RADEONDRIGetVersion failed to get the DRM version\n");
+	goto fail;
+    }
+
+    {
+	struct drm_radeon_gem_info mminfo;
+
+	if (!drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo)))
+	{
+	    info->vram_size = mminfo.vram_visible;
+	    info->gart_size = mminfo.gart_size;
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "mem size init: gart size :%llx vram size: s:%llx visible:%llx\n",
+		       mminfo.gart_size, mminfo.vram_size, mminfo.vram_visible);
+	}
+    }
+
+    if (info->ChipFamily < CHIP_FAMILY_R600) {
+	info->useEXA = TRUE;
+	info->directRenderingEnabled = TRUE;
+    }
+
+    RADEONSetPitch(pScrn);
+
+    /* Set display resolution */
+    xf86SetDpi(pScrn, 0, 0);
+
+	/* Get ScreenInit function */
+    if (!xf86LoadSubModule(pScrn, "fb")) return FALSE;
+
+    if (!xf86SetGamma(pScrn, zeros)) return FALSE;
+
+    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
+	if (!xf86LoadSubModule(pScrn, "ramdac")) return FALSE;
+    }
+
+    if (!RADEONPreInitAccel_KMS(pScrn))              goto fail;
+
+    if (pScrn->modes == NULL) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
+      goto fail;
+   }
+
+    return TRUE;
+ fail:
+    RADEONFreeRec(pScrn);
+    return FALSE;
+
+}
+
+static Bool RADEONCursorInit_KMS(ScreenPtr pScreen)
+{
+    return xf86_cursors_init (pScreen, CURSOR_WIDTH, CURSOR_HEIGHT,
+			      (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
+			       HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
+			       HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
+			       HARDWARE_CURSOR_ARGB));
+}
+
+static Bool RADEONSaveScreen_KMS(ScreenPtr pScreen, int mode)
+{
+    ScrnInfoPtr  pScrn = xf86Screens[pScreen->myNum];
+    Bool         unblank;
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "RADEONSaveScreen(%d)\n", mode);
+
+    unblank = xf86IsUnblank(mode);
+    if (unblank) SetTimeSinceLastInputEvent();
+
+    if ((pScrn != NULL) && pScrn->vtSema) {
+	if (unblank)
+	    RADEONUnblank(pScrn);
+	else
+	    RADEONBlank(pScrn);
+    }
+    return TRUE;
+}
+
+/* Called at the end of each server generation.  Restore the original
+ * text mode, unmap video memory, and unwrap and call the saved
+ * CloseScreen function.
+ */
+static Bool RADEONCloseScreen_KMS(int scrnIndex, ScreenPtr pScreen)
+{
+    ScrnInfoPtr    pScrn = xf86Screens[scrnIndex];
+    RADEONInfoPtr  info  = RADEONPTR(pScrn);
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "RADEONCloseScreen\n");
+
+    if (info->accel_state->exa) {
+	exaDriverFini(pScreen);
+	xfree(info->accel_state->exa);
+	info->accel_state->exa = NULL;
+    }
+
+    if (info->cursor) xf86DestroyCursorInfoRec(info->cursor);
+    info->cursor = NULL;
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Disposing DGA\n");
+    if (info->DGAModes) xfree(info->DGAModes);
+    info->DGAModes = NULL;
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Unmapping memory\n");
+
+    pScrn->vtSema = FALSE;
+    xf86ClearPrimInitDone(info->pEnt->index);
+    pScreen->BlockHandler = info->BlockHandler;
+    pScreen->CloseScreen = info->CloseScreen;
+    return (*pScreen->CloseScreen)(scrnIndex, pScreen);
+}
+
+
+void RADEONFreeScreen_KMS(int scrnIndex, int flags)
+{
+    ScrnInfoPtr  pScrn = xf86Screens[scrnIndex];
+    RADEONInfoPtr  info  = RADEONPTR(pScrn);
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "RADEONFreeScreen\n");
+
+    /* when server quits at PreInit, we don't need do this anymore*/
+    if (!info) return;
+
+    RADEONFreeRec(pScrn);
+}
+
+Bool RADEONScreenInit_KMS(int scrnIndex, ScreenPtr pScreen,
+			  int argc, char **argv)
+{
+    ScrnInfoPtr    pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr  info  = RADEONPTR(pScrn);
+    int            subPixelOrder = SubPixelUnknown;
+    char*          s;
+    void *front_ptr;
+
+    pScrn->fbOffset = 0;
+
+    miClearVisualTypes();
+    if (!miSetVisualTypes(pScrn->depth,
+			  miGetDefaultVisualMask(pScrn->depth),
+			  pScrn->rgbBits,
+			  pScrn->defaultVisual)) return FALSE;
+    miSetPixmapDepths ();
+
+    info->directRenderingEnabled = radeon_dri2_screen_init(pScreen);
+
+    front_ptr = info->FB;
+
+    info->bufmgr = radeon_bo_manager_gem_ctor(info->dri->drmFD);
+    if (!info->bufmgr) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "failed to initialise GEM buffer manager");
+	return FALSE;
+    }
+    drmmode_set_bufmgr(pScrn, &info->drmmode, info->bufmgr);
+
+    info->csm = radeon_cs_manager_gem_ctor(info->dri->drmFD);
+    if (!info->csm) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "failed to initialise command submission manager");
+	return FALSE;
+    }
+
+    info->cs = radeon_cs_create(info->csm, RADEON_BUFFER_SIZE/4);
+    if (!info->cs) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "failed to initialise command submission buffer");
+	return FALSE;
+    }
+
+    radeon_cs_set_limit(info->cs, RADEON_GEM_DOMAIN_GTT, info->gart_size);
+
+    radeon_setup_kernel_mem(pScreen);
+    front_ptr = info->front_bo->ptr;
+
+    if (info->r600_shadow_fb) {
+	info->fb_shadow = xcalloc(1,
+				  pScrn->displayWidth * pScrn->virtualY *
+				  ((pScrn->bitsPerPixel + 7) >> 3));
+	if (info->fb_shadow == NULL) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                       "Failed to allocate shadow framebuffer\n");
+	    info->r600_shadow_fb = FALSE;
+	} else {
+	    if (!fbScreenInit(pScreen, info->fb_shadow,
+			      pScrn->virtualX, pScrn->virtualY,
+			      pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
+			      pScrn->bitsPerPixel))
+		return FALSE;
+	}
+    }
+
+    if (info->r600_shadow_fb == FALSE) {
+	/* Init fb layer */
+	if (!fbScreenInit(pScreen, front_ptr,
+			  pScrn->virtualX, pScrn->virtualY,
+			  pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
+			  pScrn->bitsPerPixel))
+	    return FALSE;
+    }
+
+    xf86SetBlackWhitePixels(pScreen);
+
+    if (pScrn->bitsPerPixel > 8) {
+	VisualPtr  visual;
+
+	visual = pScreen->visuals + pScreen->numVisuals;
+	while (--visual >= pScreen->visuals) {
+	    if ((visual->class | DynamicClass) == DirectColor) {
+		visual->offsetRed   = pScrn->offset.red;
+		visual->offsetGreen = pScrn->offset.green;
+		visual->offsetBlue  = pScrn->offset.blue;
+		visual->redMask     = pScrn->mask.red;
+		visual->greenMask   = pScrn->mask.green;
+		visual->blueMask    = pScrn->mask.blue;
+	    }
+	}
+    }
+
+    /* Must be after RGB order fixed */
+    fbPictureInit (pScreen, 0, 0);
+
+#ifdef RENDER
+    if ((s = xf86GetOptValString(info->Options, OPTION_SUBPIXEL_ORDER))) {
+	if (strcmp(s, "RGB") == 0) subPixelOrder = SubPixelHorizontalRGB;
+	else if (strcmp(s, "BGR") == 0) subPixelOrder = SubPixelHorizontalBGR;
+	else if (strcmp(s, "NONE") == 0) subPixelOrder = SubPixelNone;
+	PictureSetSubpixelOrder (pScreen, subPixelOrder);
+    }
+#endif
+
+    pScrn->vtSema = TRUE;
+    /* Backing store setup */
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Initializing backing store\n");
+    miInitializeBackingStore(pScreen);
+    xf86SetBackingStore(pScreen);
+
+
+    if (info->directRenderingEnabled) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
+    } else {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "Direct rendering disabled\n");
+    }
+
+    if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		       "Initializing Acceleration\n");
+	if (RADEONAccelInit(pScreen)) {
+	    xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n");
+	    info->accelOn = TRUE;
+	} else {
+	    xf86DrvMsg(scrnIndex, X_ERROR,
+		       "Acceleration initialization failed\n");
+	    xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
+	    info->accelOn = FALSE;
+	}
+    } else {
+	xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
+	info->accelOn = FALSE;
+    }
+
+    /* Init DPMS */
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Initializing DPMS\n");
+    xf86DPMSInit(pScreen, xf86DPMSSet, 0);
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Initializing Cursor\n");
+
+    /* Set Silken Mouse */
+    xf86SetSilkenMouse(pScreen);
+
+    /* Cursor setup */
+    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
+	if (RADEONCursorInit_KMS(pScreen)) {
+	}
+    }
+
+    /* DGA setup */
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Initializing DGA\n");
+    RADEONDGAInit(pScreen);
+
+    /* Init Xv */
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Initializing Xv\n");
+    RADEONInitVideo(pScreen);
+
+    if (info->r600_shadow_fb == TRUE) {
+        if (!shadowSetup(pScreen)) {
+            return FALSE;
+        }
+    }
+    pScrn->pScreen = pScreen;
+
+    if (!drmmode_set_desired_modes(pScrn, &info->drmmode))
+	return FALSE;
+
+    /* Provide SaveScreen & wrap BlockHandler and CloseScreen */
+    /* Wrap CloseScreen */
+    info->CloseScreen    = pScreen->CloseScreen;
+    pScreen->CloseScreen = RADEONCloseScreen_KMS;
+    pScreen->SaveScreen  = RADEONSaveScreen_KMS;
+    info->BlockHandler = pScreen->BlockHandler;
+    pScreen->BlockHandler = RADEONBlockHandler_KMS;
+    info->CreateScreenResources = pScreen->CreateScreenResources;
+    pScreen->CreateScreenResources = RADEONCreateScreenResources_KMS;
+
+   if (!xf86CrtcScreenInit (pScreen))
+       return FALSE;
+
+   /* Wrap pointer motion to flip touch screen around */
+//    info->PointerMoved = pScrn->PointerMoved;
+//    pScrn->PointerMoved = RADEONPointerMoved;
+
+    if (!drmmode_setup_colormap(pScreen, pScrn))
+	return FALSE;
+
+   /* Note unused options */
+    if (serverGeneration == 1)
+	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "RADEONScreenInit finished\n");
+
+    return TRUE;
+}
+
+Bool RADEONEnterVT_KMS(int scrnIndex, int flags)
+{
+    ScrnInfoPtr    pScrn = xf86Screens[scrnIndex];
+    RADEONInfoPtr  info  = RADEONPTR(pScrn);
+    int ret;
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "RADEONEnterVT_KMS\n");
+
+
+    ret = ioctl(info->dri->drmFD, DRM_IOCTL_SET_MASTER, NULL);
+    if (ret == -EINVAL)
+	ErrorF("Unable to retrieve master\n");
+
+    info->accel_state->XInited3D = FALSE;
+    info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
+
+    pScrn->vtSema = TRUE;
+
+    if (!drmmode_set_desired_modes(pScrn, &info->drmmode))
+	return FALSE;
+
+    if (info->adaptor)
+	RADEONResetVideo(pScrn);
+
+    return TRUE;
+}
+
+
+void RADEONLeaveVT_KMS(int scrnIndex, int flags)
+{
+    ScrnInfoPtr    pScrn = xf86Screens[scrnIndex];
+    RADEONInfoPtr  info  = RADEONPTR(pScrn);
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "RADEONLeaveVT_KMS\n");
+
+    ioctl(info->dri->drmFD, DRM_IOCTL_DROP_MASTER, NULL);
+
+#ifdef HAVE_FREE_SHADOW
+    xf86RotateFreeShadow(pScrn);
+#endif
+
+    xf86_hide_cursors (pScrn);
+    info->accel_state->XInited3D = FALSE;
+    info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		   "Ok, leaving now...\n");
+}
+
+
+Bool RADEONSwitchMode_KMS(int scrnIndex, DisplayModePtr mode, int flags)
+{
+    ScrnInfoPtr    pScrn       = xf86Screens[scrnIndex];
+    Bool ret;
+    ret = xf86SetSingleMode (pScrn, mode, RR_Rotate_0);
+    return ret;
+
+}
+
+void RADEONAdjustFrame_KMS(int scrnIndex, int x, int y, int flags)
+{
+    ScrnInfoPtr    pScrn       = xf86Screens[scrnIndex];
+    RADEONInfoPtr  info        = RADEONPTR(pScrn);
+    drmmode_adjust_frame(pScrn, &info->drmmode, x, y, flags);
+    return;
+}
+
+static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int cpp = info->CurrentLayout.pixel_bytes;
+    int screen_size;
+    int stride = pScrn->displayWidth * cpp;
+    int total_size_bytes = 0, remain_size_bytes;
+    int pagesize = 4096;
+
+    if (info->accel_state->exa != NULL) {
+	xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n");
+	return FALSE;
+    }
+    info->accel_state->exa = exaDriverAlloc();
+    if (info->accel_state->exa == NULL)
+	return FALSE;
+
+    screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * stride;
+    {
+	int cursor_size = 64 * 4 * 64;
+	int c;
+
+	cursor_size = RADEON_ALIGN(cursor_size, pagesize);
+	for (c = 0; c < xf86_config->num_crtc; c++) {
+	    /* cursor objects */
+	    info->cursor_bo[c] = radeon_bo_open(info->bufmgr, 0, cursor_size,
+					      0, RADEON_GEM_DOMAIN_VRAM, 0);
+	    if (!info->cursor_bo[c]) {
+		return FALSE;
+	    }
+
+	    if (radeon_bo_map(info->cursor_bo[c], 1)) {
+	      ErrorF("Failed to map cursor buffer memory\n");
+	    }
+
+	    drmmode_set_cursor(pScrn, &info->drmmode, c, info->cursor_bo[c]);
+	    total_size_bytes += cursor_size;
+	}
+    }
+
+    screen_size = RADEON_ALIGN(screen_size, pagesize);
+    /* keep area front front buffer - but don't allocate it yet */
+    total_size_bytes += screen_size;
+
+    /* work out from the mm size what the exa / tex sizes need to be */
+    remain_size_bytes = info->vram_size - total_size_bytes;
+
+    info->dri->textureSize = 0;
+
+    info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size,
+				    0, RADEON_GEM_DOMAIN_VRAM, 0);
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer size: %dK\n", info->front_bo->size/1024);
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Remaining VRAM size (used for pixmaps): %dK\n", remain_size_bytes/1024);
+
+    /* set the emit limit at 90% of VRAM */
+    remain_size_bytes = (remain_size_bytes / 10) * 9;
+
+    radeon_cs_set_limit(info->cs, RADEON_GEM_DOMAIN_VRAM, remain_size_bytes);
+    return TRUE;
+}
+
+#endif
diff --git a/src/radeon_legacy_memory.c b/src/radeon_legacy_memory.c
index 861fd97..02b95ed 100644
--- a/src/radeon_legacy_memory.c
+++ b/src/radeon_legacy_memory.c
@@ -21,6 +21,20 @@ radeon_legacy_allocate_memory(ScrnInfoPtr pScrn,
     RADEONInfoPtr info = RADEONPTR(pScrn);
     uint32_t offset = 0;
 
+#ifdef XF86DRM_MODE
+    if (info->cs) {
+	struct radeon_bo *video_bo;
+
+	video_bo = radeon_bo_open(info->bufmgr, 0, size, 4096, 0, 0);
+
+	*mem_struct = video_bo;
+
+	if (!video_bo)
+	    return 0;
+
+	return (uint32_t)-1;
+    }
+#endif
 #ifdef USE_EXA
     if (info->useEXA) {
 	ExaOffscreenArea *area = *mem_struct;
@@ -94,6 +108,14 @@ radeon_legacy_free_memory(ScrnInfoPtr pScrn,
 		   void *mem_struct)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
+
+#ifdef XF86DRM_MODE
+    if (info->cs) {
+        struct radeon_bo *bo = mem_struct;
+	radeon_bo_unref(bo);
+	return;
+    }
+#endif
 #ifdef USE_EXA
     ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
 
diff --git a/src/radeon_probe.c b/src/radeon_probe.c
index 041bab6..38fe0b0 100644
--- a/src/radeon_probe.c
+++ b/src/radeon_probe.c
@@ -36,6 +36,7 @@
  * Authors:
  *   Kevin E. Martin <martin at xfree86.org>
  *   Rickard E. Faith <faith at valinux.com>
+ * KMS support - Dave Airlie <airlied at redhat.com>
  */
 
 #include "radeon_probe.h"
@@ -76,11 +77,42 @@ RADEONIdentify(int flags)
 		      RADEONChipsets);
 }
 
+
+#ifdef XF86DRM_MODE
+static Bool radeon_kernel_mode_enabled(ScrnInfoPtr pScrn, struct pci_device *pci_dev)
+{
+    char *busIdString;
+    int ret;
+
+    if (!xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
+      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
+		   "[KMS] No DRICreatePCIBusID symbol, no kernel modesetting.\n");
+	return FALSE;
+    }
+
+    busIdString = DRICreatePCIBusID(pci_dev);
+    ret = drmCheckModesettingSupported(busIdString);
+    xfree(busIdString);
+    if (ret) {
+      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
+		   "[KMS] drm report modesetting isn't supported.\n");
+	return FALSE;
+    }
+
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
+		   "[KMS] Kernel modesetting enabled.\n");
+    return TRUE;
+}
+#else
+#define radeon_kernel_mode_enabled(x, y) FALSE
+#endif
+
 static Bool
-radeon_get_scrninfo(int entity_num)
+radeon_get_scrninfo(int entity_num, void *pci_dev)
 {
     ScrnInfoPtr   pScrn = NULL;
     EntityInfoPtr pEnt;
+    int kms = 0;
 
     pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, RADEONPciChipsets,
                                 NULL,
@@ -89,6 +121,11 @@ radeon_get_scrninfo(int entity_num)
     if (!pScrn)
         return FALSE;
 
+    if (pci_dev) {
+      if (radeon_kernel_mode_enabled(pScrn, pci_dev))
+	kms = 1;
+    }
+
     pScrn->driverVersion = RADEON_VERSION_CURRENT;
     pScrn->driverName    = RADEON_DRIVER_NAME;
     pScrn->name          = RADEON_NAME;
@@ -97,14 +134,26 @@ radeon_get_scrninfo(int entity_num)
 #else
     pScrn->Probe         = RADEONProbe;
 #endif
-    pScrn->PreInit       = RADEONPreInit;
-    pScrn->ScreenInit    = RADEONScreenInit;
-    pScrn->SwitchMode    = RADEONSwitchMode;
-    pScrn->AdjustFrame   = RADEONAdjustFrame;
-    pScrn->EnterVT       = RADEONEnterVT;
-    pScrn->LeaveVT       = RADEONLeaveVT;
-    pScrn->FreeScreen    = RADEONFreeScreen;
-    pScrn->ValidMode     = RADEONValidMode;
+
+    if (kms == 1) {
+      pScrn->PreInit       = RADEONPreInit_KMS;
+      pScrn->ScreenInit    = RADEONScreenInit_KMS;
+      pScrn->SwitchMode    = RADEONSwitchMode_KMS;
+      pScrn->AdjustFrame   = RADEONAdjustFrame_KMS;
+      pScrn->EnterVT       = RADEONEnterVT_KMS;
+      pScrn->LeaveVT       = RADEONLeaveVT_KMS;
+      pScrn->FreeScreen    = RADEONFreeScreen_KMS;
+      pScrn->ValidMode     = RADEONValidMode;
+    } else {
+      pScrn->PreInit       = RADEONPreInit;
+      pScrn->ScreenInit    = RADEONScreenInit;
+      pScrn->SwitchMode    = RADEONSwitchMode;
+      pScrn->AdjustFrame   = RADEONAdjustFrame;
+      pScrn->EnterVT       = RADEONEnterVT;
+      pScrn->LeaveVT       = RADEONLeaveVT;
+      pScrn->FreeScreen    = RADEONFreeScreen;
+      pScrn->ValidMode     = RADEONValidMode;
+    }
 
     pEnt = xf86GetEntityInfo(entity_num);
 
@@ -178,7 +227,7 @@ RADEONProbe(DriverPtr drv, int flags)
 	foundScreen = TRUE;
     } else {
 	for (i = 0; i < numUsed; i++) {
-	    if (radeon_get_scrninfo(usedChips[i]))
+	    if (radeon_get_scrninfo(usedChips[i], NULL))
 		foundScreen = TRUE;
 	}
     }
@@ -199,7 +248,7 @@ radeon_pci_probe(
     intptr_t           match_data
 )
 {
-    return radeon_get_scrninfo(entity_num);
+    return radeon_get_scrninfo(entity_num, (void *)device);
 }
 
 #endif /* XSERVER_LIBPCIACCESS */
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index 31709e8..9cac15c 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -615,6 +615,7 @@ typedef struct
     RADEONSaveRec     SavedReg;         /* Original (text) mode              */
 
     void              *MMIO;            /* Map of MMIO region                */
+    int fd;                             /* for sharing across zaphod heads   */
 } RADEONEntRec, *RADEONEntPtr;
 
 /* radeon_probe.c */
@@ -636,4 +637,14 @@ extern ModeStatus           RADEONValidMode(int, DisplayModePtr, Bool, int);
 
 extern const OptionInfoRec *RADEONOptionsWeak(void);
 
+#ifdef XF86DRM_MODE
+extern Bool                 RADEONPreInit_KMS(ScrnInfoPtr, int);
+extern Bool                 RADEONScreenInit_KMS(int, ScreenPtr, int, char **);
+extern Bool                 RADEONSwitchMode_KMS(int, DisplayModePtr, int);
+extern void                 RADEONAdjustFrame_KMS(int, int, int, int);
+extern Bool                 RADEONEnterVT_KMS(int, int);
+extern void                 RADEONLeaveVT_KMS(int, int);
+extern void RADEONFreeScreen_KMS(int scrnIndex, int flags);
+#endif
+
 #endif /* _RADEON_PROBE_H_ */
commit ac4bd24a66c1bdda0293f770a3f891e2b88cc8ee
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue Jun 30 16:00:06 2009 -0400

    EXA: fix the build on servers without EXA_HANDLES_PIXMAPS

diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index d130802..42a5ebc 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -596,9 +596,10 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen)
     info->accel_state->exa->pixmapOffsetAlign = RADEON_BUFFER_ALIGN + 1;
     info->accel_state->exa->pixmapPitchAlign = 64;
 
+#ifdef EXA_HANDLES_PIXMAPS
     if (info->cs)
-      info->accel_state->exa->flags |= EXA_HANDLES_PIXMAPS;
-
+	info->accel_state->exa->flags |= EXA_HANDLES_PIXMAPS;
+#endif
 
 #ifdef RENDER
     if (info->RenderAccel) {
commit 49a0ca19ee4109cdd39a43fbf4bedf3f0557d6ec
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Tue Jun 30 17:22:50 2009 +0200

    Warning fixes.

diff --git a/src/radeon_accel.c b/src/radeon_accel.c
index e51bffe..5e24683 100644
--- a/src/radeon_accel.c
+++ b/src/radeon_accel.c
@@ -436,7 +436,7 @@ static int RADEONDRMGetNumPipes(ScrnInfoPtr pScrn, int *num_pipes)
         return drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_GETPARAM, &np, sizeof(np));
     } else {
         struct drm_radeon_info np2;
-        np2.value = (uint64_t)num_pipes;
+        np2.value = (unsigned long)num_pipes;
         np2.request = RADEON_INFO_NUM_GB_PIPES;
         return drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_INFO, &np2, sizeof(np2));
     }
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index c47dfb4..d130802 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -141,7 +141,6 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
     int retry_count = 0;
     struct radeon_cs_space_check bos[1];
     int i;
-    ACCEL_PREAMBLE();
 
     TRACE;
 
@@ -245,7 +244,6 @@ FUNC_NAME(RADEONDoPrepareCopy)(ScrnInfoPtr pScrn, uint32_t src_pitch_offset,
 			       Pixel planemask)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
-    ACCEL_PREAMBLE();
 
     /* setup 2D state */
     info->state_2d.dp_gui_master_cntl = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
commit e932836691aeaec37794fdaed2dabb22710fd171
Author: Dave Airlie <airlied at redhat.com>
Date:   Tue Jun 30 16:24:37 2009 +1000

    radeon: initial preparation for kms patch.
    
    This patch contains most of the changes to the EXA and texture video
    accel code.
    
    It adds a few bits of pixmap support but doesn't actually do anything
    useful KMS yet.
    
    Testing this should not have any regressions over what we have already,
    biggest worries are r6xx, I've fixed a textured video one, but no idea
    what other might lurk
    
    It won't build against libdrm radeon yet either

diff --git a/configure.ac b/configure.ac
index a2d7f97..0cf24e6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,6 +31,7 @@ AM_CONFIG_HEADER([config.h])
 AC_CONFIG_AUX_DIR(.)
 
 AM_INIT_AUTOMAKE([dist-bzip2])
+AC_SYS_LARGEFILE
 
 AM_MAINTAINER_MODE
 
@@ -114,6 +115,22 @@ if test "$DRI" = yes; then
 	if test "$have_damage_h" = yes; then
 		AC_DEFINE(DAMAGE,1,[Use Damage extension])
 	fi
+
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$XORG_CFLAGS $DRI_CFLAGS $CFLAGS"
+#	AC_CHECK_HEADER(xf86drmMode.h,[DRM_MODE=yes],[DRM_MODE=no],[#include <stdint.h>
+	DRM_MODE=no
+#include <stdlib.h>])
+	 if test "x$DRM_MODE" = xyes; then
+		PKG_CHECK_MODULES(LIBDRM_RADEON, [xorg-server >= 1.6 libdrm_radeon],
+		[LIBDRM_RADEON=yes], [LIBDRM_RADEON=no])
+		
+		if test "x$LIBDRM_RADEON" = xyes; then
+			AC_DEFINE(XF86DRM_MODE,1,[DRM kernel modesetting])
+			AC_DEFINE(DRI2, 1,[Enable DRI2 code])
+		fi
+        fi
+	CFLAGS="$save_CFLAGS"
 fi
 
 save_CFLAGS="$CFLAGS"
@@ -310,6 +327,8 @@ esac
 
 AC_SUBST([XORG_CFLAGS])
 AC_SUBST([DRI_CFLAGS])
+AC_SUBST([LIBDRM_RADEON_CFLAGS])
+AC_SUBST([LIBDRM_RADEON_LIBS])
 AC_SUBST([moduledir])
 
 DRIVER_NAME=ati
@@ -336,3 +355,25 @@ AC_OUTPUT([
 	src/Makefile
 	man/Makefile
 ])
+
+dnl
+dnl Output some configuration info for the user
+dnl
+echo ""
+echo "        prefix:              $prefix"
+echo "        exec_prefix:         $exec_prefix"
+echo "        libdir:              $libdir"
+echo "        includedir:          $includedir"
+
+
+echo ""
+echo "        Kernel modesetting:  $DRM_MODE"
+
+echo ""
+echo "        CFLAGS:              $CFLAGS"
+echo "        CXXFLAGS:            $CXXFLAGS"
+echo "        Macros:              $DEFINES"
+
+echo ""
+echo "        Run '${MAKE-make}' to build xf86-video-ati"
+echo ""
diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c
index 6af0949..7c91a06 100644
--- a/src/r600_textured_videofuncs.c
+++ b/src/r600_textured_videofuncs.c
@@ -297,7 +297,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     switch(pPriv->id) {
     case FOURCC_YV12:
     case FOURCC_I420:
-	accel_state->src_mc_addr[0] = pPriv->src_offset;
+	accel_state->src_mc_addr[0] = pPriv->src_offset + info->fbLocation + pScrn->fbOffset;
 	accel_state->src_size[0] = accel_state->src_pitch[0] * pPriv->h;
 
 	/* flush texture cache */
@@ -392,7 +392,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     case FOURCC_UYVY:
     case FOURCC_YUY2:
     default:
-	accel_state->src_mc_addr[0] = pPriv->src_offset;
+	accel_state->src_mc_addr[0] = pPriv->src_offset + info->fbLocation + pScrn->fbOffset;
 	accel_state->src_size[0] = accel_state->src_pitch[0] * pPriv->h;
 
 	/* flush texture cache */
diff --git a/src/radeon.h b/src/radeon.h
index 2145de5..0dce081 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -75,6 +75,7 @@
 #include "dri.h"
 #include "GL/glxint.h"
 #include "xf86drm.h"
+#include "radeon_drm.h"
 
 #ifdef DAMAGE
 #include "damage.h"
@@ -85,6 +86,13 @@
 #include "xf86Crtc.h"
 #include "X11/Xatom.h"
 
+#ifdef XF86DRM_MODE
+#include "radeon_bo.h"
+#include "radeon_cs.h"
+#else
+#include "radeon_dummy_bufmgr.h"
+#endif
+
 				/* Render support */
 #ifdef RENDER
 #include "picturestr.h"
@@ -450,6 +458,11 @@ typedef struct {
 
 typedef struct _atomBiosHandle *atomBiosHandlePtr;
 
+struct radeon_exa_pixmap_priv {
+    struct radeon_bo *bo;
+    int flags;
+};
+
 typedef struct {
     uint32_t pci_device_id;
     RADEONChipFamily chip_family;
@@ -460,6 +473,25 @@ typedef struct {
     int singledac;
 } RADEONCardInfo;
 
+#define RADEON_2D_EXA_COPY 1
+#define RADEON_2D_EXA_SOLID 2
+
+struct radeon_2d_state {
+    int op; //
+    uint32_t dst_pitch_offset;
+    uint32_t src_pitch_offset;
+    uint32_t dp_gui_master_cntl;
+    uint32_t dp_cntl;
+    uint32_t dp_write_mask;
+    uint32_t dp_brush_frgd_clr;
+    uint32_t dp_brush_bkgd_clr;
+    uint32_t dp_src_frgd_clr;
+    uint32_t dp_src_bkgd_clr;
+    uint32_t default_sc_bottom_right;
+    struct radeon_bo *dst_bo;
+    struct radeon_bo *src_bo;
+};
+    
 #ifdef XF86DRI
 struct radeon_cp {
     Bool              CPRuns;           /* CP is running */
@@ -937,6 +969,18 @@ typedef struct {
     float igp_ht_link_clk;
     float igp_ht_link_width;
 
+    int can_resize;
+    void (*reemit_current2d)(ScrnInfoPtr pScrn, int op); // emit the current 2D state into the IB 
+    struct radeon_2d_state state_2d;
+#ifdef XF86DRM_MODE
+    struct radeon_bo_manager *bufmgr;
+    struct radeon_cs_manager *csm;
+    struct radeon_cs *cs;
+#else
+    /* fake bool */
+    Bool cs;
+#endif
+
 } RADEONInfoRec, *RADEONInfoPtr;
 
 #define RADEONWaitForFifo(pScrn, entries)				\
@@ -1013,11 +1057,13 @@ extern void RADEONWaitForFifoFunction(ScrnInfoPtr pScrn, int entries);
 #ifdef XF86DRI
 extern drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn);
 extern void RADEONCPFlushIndirect(ScrnInfoPtr pScrn, int discard);
+extern void radeon_cs_flush_indirect(ScrnInfoPtr pScrn);
 extern void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn);
 extern int RADEONCPStop(ScrnInfoPtr pScrn,  RADEONInfoPtr info);
 #  ifdef USE_XAA
 extern Bool RADEONSetupMemXAA_DRI(int scrnIndex, ScreenPtr pScreen);
 #  endif
+uint32_t radeonGetPixmapOffset(PixmapPtr pPix);
 #endif
 
 #ifdef USE_XAA
@@ -1202,6 +1248,9 @@ extern void
 radeon_legacy_free_memory(ScrnInfoPtr pScrn,
 		          void *mem_struct);
 
+struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix);
+void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo);
+
 #ifdef XF86DRI
 #  ifdef USE_XAA
 /* radeon_accelfuncs.c */
@@ -1220,7 +1269,9 @@ do {									\
 
 #define RADEONCP_RELEASE(pScrn, info)					\
 do {									\
-    if (info->cp->CPInUse) {						\
+    if (info->cs) {							\
+	radeon_cs_flush_indirect(pScrn);				\
+    } else if (info->cp->CPInUse) {					\
 	RADEON_PURGE_CACHE();						\
 	RADEON_WAIT_UNTIL_IDLE();					\
 	RADEONCPReleaseIndirect(pScrn);					\
@@ -1255,7 +1306,7 @@ do {									\
 
 #define RADEONCP_REFRESH(pScrn, info)					\
 do {									\
-    if (!info->cp->CPInUse) {						\
+    if (!info->cp->CPInUse && !info->cs) {				\
 	if (info->cp->needCacheFlush) {					\
 	    RADEON_PURGE_CACHE();					\
 	    RADEON_PURGE_ZCACHE();					\
@@ -1286,54 +1337,59 @@ do {									\
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,				\
 		   "BEGIN_RING(%d) in %s\n", (unsigned int)n, __FUNCTION__);\
     }									\
-    if (++info->cp->dma_begin_count != 1) {				\
+    if (info->cs) radeon_cs_begin(info->cs, n, __FILE__, __func__, __LINE__); else { \
+      if (++info->cp->dma_begin_count != 1) {				\
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,				\
 		   "BEGIN_RING without end at %s:%d\n",			\
-		   info->cp->dma_debug_func, info->cp->dma_debug_lineno);	\
+		   info->cp->dma_debug_func, info->cp->dma_debug_lineno); \
 	info->cp->dma_begin_count = 1;					\
-    }									\
-    info->cp->dma_debug_func = __FILE__;				\
-    info->cp->dma_debug_lineno = __LINE__;				\
-    if (!info->cp->indirectBuffer) {					\
+      }									\
+      info->cp->dma_debug_func = __FILE__;				\
+      info->cp->dma_debug_lineno = __LINE__;				\
+      if (!info->cp->indirectBuffer) {					\
 	info->cp->indirectBuffer = RADEONCPGetBuffer(pScrn);		\
 	info->cp->indirectStart = 0;					\
-    } else if (info->cp->indirectBuffer->used + (n) * (int)sizeof(uint32_t) >	\
-	       info->cp->indirectBuffer->total) {		        \
+      } else if (info->cp->indirectBuffer->used + (n) * (int)sizeof(uint32_t) >	\
+		 info->cp->indirectBuffer->total) {		        \
 	RADEONCPFlushIndirect(pScrn, 1);				\
+      }									\
+      __expected = n;							\
+      __head = (pointer)((char *)info->cp->indirectBuffer->address +	\
+			 info->cp->indirectBuffer->used);		\
+      __count = 0;							\
     }									\
-    __expected = n;							\
-    __head = (pointer)((char *)info->cp->indirectBuffer->address +	\
-		       info->cp->indirectBuffer->used);			\
-    __count = 0;							\
 } while (0)
 
 #define ADVANCE_RING() do {						\
-    if (info->cp->dma_begin_count-- != 1) {				\
+    if (info->cs) radeon_cs_end(info->cs, __FILE__, __func__, __LINE__); else {		\
+      if (info->cp->dma_begin_count-- != 1) {				\
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,				\
 		   "ADVANCE_RING without begin at %s:%d\n",		\
 		   __FILE__, __LINE__);					\
 	info->cp->dma_begin_count = 0;					\
-    }									\
-    if (__count != __expected) {					\
+      }									\
+      if (__count != __expected) {					\
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,				\
 		   "ADVANCE_RING count != expected (%d vs %d) at %s:%d\n", \
 		   __count, __expected, __FILE__, __LINE__);		\
-    }									\
-    if (RADEON_VERBOSE) {						\
+      }									\
+      if (RADEON_VERBOSE) {						\
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,				\
 		   "ADVANCE_RING() start: %d used: %d count: %d\n",	\
 		   info->cp->indirectStart,				\
 		   info->cp->indirectBuffer->used,			\
 		   __count * (int)sizeof(uint32_t));			\
+      }									\
+      info->cp->indirectBuffer->used += __count * (int)sizeof(uint32_t); \
     }									\
-    info->cp->indirectBuffer->used += __count * (int)sizeof(uint32_t);	\
-} while (0)
+  } while (0)
 
 #define OUT_RING(x) do {						\
     if (RADEON_VERBOSE) {						\
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,				\
 		   "   OUT_RING(0x%08x)\n", (unsigned int)(x));		\
     }									\
+    if (info->cs) radeon_cs_write_dword(info->cs, (x)); else		\
     __head[__count++] = (x);						\
 } while (0)
 
@@ -1343,12 +1399,22 @@ do {									\
     OUT_RING(val);							\
 } while (0)
 
+#define OUT_RING_RELOC(x, read_domains, write_domain)			\
+  do {									\
+	int _ret; \
+    _ret = radeon_cs_write_reloc(info->cs, x, read_domains, write_domain, 0); \
+	if (_ret) ErrorF("reloc emit failure %d\n", _ret); \
+  } while(0)
+
+
 #define FLUSH_RING()							\
 do {									\
     if (RADEON_VERBOSE)							\
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,				\
 		   "FLUSH_RING in %s\n", __FUNCTION__);			\
-    if (info->cp->indirectBuffer)					\
+    if (info->cs)							\
+	radeon_cs_flush_indirect(pScrn); 				\
+    else if (info->cp->indirectBuffer)					\
 	RADEONCPFlushIndirect(pScrn, 0);				\
 } while (0)
 
@@ -1434,8 +1500,12 @@ do {									\
 	case EXA_ENGINEMODE_2D:						\
 	    break;							\
 	}								\
-	if (flush && info->directRenderingEnabled)                      \
-	    RADEONCPFlushIndirect(pScrn, 1);                            \
+	if (flush) {							\
+    	    if (info->cs)						\
+	        radeon_cs_flush_indirect(pScrn);			\
+            else if (info->directRenderingEnabled)                     	\
+	        RADEONCPFlushIndirect(pScrn, 1);                        \
+	}								\
         info->accel_state->engineMode = EXA_ENGINEMODE_2D;              \
 } while (0);
 
@@ -1450,7 +1520,9 @@ do {									\
 	    break;							\
 	}								\
 	if (flush) {							\
-	    if (info->directRenderingEnabled)				\
+    	    if (info->cs)						\
+	        radeon_cs_flush_indirect(pScrn);			\
+	    else if (info->directRenderingEnabled)				\
 	        RADEONCPFlushIndirect(pScrn, 1);                        \
 	    RADEONInit3DEngine(pScrn);                                  \
 	}                                                               \
diff --git a/src/radeon_accel.c b/src/radeon_accel.c
index f90b386..e51bffe 100644
--- a/src/radeon_accel.c
+++ b/src/radeon_accel.c
@@ -375,6 +375,9 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn)
     RADEONInfoPtr  info       = RADEONPTR(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
 
+    if (info->cs)
+      return;
+
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "EngineRestore (%d/%d)\n",
 		   info->CurrentLayout.pixel_code,
@@ -421,6 +424,24 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn)
     info->accel_state->XInited3D = FALSE;
 }
 
+static int RADEONDRMGetNumPipes(ScrnInfoPtr pScrn, int *num_pipes)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    if (info->dri->pKernelDRMVersion->version_major < 2) {
+        drm_radeon_getparam_t np;
+
+        memset(&np, 0, sizeof(np));
+        np.param = RADEON_PARAM_NUM_GB_PIPES;
+        np.value = num_pipes;
+        return drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_GETPARAM, &np, sizeof(np));
+    } else {
+        struct drm_radeon_info np2;
+        np2.value = (uint64_t)num_pipes;
+        np2.request = RADEON_INFO_NUM_GB_PIPES;
+        return drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_INFO, &np2, sizeof(np2));
+    }
+}
+
 /* Initialize the acceleration hardware */
 void RADEONEngineInit(ScrnInfoPtr pScrn)
 {
@@ -436,15 +457,9 @@ void RADEONEngineInit(ScrnInfoPtr pScrn)
 
 #ifdef XF86DRI
     if (info->directRenderingEnabled && (IS_R300_3D || IS_R500_3D)) {
-	drm_radeon_getparam_t np;
 	int num_pipes;
 
-	memset(&np, 0, sizeof(np));
-	np.param = RADEON_PARAM_NUM_GB_PIPES;
-	np.value = &num_pipes;
-
-	if (drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_GETPARAM, &np,
-				sizeof(np)) < 0) {
+	if(RADEONDRMGetNumPipes(pScrn, &num_pipes) < 0) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		       "Failed to determine num pipes from DRM, falling back to "
 		       "manual look-up!\n");
@@ -455,64 +470,67 @@ void RADEONEngineInit(ScrnInfoPtr pScrn)
     }
 #endif
 
-    if ((info->ChipFamily == CHIP_FAMILY_RV410) ||
-	(info->ChipFamily == CHIP_FAMILY_R420)  ||
-	(info->ChipFamily == CHIP_FAMILY_RS600) ||
-	(info->ChipFamily == CHIP_FAMILY_RS690) ||
-	(info->ChipFamily == CHIP_FAMILY_RS740) ||
-	(info->ChipFamily == CHIP_FAMILY_RS400) ||
-	(info->ChipFamily == CHIP_FAMILY_RS480) ||
-	IS_R500_3D) {
-	if (info->accel_state->num_gb_pipes == 0) {
-	    uint32_t gb_pipe_sel = INREG(R400_GB_PIPE_SELECT);
-
-	    info->accel_state->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1;
-	    if (IS_R500_3D)
-		OUTPLL(pScrn, R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4));
-	}
-    } else {
-	if (info->accel_state->num_gb_pipes == 0) {
-	    if ((info->ChipFamily == CHIP_FAMILY_R300) ||
-		(info->ChipFamily == CHIP_FAMILY_R350)) {
-		/* R3xx chips */
-		info->accel_state->num_gb_pipes = 2;
-	    } else {
-		/* RV3xx chips */
-		info->accel_state->num_gb_pipes = 1;
+    if (!info->cs) {
+	if ((info->ChipFamily == CHIP_FAMILY_RV410) ||
+	    (info->ChipFamily == CHIP_FAMILY_R420)  ||
+	    (info->ChipFamily == CHIP_FAMILY_RS600) ||
+	    (info->ChipFamily == CHIP_FAMILY_RS690) ||
+	    (info->ChipFamily == CHIP_FAMILY_RS740) ||
+	    (info->ChipFamily == CHIP_FAMILY_RS400) ||
+	    (info->ChipFamily == CHIP_FAMILY_RS480) ||
+	    IS_R500_3D) {
+	    if (info->accel_state->num_gb_pipes == 0) {
+		uint32_t gb_pipe_sel = INREG(R400_GB_PIPE_SELECT);
+
+		info->accel_state->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1;
+		if (IS_R500_3D)
+		    OUTPLL(pScrn, R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4));
+	    }
+	} else {
+	    if (info->accel_state->num_gb_pipes == 0) {
+		if ((info->ChipFamily == CHIP_FAMILY_R300) ||
+		    (info->ChipFamily == CHIP_FAMILY_R350)) {
+		    /* R3xx chips */
+		    info->accel_state->num_gb_pipes = 2;
+		} else {
+		    /* RV3xx chips */
+		    info->accel_state->num_gb_pipes = 1;
+		}
 	    }
-	}
-    }
-
-    /* RV410 SE cards only have 1 quadpipe */
-    if ((info->Chipset == PCI_CHIP_RV410_5E4C) ||
-	(info->Chipset == PCI_CHIP_RV410_5E4F))
-	info->accel_state->num_gb_pipes = 1;
-
-    if (IS_R300_3D || IS_R500_3D)
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "num quad-pipes is %d\n", info->accel_state->num_gb_pipes);
-
-    if (IS_R300_3D || IS_R500_3D) {
-	uint32_t gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16);
-
-	switch(info->accel_state->num_gb_pipes) {
-	case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break;
-	case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break;
-	case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break;
-	default:
-	case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break;
 	}
 
-	OUTREG(R300_GB_TILE_CONFIG, gb_tile_config);
-	OUTREG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
-	OUTREG(R300_DST_PIPE_CONFIG, INREG(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG);
-	OUTREG(R300_RB2D_DSTCACHE_MODE, (INREG(R300_RB2D_DSTCACHE_MODE) |
-					 R300_DC_AUTOFLUSH_ENABLE |
-					 R300_DC_DC_DISABLE_IGNORE_PE));
-    } else
-	OUTREG(RADEON_RB3D_CNTL, 0);
+	/* RV410 SE cards only have 1 quadpipe */
+	if ((info->Chipset == PCI_CHIP_RV410_5E4C) ||
+	    (info->Chipset == PCI_CHIP_RV410_5E4F))
+	    info->accel_state->num_gb_pipes = 1;
+
+	if (IS_R300_3D || IS_R500_3D)
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "num quad-pipes is %d\n", info->accel_state->num_gb_pipes);
+
+	if (IS_R300_3D || IS_R500_3D) {
+	    uint32_t gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16);
+	    
+	    switch(info->accel_state->num_gb_pipes) {
+	    case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break;
+	    case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break;
+	    case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break;
+	    default:
+	    case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break;
+	    }
 
-    RADEONEngineReset(pScrn);
+	    OUTREG(R300_GB_TILE_CONFIG, gb_tile_config);
+	    OUTREG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
+	    if (info->ChipFamily >= CHIP_FAMILY_R420)
+		OUTREG(R300_DST_PIPE_CONFIG, INREG(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG);
+	    OUTREG(R300_RB2D_DSTCACHE_MODE, (INREG(R300_RB2D_DSTCACHE_MODE) |
+					     R300_DC_AUTOFLUSH_ENABLE |
+					     R300_DC_DC_DISABLE_IGNORE_PE));
+	} else
+	    OUTREG(RADEON_RB3D_CNTL, 0);
+	
+	RADEONEngineReset(pScrn);
+    }
 
     switch (info->CurrentLayout.pixel_code) {
     case 8:  datatype = 2; break;
@@ -536,6 +554,24 @@ void RADEONEngineInit(ScrnInfoPtr pScrn)
     RADEONEngineRestore(pScrn);
 }
 
+uint32_t radeonGetPixmapOffset(PixmapPtr pPix)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    uint32_t offset = 0;
+    if (info->cs)
+	return 0;
+#ifdef USE_EXA
+    if (info->useEXA) {
+	offset = exaGetPixmapOffset(pPix);
+    } else
+#endif
+    {
+	offset = pPix->devPrivate.ptr - info->FB;
+    }
+    offset += info->fbLocation + pScrn->fbOffset;
+    return offset;
+}
 
 #define ACCEL_MMIO
 #define ACCEL_PREAMBLE()        unsigned char *RADEONMMIO = info->MMIO
@@ -620,6 +656,20 @@ int RADEONCPStop(ScrnInfoPtr pScrn, RADEONInfoPtr info)
     }
 }
 
+#define RADEON_IB_RESERVE (16 * sizeof(uint32_t))
+
+void radeon_cs_flush_indirect(ScrnInfoPtr pScrn)
+{
+#ifdef XF86DRM_MODE
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+
+    if (!info->cs->cdw)
+	return;
+    radeon_cs_emit(info->cs);
+    radeon_cs_erase(info->cs);
+#endif
+}
+
 /* Get an indirect buffer for the CP 2D acceleration commands  */
 drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn)
 {
@@ -696,6 +746,7 @@ void RADEONCPFlushIndirect(ScrnInfoPtr pScrn, int discard)
     int                start  = info->cp->indirectStart;
     drm_radeon_indirect_t  indirect;
 
+    assert(!info->cs);
     if (!buffer) return;
     if (start == buffer->used && !discard) return;
 
@@ -745,6 +796,7 @@ void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn)
     int                start  = info->cp->indirectStart;
     drm_radeon_indirect_t  indirect;
 
+    assert(!info->cs);
     if (info->ChipFamily >= CHIP_FAMILY_R600) {
 	if (buffer && (buffer->used & 0x3c)) {
 	    RING_LOCALS;
diff --git a/src/radeon_drm.h b/src/radeon_drm.h
index 54bc234..dd0087a 100644
--- a/src/radeon_drm.h
+++ b/src/radeon_drm.h
@@ -493,6 +493,16 @@ typedef struct {
 #define DRM_RADEON_SETPARAM   0x19
 #define DRM_RADEON_SURF_ALLOC 0x1a
 #define DRM_RADEON_SURF_FREE  0x1b
+/* KMS ioctl */
+#define DRM_RADEON_GEM_INFO		0x1c
+#define DRM_RADEON_GEM_CREATE		0x1d
+#define DRM_RADEON_GEM_MMAP		0x1e
+#define DRM_RADEON_GEM_PREAD		0x21
+#define DRM_RADEON_GEM_PWRITE		0x22
+#define DRM_RADEON_GEM_SET_DOMAIN	0x23
+#define DRM_RADEON_GEM_WAIT_IDLE	0x24
+#define DRM_RADEON_CS			0x26
+#define DRM_RADEON_INFO			0x27
 
 #define DRM_IOCTL_RADEON_CP_INIT    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)
 #define DRM_IOCTL_RADEON_CP_START   DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_START)
@@ -521,6 +531,17 @@ typedef struct {
 #define DRM_IOCTL_RADEON_SETPARAM   DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t)
 #define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t)
 #define DRM_IOCTL_RADEON_SURF_FREE  DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t)
+/* KMS */
+#define DRM_IOCTL_RADEON_GEM_INFO	DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_INFO, struct drm_radeon_gem_info)
+#define DRM_IOCTL_RADEON_GEM_CREATE	DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_CREATE, struct drm_radeon_gem_create)
+#define DRM_IOCTL_RADEON_GEM_MMAP	DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_MMAP, struct drm_radeon_gem_mmap)
+#define DRM_IOCTL_RADEON_GEM_PREAD	DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PREAD, struct drm_radeon_gem_pread)
+#define DRM_IOCTL_RADEON_GEM_PWRITE	DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PWRITE, struct drm_radeon_gem_pwrite)
+#define DRM_IOCTL_RADEON_GEM_SET_DOMAIN	DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_DOMAIN, struct drm_radeon_gem_set_domain)
+#define DRM_IOCTL_RADEON_GEM_WAIT_IDLE	DRM_IOW(DRM_COMMAND_BASE + DRM_RADEON_GEM_WAIT_IDLE, struct drm_radeon_gem_wait_idle) 
+#define DRM_IOCTL_RADEON_CS		DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs)
+#define DRM_IOCTL_RADEON_INFO		DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INFO, struct drm_radeon_info)
+
 
 typedef struct drm_radeon_init {
 	enum {
@@ -753,4 +774,112 @@ typedef struct drm_radeon_surface_free {
 #define	DRM_RADEON_VBLANK_CRTC1		1
 #define	DRM_RADEON_VBLANK_CRTC2		2
 
+/*
+ * Kernel modesetting world below.
+ */
+#define RADEON_GEM_DOMAIN_CPU		0x1
+#define RADEON_GEM_DOMAIN_GTT		0x2
+#define RADEON_GEM_DOMAIN_VRAM		0x4
+
+struct drm_radeon_gem_info {
+	uint64_t	gart_size;
+	uint64_t	vram_size;
+	uint64_t	vram_visible;
+};
+
+#define RADEON_GEM_NO_BACKING_STORE 1
+
+struct drm_radeon_gem_create {
+	uint64_t	size;
+	uint64_t	alignment;
+	uint32_t	handle;
+	uint32_t	initial_domain;
+	uint32_t	flags;
+};
+
+struct drm_radeon_gem_mmap {
+	uint32_t	handle;
+	uint32_t	pad;
+	uint64_t	offset;
+	uint64_t	size;
+	uint64_t	addr_ptr;
+};
+
+struct drm_radeon_gem_set_domain {
+	uint32_t	handle;
+	uint32_t		read_domains;
+	uint32_t		write_domain;
+};
+
+struct drm_radeon_gem_wait_idle {
+	uint32_t	handle;
+	uint32_t	pad;
+};
+
+struct drm_radeon_gem_busy {
+	uint32_t	handle;
+	uint32_t	busy;
+};
+
+struct drm_radeon_gem_pread {
+	/** Handle for the object being read. */
+	uint32_t handle;
+	uint32_t pad;
+	/** Offset into the object to read from */
+	uint64_t offset;
+	/** Length of data to read */
+	uint64_t size;
+	/** Pointer to write the data into. */
+	/* void *, but pointers are not 32/64 compatible */
+	uint64_t data_ptr;
+};
+
+struct drm_radeon_gem_pwrite {
+	/** Handle for the object being written to. */
+	uint32_t handle;
+	uint32_t pad;
+	/** Offset into the object to write to */
+	uint64_t offset;
+	/** Length of data to write */
+	uint64_t size;
+	/** Pointer to read the data from. */
+	/* void *, but pointers are not 32/64 compatible */
+	uint64_t data_ptr;
+};
+
+#define RADEON_CHUNK_ID_RELOCS	0x01
+#define RADEON_CHUNK_ID_IB	0x02
+
+struct drm_radeon_cs_chunk {
+	uint32_t		chunk_id;
+	uint32_t		length_dw;
+	uint64_t		chunk_data;
+};
+
+struct drm_radeon_cs_reloc {
+	uint32_t		handle;
+	uint32_t		read_domains;
+	uint32_t		write_domain;
+	uint32_t		flags;
+};
+
+struct drm_radeon_cs {
+	uint32_t		num_chunks;
+	uint32_t		cs_id;
+	/* this points to uint64_t * which point to cs chunks */
+	uint64_t		chunks;
+	/* updates to the limits after this CS ioctl */
+	uint64_t		gart_limit;
+	uint64_t		vram_limit;
+};
+
+#define RADEON_INFO_DEVICE_ID		0x00
+#define RADEON_INFO_NUM_GB_PIPES	0x01
+
+struct drm_radeon_info {
+	uint32_t		request;
+	uint32_t		pad;
+	uint64_t		value;
+};
+
 #endif
diff --git a/src/radeon_dummy_bufmgr.h b/src/radeon_dummy_bufmgr.h
new file mode 100644
index 0000000..bf89292
--- /dev/null
+++ b/src/radeon_dummy_bufmgr.h
@@ -0,0 +1,57 @@
+
+#ifndef RADEON_DUMMY_BUFMGR_H
+#define RADEON_DUMMY_BUFMGR_H
+/* when we don't have modesetting but we still need these functions */
+
+struct radeon_bo {
+  int dummy;
+  void *ptr;
+};
+
+static inline int radeon_cs_begin(Bool dummy, int d2, const char *file,
+				   const char *func, int line)
+{
+  return 0;
+}
+
+static inline int radeon_cs_end(Bool dummy, const char *file,
+				const char *func, int line)
+{
+  return 0;
+}
+
+static inline void radeon_cs_write_dword(Bool cs, uint32_t dword)
+{
+}
+
+static inline int radeon_cs_write_reloc(Bool cs,
+                                        struct radeon_bo *bo,
+                                        uint32_t read_domain,
+                                        uint32_t write_domain,
+                                        uint32_t flags)
+{
+  return 0;
+}
+
+static inline int radeon_bo_map(struct radeon_bo *bo, int write) {return 0;}
+static inline void radeon_bo_ref(struct radeon_bo *bo) {return;}
+static inline struct radeon_bo *radeon_bo_unref(struct radeon_bo *bo) {return NULL;}
+static inline void radeon_bo_unmap(struct radeon_bo *bo) {return;}
+static inline int radeon_bo_wait(struct radeon_bo *bo) {return 0;}
+
+
+struct radeon_cs_space_check {
+  struct radeon_bo *bo;
+  int read_domains;
+  int write_domain;
+  int new_accounted;
+};
+
+static inline int radeon_cs_space_check(Bool cs, struct radeon_cs_space_check *bos, int num)
+{
+  return 0;
+}
+#define RADEON_CS_SPACE_OP_TO_BIG 0
+#define RADEON_CS_SPACE_FLUSH 1
+
+#endif
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index ae68146..5b20eca 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -120,6 +120,15 @@ static __inline__ uint32_t F_TO_DW(float val)
     return tmp.l;
 }
 
+static inline void radeon_add_pixmap(struct radeon_cs_space_check *bos, int index, PixmapPtr pPix, int read_domains, int write_domain)
+{
+    struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix);
+    bos[index].bo = driver_priv->bo;
+    bos[index].read_domains = read_domains;
+    bos[index].write_domain = write_domain;
+    bos[index].new_accounted = 0;
+}
+
 /* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we
  * require src and dest datatypes to be equal.
  */
@@ -179,7 +188,6 @@ static Bool RADEONGetOffsetPitch(PixmapPtr pPix, int bpp, uint32_t *pitch_offset
 
 Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
 {
-	RINFO_FROM_SCREEN(pPix->drawable.pScreen);
 	uint32_t pitch, offset;
 	int bpp;
 
@@ -187,7 +195,7 @@ Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
 	if (bpp == 24)
 		bpp = 8;
 
-	offset = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset;
+	offset = radeonGetPixmapOffset(pPix);
 	pitch = exaGetPixmapPitch(pPix);
 
 	return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch);
@@ -224,7 +232,7 @@ int RADEONBiggerCrtcArea(PixmapPtr pPix)
 
 static unsigned long swapper_surfaces[6];
 
-static Bool RADEONPrepareAccess(PixmapPtr pPix, int index)
+static Bool RADEONPrepareAccess_BE(PixmapPtr pPix, int index)
 {
     RINFO_FROM_SCREEN(pPix->drawable.pScreen);
     unsigned char *RADEONMMIO = info->MMIO;
@@ -290,7 +298,7 @@ static Bool RADEONPrepareAccess(PixmapPtr pPix, int index)
     return TRUE;
 }
 
-static void RADEONFinishAccess(PixmapPtr pPix, int index)
+static void RADEONFinishAccess_BE(PixmapPtr pPix, int index)
 {
     RINFO_FROM_SCREEN(pPix->drawable.pScreen);
     unsigned char *RADEONMMIO = info->MMIO;
@@ -323,6 +331,123 @@ static void RADEONFinishAccess(PixmapPtr pPix, int index)
 
 #endif /* X_BYTE_ORDER == X_BIG_ENDIAN */
 
+#ifdef XF86DRM_MODE
+static Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
+{
+    RINFO_FROM_SCREEN(pPix->drawable.pScreen);
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int ret;
+
+    driver_priv = exaGetPixmapDriverPrivate(pPix);
+    if (!driver_priv)
+      return FALSE;
+
+    /* if we have more refs than just the BO then flush */
+    if (driver_priv->bo->cref > 1)
+      RADEONCPFlushIndirect(pScrn, 0);
+    
+    radeon_bo_wait(driver_priv->bo);
+
+    /* flush IB */
+    ret = radeon_bo_map(driver_priv->bo, 1);
+    if (ret) {
+      FatalError("failed to map pixmap %d\n", ret);
+      return FALSE;
+    }
+
+    pPix->devPrivate.ptr = driver_priv->bo->ptr;
+
+    return TRUE;
+}
+
+static void RADEONFinishAccess_CS(PixmapPtr pPix, int index)
+{
+    struct radeon_exa_pixmap_priv *driver_priv;
+
+    driver_priv = exaGetPixmapDriverPrivate(pPix);
+    if (!driver_priv)
+        return;
+
+    radeon_bo_unmap(driver_priv->bo);
+    pPix->devPrivate.ptr = NULL;
+}
+
+
+void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    struct radeon_exa_pixmap_priv *new_priv;
+
+    new_priv = xcalloc(1, sizeof(struct radeon_exa_pixmap_priv));
+    if (!new_priv)
+	return NULL;
+
+    if (size == 0)
+	return new_priv;
+
+    new_priv->bo = radeon_bo_open(info->bufmgr, 0, size,
+				align, 0, 0);
+    if (!new_priv->bo) {
+	xfree(new_priv);
+	ErrorF("Failed to alloc memory\n");
+	return NULL;
+    }
+    
+    return new_priv;
+
+}
+
+static void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    struct radeon_exa_pixmap_priv *driver_priv = driverPriv;
+
+    radeon_bo_unref(driver_priv->bo);
+    xfree(driverPriv);
+}
+
+struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    struct radeon_exa_pixmap_priv *driver_priv;
+    driver_priv = exaGetPixmapDriverPrivate(pPix);
+    return driver_priv->bo;
+}
+
+void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+
+    struct radeon_exa_pixmap_priv *driver_priv;
+
+    driver_priv = exaGetPixmapDriverPrivate(pPix);
+    if (driver_priv) {
+	if (driver_priv->bo)
+	    radeon_bo_unref(driver_priv->bo);
+
+	radeon_bo_ref(bo);
+	driver_priv->bo = bo;
+    }
+}
+
+static Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix)
+{
+    struct radeon_exa_pixmap_priv *driver_priv;
+
+    driver_priv = exaGetPixmapDriverPrivate(pPix);
+
+    if (!driver_priv)
+       return FALSE;
+    if (driver_priv->bo)
+       return TRUE;
+    return FALSE;
+}
+#endif
+
 #define ENTER_DRAW(x) TRACE
 #define LEAVE_DRAW(x) TRACE
 /***********************************************************************/
@@ -332,6 +457,7 @@ static void RADEONFinishAccess(PixmapPtr pPix, int index)
 #define BEGIN_ACCEL(n)		RADEONWaitForFifo(pScrn, (n))
 #define OUT_ACCEL_REG(reg, val)	OUTREG(reg, val)
 #define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val))
+#define OUT_RELOC(x, read, write)            do {} while(0)
 #define FINISH_ACCEL()
 
 #ifdef RENDER
@@ -345,6 +471,7 @@ static void RADEONFinishAccess(PixmapPtr pPix, int index)
 #undef OUT_ACCEL_REG
 #undef OUT_ACCEL_REG_F
 #undef FINISH_ACCEL
+#undef OUT_RELOC
 
 #ifdef XF86DRI
 
@@ -355,6 +482,7 @@ static void RADEONFinishAccess(PixmapPtr pPix, int index)
 #define BEGIN_ACCEL(n)		BEGIN_RING(2*(n))
 #define OUT_ACCEL_REG(reg, val)	OUT_RING_REG(reg, val)
 #define FINISH_ACCEL()		ADVANCE_RING()
+#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write)
 
 #define OUT_RING_F(x) OUT_RING(F_TO_DW(x))
 
@@ -523,6 +651,10 @@ RADEONTexOffsetStart(PixmapPtr pPix)
 {
     RINFO_FROM_SCREEN(pPix->drawable.pScreen);
     unsigned long long offset;
+
+    if (exaGetPixmapDriverPrivate(pPix))
+	return -1;
+
     exaMoveInPixmap(pPix);
     ExaOffscreenMarkUsed(pPix);
 
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index ac82952..c47dfb4 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -74,6 +74,9 @@ FUNC_NAME(RADEONSync)(ScreenPtr pScreen, int marker)
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     RADEONInfoPtr info = RADEONPTR(pScrn);
 
+    if (info->cs)
+	    return;
+
     TRACE;
 
     if (info->accel_state->exaMarkerSynced != marker) {
@@ -84,11 +87,60 @@ FUNC_NAME(RADEONSync)(ScreenPtr pScreen, int marker)
     RADEONPTR(pScrn)->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
 }
 
+static void FUNC_NAME(Emit2DState)(ScrnInfoPtr pScrn, int op)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    int has_src;
+    ACCEL_PREAMBLE();
+
+    /* don't emit if no operation in progress */
+    if (info->state_2d.op == 0 && op == 0)
+	return;
+
+    has_src = info->state_2d.src_pitch_offset || (info->cs && info->state_2d.src_bo);
+
+    if (has_src) {
+      BEGIN_ACCEL_RELOC(10, 2);
+    } else {
+      BEGIN_ACCEL_RELOC(9, 1);
+    }
+    OUT_ACCEL_REG(RADEON_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right);
+    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl);
+    OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr);
+    OUT_ACCEL_REG(RADEON_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr);
+    OUT_ACCEL_REG(RADEON_DP_SRC_FRGD_CLR,   info->state_2d.dp_src_frgd_clr);
+    OUT_ACCEL_REG(RADEON_DP_SRC_BKGD_CLR,   info->state_2d.dp_src_bkgd_clr);
+    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, info->state_2d.dp_write_mask);
+    OUT_ACCEL_REG(RADEON_DP_CNTL, info->state_2d.dp_cntl);
+
+    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset);
+    if (info->cs)
+	OUT_RELOC(info->state_2d.dst_bo, 0, RADEON_GEM_DOMAIN_VRAM);
+
+    if (has_src) {
+	    OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset);
+	    if (info->cs)
+		OUT_RELOC(info->state_2d.src_bo, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0);
+	    
+    }
+    FINISH_ACCEL();
+
+    if (op)
+	info->state_2d.op = op;
+    if (info->cs)
+	info->reemit_current2d = FUNC_NAME(Emit2DState);
+}
+
 static Bool
 FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 {
     RINFO_FROM_SCREEN(pPix->drawable.pScreen);
     uint32_t datatype, dst_pitch_offset;
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int ret;
+    int retry_count = 0;
+    struct radeon_cs_space_check bos[1];
+    int i;
     ACCEL_PREAMBLE();
 
     TRACE;
@@ -101,21 +153,54 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 	RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch failed\n"));
 
     RADEON_SWITCH_TO_2D();
+ retry:
+    if (info->cs) {
+      
+	i = 0;
+	driver_priv = exaGetPixmapDriverPrivate(pPix);
+	bos[i].bo = driver_priv->bo;
+	bos[i].read_domains = 0;
+	bos[i].write_domain = RADEON_GEM_DOMAIN_VRAM;;
+	bos[i].new_accounted = 0;
+	i++;
+
+	ret = radeon_cs_space_check(info->cs, bos, i);
+	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
+	}
+	if (ret == RADEON_CS_SPACE_FLUSH) {
+	    radeon_cs_flush_indirect(pScrn);
+	    retry_count++;
+	    if (retry_count == 2)
+	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
+	    goto retry;
+	}
+    }
 
-    BEGIN_ACCEL(5);
-    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL,
-	    RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-	    RADEON_GMC_BRUSH_SOLID_COLOR |
-	    (datatype << 8) |
-	    RADEON_GMC_SRC_DATATYPE_COLOR |
-	    RADEON_ROP[alu].pattern |
-	    RADEON_GMC_CLR_CMP_CNTL_DIS);
-    OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg);
-    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, pm);
-    OUT_ACCEL_REG(RADEON_DP_CNTL,
-	(RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM));
-    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset);
-    FINISH_ACCEL();
+
+    info->state_2d.default_sc_bottom_right = (RADEON_DEFAULT_SC_RIGHT_MAX |
+					       RADEON_DEFAULT_SC_BOTTOM_MAX);
+    info->state_2d.dp_brush_bkgd_clr = 0x00000000;
+    info->state_2d.dp_src_frgd_clr = 0xffffffff;
+    info->state_2d.dp_src_bkgd_clr = 0x00000000;
+    info->state_2d.dp_gui_master_cntl = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+					  RADEON_GMC_BRUSH_SOLID_COLOR |
+					  (datatype << 8) |
+					  RADEON_GMC_SRC_DATATYPE_COLOR |
+					  RADEON_ROP[alu].pattern |
+					  RADEON_GMC_CLR_CMP_CNTL_DIS);
+    info->state_2d.dp_brush_frgd_clr = fg;
+    info->state_2d.dp_cntl = (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM);
+    info->state_2d.dp_write_mask = pm;
+    info->state_2d.dst_pitch_offset = dst_pitch_offset;
+    info->state_2d.src_pitch_offset = 0;
+    info->state_2d.src_bo = NULL;
+
+    driver_priv = exaGetPixmapDriverPrivate(pPix);
+    if (driver_priv)
+      info->state_2d.dst_bo = driver_priv->bo;
+
+    FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_SOLID);
 
     return TRUE;
 }
@@ -146,6 +231,7 @@ FUNC_NAME(RADEONDone2D)(PixmapPtr pPix)
 
     TRACE;
 
+    info->state_2d.op = 0;
     BEGIN_ACCEL(2);
     OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
     OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
@@ -161,25 +247,28 @@ FUNC_NAME(RADEONDoPrepareCopy)(ScrnInfoPtr pScrn, uint32_t src_pitch_offset,
     RADEONInfoPtr info = RADEONPTR(pScrn);
     ACCEL_PREAMBLE();
 
-    RADEON_SWITCH_TO_2D();
-
-    BEGIN_ACCEL(5);
-    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL,
-	RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-	RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
-	RADEON_GMC_BRUSH_NONE |
-	(datatype << 8) |
-	RADEON_GMC_SRC_DATATYPE_COLOR |
-	RADEON_ROP[rop].rop |
-	RADEON_DP_SRC_SOURCE_MEMORY |
-	RADEON_GMC_CLR_CMP_CNTL_DIS);
-    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
-    OUT_ACCEL_REG(RADEON_DP_CNTL,
-	((info->accel_state->xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) |
-	 (info->accel_state->ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0)));
-    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset);
-    OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset);
-    FINISH_ACCEL();
+    /* setup 2D state */
+    info->state_2d.dp_gui_master_cntl = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+					  RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+					  RADEON_GMC_BRUSH_NONE |
+					  (datatype << 8) |
+					  RADEON_GMC_SRC_DATATYPE_COLOR |
+					  RADEON_ROP[rop].rop |
+					  RADEON_DP_SRC_SOURCE_MEMORY |
+					  RADEON_GMC_CLR_CMP_CNTL_DIS);
+    info->state_2d.dp_cntl = ((info->accel_state->xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) |
+			       (info->accel_state->ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0));
+    info->state_2d.dp_brush_frgd_clr = 0xffffffff;
+    info->state_2d.dp_brush_bkgd_clr = 0x00000000;
+    info->state_2d.dp_src_frgd_clr = 0xffffffff;
+    info->state_2d.dp_src_bkgd_clr = 0x00000000;
+    info->state_2d.dp_write_mask = planemask;
+    info->state_2d.dst_pitch_offset = dst_pitch_offset;
+    info->state_2d.src_pitch_offset = src_pitch_offset;
+    info->state_2d.default_sc_bottom_right =  (RADEON_DEFAULT_SC_RIGHT_MAX
+						| RADEON_DEFAULT_SC_BOTTOM_MAX);
+
+    FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_COPY);
 }
 
 static Bool
@@ -190,9 +279,42 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc,   PixmapPtr pDst,
 {
     RINFO_FROM_SCREEN(pDst->drawable.pScreen);
     uint32_t datatype, src_pitch_offset, dst_pitch_offset;
-
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int ret;
+    int retry_count = 0;
+    struct radeon_cs_space_check bos[2];
+    int i;
     TRACE;
 
+    RADEON_SWITCH_TO_2D();
+retry:
+    if (info->cs) {
+      
+	driver_priv = exaGetPixmapDriverPrivate(pSrc);
+	info->state_2d.src_bo = driver_priv->bo;
+
+	driver_priv = exaGetPixmapDriverPrivate(pDst);
+	info->state_2d.dst_bo = driver_priv->bo;
+
+	i = 0;
+	radeon_add_pixmap(bos, i++, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	radeon_add_pixmap(bos, i++, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
+
+	ret = radeon_cs_space_check(info->cs, bos, i);
+	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
+	}
+	if (ret == RADEON_CS_SPACE_FLUSH) {
+	    radeon_cs_flush_indirect(pScrn);
+	    retry_count++;
+	    if (retry_count == 2)
+	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
+	    goto retry;
+	}
+    }
+
+
     info->accel_state->xdir = xdir;
     info->accel_state->ydir = ydir;
 
@@ -256,6 +378,9 @@ RADEONUploadToScreenCP(PixmapPtr pDst, int x, int y, int w, int h,
 
     TRACE;
 
+    if (info->cs)
+	return FALSE;
+
     if (bpp < 8)
 	return FALSE;
 
@@ -458,9 +583,9 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen)
 #endif
 
 #if X_BYTE_ORDER == X_BIG_ENDIAN
-    info->accel_state->exa->PrepareAccess = RADEONPrepareAccess;
-    info->accel_state->exa->FinishAccess = RADEONFinishAccess;
-#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */
+    info->accel_state->exa->PrepareAccess = RADEONPrepareAccess_BE;
+    info->accel_state->exa->FinishAccess = RADEONFinishAccess_BE;
+#endif
 
     info->accel_state->exa->flags = EXA_OFFSCREEN_PIXMAPS;
 #ifdef EXA_SUPPORTS_PREPARE_AUX
@@ -473,6 +598,10 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen)
     info->accel_state->exa->pixmapOffsetAlign = RADEON_BUFFER_ALIGN + 1;
     info->accel_state->exa->pixmapPitchAlign = 64;
 
+    if (info->cs)
+      info->accel_state->exa->flags |= EXA_HANDLES_PIXMAPS;
+
+
 #ifdef RENDER
     if (info->RenderAccel) {
 	if (IS_R300_3D || IS_R500_3D) {
@@ -510,6 +639,19 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen)
     }
 #endif
 
+#ifdef XF86DRM_MODE
+#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 4)
+    if (info->cs) {
+        info->accel_state->exa->CreatePixmap = RADEONEXACreatePixmap;
+        info->accel_state->exa->DestroyPixmap = RADEONEXADestroyPixmap;
+        info->accel_state->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen;
+	info->accel_state->exa->PrepareAccess = RADEONPrepareAccess_CS;
+	info->accel_state->exa->FinishAccess = RADEONFinishAccess_CS;
+    }
+#endif
+#endif
+
+
 #if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3)
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting EXA maxPitchBytes\n");
 
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index e274205..60c40a2 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -365,13 +365,14 @@ static Bool FUNC_NAME(R100TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
     Bool repeat = pPict->repeat && pPict->repeatType != RepeatPad &&
 	!(unit == 0 && (info->accel_state->need_src_tile_x || info->accel_state->need_src_tile_y));
     int i;
+    struct radeon_exa_pixmap_priv *driver_priv;
     ACCEL_PREAMBLE();
 
     txpitch = exaGetPixmapPitch(pPix);
-    txoffset = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset;
+    txoffset = 0;
+
+    CHECK_OFFSET(pPix, 0x1f, "texture");
 
-    if ((txoffset & 0x1f) != 0)
-	RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset));
     if ((txpitch & 0x1f) != 0)
 	RADEON_FALLBACK(("Bad texture pitch 0x%x\n", (int)txpitch));
 
@@ -426,23 +427,27 @@ static Bool FUNC_NAME(R100TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 	}
     }
 
-    BEGIN_ACCEL(5);
+    BEGIN_ACCEL_RELOC(5, 1);
     if (unit == 0) {
 	OUT_ACCEL_REG(RADEON_PP_TXFILTER_0, txfilter);
 	OUT_ACCEL_REG(RADEON_PP_TXFORMAT_0, txformat);
-	OUT_ACCEL_REG(RADEON_PP_TXOFFSET_0, txoffset);
 	OUT_ACCEL_REG(RADEON_PP_TEX_SIZE_0,
 	    (pPix->drawable.width - 1) |
 	    ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
 	OUT_ACCEL_REG(RADEON_PP_TEX_PITCH_0, txpitch - 32);
+
+	EMIT_READ_OFFSET(RADEON_PP_TXOFFSET_0, txoffset, pPix);
+	/* emit a texture relocation */
     } else {
 	OUT_ACCEL_REG(RADEON_PP_TXFILTER_1, txfilter);
 	OUT_ACCEL_REG(RADEON_PP_TXFORMAT_1, txformat);
-	OUT_ACCEL_REG(RADEON_PP_TXOFFSET_1, txoffset);
+
 	OUT_ACCEL_REG(RADEON_PP_TEX_SIZE_1,
 	    (pPix->drawable.width - 1) |
 	    ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
 	OUT_ACCEL_REG(RADEON_PP_TEX_PITCH_1, txpitch - 32);
+	EMIT_READ_OFFSET(RADEON_PP_TXOFFSET_1, txoffset, pPix);
+	/* emit a texture relocation */
     }
     FINISH_ACCEL();
 
@@ -548,9 +553,13 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
 					    PixmapPtr pDst)
 {
     RINFO_FROM_SCREEN(pDst->drawable.pScreen);
-    uint32_t dst_format, dst_offset, dst_pitch, colorpitch;
+    uint32_t dst_format, dst_pitch, colorpitch;
     uint32_t pp_cntl, blendcntl, cblend, ablend;
     int pixel_shift;
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int retry_count = 0;
+    struct radeon_cs_space_check bos[3];
+    int i, ret;
     ACCEL_PREAMBLE();
 
     TRACE;
@@ -568,24 +577,45 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
 
     pixel_shift = pDst->drawable.bitsPerPixel >> 4;
 
-    dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
     dst_pitch = exaGetPixmapPitch(pDst);
     colorpitch = dst_pitch >> pixel_shift;
     if (RADEONPixmapIsColortiled(pDst))
 	colorpitch |= RADEON_COLOR_TILE_ENABLE;
 
-    dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
-    dst_pitch = exaGetPixmapPitch(pDst);
-    if ((dst_offset & 0x0f) != 0)
-	RADEON_FALLBACK(("Bad destination offset 0x%x\n", (int)dst_offset));
+    CHECK_OFFSET(pDst, 0x0f, "destination");
+
     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
 
+    /* switch to 3D before doing buffer space checks as it may flush */
+    RADEON_SWITCH_TO_3D();
+ retry:
+    if (info->cs) {
+      
+	i = 0;
+	radeon_add_pixmap(bos, i++, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	if (pMask)
+	    radeon_add_pixmap(bos, i++, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	radeon_add_pixmap(bos, i++, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
+
+	ret = radeon_cs_space_check(info->cs, bos, i);
+	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
+	}
+	if (ret == RADEON_CS_SPACE_FLUSH) {
+	    radeon_cs_flush_indirect(pScrn);
+	    retry_count++;
+	    if (retry_count == 2)
+	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
+	    goto retry;
+	}
+    }
+
     if (!RADEONSetupSourceTile(pSrcPicture, pSrc, FALSE, TRUE))
 	return FALSE;
 
-    RADEON_SWITCH_TO_3D();
-
     if (!FUNC_NAME(R100TextureSetup)(pSrcPicture, pSrc, 0))
 	return FALSE;
     pp_cntl = RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE;
@@ -598,10 +628,10 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
 	info->accel_state->is_transform[1] = FALSE;
     }
 
-    BEGIN_ACCEL(10);
+    BEGIN_ACCEL_RELOC(10, 1);
     OUT_ACCEL_REG(RADEON_PP_CNTL, pp_cntl);
     OUT_ACCEL_REG(RADEON_RB3D_CNTL, dst_format | RADEON_ALPHA_BLEND_ENABLE);
-    OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset);
+    EMIT_WRITE_OFFSET(RADEON_RB3D_COLOROFFSET, 0, pDst);
     OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, colorpitch);
 
     /* IN operator: Multiply src by mask components or mask alpha.
@@ -705,13 +735,14 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
     Bool repeat = pPict->repeat && pPict->repeatType != RepeatPad &&
 	!(unit == 0 && (info->accel_state->need_src_tile_x || info->accel_state->need_src_tile_y));
     int i;
+    struct radeon_exa_pixmap_priv *driver_priv;
     ACCEL_PREAMBLE();
 
     txpitch = exaGetPixmapPitch(pPix);
-    txoffset = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset;
 
-    if ((txoffset & 0x1f) != 0)
-	RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset));
+    txoffset = 0;
+    CHECK_OFFSET(pPix, 0x1f, "texture");
+
     if ((txpitch & 0x1f) != 0)
 	RADEON_FALLBACK(("Bad texture pitch 0x%x\n", (int)txpitch));
 
@@ -768,7 +799,7 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 	}
     }
 
-    BEGIN_ACCEL(6);
+    BEGIN_ACCEL_RELOC(6, 1);
     if (unit == 0) {
 	OUT_ACCEL_REG(R200_PP_TXFILTER_0, txfilter);
 	OUT_ACCEL_REG(R200_PP_TXFORMAT_0, txformat);
@@ -776,7 +807,7 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 	OUT_ACCEL_REG(R200_PP_TXSIZE_0, (pPix->drawable.width - 1) |
 		      ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
 	OUT_ACCEL_REG(R200_PP_TXPITCH_0, txpitch - 32);
-	OUT_ACCEL_REG(R200_PP_TXOFFSET_0, txoffset);
+	EMIT_READ_OFFSET(R200_PP_TXOFFSET_0, txoffset, pPix);
     } else {
 	OUT_ACCEL_REG(R200_PP_TXFILTER_1, txfilter);
 	OUT_ACCEL_REG(R200_PP_TXFORMAT_1, txformat);
@@ -784,7 +815,8 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 	OUT_ACCEL_REG(R200_PP_TXSIZE_1, (pPix->drawable.width - 1) |
 		      ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
 	OUT_ACCEL_REG(R200_PP_TXPITCH_1, txpitch - 32);
-	OUT_ACCEL_REG(R200_PP_TXOFFSET_1, txoffset);
+	EMIT_READ_OFFSET(R200_PP_TXOFFSET_1, txoffset, pPix);
+	/* emit a texture relocation */
     }
     FINISH_ACCEL();
 
@@ -878,9 +910,13 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
 				PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
 {
     RINFO_FROM_SCREEN(pDst->drawable.pScreen);
-    uint32_t dst_format, dst_offset, dst_pitch;
+    uint32_t dst_format, dst_pitch;
     uint32_t pp_cntl, blendcntl, cblend, ablend, colorpitch;
     int pixel_shift;
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int retry_count = 0;
+    struct radeon_cs_space_check bos[3];
+    int i, ret;
     ACCEL_PREAMBLE();
 
     TRACE;
@@ -898,22 +934,45 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
 
     pixel_shift = pDst->drawable.bitsPerPixel >> 4;
 
-    dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
     dst_pitch = exaGetPixmapPitch(pDst);
     colorpitch = dst_pitch >> pixel_shift;
     if (RADEONPixmapIsColortiled(pDst))
 	colorpitch |= RADEON_COLOR_TILE_ENABLE;
 
-    if ((dst_offset & 0x0f) != 0)
-	RADEON_FALLBACK(("Bad destination offset 0x%x\n", (int)dst_offset));
+    CHECK_OFFSET(pDst, 0xf, "destination");
+
     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
 
+    /* switch to 3D before doing buffer space checks as it may flush */
+    RADEON_SWITCH_TO_3D();
+
+ retry:
+    if (info->cs) {
+      
+	i = 0;
+	radeon_add_pixmap(bos, i++, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	if (pMask)
+	    radeon_add_pixmap(bos, i++, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	radeon_add_pixmap(bos, i++, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
+
+	ret = radeon_cs_space_check(info->cs, bos, i);
+	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
+	}
+	if (ret == RADEON_CS_SPACE_FLUSH) {
+	    radeon_cs_flush_indirect(pScrn);
+	    retry_count++;
+	    if (retry_count == 2)
+	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
+	    goto retry;
+	}
+    }
     if (!RADEONSetupSourceTile(pSrcPicture, pSrc, FALSE, TRUE))
 	return FALSE;
 
-    RADEON_SWITCH_TO_3D();
-
     if (!FUNC_NAME(R200TextureSetup)(pSrcPicture, pSrc, 0))
 	return FALSE;
     pp_cntl = RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE;
@@ -926,11 +985,12 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
 	info->accel_state->is_transform[1] = FALSE;
     }
 
-    BEGIN_ACCEL(13);
+    BEGIN_ACCEL_RELOC(13, 1);
 
     OUT_ACCEL_REG(RADEON_PP_CNTL, pp_cntl);
     OUT_ACCEL_REG(RADEON_RB3D_CNTL, dst_format | RADEON_ALPHA_BLEND_ENABLE);
-    OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset);
+
+    EMIT_WRITE_OFFSET(RADEON_RB3D_COLOROFFSET, 0, pDst);
 
     OUT_ACCEL_REG(R200_SE_VTX_FMT_0, R200_VTX_XY);
     if (pMask)
@@ -1004,6 +1064,10 @@ static Bool R300CheckCompositeTexture(PicturePtr pPict,
 				      int unit,
 				      Bool is_r500)
 {
+    ScreenPtr pScreen = pDstPict->pDrawable->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+
     int w = pPict->pDrawable->width;
     int h = pPict->pDrawable->height;
     int i;
@@ -1029,8 +1093,17 @@ static Bool R300CheckCompositeTexture(PicturePtr pPict,
 	RADEON_FALLBACK(("Unsupported picture format 0x%x\n",
 			 (int)pPict->format));
 
-    if (!RADEONCheckTexturePOT(pPict, unit == 0))
+    if (!RADEONCheckTexturePOT(pPict, unit == 0)) {
+	if (info->cs) {
+    		struct radeon_exa_pixmap_priv *driver_priv;
+		PixmapPtr pPix;
+
+    		pPix = RADEONGetDrawablePixmap(pPict->pDrawable);
+		driver_priv = exaGetPixmapDriverPrivate(pPix);
+		//TODOradeon_bufmgr_gem_force_gtt(driver_priv->bo);
+	}
 	return FALSE;
+    }
 
     if (pPict->filter != PictFilterNearest &&
 	pPict->filter != PictFilterBilinear)
@@ -1062,15 +1135,16 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
     int w = pPict->pDrawable->width;
     int h = pPict->pDrawable->height;
     int i, pixel_shift;
+    struct radeon_exa_pixmap_priv *driver_priv;
     ACCEL_PREAMBLE();
 
     TRACE;
 
     txpitch = exaGetPixmapPitch(pPix);
-    txoffset = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset;
+    txoffset = 0;
+
+    CHECK_OFFSET(pPix, 0x1f, "texture");
 
-    if ((txoffset & 0x1f) != 0)
-	RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset));
     if ((txpitch & 0x1f) != 0)
 	RADEON_FALLBACK(("Bad texture pitch 0x%x\n", (int)txpitch));
 
@@ -1156,13 +1230,15 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 	RADEON_FALLBACK(("Bad filter 0x%x\n", pPict->filter));
     }
 
-    BEGIN_ACCEL(pPict->repeat ? 6 : 7);
+    BEGIN_ACCEL_RELOC(pPict->repeat ? 6 : 7, 1);
     OUT_ACCEL_REG(R300_TX_FILTER0_0 + (unit * 4), txfilter);
     OUT_ACCEL_REG(R300_TX_FILTER1_0 + (unit * 4), 0);
     OUT_ACCEL_REG(R300_TX_FORMAT0_0 + (unit * 4), txformat0);
     OUT_ACCEL_REG(R300_TX_FORMAT1_0 + (unit * 4), txformat1);
     OUT_ACCEL_REG(R300_TX_FORMAT2_0 + (unit * 4), txpitch);
-    OUT_ACCEL_REG(R300_TX_OFFSET_0 + (unit * 4), txoffset);
+
+    EMIT_READ_OFFSET((R300_TX_OFFSET_0 + (unit * 4)), txoffset, pPix);
+
     if (!pPict->repeat)
 	OUT_ACCEL_REG(R300_TX_BORDER_COLOR_0 + (unit * 4), 0);
     FINISH_ACCEL();
@@ -1321,14 +1397,18 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 				PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
 {
     RINFO_FROM_SCREEN(pDst->drawable.pScreen);
-    uint32_t dst_format, dst_offset, dst_pitch;
+    uint32_t dst_format, dst_pitch;
     uint32_t txenable, colorpitch;
     uint32_t blendcntl, output_fmt;
     uint32_t src_color, src_alpha;
     uint32_t mask_color, mask_alpha;
     int pixel_shift;
+    int ret;
+    int retry_count = 0;
+    struct radeon_exa_pixmap_priv *driver_priv;
+    struct radeon_cs_space_check bos[3];
+    int i;
     ACCEL_PREAMBLE();
-
     TRACE;
 
     if (!R300GetDestFormat(pDstPicture, &dst_format))
@@ -1341,7 +1421,6 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 
     pixel_shift = pDst->drawable.bitsPerPixel >> 4;
 
-    dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
     dst_pitch = exaGetPixmapPitch(pDst);
     colorpitch = dst_pitch >> pixel_shift;
 
@@ -1350,16 +1429,41 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 
     colorpitch |= dst_format;
 
-    if ((dst_offset & 0x0f) != 0)
-	RADEON_FALLBACK(("Bad destination offset 0x%x\n", (int)dst_offset));
+    CHECK_OFFSET(pDst, 0x0f, "destination");
+
     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
 
+    /* have to execute switch before doing buffer sizing check as it flushes */
+    RADEON_SWITCH_TO_3D();
+ retry:
+    if (info->cs) {
+      
+	i = 0;
+	driver_priv = exaGetPixmapDriverPrivate(pSrc);
+	radeon_add_pixmap(bos, i++, pSrc, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	if (pMask)
+	    radeon_add_pixmap(bos, i++, pMask, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+
+	radeon_add_pixmap(bos, i++, pDst, 0, RADEON_GEM_DOMAIN_VRAM);
+
+	ret = radeon_cs_space_check(info->cs, bos, i);
+	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
+	}
+	if (ret == RADEON_CS_SPACE_FLUSH) {
+            radeon_cs_flush_indirect(pScrn);
+	    retry_count++;
+	    if (retry_count == 2)
+	        RADEON_FALLBACK(("Not enough Video RAM - this really shouldn't happen\nm"));
+	    goto retry;
+	}
+    }
+
     if (!RADEONSetupSourceTile(pSrcPicture, pSrc, TRUE, FALSE))
 	return FALSE;
 
-    RADEON_SWITCH_TO_3D();
-
     if (!FUNC_NAME(R300TextureSetup)(pSrcPicture, pSrc, 0))
 	return FALSE;
     txenable = R300_TEX_0_ENABLE;
@@ -1945,9 +2049,9 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
     }
     FINISH_ACCEL();
 
-    BEGIN_ACCEL(3);
-
-    OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, dst_offset);
+    
+    BEGIN_ACCEL_RELOC(3, 1);
+    EMIT_WRITE_OFFSET(R300_RB3D_COLOROFFSET0, 0, pDst);
     OUT_ACCEL_REG(R300_RB3D_COLORPITCH0, colorpitch);
 
     blendcntl = RADEONGetBlendCntl(op, pMaskPicture, pDstPicture->format);
diff --git a/src/radeon_macros.h b/src/radeon_macros.h
index 8575884..15d9d73 100644
--- a/src/radeon_macros.h
+++ b/src/radeon_macros.h
@@ -160,4 +160,41 @@ do {									\
 #define INPCIE_P(pScrn, addr) R600INPCIE_PORT(pScrn, addr)
 #define OUTPCIE_P(pScrn, addr, val) R600OUTPCIE_PORT(pScrn, addr, val)
 
+#define BEGIN_ACCEL_RELOC(n, r) do {		\
+	int _nqw = (n) + (info->cs ? (r) : 0);	\
+	BEGIN_ACCEL(_nqw);			\
+    } while (0)
+
+#define CHECK_OFFSET(pPix, mask, type) do {	\
+    if (!info->cs) {			       \
+	uint32_t _pix_offset = radeonGetPixmapOffset(pPix);	\
+	if ((_pix_offset & mask) != 0)					\
+	    RADEON_FALLBACK(("Bad %s offset 0x%x\n", type, (int)pix_offset)); \
+    }									\
+    } while(0)
+
+#define EMIT_OFFSET(reg, value, pPix, rd, wd) do {		\
+    if (info->cs) {						\
+	driver_priv = exaGetPixmapDriverPrivate(pPix);		\
+	OUT_ACCEL_REG((reg), 0);				\
+	OUT_RELOC(driver_priv->bo, (rd), (wd));			\
+    } else {							\
+	uint32_t _pix_offset;					\
+	_pix_offset = radeonGetPixmapOffset(pPix);	\
+	OUT_ACCEL_REG((reg), _pix_offset | value);		\
+    }								\
+    } while(0)
+
+#define EMIT_READ_OFFSET(reg, value, pPix) EMIT_OFFSET(reg, value, pPix, (RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT), 0)
+#define EMIT_WRITE_OFFSET(reg, value, pPix) EMIT_OFFSET(reg, value, pPix, 0, RADEON_GEM_DOMAIN_VRAM)
+
+#define OUT_TEXTURE_REG(reg, offset, bo) do {   \
+    if (info->cs) {                                                     \
+      OUT_ACCEL_REG((reg), (offset));                                   \
+      OUT_RELOC((bo), RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); \
+    } else {                                                            \
+      OUT_ACCEL_REG((reg), (offset) + info->fbLocation + pScrn->fbOffset);} \
+  } while(0)
+
+
 #endif
diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c
index ab743be..10414b9 100644
--- a/src/radeon_textured_video.c
+++ b/src/radeon_textured_video.c
@@ -142,6 +142,7 @@ static REF_TRANSFORM trans[2] =
 #define BEGIN_ACCEL(n)		RADEONWaitForFifo(pScrn, (n))
 #define OUT_ACCEL_REG(reg, val)	OUTREG(reg, val)
 #define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val))
+#define OUT_RELOC(x, read, write) do {} while(0)
 #define FINISH_ACCEL()
 
 #include "radeon_textured_videofuncs.c"
@@ -151,6 +152,7 @@ static REF_TRANSFORM trans[2] =
 #undef BEGIN_ACCEL
 #undef OUT_ACCEL_REG
 #undef OUT_ACCEL_REG_F
+#undef OUT_RELOC
 #undef FINISH_ACCEL
 
 #ifdef XF86DRI
@@ -164,6 +166,7 @@ static REF_TRANSFORM trans[2] =
 #define OUT_ACCEL_REG_F(reg, val)	OUT_ACCEL_REG(reg, F_TO_DW(val))
 #define FINISH_ACCEL()		ADVANCE_RING()
 #define OUT_RING_F(x) OUT_RING(F_TO_DW(x))
+#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write)
 
 #include "radeon_textured_videofuncs.c"
 
@@ -323,6 +326,9 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
 								size * 2, 64);
 	if (pPriv->video_offset == 0)
 	    return BadAlloc;
+
+	if (info->cs)
+	    pPriv->src_bo = pPriv->video_memory;
     }
 
     /* Bicubic filter loading */
@@ -333,6 +339,9 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
 	pPriv->bicubic_src_offset = pPriv->bicubic_offset + info->fbLocation + pScrn->fbOffset;
 	if (pPriv->bicubic_offset == 0)
 		pPriv->bicubic_enabled = FALSE;
+
+	if (info->cs)
+	    pPriv->bicubic_bo = pPriv->bicubic_memory;
     }
 
     if (pDraw->type == DRAWABLE_WINDOW)
@@ -361,8 +370,18 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
     top = (y1 >> 16) & ~1;
     nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
 
-    pPriv->src_offset = pPriv->video_offset + info->fbLocation + pScrn->fbOffset;
-    pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset);
+    pPriv->src_offset = pPriv->video_offset;
+    if (info->cs) {
+	int ret;
+	radeon_bo_wait(pPriv->src_bo);
+	ret = radeon_bo_map(pPriv->src_bo, 1);
+	if (ret) 
+	    return BadAlloc;
+	
+	pPriv->src_addr = pPriv->src_bo->ptr;
+    } else {
+	pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset);
+    }
     pPriv->src_pitch = dstPitch;
 
     pPriv->planeu_offset = dstPitch * dst_height;
@@ -431,9 +450,23 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
 
     /* Upload bicubic filter tex */
     if (pPriv->bicubic_enabled) {
-	if (info->ChipFamily < CHIP_FAMILY_R600)
-	    RADEONCopyData(pScrn, (uint8_t *)bicubic_tex_512,
-			   (uint8_t *)(info->FB + pPriv->bicubic_offset), 1024, 1024, 1, 512, 2);
+	if (info->ChipFamily < CHIP_FAMILY_R600) {
+	    uint8_t *bicubic_addr;
+	    int ret;
+	    if (info->cs) {
+		radeon_bo_wait(pPriv->bicubic_bo);
+		ret = radeon_bo_map(pPriv->bicubic_bo, 1);
+		if (ret)
+		    return BadAlloc;
+		
+		bicubic_addr = pPriv->bicubic_bo->ptr;
+	    } else
+		bicubic_addr = (uint8_t *)(info->FB + pPriv->bicubic_offset);
+
+	    RADEONCopyData(pScrn, (uint8_t *)bicubic_tex_512, bicubic_addr, 1024, 1024, 1, 512, 2);
+	   if (info->cs)
+	       radeon_bo_unmap(pPriv->bicubic_bo);
+	}
     }
 
     /* update cliplist */
@@ -453,6 +486,8 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
     pPriv->w = width;
     pPriv->h = height;
 
+    if (info->cs)
+	radeon_bo_unmap(pPriv->src_bo);
 #ifdef XF86DRI
     if (info->directRenderingEnabled) {
 	if (IS_R600_3D)
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index 47878fc..b9930c7 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -92,27 +92,69 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
     PixmapPtr pPixmap = pPriv->pPixmap;
-    uint32_t txformat, txsize, txpitch;
-    uint32_t dst_offset, dst_pitch, dst_format;
+    struct radeon_exa_pixmap_priv *driver_priv;
+    struct radeon_cs_space_check bos[3];
+    uint32_t txformat, txsize, txpitch, txoffset;
+    uint32_t dst_pitch, dst_format;
     uint32_t colorpitch;
     Bool isplanar = FALSE;
     int dstxoff, dstyoff, pixel_shift, vtx_count;
     BoxPtr pBox = REGION_RECTS(&pPriv->clip);
     int nBox = REGION_NUM_RECTS(&pPriv->clip);
+    int i, ret, retry_count = 0;
     ACCEL_PREAMBLE();
 
+ retry:
+    if (info->cs) {
+      
+	i = 0;
+	bos[i].bo = pPriv->src_bo;
+	bos[i].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
+	bos[i].write_domain = 0;
+	bos[i].new_accounted = 0;
+	i++;
+
+	if (pPriv->bicubic_enabled) {
+	    bos[i].bo = pPriv->bicubic_bo;
+	    bos[i].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
+	    bos[i].write_domain = 0;
+	    bos[i].new_accounted = 0;
+	    i++;
+	}
+
+	driver_priv = exaGetPixmapDriverPrivate(pPixmap);
+	bos[i].bo = driver_priv->bo;
+	bos[i].read_domains = 0;
+	bos[i].write_domain = RADEON_GEM_DOMAIN_VRAM;
+	bos[i].new_accounted = 0;
+	i++;
+
+	ret = radeon_cs_space_check(info->cs, bos, i);
+	if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
+	    ErrorF("Not enough RAM to hw accel composite operation\n");
+	    return;
+	}
+	if (ret == RADEON_CS_SPACE_FLUSH) {
+	    radeon_cs_flush_indirect(pScrn);
+	    retry_count++;
+	    if (retry_count == 2) {
+	        ErrorF("Not enough RAM to hw accel composite operation\n");
+	        return;
+	    }
+	    goto retry;
+	}
+    }
+
     pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
 
+    
 #ifdef USE_EXA
     if (info->useEXA) {
-	dst_offset = exaGetPixmapOffset(pPixmap) + info->fbLocation + pScrn->fbOffset;
 	dst_pitch = exaGetPixmapPitch(pPixmap);
     } else
 #endif
     {
-	dst_offset = (pPixmap->devPrivate.ptr - info->FB) +
-	    info->fbLocation + pScrn->fbOffset;
-	dst_pitch = pPixmap->devKind;
+        dst_pitch = pPixmap->devKind;
     }
 
 #ifdef COMPOSITE
@@ -175,10 +217,12 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
     if (RADEONTilingEnabled(pScrn, pPixmap))
 	colorpitch |= RADEON_COLOR_TILE_ENABLE;
 
-    BEGIN_ACCEL(4);
+    txoffset = info->cs ? 0 : pPriv->src_offset;
+
+    BEGIN_ACCEL_RELOC(4,1);
 
     OUT_ACCEL_REG(RADEON_RB3D_CNTL, dst_format);
-    OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset);
+    EMIT_WRITE_OFFSET(RADEON_RB3D_COLOROFFSET, 0, pPixmap);
     OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, colorpitch);
     OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL,
 		  RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO);
@@ -215,7 +259,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		      RADEON_CLAMP_T_CLAMP_LAST |
 		      RADEON_YUV_TO_RGB);
 	OUT_ACCEL_REG(RADEON_PP_TXFORMAT_0, txformat | RADEON_TXFORMAT_ST_ROUTE_STQ0);
-	OUT_ACCEL_REG(RADEON_PP_TXOFFSET_0, pPriv->src_offset);
+	OUT_TEXTURE_REG(R200_PP_TXOFFSET_0, txoffset, pPriv->src_bo);
 	OUT_ACCEL_REG(RADEON_PP_TXCBLEND_0,
 		      RADEON_COLOR_ARG_A_ZERO |
 		      RADEON_COLOR_ARG_B_ZERO |
@@ -242,7 +286,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		      RADEON_CLAMP_S_CLAMP_LAST |
 		      RADEON_CLAMP_T_CLAMP_LAST);
 	OUT_ACCEL_REG(RADEON_PP_TXFORMAT_1, txformat | RADEON_TXFORMAT_ST_ROUTE_STQ1);
-	OUT_ACCEL_REG(RADEON_PP_TXOFFSET_1, pPriv->src_offset + pPriv->planeu_offset);
+	OUT_TEXTURE_REG(R200_PP_TXOFFSET_1, txoffset + pPriv->planeu_offset, pPriv->src_bo);
 	OUT_ACCEL_REG(RADEON_PP_TXCBLEND_1,
 		      RADEON_COLOR_ARG_A_ZERO |
 		      RADEON_COLOR_ARG_B_ZERO |
@@ -266,7 +310,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		      RADEON_CLAMP_S_CLAMP_LAST |
 		      RADEON_CLAMP_T_CLAMP_LAST);
 	OUT_ACCEL_REG(RADEON_PP_TXFORMAT_2, txformat | RADEON_TXFORMAT_ST_ROUTE_STQ1);
-	OUT_ACCEL_REG(RADEON_PP_TXOFFSET_2, pPriv->src_offset + pPriv->planev_offset);
+	OUT_TEXTURE_REG(R200_PP_TXOFFSET_2, txoffset + pPriv->planev_offset, pPriv->src_bo);
 	OUT_ACCEL_REG(RADEON_PP_TXCBLEND_2,
 		      RADEON_COLOR_ARG_A_ZERO |
 		      RADEON_COLOR_ARG_B_ZERO |
@@ -299,7 +343,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		      RADEON_CLAMP_T_CLAMP_LAST |
 		      RADEON_YUV_TO_RGB);
 	OUT_ACCEL_REG(RADEON_PP_TXFORMAT_0, txformat | RADEON_TXFORMAT_ST_ROUTE_STQ0);
-	OUT_ACCEL_REG(RADEON_PP_TXOFFSET_0, pPriv->src_offset);
+	OUT_TEXTURE_REG(RADEON_PP_TXOFFSET_0, txoffset, pPriv->src_bo);
 	OUT_ACCEL_REG(RADEON_PP_TXCBLEND_0,
 		      RADEON_COLOR_ARG_A_ZERO |
 		      RADEON_COLOR_ARG_B_ZERO |
@@ -448,9 +492,10 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
     PixmapPtr pPixmap = pPriv->pPixmap;
+    struct radeon_exa_pixmap_priv *driver_priv;
     uint32_t txformat;
-    uint32_t txfilter, txsize, txpitch;
-    uint32_t dst_offset, dst_pitch, dst_format;
+    uint32_t txfilter, txsize, txpitch, txoffset;
+    uint32_t dst_pitch, dst_format;
     uint32_t colorpitch;
     Bool isplanar = FALSE;
     int dstxoff, dstyoff, pixel_shift, vtx_count;
@@ -473,15 +518,12 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 
 #ifdef USE_EXA
     if (info->useEXA) {
-	dst_offset = exaGetPixmapOffset(pPixmap) + info->fbLocation + pScrn->fbOffset;
 	dst_pitch = exaGetPixmapPitch(pPixmap);
     } else
 #endif
-	{
-	    dst_offset = (pPixmap->devPrivate.ptr - info->FB) +
-		info->fbLocation + pScrn->fbOffset;
-	    dst_pitch = pPixmap->devKind;
-	}
+    {
+	dst_pitch = pPixmap->devKind;
+    }
 
 #ifdef COMPOSITE
     dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
@@ -546,7 +588,7 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     BEGIN_ACCEL(4);
 
     OUT_ACCEL_REG(RADEON_RB3D_CNTL, dst_format);
-    OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset);
+    EMIT_WRITE_OFFSET(RADEON_RB3D_COLOROFFSET, 0, pPixmap);
     OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, colorpitch);
 
     OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL,
@@ -590,6 +632,8 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	vcscale = 0.125;
     }
 
+    txoffset = info->cs ? 0 : pPriv->src_offset;
+
     if (isplanar) {
 	/* need 2 texcoord sets (even though they are identical) due
 	   to denormalization! hw apparently can't premultiply
@@ -621,21 +665,21 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 		      (pPriv->w - 1) |
 		      ((pPriv->h - 1) << RADEON_TEX_VSIZE_SHIFT));
 	OUT_ACCEL_REG(R200_PP_TXPITCH_0, pPriv->src_pitch - 32);
-	OUT_ACCEL_REG(R200_PP_TXOFFSET_0, pPriv->src_offset);
+	OUT_TEXTURE_REG(R200_PP_TXOFFSET_0, txoffset, pPriv->src_bo);
 
 	OUT_ACCEL_REG(R200_PP_TXFILTER_1, txfilter);
 	OUT_ACCEL_REG(R200_PP_TXFORMAT_1, txformat | R200_TXFORMAT_ST_ROUTE_STQ1);
 	OUT_ACCEL_REG(R200_PP_TXFORMAT_X_1, 0);
 	OUT_ACCEL_REG(R200_PP_TXSIZE_1, txsize);
 	OUT_ACCEL_REG(R200_PP_TXPITCH_1, txpitch);
-	OUT_ACCEL_REG(R200_PP_TXOFFSET_1, pPriv->src_offset + pPriv->planeu_offset);
+	OUT_TEXTURE_REG(R200_PP_TXOFFSET_1, txoffset + pPriv->planeu_offset, pPriv->src_bo);
 
 	OUT_ACCEL_REG(R200_PP_TXFILTER_2, txfilter);
 	OUT_ACCEL_REG(R200_PP_TXFORMAT_2, txformat | R200_TXFORMAT_ST_ROUTE_STQ1);
 	OUT_ACCEL_REG(R200_PP_TXFORMAT_X_2, 0);
 	OUT_ACCEL_REG(R200_PP_TXSIZE_2, txsize);
 	OUT_ACCEL_REG(R200_PP_TXPITCH_2, txpitch);
-	OUT_ACCEL_REG(R200_PP_TXOFFSET_2, pPriv->src_offset + pPriv->planev_offset);
+	OUT_TEXTURE_REG(R200_PP_TXOFFSET_2, txoffset + pPriv->planev_offset, pPriv->src_bo);
 
 	/* similar to r300 code. Note the big problem is that hardware constants
 	 * are 8 bits only, representing 0.0-1.0. We can get that up (using bias
@@ -777,7 +821,7 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 		      (pPriv->w - 1) |
 		      ((pPriv->h - 1) << RADEON_TEX_VSIZE_SHIFT));
 	OUT_ACCEL_REG(R200_PP_TXPITCH_0, pPriv->src_pitch - 32);
-	OUT_ACCEL_REG(R200_PP_TXOFFSET_0, pPriv->src_offset);
+	OUT_TEXTURE_REG(R200_PP_TXOFFSET_0, txoffset, pPriv->src_bo);
 
 	/* MAD temp1 / 2, const0.a * 2, temp0.ggg, -const0.rgb */
 	OUT_ACCEL_REG(R200_PP_TXCBLEND_0,
@@ -980,9 +1024,10 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
     PixmapPtr pPixmap = pPriv->pPixmap;
+    struct radeon_exa_pixmap_priv *driver_priv;
     uint32_t txfilter, txformat0, txformat1, txoffset, txpitch;
-    uint32_t dst_offset, dst_pitch, dst_format;
-    uint32_t txenable, colorpitch;
+    uint32_t dst_pitch, dst_format;
+    uint32_t txenable, colorpitch, bicubic_offset;
     uint32_t output_fmt;
     Bool isplanar = FALSE;
     int dstxoff, dstyoff, pixel_shift, vtx_count;
@@ -994,15 +1039,12 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 
 #ifdef USE_EXA
     if (info->useEXA) {
-	dst_offset = exaGetPixmapOffset(pPixmap) + info->fbLocation + pScrn->fbOffset;
 	dst_pitch = exaGetPixmapPitch(pPixmap);
     } else
 #endif
-	{
-	    dst_offset = (pPixmap->devPrivate.ptr - info->FB) +
-		info->fbLocation + pScrn->fbOffset;
-	    dst_pitch = pPixmap->devKind;
-	}
+    {
+	dst_pitch = pPixmap->devKind;
+    }
 
 #ifdef COMPOSITE
     dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
@@ -1095,9 +1137,9 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 		R300_TX_MIN_FILTER_LINEAR |
 		(0 << R300_TX_ID_SHIFT));
 
-    txoffset = pPriv->src_offset;
+    txoffset = info->cs ? 0 : pPriv->src_offset;
 
-    BEGIN_ACCEL(6);
+    BEGIN_ACCEL_RELOC(6, 1);
     OUT_ACCEL_REG(R300_TX_FILTER0_0, txfilter);
     OUT_ACCEL_REG(R300_TX_FILTER1_0, 0);
     OUT_ACCEL_REG(R300_TX_FORMAT0_0, txformat0);
@@ -1106,7 +1148,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     else
 	OUT_ACCEL_REG(R300_TX_FORMAT1_0, txformat1);
     OUT_ACCEL_REG(R300_TX_FORMAT2_0, txpitch);
-    OUT_ACCEL_REG(R300_TX_OFFSET_0, txoffset);
+    OUT_TEXTURE_REG(R300_TX_OFFSET_0, txoffset, pPriv->src_bo);
     FINISH_ACCEL();
 
     txenable = R300_TEX_0_ENABLE;
@@ -1122,19 +1164,19 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 		    R300_TX_MIN_FILTER_LINEAR |
 		    R300_TX_MAG_FILTER_LINEAR);
 
-	BEGIN_ACCEL(12);
+	BEGIN_ACCEL_RELOC(12, 2);
 	OUT_ACCEL_REG(R300_TX_FILTER0_1, txfilter | (1 << R300_TX_ID_SHIFT));
 	OUT_ACCEL_REG(R300_TX_FILTER1_1, 0);
 	OUT_ACCEL_REG(R300_TX_FORMAT0_1, txformat0);
 	OUT_ACCEL_REG(R300_TX_FORMAT1_1, R300_TX_FORMAT_X8 | R300_TX_FORMAT_CACHE_FOURTH_REGION_2);
 	OUT_ACCEL_REG(R300_TX_FORMAT2_1, txpitch);
-	OUT_ACCEL_REG(R300_TX_OFFSET_1, txoffset + pPriv->planeu_offset);
+	OUT_TEXTURE_REG(R300_TX_OFFSET_1, txoffset + pPriv->planeu_offset, pPriv->src_bo);
 	OUT_ACCEL_REG(R300_TX_FILTER0_2, txfilter | (2 << R300_TX_ID_SHIFT));
 	OUT_ACCEL_REG(R300_TX_FILTER1_2, 0);
 	OUT_ACCEL_REG(R300_TX_FORMAT0_2, txformat0);
 	OUT_ACCEL_REG(R300_TX_FORMAT1_2, R300_TX_FORMAT_X8 | R300_TX_FORMAT_CACHE_FOURTH_REGION_3);
 	OUT_ACCEL_REG(R300_TX_FORMAT2_2, txpitch);
-	OUT_ACCEL_REG(R300_TX_OFFSET_2, txoffset + pPriv->planev_offset);
+	OUT_TEXTURE_REG(R300_TX_OFFSET_2, txoffset + pPriv->planev_offset, pPriv->src_bo);
 	FINISH_ACCEL();
 	txenable |= R300_TEX_1_ENABLE | R300_TEX_2_ENABLE;
     }
@@ -1155,13 +1197,18 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 		    R300_TX_MAG_FILTER_NEAREST |
 		    (1 << R300_TX_ID_SHIFT));
 
-	BEGIN_ACCEL(6);
+	if (info->cs)
+	    bicubic_offset = 0;
+	else
+	    bicubic_offset = pPriv->bicubic_src_offset;
+       
+	BEGIN_ACCEL_RELOC(6, 1);
 	OUT_ACCEL_REG(R300_TX_FILTER0_1, txfilter);
 	OUT_ACCEL_REG(R300_TX_FILTER1_1, 0);
 	OUT_ACCEL_REG(R300_TX_FORMAT0_1, txformat0);
 	OUT_ACCEL_REG(R300_TX_FORMAT1_1, txformat1);
 	OUT_ACCEL_REG(R300_TX_FORMAT2_1, txpitch);
-	OUT_ACCEL_REG(R300_TX_OFFSET_1, pPriv->bicubic_src_offset);
+	OUT_TEXTURE_REG(R300_TX_OFFSET_1, bicubic_offset, pPriv->bicubic_bo);
 	FINISH_ACCEL();
 
 	/* Enable tex 1 */
@@ -2205,11 +2252,11 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	FINISH_ACCEL();
     }
 
-    BEGIN_ACCEL(6);
+    BEGIN_ACCEL_RELOC(6, 1);
     OUT_ACCEL_REG(R300_TX_INVALTAGS, 0);
     OUT_ACCEL_REG(R300_TX_ENABLE, txenable);
 
-    OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, dst_offset);
+    EMIT_WRITE_OFFSET(R300_RB3D_COLOROFFSET0, 0, pPixmap);
     OUT_ACCEL_REG(R300_RB3D_COLORPITCH0, colorpitch);
 
     /* no need to enable blending */
@@ -2407,8 +2454,9 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
     PixmapPtr pPixmap = pPriv->pPixmap;
+    struct radeon_exa_pixmap_priv *driver_priv;
     uint32_t txfilter, txformat0, txformat1, txoffset, txpitch;
-    uint32_t dst_offset, dst_pitch, dst_format;
+    uint32_t dst_pitch, dst_format;
     uint32_t txenable, colorpitch;
     uint32_t output_fmt;
     Bool isplanar = FALSE;
@@ -2421,15 +2469,12 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 
 #ifdef USE_EXA
     if (info->useEXA) {
-	dst_offset = exaGetPixmapOffset(pPixmap) + info->fbLocation + pScrn->fbOffset;
 	dst_pitch = exaGetPixmapPitch(pPixmap);
     } else
 #endif
-	{
-	    dst_offset = (pPixmap->devPrivate.ptr - info->FB) +
-		info->fbLocation + pScrn->fbOffset;
-	    dst_pitch = pPixmap->devKind;
-	}
+    {
+	dst_pitch = pPixmap->devKind;
+    }
 
 #ifdef COMPOSITE
     dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
@@ -2528,15 +2573,15 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
     if ((pPriv->h - 1) & 0x800)
 	txpitch |= R500_TXHEIGHT_11;
 
-    txoffset = pPriv->src_offset;
+    txoffset = info->cs ? 0 : pPriv->src_offset;
 
-    BEGIN_ACCEL(6);
+    BEGIN_ACCEL_RELOC(6, 1);
     OUT_ACCEL_REG(R300_TX_FILTER0_0, txfilter);
     OUT_ACCEL_REG(R300_TX_FILTER1_0, 0);
     OUT_ACCEL_REG(R300_TX_FORMAT0_0, txformat0);
     OUT_ACCEL_REG(R300_TX_FORMAT1_0, txformat1);
     OUT_ACCEL_REG(R300_TX_FORMAT2_0, txpitch);
-    OUT_ACCEL_REG(R300_TX_OFFSET_0, txoffset);
+    OUT_TEXTURE_REG(R300_TX_OFFSET_0, txoffset, pPriv->src_bo);
     FINISH_ACCEL();
 
     txenable = R300_TEX_0_ENABLE;
@@ -3758,11 +3803,11 @@ FUNC_NAME(R500DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 	FINISH_ACCEL();
     }
 
-    BEGIN_ACCEL(6);
+    BEGIN_ACCEL_RELOC(6, 1);
     OUT_ACCEL_REG(R300_TX_INVALTAGS, 0);
     OUT_ACCEL_REG(R300_TX_ENABLE, txenable);
 
-    OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, dst_offset);
+    EMIT_WRITE_OFFSET(R300_RB3D_COLOROFFSET0, 0, pPixmap);
     OUT_ACCEL_REG(R300_RB3D_COLORPITCH0, colorpitch);
 
     /* no need to enable blending */
diff --git a/src/radeon_video.h b/src/radeon_video.h
index 0cf8168..aeb6441 100644
--- a/src/radeon_video.h
+++ b/src/radeon_video.h
@@ -120,6 +120,9 @@ typedef struct {
     int drw_x, drw_y;
     int src_x, src_y;
     int vsync;
+
+    struct radeon_bo *src_bo;
+    struct radeon_bo *bicubic_bo;
 } RADEONPortPrivRec, *RADEONPortPrivPtr;
 
 /* Reference color space transform data */
commit bb04b450ed00ca4b1aa44c33085567d47b33b547
Author: Fredrik Höglund <fredrik at kde.org>
Date:   Mon Jun 29 22:38:26 2009 +0200

    Check if the composite op is supported in R200CheckComposite.

diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 4610d80..e274205 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -807,6 +807,10 @@ static Bool R200CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP
 
     TRACE;
 
+    /* Check for unsupported compositing operations. */
+    if (op >= sizeof(RadeonBlendOp) / sizeof(RadeonBlendOp[0]))
+	RADEON_FALLBACK(("Unsupported Composite op 0x%x\n", op));
+
     if (!pSrcPicture->pDrawable)
 	return FALSE;
 
commit f39cafc5c4a93a16ac93756473ebb1f33c7881db
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Sun Jun 28 20:42:49 2009 -0400

    radeon: call hdmi-b connectors dvi in randr
    
    Technically HDMI-B is a glorfied DL DVI, but this is confusing
    to users, so call it DVI when reporting randr outputs.  This
    allows us to remove two quirks where the bios was actually
    correct.

diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index e654228..f590d5b 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -1625,22 +1625,6 @@ static void RADEONApplyATOMQuirks(ScrnInfoPtr pScrn, int index)
 	}
     }
 
-    /* ASUS HD 3600 XT board lists the DVI port as HDMI */
-    if ((info->Chipset == PCI_CHIP_RV635_9598) &&
-	(PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) &&
-	(PCI_SUB_DEVICE_ID(info->PciInfo) == 0x01da)) {
-	if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_B)
-	    info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_D;
-    }
-
-    /* ASUS HD 3450 board lists the DVI port as HDMI */
-    if ((info->Chipset == PCI_CHIP_RV620_95C5) &&
-	(PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) &&
-	(PCI_SUB_DEVICE_ID(info->PciInfo) == 0x01e2)) {
-	if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_B)
-	    info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_D;
-    }
-
     /* some BIOSes seem to report DAC on HDMI - usually this is a board with
      * HDMI + VGA reporting as HDMI
      */
@@ -1649,8 +1633,7 @@ static void RADEONApplyATOMQuirks(ScrnInfoPtr pScrn, int index)
 	    info->BiosConnector[index].devices &= ~(ATOM_DEVICE_DFP_SUPPORT);
 	    info->BiosConnector[index].ConnectorType = CONNECTOR_VGA;
 	    info->BiosConnector[index].connector_object = 0;
-	} else
-	    info->BiosConnector[index].devices &= ~(ATOM_DEVICE_CRT_SUPPORT);
+	}
     }
 
 }
diff --git a/src/radeon_output.c b/src/radeon_output.c
index 62edd05..f554824 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -2727,12 +2727,12 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn)
 	    RADEONConnectorType conntype = info->BiosConnector[i].ConnectorType;
 	    if ((conntype == CONNECTOR_DVI_D) ||
 		(conntype == CONNECTOR_DVI_I) ||
-		(conntype == CONNECTOR_DVI_A)) {
+		(conntype == CONNECTOR_DVI_A) ||
+		(conntype == CONNECTOR_HDMI_TYPE_B)) {
 		num_dvi++;
 	    } else if (conntype == CONNECTOR_VGA) {
 		num_vga++;
-	    } else if ((conntype == CONNECTOR_HDMI_TYPE_A) ||
-		       (conntype == CONNECTOR_HDMI_TYPE_B)) {
+	    } else if (conntype == CONNECTOR_HDMI_TYPE_A) {
 		num_hdmi++;
 	    } else if (conntype == CONNECTOR_DISPLAY_PORT) {
 		num_dp++;
@@ -2762,14 +2762,18 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn)
 	    radeon_output->linkb = info->BiosConnector[i].linkb;
 	    radeon_output->connector_id = info->BiosConnector[i].connector_object;
 
+	    /* Technically HDMI-B is a glorfied DL DVI so the bios is correct,
+	     * but this can be confusing to users when it comes to output names,
+	     * so call it DVI
+	     */
 	    if ((conntype == CONNECTOR_DVI_D) ||
 		(conntype == CONNECTOR_DVI_I) ||
-		(conntype == CONNECTOR_DVI_A)) {
+		(conntype == CONNECTOR_DVI_A) ||
+		(conntype == CONNECTOR_HDMI_TYPE_B)) {
 		output = RADEONOutputCreate(pScrn, "DVI-%d", --num_dvi);
 	    } else if (conntype == CONNECTOR_VGA) {
 		output = RADEONOutputCreate(pScrn, "VGA-%d", --num_vga);
-	    } else if ((conntype == CONNECTOR_HDMI_TYPE_A) ||
-		       (conntype == CONNECTOR_HDMI_TYPE_B)) {
+	    } else if (conntype == CONNECTOR_HDMI_TYPE_A) {
 		output = RADEONOutputCreate(pScrn, "HDMI-%d", --num_hdmi);
 	    } else if (conntype == CONNECTOR_DISPLAY_PORT) {
 		output = RADEONOutputCreate(pScrn, "DisplayPort-%d", --num_dp);
commit 407e676b04117c7ca3dcc0cc072f3552b03c64e5
Author: Roland Scheidegger <sroland at tungstengraphics.com>
Date:   Sun Jun 28 16:54:32 2009 -0400

    R6xx/R7xx: fix pixel centers
    
    Make sure we are using GL mode (centers at 0.5) rather
    than D3D mode (centers at 0.0).  This also fixes fdo
    bug 21963.

diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c
index e9741cd..65834bf 100644
--- a/src/r6xx_accel.c
+++ b/src/r6xx_accel.c
@@ -974,7 +974,7 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib)
     EREG(ib, PA_SU_POLY_OFFSET_FRONT_OFFSET,      0);
 
     EREG(ib, PA_SU_LINE_CNTL,                     (8 << PA_SU_LINE_CNTL__WIDTH_shift)); /* Line width 1 pixel */
-    EREG(ib, PA_SU_VTX_CNTL,                      ((2 << PA_SU_VTX_CNTL__ROUND_MODE_shift) |
+    EREG(ib, PA_SU_VTX_CNTL,                      ((2 << PA_SU_VTX_CNTL__ROUND_MODE_shift) | PIX_CENTER_bit |
 						   (5 << QUANT_MODE_shift))); /* Round to Even, fixed point 1/256 */
     EREG(ib, PA_SU_POLY_OFFSET_CLAMP,             0);
 
commit 68001981f22173ff949720055dba89291f284474
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Sun Jun 28 16:20:10 2009 -0400

    Add some missing M96 pci ids
    
    fixes fdo bug 22404

diff --git a/src/ati_pciids_gen.h b/src/ati_pciids_gen.h
index 17dc4f9..92ae397 100644
--- a/src/ati_pciids_gen.h
+++ b/src/ati_pciids_gen.h
@@ -354,7 +354,9 @@
 #define PCI_CHIP_RV770_946B 0x946B
 #define PCI_CHIP_RV770_947A 0x947A
 #define PCI_CHIP_RV770_947B 0x947B
+#define PCI_CHIP_RV730_9480 0x9480
 #define PCI_CHIP_RV730_9487 0x9487
+#define PCI_CHIP_RV730_9488 0x9488
 #define PCI_CHIP_RV730_9489 0x9489
 #define PCI_CHIP_RV730_948F 0x948F
 #define PCI_CHIP_RV730_9490 0x9490
diff --git a/src/pcidb/ati_pciids.csv b/src/pcidb/ati_pciids.csv
index 007deec..5e78bda 100644
--- a/src/pcidb/ati_pciids.csv
+++ b/src/pcidb/ati_pciids.csv
@@ -355,7 +355,9 @@
 "0x946B","RV770_946B","RV770",1,,,,,"ATI M98"
 "0x947A","RV770_947A","RV770",1,,,,,"ATI M98"
 "0x947B","RV770_947B","RV770",1,,,,,"ATI M98"
+"0x9480","RV730_9480","RV730",1,,,,,"ATI Mobility Radeon HD 4650"
 "0x9487","RV730_9487","RV730",,,,,,"ATI Radeon RV730 (AGP)"
+"0x9488","RV730_9488","RV730",1,,,,,"ATI Mobility Radeon HD 4670"
 "0x9489","RV730_9489","RV730",1,,,,,"ATI FirePro M5750"
 "0x948F","RV730_948F","RV730",,,,,,"ATI Radeon RV730 (AGP)"
 "0x9490","RV730_9490","RV730",,,,,,"ATI RV730XT [Radeon HD 4670]"
diff --git a/src/radeon_chipinfo_gen.h b/src/radeon_chipinfo_gen.h
index 1527a60..bffe88e 100644
--- a/src/radeon_chipinfo_gen.h
+++ b/src/radeon_chipinfo_gen.h
@@ -274,7 +274,9 @@ RADEONCardInfo RADEONCards[] = {
  { 0x946B, CHIP_FAMILY_RV770, 1, 0, 0, 0, 0 },
  { 0x947A, CHIP_FAMILY_RV770, 1, 0, 0, 0, 0 },
  { 0x947B, CHIP_FAMILY_RV770, 1, 0, 0, 0, 0 },
+ { 0x9480, CHIP_FAMILY_RV730, 1, 0, 0, 0, 0 },
  { 0x9487, CHIP_FAMILY_RV730, 0, 0, 0, 0, 0 },
+ { 0x9488, CHIP_FAMILY_RV730, 1, 0, 0, 0, 0 },
  { 0x9489, CHIP_FAMILY_RV730, 1, 0, 0, 0, 0 },
  { 0x948F, CHIP_FAMILY_RV730, 0, 0, 0, 0, 0 },
  { 0x9490, CHIP_FAMILY_RV730, 0, 0, 0, 0, 0 },
diff --git a/src/radeon_chipset_gen.h b/src/radeon_chipset_gen.h
index 3288386..76966bf 100644
--- a/src/radeon_chipset_gen.h
+++ b/src/radeon_chipset_gen.h
@@ -274,7 +274,9 @@ static SymTabRec RADEONChipsets[] = {
   { PCI_CHIP_RV770_946B, "ATI M98" },
   { PCI_CHIP_RV770_947A, "ATI M98" },
   { PCI_CHIP_RV770_947B, "ATI M98" },
+  { PCI_CHIP_RV730_9480, "ATI Mobility Radeon HD 4650" },
   { PCI_CHIP_RV730_9487, "ATI Radeon RV730 (AGP)" },
+  { PCI_CHIP_RV730_9488, "ATI Mobility Radeon HD 4670" },
   { PCI_CHIP_RV730_9489, "ATI FirePro M5750" },
   { PCI_CHIP_RV730_948F, "ATI Radeon RV730 (AGP)" },
   { PCI_CHIP_RV730_9490, "ATI RV730XT [Radeon HD 4670]" },
diff --git a/src/radeon_pci_chipset_gen.h b/src/radeon_pci_chipset_gen.h
index 0a48ad7..4995b4b 100644
--- a/src/radeon_pci_chipset_gen.h
+++ b/src/radeon_pci_chipset_gen.h
@@ -274,7 +274,9 @@ PciChipsets RADEONPciChipsets[] = {
  { PCI_CHIP_RV770_946B, PCI_CHIP_RV770_946B, RES_SHARED_VGA },
  { PCI_CHIP_RV770_947A, PCI_CHIP_RV770_947A, RES_SHARED_VGA },
  { PCI_CHIP_RV770_947B, PCI_CHIP_RV770_947B, RES_SHARED_VGA },
+ { PCI_CHIP_RV730_9480, PCI_CHIP_RV730_9480, RES_SHARED_VGA },
  { PCI_CHIP_RV730_9487, PCI_CHIP_RV730_9487, RES_SHARED_VGA },
+ { PCI_CHIP_RV730_9488, PCI_CHIP_RV730_9488, RES_SHARED_VGA },
  { PCI_CHIP_RV730_9489, PCI_CHIP_RV730_9489, RES_SHARED_VGA },
  { PCI_CHIP_RV730_948F, PCI_CHIP_RV730_948F, RES_SHARED_VGA },
  { PCI_CHIP_RV730_9490, PCI_CHIP_RV730_9490, RES_SHARED_VGA },
diff --git a/src/radeon_pci_device_match_gen.h b/src/radeon_pci_device_match_gen.h
index f3fd3d9..b087239 100644
--- a/src/radeon_pci_device_match_gen.h
+++ b/src/radeon_pci_device_match_gen.h
@@ -274,7 +274,9 @@ static const struct pci_id_match radeon_device_match[] = {
  ATI_DEVICE_MATCH( PCI_CHIP_RV770_946B, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV770_947A, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV770_947B, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV730_9480, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_9487, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV730_9488, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_9489, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_948F, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV730_9490, 0 ),
commit 06d5d8d7fd92b58b2467c782e57a80a3520a2c90
Author: Adam Jackson <ajax at redhat.com>
Date:   Thu Jun 25 13:51:36 2009 -0400

    Add a (harmlessly) missing break statement.

diff --git a/src/radeon_output.c b/src/radeon_output.c
index 40c0699..62edd05 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -254,6 +254,7 @@ radeon_ddc_connected(xf86OutputPtr output)
 	     * or AUXCH.
 	     */
 	    MonType = MT_DFP;
+	    break;
 	case CONNECTOR_HDMI_TYPE_B:
 	case CONNECTOR_DVI_I:
 	    if (monitor_is_digital(MonInfo))
commit 7d1d968fdc8de1e0ab0be916a1f3a4a398af47aa
Author: Adam Jackson <ajax at redhat.com>
Date:   Thu Jun 25 13:49:18 2009 -0400

    Cosmetic cleanup to digital output detection
    
    No functional change, but this logic would need extending anyway for
    DisplayID, so unify it now.

diff --git a/src/radeon_output.c b/src/radeon_output.c
index e307bf0..40c0699 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -209,6 +209,12 @@ radeon_set_active_device(xf86OutputPtr output)
     }
 }
 
+static Bool
+monitor_is_digital(xf86MonPtr MonInfo)
+{
+    return (MonInfo->rawData[0x14] & 0x80) != 0;
+}
+
 static RADEONMonitorType
 radeon_ddc_connected(xf86OutputPtr output)
 {
@@ -235,7 +241,7 @@ radeon_ddc_connected(xf86OutputPtr output)
 	case CONNECTOR_DVI_D:
 	case CONNECTOR_HDMI_TYPE_A:
 	    if (radeon_output->shared_ddc) {
-		if (MonInfo->rawData[0x14] & 0x80) /* if it's digital and DVI/HDMI/etc. */
+		if (monitor_is_digital(MonInfo))
 		    MonType = MT_DFP;
 		else
 		    MonType = MT_NONE;
@@ -250,7 +256,7 @@ radeon_ddc_connected(xf86OutputPtr output)
 	    MonType = MT_DFP;
 	case CONNECTOR_HDMI_TYPE_B:
 	case CONNECTOR_DVI_I:
-	    if (MonInfo->rawData[0x14] & 0x80) /* if it's digital and DVI */
+	    if (monitor_is_digital(MonInfo))
 		MonType = MT_DFP;
 	    else
 		MonType = MT_CRT;
@@ -259,7 +265,7 @@ radeon_ddc_connected(xf86OutputPtr output)
 	case CONNECTOR_DVI_A:
 	default:
 	    if (radeon_output->shared_ddc) {
-		if (MonInfo->rawData[0x14] & 0x80) /* if it's digital and VGA */
+		if (monitor_is_digital(MonInfo))
 		    MonType = MT_NONE;
 		else
 		    MonType = MT_CRT;
commit 96581746eea2f4e29a04f9266ec9649f25480424
Author: Adam Jackson <ajax at redhat.com>
Date:   Wed Jun 24 17:05:47 2009 -0400

    atom: Fix phantom VGA connector when HDMI-B present.
    
    HDMI-B is really a glorified DL-DVI connector, the analog pins work fine.

diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index 6375626..e654228 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -1644,8 +1644,7 @@ static void RADEONApplyATOMQuirks(ScrnInfoPtr pScrn, int index)
     /* some BIOSes seem to report DAC on HDMI - usually this is a board with
      * HDMI + VGA reporting as HDMI
      */
-    if ((info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) ||
-	(info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_B)) {
+    if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) {
 	if (info->BiosConnector[index].devices & (ATOM_DEVICE_CRT_SUPPORT)) {
 	    info->BiosConnector[index].devices &= ~(ATOM_DEVICE_DFP_SUPPORT);
 	    info->BiosConnector[index].ConnectorType = CONNECTOR_VGA;
diff --git a/src/radeon_output.c b/src/radeon_output.c
index e453cc2..e307bf0 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -234,7 +234,6 @@ radeon_ddc_connected(xf86OutputPtr output)
 	    break;
 	case CONNECTOR_DVI_D:
 	case CONNECTOR_HDMI_TYPE_A:
-	case CONNECTOR_HDMI_TYPE_B:
 	    if (radeon_output->shared_ddc) {
 		if (MonInfo->rawData[0x14] & 0x80) /* if it's digital and DVI/HDMI/etc. */
 		    MonType = MT_DFP;
@@ -249,6 +248,7 @@ radeon_ddc_connected(xf86OutputPtr output)
 	     * or AUXCH.
 	     */
 	    MonType = MT_DFP;
+	case CONNECTOR_HDMI_TYPE_B:
 	case CONNECTOR_DVI_I:
 	    if (MonInfo->rawData[0x14] & 0x80) /* if it's digital and DVI */
 		MonType = MT_DFP;
commit 496adc4dc7cf53fc6acfecb1158f1491d5f36168
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Fri Jun 19 14:37:01 2009 +0200

    Revert "Build fixes for -Werror that aren't ready for prime time yet."
    
    This reverts commit ab20ea1530ec8a3a9fd4089775c4e157e50fe1bf.
    
    Whoops, pushed wrong branch...

diff --git a/src/radeon_dga.c b/src/radeon_dga.c
index d61c2ce..6b0fabe 100644
--- a/src/radeon_dga.c
+++ b/src/radeon_dga.c
@@ -161,7 +161,7 @@ SECOND_PASS:
 	    currentMode->yViewportStep  = 1;
 	    currentMode->viewportFlags  = DGA_FLIP_RETRACE;
 	    currentMode->offset         = 0;
-	    currentMode->address        = (unsigned char*)(unsigned long)info->LinearAddr;
+	    currentMode->address        = (unsigned char*)info->LinearAddr;
 	    currentMode->bytesPerScanline = pitch * Bpp;
 	    currentMode->imageWidth     = pitch;
 	    currentMode->imageHeight    = (info->FbMapSize
@@ -457,7 +457,7 @@ static Bool RADEON_OpenFramebuffer(ScrnInfoPtr pScrn,
     RADEONInfoPtr  info = RADEONPTR(pScrn);
 
     *name   = NULL;             /* no special device */
-    *mem    = (unsigned char*)(unsigned long)info->LinearAddr;
+    *mem    = (unsigned char*)info->LinearAddr;
     *size   = info->FbMapSize;
     *offset = 0;
     *flags  = 0; /* DGA_NEED_ROOT; -- don't need root, just /dev/mem access */
diff --git a/src/radeon_dri.c b/src/radeon_dri.c
index cfa5f58..19f7abe 100644
--- a/src/radeon_dri.c
+++ b/src/radeon_dri.c
@@ -1578,7 +1578,7 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen)
     pDRIInfo->ddxDriverMajorVersion      = info->allowColorTiling ? 5 : 4;
     pDRIInfo->ddxDriverMinorVersion      = 3;
     pDRIInfo->ddxDriverPatchVersion      = 0;
-    pDRIInfo->frameBufferPhysicalAddress = (void *)(unsigned long)info->LinearAddr + info->dri->frontOffset;
+    pDRIInfo->frameBufferPhysicalAddress = (void *)info->LinearAddr + info->dri->frontOffset;
     pDRIInfo->frameBufferSize            = info->FbMapSize - info->FbSecureSize;
     pDRIInfo->frameBufferStride          = (pScrn->displayWidth *
 					    info->CurrentLayout.pixel_bytes);
commit ab20ea1530ec8a3a9fd4089775c4e157e50fe1bf
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Sun Jun 14 16:50:07 2009 +0200

    Build fixes for -Werror that aren't ready for prime time yet.

diff --git a/src/radeon_dga.c b/src/radeon_dga.c
index 6b0fabe..d61c2ce 100644
--- a/src/radeon_dga.c
+++ b/src/radeon_dga.c
@@ -161,7 +161,7 @@ SECOND_PASS:
 	    currentMode->yViewportStep  = 1;
 	    currentMode->viewportFlags  = DGA_FLIP_RETRACE;
 	    currentMode->offset         = 0;
-	    currentMode->address        = (unsigned char*)info->LinearAddr;
+	    currentMode->address        = (unsigned char*)(unsigned long)info->LinearAddr;
 	    currentMode->bytesPerScanline = pitch * Bpp;
 	    currentMode->imageWidth     = pitch;
 	    currentMode->imageHeight    = (info->FbMapSize
@@ -457,7 +457,7 @@ static Bool RADEON_OpenFramebuffer(ScrnInfoPtr pScrn,
     RADEONInfoPtr  info = RADEONPTR(pScrn);
 
     *name   = NULL;             /* no special device */
-    *mem    = (unsigned char*)info->LinearAddr;
+    *mem    = (unsigned char*)(unsigned long)info->LinearAddr;
     *size   = info->FbMapSize;
     *offset = 0;
     *flags  = 0; /* DGA_NEED_ROOT; -- don't need root, just /dev/mem access */
diff --git a/src/radeon_dri.c b/src/radeon_dri.c
index 19f7abe..cfa5f58 100644
--- a/src/radeon_dri.c
+++ b/src/radeon_dri.c
@@ -1578,7 +1578,7 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen)
     pDRIInfo->ddxDriverMajorVersion      = info->allowColorTiling ? 5 : 4;
     pDRIInfo->ddxDriverMinorVersion      = 3;
     pDRIInfo->ddxDriverPatchVersion      = 0;
-    pDRIInfo->frameBufferPhysicalAddress = (void *)info->LinearAddr + info->dri->frontOffset;
+    pDRIInfo->frameBufferPhysicalAddress = (void *)(unsigned long)info->LinearAddr + info->dri->frontOffset;
     pDRIInfo->frameBufferSize            = info->FbMapSize - info->FbSecureSize;
     pDRIInfo->frameBufferStride          = (pScrn->displayWidth *
 					    info->CurrentLayout.pixel_bytes);


More information about the xorg-commit mailing list