Blob Blame History Raw
diff --git a/src/AtomBios/CD_Operations.c b/src/AtomBios/CD_Operations.c
index 509aa0c..58c4ae9 100644
--- a/src/AtomBios/CD_Operations.c
+++ b/src/AtomBios/CD_Operations.c
@@ -44,7 +44,6 @@ Revision History:
 #include "xorg-server.h"
 
 #include "Decoder.h"
-#include	"atombios.h"
 
 VOID PutDataRegister(PARSER_TEMP_DATA STACK_BASED * pParserTempData);
 VOID PutDataPS(PARSER_TEMP_DATA STACK_BASED * pParserTempData);
@@ -231,7 +230,7 @@ UINT32 IndirectInputOutput(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
 		IndirectIOParserCommands[*pParserTempData->IndirectIOTablePointer].func(pParserTempData);
 		pParserTempData->IndirectIOTablePointer+=IndirectIOParserCommands[*pParserTempData->IndirectIOTablePointer].csize;
 	    }
-	    pParserTempData->IndirectIOTablePointer-=*(UINT16*)(pParserTempData->IndirectIOTablePointer+1);
+	    pParserTempData->IndirectIOTablePointer-=UINT16LE_TO_CPU(*(UINT16*)(pParserTempData->IndirectIOTablePointer+1));
 	    pParserTempData->IndirectIOTablePointer++;
 	    return pParserTempData->IndirectData;
 	} else pParserTempData->IndirectIOTablePointer+=IndirectIOParserCommands[*pParserTempData->IndirectIOTablePointer].csize;
@@ -243,7 +242,7 @@ UINT32 IndirectInputOutput(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
 
 VOID PutDataRegister(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
 {
-    pParserTempData->Index=(UINT32)pParserTempData->pCmd->Parameters.WordXX.PA_Destination;
+    pParserTempData->Index=(UINT32)UINT16LE_TO_CPU(pParserTempData->pCmd->Parameters.WordXX.PA_Destination);
     pParserTempData->Index+=pParserTempData->CurrentRegBlock;
     switch(pParserTempData->Multipurpose.CurrentPort){
 	case ATI_RegsPort:
@@ -269,16 +268,16 @@ VOID PutDataRegister(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
 VOID PutDataPS(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
 {
     *(pParserTempData->pDeviceData->pParameterSpace+pParserTempData->pCmd->Parameters.ByteXX.PA_Destination)=
-	pParserTempData->DestData32;
+	    CPU_TO_UINT32LE(pParserTempData->DestData32);
 }
 
 VOID PutDataWS(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
 {
     if (pParserTempData->pCmd->Parameters.ByteXX.PA_Destination < WS_QUOTIENT_C)
-	*(pParserTempData->pWorkingTableData->pWorkSpace+pParserTempData->pCmd->Parameters.ByteXX.PA_Destination) = pParserTempData->DestData32;
+      *(pParserTempData->pWorkingTableData->pWorkSpace+pParserTempData->pCmd->Parameters.ByteXX.PA_Destination) = pParserTempData->DestData32;
     else
-	switch (pParserTempData->pCmd->Parameters.ByteXX.PA_Destination)
-	{
+	  switch (pParserTempData->pCmd->Parameters.ByteXX.PA_Destination)
+	  {
 	    case WS_REMINDER_C:
 		pParserTempData->MultiplicationOrDivision.Division.Reminder32=pParserTempData->DestData32;
 		break;
@@ -339,7 +338,7 @@ VOID SkipParameters16(PARSER_TEMP_DATA STACK_BASED *	pParserTempData)
 
 UINT32 GetParametersRegister(PARSER_TEMP_DATA STACK_BASED *	pParserTempData)
 {
-    pParserTempData->Index=*(UINT16*)pParserTempData->pWorkingTableData->IP;
+    pParserTempData->Index=UINT16LE_TO_CPU(*(UINT16*)pParserTempData->pWorkingTableData->IP);
     pParserTempData->pWorkingTableData->IP+=sizeof(UINT16);
     pParserTempData->Index+=pParserTempData->CurrentRegBlock;
     switch(pParserTempData->Multipurpose.CurrentPort)
@@ -361,9 +360,11 @@ UINT32 GetParametersRegister(PARSER_TEMP_DATA STACK_BASED *	pParserTempData)
 
 UINT32 GetParametersPS(PARSER_TEMP_DATA STACK_BASED *	pParserTempData)
 {
+    UINT32 data;
     pParserTempData->Index=*pParserTempData->pWorkingTableData->IP;
     pParserTempData->pWorkingTableData->IP+=sizeof(UINT8);
-    return *(pParserTempData->pDeviceData->pParameterSpace+pParserTempData->Index);
+    data = UINT32LE_TO_CPU(*(pParserTempData->pDeviceData->pParameterSpace+pParserTempData->Index));
+    return data;
 }
 
 UINT32 GetParametersWS(PARSER_TEMP_DATA STACK_BASED *	pParserTempData)
@@ -419,9 +420,12 @@ UINT32 GetParametersMC(PARSER_TEMP_DATA STACK_BASED *	pParserTempData)
 
 UINT32 GetParametersIndirect(PARSER_TEMP_DATA STACK_BASED *	pParserTempData)
 {
-    pParserTempData->Index=*(UINT16*)pParserTempData->pWorkingTableData->IP;
+	  UINT32 ret;
+
+    pParserTempData->Index=UINT16LE_TO_CPU(*(UINT16*)pParserTempData->pWorkingTableData->IP);
     pParserTempData->pWorkingTableData->IP+=sizeof(UINT16);
-    return *(UINT32*)(RELATIVE_TO_BIOS_IMAGE(pParserTempData->Index)+pParserTempData->CurrentDataBlock);
+    ret = UINT32LE_TO_CPU(*(UINT32*)(RELATIVE_TO_BIOS_IMAGE(pParserTempData->Index)+pParserTempData->CurrentDataBlock));
+    return ret;
 }
 
 UINT32 GetParametersDirect8(PARSER_TEMP_DATA STACK_BASED *	pParserTempData)
@@ -435,7 +439,7 @@ UINT32 GetParametersDirect8(PARSER_TEMP_DATA STACK_BASED *	pParserTempData)
 UINT32 GetParametersDirect16(PARSER_TEMP_DATA STACK_BASED *	pParserTempData)
 {
     pParserTempData->CD_Mask.SrcAlignment=alignmentLowerWord;
-    pParserTempData->Index=*(UINT16*)pParserTempData->pWorkingTableData->IP;
+    pParserTempData->Index=UINT16LE_TO_CPU(*(UINT16*)pParserTempData->pWorkingTableData->IP);
     pParserTempData->pWorkingTableData->IP+=sizeof(UINT16);
     return pParserTempData->Index;
 }
@@ -443,7 +447,7 @@ UINT32 GetParametersDirect16(PARSER_TEMP_DATA STACK_BASED *	pParserTempData)
 UINT32 GetParametersDirect32(PARSER_TEMP_DATA STACK_BASED *	pParserTempData)
 {
     pParserTempData->CD_Mask.SrcAlignment=alignmentDword;
-    pParserTempData->Index=*(UINT32*)pParserTempData->pWorkingTableData->IP;
+    pParserTempData->Index=UINT32LE_TO_CPU(*(UINT32*)pParserTempData->pWorkingTableData->IP);
     pParserTempData->pWorkingTableData->IP+=sizeof(UINT32);
     return pParserTempData->Index;
 }
@@ -474,7 +478,7 @@ VOID ProcessMove(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
 {
     if (pParserTempData->CD_Mask.SrcAlignment!=alignmentDword)
     {
-	pParserTempData->DestData32=GetDestination[pParserTempData->ParametersType.Destination](pParserTempData);
+				pParserTempData->DestData32=GetDestination[pParserTempData->ParametersType.Destination](pParserTempData);
     } else
     {
 	SkipDestination[pParserTempData->ParametersType.Destination](pParserTempData);
@@ -664,7 +668,8 @@ VOID ProcessSwitch(PARSER_TEMP_DATA STACK_BASED * pParserTempData){
     pParserTempData->SourceData32=GetSource[pParserTempData->ParametersType.Source](pParserTempData);
     pParserTempData->SourceData32 >>= SourceAlignmentShift[pParserTempData->CD_Mask.SrcAlignment];
     pParserTempData->SourceData32 &= AlignmentMask[pParserTempData->CD_Mask.SrcAlignment];
-    while ( *(UINT16*)pParserTempData->pWorkingTableData->IP != (((UINT16)NOP_OPCODE << 8)+NOP_OPCODE))
+
+    while ( UINT16LE_TO_CPU(*(UINT16*)pParserTempData->pWorkingTableData->IP) != (((UINT16)NOP_OPCODE << 8)+NOP_OPCODE))
     {
 	if (*pParserTempData->pWorkingTableData->IP == 'c')
 	{
@@ -673,7 +678,7 @@ VOID ProcessSwitch(PARSER_TEMP_DATA STACK_BASED * pParserTempData){
 	    pParserTempData->Index=GetParametersDirect16(pParserTempData);
 	    if (pParserTempData->SourceData32 == pParserTempData->DestData32)
 	    {
-		pParserTempData->pWorkingTableData->IP= RELATIVE_TO_TABLE(pParserTempData->Index);
+ 	        pParserTempData->pWorkingTableData->IP= RELATIVE_TO_TABLE(pParserTempData->Index);
 		return;
 	    }
 	}
@@ -695,7 +700,7 @@ VOID	cmdSetDataBlock(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
         } else
 	{
 	    pMasterDataTable = GetDataMasterTablePointer(pParserTempData->pDeviceData);
-	    pParserTempData->CurrentDataBlock= (TABLE_UNIT_TYPE)((PTABLE_UNIT_TYPE)pMasterDataTable)[value];
+	    pParserTempData->CurrentDataBlock= UINT16LE_TO_CPU((TABLE_UNIT_TYPE)((PTABLE_UNIT_TYPE)pMasterDataTable)[value]);
 	}
     }
     pParserTempData->pWorkingTableData->IP+=sizeof(COMMAND_TYPE_OPCODE_VALUE_BYTE);
@@ -704,13 +709,13 @@ VOID	cmdSetDataBlock(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
 VOID	cmdSet_ATI_Port(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
 {
     pParserTempData->Multipurpose.CurrentPort=ATI_RegsPort;
-    pParserTempData->CurrentPortID = (UINT8)((COMMAND_TYPE_1*)pParserTempData->pWorkingTableData->IP)->Parameters.WordXX.PA_Destination;
+    pParserTempData->CurrentPortID = (UINT8)UINT16LE_TO_CPU(((COMMAND_TYPE_1*)pParserTempData->pWorkingTableData->IP)->Parameters.WordXX.PA_Destination);
     pParserTempData->pWorkingTableData->IP+=sizeof(COMMAND_TYPE_OPCODE_OFFSET16);
 }
 
 VOID	cmdSet_Reg_Block(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
 {
-    pParserTempData->CurrentRegBlock = ((COMMAND_TYPE_1*)pParserTempData->pWorkingTableData->IP)->Parameters.WordXX.PA_Destination;
+    pParserTempData->CurrentRegBlock = UINT16LE_TO_CPU(((COMMAND_TYPE_1*)pParserTempData->pWorkingTableData->IP)->Parameters.WordXX.PA_Destination);
     pParserTempData->pWorkingTableData->IP+=sizeof(COMMAND_TYPE_OPCODE_OFFSET16);
 }
 
@@ -754,19 +759,23 @@ VOID ProcessDebug(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
 
 VOID ProcessDS(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
 {
-    pParserTempData->pWorkingTableData->IP+=((COMMAND_TYPE_1*)pParserTempData->pWorkingTableData->IP)->Parameters.WordXX.PA_Destination+sizeof(COMMAND_TYPE_OPCODE_OFFSET16);
+    pParserTempData->pWorkingTableData->IP+=UINT16LE_TO_CPU(((COMMAND_TYPE_1*)pParserTempData->pWorkingTableData->IP)->Parameters.WordXX.PA_Destination)+sizeof(COMMAND_TYPE_OPCODE_OFFSET16);
 }
 
 
-VOID	cmdCall_Table(PARSER_TEMP_DATA STACK_BASED * pParserTempData){
+VOID	cmdCall_Table(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
+{
     UINT16*	MasterTableOffset;
     pParserTempData->pWorkingTableData->IP+=sizeof(COMMAND_TYPE_OPCODE_VALUE_BYTE);
     MasterTableOffset = GetCommandMasterTablePointer(pParserTempData->pDeviceData);
     if(((PTABLE_UNIT_TYPE)MasterTableOffset)[((COMMAND_TYPE_OPCODE_VALUE_BYTE*)pParserTempData->pCmd)->Value]!=0 )  // if the offset is not ZERO
     {
+	ATOM_TABLE_ATTRIBUTE lTableAttr;
+
 	pParserTempData->CommandSpecific.IndexInMasterTable=GetTrueIndexInMasterTable(pParserTempData,((COMMAND_TYPE_OPCODE_VALUE_BYTE*)pParserTempData->pCmd)->Value);
-	pParserTempData->Multipurpose.PS_SizeInDwordsUsedByCallingTable =
-	    (((ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *)pParserTempData->pWorkingTableData->pTableHead)->TableAttribute.PS_SizeInBytes>>2);
+
+	lTableAttr = GetCommandTableAttribute(pParserTempData->pWorkingTableData->pTableHead);
+	pParserTempData->Multipurpose.PS_SizeInDwordsUsedByCallingTable = (lTableAttr.PS_SizeInBytes >>2);
 	pParserTempData->pDeviceData->pParameterSpace+=
 	    pParserTempData->Multipurpose.PS_SizeInDwordsUsedByCallingTable;
 	pParserTempData->Status=CD_CALL_TABLE;
@@ -792,7 +801,7 @@ VOID ProcessJump(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
 	(pParserTempData->ParametersType.Destination == pParserTempData->CompareFlags ))
     {
 
-	pParserTempData->pWorkingTableData->IP= RELATIVE_TO_TABLE(((COMMAND_TYPE_OPCODE_OFFSET16*)pParserTempData->pWorkingTableData->IP)->CD_Offset16);
+      pParserTempData->pWorkingTableData->IP= RELATIVE_TO_TABLE(UINT16LE_TO_CPU(((COMMAND_TYPE_OPCODE_OFFSET16*)pParserTempData->pWorkingTableData->IP)->CD_Offset16));
     } else
     {
 	pParserTempData->pWorkingTableData->IP+=sizeof(COMMAND_TYPE_OPCODE_OFFSET16);
@@ -805,7 +814,7 @@ VOID ProcessJumpE(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
 	(pParserTempData->CompareFlags == pParserTempData->ParametersType.Destination))
     {
 
-	pParserTempData->pWorkingTableData->IP= RELATIVE_TO_TABLE(((COMMAND_TYPE_OPCODE_OFFSET16*)pParserTempData->pWorkingTableData->IP)->CD_Offset16);
+      pParserTempData->pWorkingTableData->IP= RELATIVE_TO_TABLE(UINT16LE_TO_CPU(((COMMAND_TYPE_OPCODE_OFFSET16*)pParserTempData->pWorkingTableData->IP)->CD_Offset16));
     } else
     {
 	pParserTempData->pWorkingTableData->IP+=sizeof(COMMAND_TYPE_OPCODE_OFFSET16);
@@ -817,7 +826,7 @@ VOID ProcessJumpNE(PARSER_TEMP_DATA STACK_BASED * pParserTempData)
     if (pParserTempData->CompareFlags != Equal)
     {
 
-	pParserTempData->pWorkingTableData->IP= RELATIVE_TO_TABLE(((COMMAND_TYPE_OPCODE_OFFSET16*)pParserTempData->pWorkingTableData->IP)->CD_Offset16);
+      pParserTempData->pWorkingTableData->IP= RELATIVE_TO_TABLE(UINT16LE_TO_CPU(((COMMAND_TYPE_OPCODE_OFFSET16*)pParserTempData->pWorkingTableData->IP)->CD_Offset16));
     } else
     {
 	pParserTempData->pWorkingTableData->IP+=sizeof(COMMAND_TYPE_OPCODE_OFFSET16);
diff --git a/src/AtomBios/Decoder.c b/src/AtomBios/Decoder.c
index e8b3b6e..73aac94 100644
--- a/src/AtomBios/Decoder.c
+++ b/src/AtomBios/Decoder.c
@@ -40,12 +40,9 @@ Revision History:
 #endif
 
 #include <X11/Xos.h>
-
+#include "xorg-server.h"
 
 #include "Decoder.h"
-#include "atombios.h"
-#include "CD_binding.h"
-#include "CD_Common_Types.h"
 
 #ifndef DISABLE_EASF
 	#include "easf.h"
@@ -77,13 +74,13 @@ UINT16* GetCommandMasterTablePointer(DEVICE_DATA STACK_BASED*  pDeviceData)
     /*
     make MasterTableOffset point to EASF_ASIC_SETUP_TABLE structure, including usSize.
     */
-		MasterTableOffset = (UINT16 *) (pDeviceData->pBIOS_Image+((EASF_ASIC_DESCRIPTOR*)pDeviceData->pBIOS_Image)->usAsicSetupTable_Offset);
+		MasterTableOffset = (UINT16 *) (pDeviceData->pBIOS_Image+(UINT16LE_TO_CPU(((EASF_ASIC_DESCRIPTOR*)pDeviceData->pBIOS_Image)->usAsicSetupTable_Offset));
 	} else
 #endif
 	{
 #ifndef		UEFI_BUILD
-		MasterTableOffset = (UINT16 *)(*(UINT16 *)(pDeviceData->pBIOS_Image+OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER) + pDeviceData->pBIOS_Image);
-		MasterTableOffset = (UINT16 *)((ULONG)((ATOM_ROM_HEADER *)MasterTableOffset)->usMasterCommandTableOffset + pDeviceData->pBIOS_Image );
+		MasterTableOffset = (UINT16 *)(UINT16LE_TO_CPU(*(UINT16 *)(pDeviceData->pBIOS_Image+OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER)) + pDeviceData->pBIOS_Image);
+		MasterTableOffset = (UINT16 *)((ULONG)UINT16LE_TO_CPU(((ATOM_ROM_HEADER *)MasterTableOffset)->usMasterCommandTableOffset) + pDeviceData->pBIOS_Image );
 		MasterTableOffset =(UINT16 *) &(((ATOM_MASTER_COMMAND_TABLE *)MasterTableOffset)->ListOfCommandTables);
 #else
 	MasterTableOffset = (UINT16 *)(&(GetCommandMasterTable( )->ListOfCommandTables));
@@ -97,8 +94,8 @@ UINT16* GetDataMasterTablePointer(DEVICE_DATA STACK_BASED*  pDeviceData)
 	UINT16		*MasterTableOffset;
 	
 #ifndef		UEFI_BUILD
-	MasterTableOffset = (UINT16 *)(*(UINT16 *)(pDeviceData->pBIOS_Image+OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER) + pDeviceData->pBIOS_Image);
-	MasterTableOffset = (UINT16 *)((ULONG)((ATOM_ROM_HEADER *)MasterTableOffset)->usMasterDataTableOffset + pDeviceData->pBIOS_Image );
+	MasterTableOffset = (UINT16 *)(UINT16LE_TO_CPU(*(UINT16 *)(pDeviceData->pBIOS_Image+OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER)) + pDeviceData->pBIOS_Image);
+	MasterTableOffset = (UINT16 *)((ULONG)(UINT16LE_TO_CPU(((ATOM_ROM_HEADER *)MasterTableOffset)->usMasterDataTableOffset)) + pDeviceData->pBIOS_Image );
 	MasterTableOffset =(UINT16 *) &(((ATOM_MASTER_DATA_TABLE *)MasterTableOffset)->ListOfDataTables);
 #else
 	MasterTableOffset = (UINT16 *)(&(GetDataMasterTable( )->ListOfDataTables));
@@ -129,11 +126,29 @@ UINT8 GetTrueIndexInMasterTable(PARSER_TEMP_DATA STACK_BASED * pParserTempData,
 	}
 }
 
+ATOM_TABLE_ATTRIBUTE GetCommandTableAttribute(UINT8 *pTableHeader)
+{
+  ATOM_TABLE_ATTRIBUTE_ACCESS lTableAccess;
+
+  /* It's unclear whether this union trick breaks C aliasing rules,
+   * however, it's explicitely permitted by gcc, and we have other
+   * case where the code relies on a union being accessed by either
+   * of the "ways" and stay consistent so if a compiler breaks this
+   * assumption, it will probably need us to compile without strict
+   * aliasing enforcement
+	 */
+	lTableAccess.sbfAccess = ((ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *)pTableHeader)->TableAttribute;
+	lTableAccess.susAccess = UINT16LE_TO_CPU(lTableAccess.susAccess);
+
+	return lTableAccess.sbfAccess;
+}
+
 CD_STATUS ParseTable(DEVICE_DATA STACK_BASED* pDeviceData, UINT8 IndexInMasterTable)
 {
 	PARSER_TEMP_DATA	ParserTempData;
   WORKING_TABLE_DATA STACK_BASED* prevWorkingTableData;
 
+  memset(&ParserTempData, 0, sizeof(PARSER_TEMP_DATA));
   ParserTempData.pDeviceData=(DEVICE_DATA*)pDeviceData;
 #ifndef DISABLE_EASF
   if (pDeviceData->format == TABLE_FORMAT_EASF)
@@ -143,7 +158,7 @@ CD_STATUS ParseTable(DEVICE_DATA STACK_BASED* pDeviceData, UINT8 IndexInMasterTa
 #endif
   {
     ParserTempData.pCmd=(GENERIC_ATTRIBUTE_COMMAND*)GetDataMasterTablePointer(pDeviceData);
-    ParserTempData.IndirectIOTablePointer=(UINT8*)((ULONG)(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[INDIRECT_IO_TABLE]) + pDeviceData->pBIOS_Image);
+    ParserTempData.IndirectIOTablePointer=(UINT8*)((ULONG)(UINT16LE_TO_CPU(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[INDIRECT_IO_TABLE])) + pDeviceData->pBIOS_Image);
     ParserTempData.IndirectIOTablePointer+=sizeof(ATOM_COMMON_TABLE_HEADER);
   }
 
@@ -160,65 +175,66 @@ CD_STATUS ParseTable(DEVICE_DATA STACK_BASED* pDeviceData, UINT8 IndexInMasterTa
 		ParserTempData.Status=CD_CALL_TABLE;
 
 		do{
-
+			
 			if (ParserTempData.Status==CD_CALL_TABLE)
-      {
+			{
 				IndexInMasterTable=ParserTempData.CommandSpecific.IndexInMasterTable;
 				if(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]!=0)  // if the offset is not ZERO
-					{
+				{
+				  ATOM_TABLE_ATTRIBUTE lTableAttr;
+				  lTableAttr = GetCommandTableAttribute(UINT16LE_TO_CPU(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable])+pDeviceData->pBIOS_Image);
 #ifndef		UEFI_BUILD
   					ParserTempData.pWorkingTableData =(WORKING_TABLE_DATA STACK_BASED*) AllocateWorkSpace(pDeviceData,
-								((ATOM_COMMON_ROM_COMMAND_TABLE_HEADER*)(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]+pDeviceData->pBIOS_Image))->TableAttribute.WS_SizeInBytes+sizeof(WORKING_TABLE_DATA));
+															      lTableAttr.WS_SizeInBytes+sizeof(WORKING_TABLE_DATA));
 #else
-  					ParserTempData.pWorkingTableData =(WORKING_TABLE_DATA STACK_BASED*) AllocateWorkSpace(pDeviceData,
-								((ATOM_COMMON_ROM_COMMAND_TABLE_HEADER*)(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]))->TableAttribute.WS_SizeInBytes+sizeof(WORKING_TABLE_DATA));
+				  ParserTempData.pWorkingTableData =(WORKING_TABLE_DATA STACK_BASED*) AllocateWorkSpace(pDeviceData,
+															lTableAttr.WS_SizeInBytes+sizeof(WORKING_TABLE_DATA));
 #endif
-            if (ParserTempData.pWorkingTableData!=NULL)
-            {
-						  ParserTempData.pWorkingTableData->pWorkSpace=(WORKSPACE_POINTER STACK_BASED*)((UINT8*)ParserTempData.pWorkingTableData+sizeof(WORKING_TABLE_DATA));
+					if (ParserTempData.pWorkingTableData!=NULL)
+					{
+						ParserTempData.pWorkingTableData->pWorkSpace=(WORKSPACE_POINTER STACK_BASED*)((UINT8*)ParserTempData.pWorkingTableData+sizeof(WORKING_TABLE_DATA));
 #ifndef		UEFI_BUILD
-						  ParserTempData.pWorkingTableData->pTableHead  = (UINT8 *)(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]+pDeviceData->pBIOS_Image);
+				      ParserTempData.pWorkingTableData->pTableHead  = (UINT8 *)(UINT16LE_TO_CPU(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable])+pDeviceData->pBIOS_Image);
 #else
-						  ParserTempData.pWorkingTableData->pTableHead  = (UINT8 *)(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]);
+				      ParserTempData.pWorkingTableData->pTableHead  = (UINT8 *)(UINT16LE_TO_CPU(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]));
 #endif
-	 					  ParserTempData.pWorkingTableData->IP=((UINT8*)ParserTempData.pWorkingTableData->pTableHead)+sizeof(ATOM_COMMON_ROM_COMMAND_TABLE_HEADER);
-              ParserTempData.pWorkingTableData->prevWorkingTableData=prevWorkingTableData;
-              prevWorkingTableData=ParserTempData.pWorkingTableData;
-              ParserTempData.Status = CD_SUCCESS;
-            } else ParserTempData.Status = CD_UNEXPECTED_BEHAVIOR;
-					} else ParserTempData.Status = CD_EXEC_TABLE_NOT_FOUND;
+						ParserTempData.pWorkingTableData->IP=((UINT8*)ParserTempData.pWorkingTableData->pTableHead)+sizeof(ATOM_COMMON_ROM_COMMAND_TABLE_HEADER);
+						ParserTempData.pWorkingTableData->prevWorkingTableData=prevWorkingTableData;
+						prevWorkingTableData=ParserTempData.pWorkingTableData;
+						ParserTempData.Status = CD_SUCCESS;
+					} else ParserTempData.Status = CD_UNEXPECTED_BEHAVIOR;
+				} else ParserTempData.Status = CD_EXEC_TABLE_NOT_FOUND;
 			}
 			if (!CD_ERROR(ParserTempData.Status))
 			{
-        ParserTempData.Status = CD_SUCCESS;
+				ParserTempData.Status = CD_SUCCESS;
 				while (!CD_ERROR_OR_COMPLETED(ParserTempData.Status))  
-        {
-
+				{
 					if (IS_COMMAND_VALID(((COMMAND_HEADER*)ParserTempData.pWorkingTableData->IP)->Opcode))
-          {
+					{
 						ParserTempData.pCmd = (GENERIC_ATTRIBUTE_COMMAND*)ParserTempData.pWorkingTableData->IP;
-
+						
 						if (IS_END_OF_TABLE(((COMMAND_HEADER*)ParserTempData.pWorkingTableData->IP)->Opcode))
 						{
 							ParserTempData.Status=CD_COMPLETED;
-              prevWorkingTableData=ParserTempData.pWorkingTableData->prevWorkingTableData;
-
+							prevWorkingTableData=ParserTempData.pWorkingTableData->prevWorkingTableData;
+							
 							FreeWorkSpace(pDeviceData, ParserTempData.pWorkingTableData);
-              ParserTempData.pWorkingTableData=prevWorkingTableData;
-              if (prevWorkingTableData!=NULL)
-              {
-							  ParserTempData.pDeviceData->pParameterSpace-=
-								  		(((ATOM_COMMON_ROM_COMMAND_TABLE_HEADER*)ParserTempData.pWorkingTableData->
-									  		pTableHead)->TableAttribute.PS_SizeInBytes>>2);
-              } 
-						// if there is a parent table where to return, then restore PS_pointer to the original state
+							ParserTempData.pWorkingTableData=prevWorkingTableData;
+							if (prevWorkingTableData!=NULL)
+							{
+								ATOM_TABLE_ATTRIBUTE lTableAttr;
+								lTableAttr = GetCommandTableAttribute(ParserTempData.pWorkingTableData->pTableHead);
+								ParserTempData.pDeviceData->pParameterSpace-=(lTableAttr.PS_SizeInBytes>>2);
+							} 
+							// if there is a parent table where to return, then restore PS_pointer to the original state
 						}
 						else
 						{
-              IndexInMasterTable=ProcessCommandProperties((PARSER_TEMP_DATA STACK_BASED *)&ParserTempData);
+							IndexInMasterTable=ProcessCommandProperties((PARSER_TEMP_DATA STACK_BASED *)&ParserTempData);
 							(*CallTable[IndexInMasterTable].function)((PARSER_TEMP_DATA STACK_BASED *)&ParserTempData);
 #if (PARSER_TYPE!=DRIVER_TYPE_PARSER)
-              BIOS_STACK_MODIFIER();
+							BIOS_STACK_MODIFIER();
 #endif
 						}
 					}
@@ -227,13 +243,13 @@ CD_STATUS ParseTable(DEVICE_DATA STACK_BASED* pDeviceData, UINT8 IndexInMasterTa
 						ParserTempData.Status=CD_INVALID_OPCODE;
 						break;
 					}
-
+					
 				}	// while
 			}	// if
 			else
 				break;
 		} while (prevWorkingTableData!=NULL);
-    if (ParserTempData.Status == CD_COMPLETED) return CD_SUCCESS;
+		if (ParserTempData.Status == CD_COMPLETED) return CD_SUCCESS;
 		return ParserTempData.Status;
 	} else return CD_SUCCESS;
 }
diff --git a/src/AtomBios/hwserv_drv.c b/src/AtomBios/hwserv_drv.c
index a5f5a5b..9f2b6b9 100644
--- a/src/AtomBios/hwserv_drv.c
+++ b/src/AtomBios/hwserv_drv.c
@@ -34,8 +34,14 @@ Revision History:
 
 	NEG:27.09.2002	Initiated.
 --*/
-#include "CD_binding.h"
-#include "CD_hw_services.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <X11/Xos.h>
+#include "xorg-server.h"
+
+#include "Decoder.h"
 
 //trace settings
 #if DEBUG_OUTPUT_DEVICE & 1
@@ -249,12 +255,12 @@ VOID	WriteReg32(PARSER_TEMP_DATA STACK_BASED * pWorkingTableData)
 
 VOID	ReadIndReg32 (PARSER_TEMP_DATA STACK_BASED * pWorkingTableData)
 {
-    pWorkingTableData->IndirectData = CailReadATIRegister(pWorkingTableData->pDeviceData->CAIL,*(UINT16*)(pWorkingTableData->IndirectIOTablePointer+1));
+    pWorkingTableData->IndirectData = CailReadATIRegister(pWorkingTableData->pDeviceData->CAIL,UINT16LE_TO_CPU(*(UINT16*)(pWorkingTableData->IndirectIOTablePointer+1)));
 }
 
 VOID	WriteIndReg32(PARSER_TEMP_DATA STACK_BASED * pWorkingTableData)
 {
-    CailWriteATIRegister(pWorkingTableData->pDeviceData->CAIL,*(UINT16*)(pWorkingTableData->IndirectIOTablePointer+1),pWorkingTableData->IndirectData );
+    CailWriteATIRegister(pWorkingTableData->pDeviceData->CAIL,UINT16LE_TO_CPU(*(UINT16*)(pWorkingTableData->IndirectIOTablePointer+1)),pWorkingTableData->IndirectData);
 }
 
 #endif
diff --git a/src/AtomBios/includes/CD_Common_Types.h b/src/AtomBios/includes/CD_Common_Types.h
index c60b652..071b8fd 100644
--- a/src/AtomBios/includes/CD_Common_Types.h
+++ b/src/AtomBios/includes/CD_Common_Types.h
@@ -155,6 +155,18 @@ typedef unsigned long ULONG_PTR;
 #ifndef FGL_LINUX
 #pragma warning ( default : 4142 )
 #endif
+
+#ifndef ATOM_BIG_ENDIAN
+#ifdef X_BYTE_ORDER
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+#define ATOM_BIG_ENDIAN		1
+#endif
+#endif
+#endif
+#ifndef ATOM_BIG_ENDIAN
+#define ATOM_BIG_ENDIAN		0
+#endif
+
 #endif // _COMMON_TYPES_H_
 
 // EOF
diff --git a/src/AtomBios/includes/CD_Definitions.h b/src/AtomBios/includes/CD_Definitions.h
index 98fd495..c00e93e 100644
--- a/src/AtomBios/includes/CD_Definitions.h
+++ b/src/AtomBios/includes/CD_Definitions.h
@@ -39,11 +39,12 @@ NEG:27.08.2002	Initiated.
 #ifndef _CD_DEFINITIONS_H
 #define _CD_DEFINITIONS_H_
 #ifdef DRIVER_PARSER
-VOID *AllocateMemory(VOID *, UINT16);
+VOID *AllocateMemory(DEVICE_DATA *, UINT16);
 VOID ReleaseMemory(DEVICE_DATA * , WORKING_TABLE_DATA* );
 #endif
 CD_STATUS ParseTable(DEVICE_DATA* pDeviceData, UINT8 IndexInMasterTable);
 //CD_STATUS CD_MainLoop(PARSER_TEMP_DATA_POINTER pParserTempData);
 CD_STATUS Main_Loop(DEVICE_DATA* pDeviceData,UINT16 *MasterTableOffset,UINT8 IndexInMasterTable);
 UINT16* GetCommandMasterTablePointer(DEVICE_DATA*  pDeviceData);
+ATOM_TABLE_ATTRIBUTE GetCommandTableAttribute(UINT8 *pTableHeader);
 #endif //CD_DEFINITIONS
diff --git a/src/AtomBios/includes/CD_Structs.h b/src/AtomBios/includes/CD_Structs.h
index c43f81d..01fb80e 100644
--- a/src/AtomBios/includes/CD_Structs.h
+++ b/src/AtomBios/includes/CD_Structs.h
@@ -35,10 +35,18 @@ Revision History:
 NEG:26.08.2002	Initiated.
 --*/
 
-#include "CD_binding.h"
 #ifndef _CD_STRUCTS_H_
 #define _CD_STRUCTS_H_
 
+#include "CD_binding.h"
+
+/* Endaianness should be specified before inclusion,
+ * default to little endian
+ */
+#ifndef ATOM_BIG_ENDIAN
+#error Endian not specified
+#endif
+
 #ifdef		UEFI_BUILD
 typedef	UINT16**	PTABLE_UNIT_TYPE;
 typedef	UINTN		TABLE_UNIT_TYPE;
@@ -304,9 +312,15 @@ typedef union _PARAMETER_ACCESS {
 }PARAMETER_ACCESS;
 
 typedef	struct _COMMAND_ATTRIBUTE {
+#if ATOM_BIG_ENDIAN
+    UINT8		DestinationAlignment:2;
+    UINT8		SourceAlignment:3;
+    UINT8		Source:3;
+#else
     UINT8		Source:3;
     UINT8		SourceAlignment:3;
     UINT8		DestinationAlignment:2;
+#endif
 }COMMAND_ATTRIBUTE;
 
 typedef struct _SOURCE_DESTINATION_ALIGNMENT{
@@ -363,11 +377,19 @@ typedef union  _COMMAND_SPECIFIC_UNION{
 
 
 typedef struct _CD_GENERIC_BYTE{
+#if ATOM_BIG_ENDIAN
+    UINT16					PS_SizeInDwordsUsedByCallingTable:5;
+    UINT16					CurrentPort:2;
+    UINT16					CommandAccessType:3;
+    UINT16					CurrentParameterSize:3;
+    UINT16					CommandType:3;
+#else
     UINT16					CommandType:3;
     UINT16					CurrentParameterSize:3;
     UINT16					CommandAccessType:3;
     UINT16					CurrentPort:2;
     UINT16					PS_SizeInDwordsUsedByCallingTable:5;
+#endif
 }CD_GENERIC_BYTE;
 
 typedef UINT8	COMMAND_TYPE_OPCODE_ONLY;
diff --git a/src/AtomBios/includes/Decoder.h b/src/AtomBios/includes/Decoder.h
index 24c25fc..1e143f0 100644
--- a/src/AtomBios/includes/Decoder.h
+++ b/src/AtomBios/includes/Decoder.h
@@ -47,12 +47,32 @@ NEG:27.08.2002	Initiated.
 #define PARSER_VERSION_MAJOR                   0x00000000
 #define PARSER_VERSION_MINOR                   0x0000000E
 #define PARSER_VERSION                         (PARSER_VERSION_MAJOR | PARSER_VERSION_MINOR)
-#include "CD_binding.h"
+
 #include "CD_Common_Types.h"
+
+#include "atombios.h"
+
+/* these depends on some struct defined in atombios.h */
+#include "CD_binding.h"
 #include "CD_hw_services.h"
 #include "CD_Structs.h"
-#include "CD_Definitions.h"
 #include "CD_Opcodes.h"
+#include "CD_Definitions.h"
+
+#if ATOM_BIG_ENDIAN
+extern UINT16 ATOM_BSWAP16(UINT16 x);
+extern UINT32 ATOM_BSWAP32(UINT32 x);
+
+#define CPU_TO_UINT16LE(x)	ATOM_BSWAP16(x)
+#define CPU_TO_UINT32LE(x)	ATOM_BSWAP32(x)
+#define UINT16LE_TO_CPU(x)	ATOM_BSWAP16(x)
+#define UINT32LE_TO_CPU(x)	ATOM_BSWAP32(x)
+#else
+#define CPU_TO_UINT16LE(x)	(x)
+#define CPU_TO_UINT32LE(x)	(x)
+#define UINT16LE_TO_CPU(x)	(x)
+#define UINT32LE_TO_CPU(x)	(x)
+#endif
 
 #define	SOURCE_ONLY_CMD_TYPE		0//0xFE
 #define SOURCE_DESTINATION_CMD_TYPE	1//0xFD
diff --git a/src/AtomBios/includes/atombios.h b/src/AtomBios/includes/atombios.h
index 17483a6..2e7dc6c 100644
--- a/src/AtomBios/includes/atombios.h
+++ b/src/AtomBios/includes/atombios.h
@@ -34,6 +34,12 @@
 
 #define ATOM_HEADER_VERSION (ATOM_VERSION_MAJOR | ATOM_VERSION_MINOR)
 
+/* Endianness should be specified before inclusion,
+ * default to little endian
+ */
+#ifndef ATOM_BIG_ENDIAN
+#error Endian not specified
+#endif
 
 #ifdef _H2INC
   #ifndef ULONG 
@@ -304,7 +310,7 @@ typedef struct _ATOM_MASTER_COMMAND_TABLE
 
 typedef struct _ATOM_TABLE_ATTRIBUTE
 {
-#if X_BYTE_ORDER == X_BIG_ENDIAN
+#if ATOM_BIG_ENDIAN
   USHORT  UpdatedByUtility:1;         //[15]=Table updated by utility flag
   USHORT  PS_SizeInBytes:7;           //[14:8]=Size of parameter space in Bytes (multiple of a dword), 
   USHORT  WS_SizeInBytes:8;           //[7:0]=Size of workspace in Bytes (in multiple of a dword), 
@@ -315,6 +321,12 @@ typedef struct _ATOM_TABLE_ATTRIBUTE
 #endif
 }ATOM_TABLE_ATTRIBUTE;
 
+typedef union _ATOM_TABLE_ATTRIBUTE_ACCESS
+{
+  ATOM_TABLE_ATTRIBUTE sbfAccess;
+  USHORT               susAccess;
+}ATOM_TABLE_ATTRIBUTE_ACCESS;
+
 // Common header for all command tables.
 //Every table pointed by _ATOM_MASTER_COMMAND_TABLE has this common header. 
 //And the pointer actually points to this header.
@@ -1258,7 +1270,7 @@ typedef struct _ATOM_MULTIMEDIA_CONFIG_INFO
 //Please don't add or expand this bitfield structure below, this one will retire soon.!
 typedef struct _ATOM_FIRMWARE_CAPABILITY
 {
-#if X_BYTE_ORDER == X_BIG_ENDIAN
+#if ATOM_BIG_ENDIAN
   USHORT Reserved:3;
   USHORT HyperMemory_Size:4;
   USHORT HyperMemory_Support:1;
@@ -1767,7 +1779,7 @@ for Griffin or Greyhound. SBIOS needs to convert to actual time by:
 
 typedef struct _ATOM_I2C_ID_CONFIG
 {
-#if X_BYTE_ORDER == X_BIG_ENDIAN
+#if ATOM_BIG_ENDIAN
   UCHAR   bfHW_Capable:1;
   UCHAR   bfHW_EngineID:3;
   UCHAR   bfI2C_LineMux:4;
@@ -1820,7 +1832,7 @@ typedef struct _ATOM_GPIO_I2C_INFO
 //Please don't add or expand this bitfield structure below, this one will retire soon.!
 typedef struct _ATOM_MODE_MISC_INFO
 { 
-#if X_BYTE_ORDER == X_BIG_ENDIAN
+#if ATOM_BIG_ENDIAN
   USHORT Reserved:6;
   USHORT RGB888:1;
   USHORT DoubleClock:1;
@@ -3426,7 +3438,7 @@ typedef struct _ATOM_MEMORY_VENDOR_BLOCK{
 
 
 typedef struct _ATOM_MEMORY_SETTING_ID_CONFIG{
-#if X_BYTE_ORDER == X_BIG_ENDIAN
+#if ATOM_BIG_ENDIAN
 	ULONG												ucMemBlkId:8;
 	ULONG												ulMemClockRange:24;
 #else
@@ -4072,7 +4084,7 @@ typedef struct  _COMPASSIONATE_DATA
 
 typedef struct _ATOM_CONNECTOR_INFO
 {
-#if X_BYTE_ORDER == X_BIG_ENDIAN
+#if ATOM_BIG_ENDIAN
   UCHAR   bfConnectorType:4;
   UCHAR   bfAssociatedDAC:4;
 #else
diff --git a/src/Makefile.am b/src/Makefile.am
index 5333495..97c686b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -26,8 +26,11 @@
 # _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 =
+
 if DRI
 RADEON_DRI_SRCS = radeon_dri.c
+radeon_drv_la_LIBADD += $(DRI_LIBS)
 endif
 
 RADEON_ATOMBIOS_SOURCES = \
@@ -70,6 +73,11 @@ AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ @XMODES_CFLAGS@ -DDISABLE_EASF -DENABLE_A
 
 INCLUDES = -I$(srcdir)/AtomBios/includes
 
+if XSERVER_LIBPCIACCESS
+ati_drv_la_LIBADD = $(PCIACCESS_LIBS)
+radeon_drv_la_LIBADD += $(PCIACCESS_LIBS)
+endif
+
 ati_drv_la_LTLIBRARIES = ati_drv.la
 ati_drv_la_LDFLAGS = -module -avoid-version
 ati_drv_ladir = @moduledir@/drivers
diff --git a/src/ati_pciids_gen.h b/src/ati_pciids_gen.h
index a740df8..633c5d3 100644
--- a/src/ati_pciids_gen.h
+++ b/src/ati_pciids_gen.h
@@ -1,4 +1,5 @@
 #define PCI_CHIP_RV380_3150 0x3150
+#define PCI_CHIP_RV380_3151 0x3151
 #define PCI_CHIP_RV380_3152 0x3152
 #define PCI_CHIP_RV380_3154 0x3154
 #define PCI_CHIP_RV380_3E50 0x3E50
@@ -330,6 +331,9 @@
 #define PCI_CHIP_R600_940A 0x940A
 #define PCI_CHIP_R600_940B 0x940B
 #define PCI_CHIP_R600_940F 0x940F
+#define PCI_CHIP_RV770_9440 0x9440
+#define PCI_CHIP_RV770_9441 0x9441
+#define PCI_CHIP_RV770_9442 0x9442
 #define PCI_CHIP_RV610_94C0 0x94C0
 #define PCI_CHIP_RV610_94C1 0x94C1
 #define PCI_CHIP_RV610_94C3 0x94C3
@@ -347,6 +351,7 @@
 #define PCI_CHIP_RV670_9507 0x9507
 #define PCI_CHIP_RV670_950F 0x950F
 #define PCI_CHIP_RV670_9511 0x9511
+#define PCI_CHIP_RV670_9515 0x9515
 #define PCI_CHIP_RV630_9580 0x9580
 #define PCI_CHIP_RV630_9581 0x9581
 #define PCI_CHIP_RV630_9583 0x9583
diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 363addf..8f5b40a 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -48,6 +48,29 @@
 #include "sarea.h"
 #endif
 
+AtomBiosResult
+atombios_lock_crtc(atomBiosHandlePtr atomBIOS, int crtc, int lock)
+{
+    ENABLE_CRTC_PS_ALLOCATION crtc_data;
+    AtomBiosArgRec data;
+    unsigned char *space;
+
+    crtc_data.ucCRTC = crtc;
+    crtc_data.ucEnable = lock;
+
+    data.exec.index = GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters);
+    data.exec.dataSpace = (void *)&space;
+    data.exec.pspace = &crtc_data;
+
+    if (RHDAtomBiosFunc(atomBIOS->scrnIndex, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
+	ErrorF("%s CRTC %d success\n", lock? "Lock":"Unlock", crtc);
+	return ATOM_SUCCESS ;
+    }
+
+    ErrorF("Lock CRTC failed\n");
+    return ATOM_NOT_IMPLEMENTED;
+}
+
 static AtomBiosResult
 atombios_enable_crtc(atomBiosHandlePtr atomBIOS, int crtc, int state)
 {
@@ -105,7 +128,7 @@ atombios_blank_crtc(atomBiosHandlePtr atomBIOS, int crtc, int state)
     crtc_data.ucCRTC = crtc;
     crtc_data.ucBlanking = state;
 
-    data.exec.index = offsetof(ATOM_MASTER_LIST_OF_COMMAND_TABLES, BlankCRTC) / sizeof(unsigned short);
+    data.exec.index = GetIndexIntoMasterTable(COMMAND, BlankCRTC);
     data.exec.dataSpace = (void *)&space;
     data.exec.pspace = &crtc_data;
 
@@ -146,10 +169,27 @@ atombios_set_crtc_timing(atomBiosHandlePtr atomBIOS, SET_CRTC_TIMING_PARAMETERS_
 {
     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;
 
     data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing);
     data.exec.dataSpace = (void *)&space;
-    data.exec.pspace = crtc_param;
+    data.exec.pspace = &conv_param;
 
     if (RHDAtomBiosFunc(atomBIOS->scrnIndex, atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
 	ErrorF("Set CRTC Timing success\n");
@@ -185,7 +225,11 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode, int pll_flags)
     if (IS_AVIVO_VARIANT) {
 	uint32_t temp;
 
-	pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+	if (mode->Clock > 120000) /* range limits??? */
+	    pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+	else
+	    pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+
 
 	RADEONComputePLL(&info->pll, mode->Clock, &temp, &fb_div, &ref_div, &post_div, pll_flags);
 	sclock = temp;
@@ -235,9 +279,9 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode, int pll_flags)
 	case 1:
 	case 2:
 	    spc2_ptr = (PIXEL_CLOCK_PARAMETERS_V2*)&spc_param.sPCLKInput;
-	    spc2_ptr->usPixelClock = sclock;
-	    spc2_ptr->usRefDiv = ref_div;
-	    spc2_ptr->usFbDiv = fb_div;
+	    spc2_ptr->usPixelClock = cpu_to_le16(sclock);
+	    spc2_ptr->usRefDiv = cpu_to_le16(ref_div);
+	    spc2_ptr->usFbDiv = cpu_to_le16(fb_div);
 	    spc2_ptr->ucPostDiv = post_div;
 	    spc2_ptr->ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
 	    spc2_ptr->ucCRTC = radeon_crtc->crtc_id;
@@ -246,9 +290,9 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode, int pll_flags)
 	    break;
 	case 3:
 	    spc3_ptr = (PIXEL_CLOCK_PARAMETERS_V3*)&spc_param.sPCLKInput;
-	    spc3_ptr->usPixelClock = sclock;
-	    spc3_ptr->usRefDiv = ref_div;
-	    spc3_ptr->usFbDiv = fb_div;
+	    spc3_ptr->usPixelClock = cpu_to_le16(sclock);
+	    spc3_ptr->usRefDiv = cpu_to_le16(ref_div);
+	    spc3_ptr->usFbDiv = cpu_to_le16(fb_div);
 	    spc3_ptr->ucPostDiv = post_div;
 	    spc3_ptr->ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
 	    spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2);
@@ -442,9 +486,6 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc,
 	    fb_location = fb_location + (char *)crtc->rotatedData - (char *)info->FB;
 	}
 
-	/* lock the grph regs */
-	OUTREG(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, AVIVO_D1GRPH_UPDATE_LOCK);
-
 	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);
@@ -459,26 +500,27 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc,
 	       crtc->scrn->displayWidth);
 	OUTREG(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
 
-	/* unlock the grph regs */
-	OUTREG(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, 0);
-
-	/* lock the mode regs */
-	OUTREG(AVIVO_D1SCL_UPDATE + radeon_crtc->crtc_offset, AVIVO_D1SCL_UPDATE_LOCK);
-
 	OUTREG(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
 	       		mode->VDisplay);
 	OUTREG(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, (x << 16) | y);
 	OUTREG(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
 	       (mode->HDisplay << 16) | mode->VDisplay);
-	/* unlock the mode regs */
-	OUTREG(AVIVO_D1SCL_UPDATE + radeon_crtc->crtc_offset, 0);
 
+	if (adjusted_mode->Flags & V_INTERLACE)
+	    OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
+		   AVIVO_D1MODE_INTERLEAVE_EN);
+	else
+	    OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
+		   0);
     }
 
     atombios_crtc_set_pll(crtc, adjusted_mode, pll_flags);
 
     atombios_set_crtc_timing(info->atomBIOS, &crtc_timing);
 
+    if (info->DispPriority)
+	RADEONInitDispBandwidth(pScrn);
+
     if (tilingChanged) {
 	/* need to redraw front buffer, I guess this can be considered a hack ? */
 	/* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
@@ -492,3 +534,126 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc,
 
 }
 
+/* Calculate display buffer watermark to prevent buffer underflow */
+void
+RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn,
+			      DisplayModePtr mode1, int pixel_bytes1,
+			      DisplayModePtr mode2, int pixel_bytes2)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    RADEONEntPtr pRADEONEnt   = RADEONEntPriv(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    uint32_t dc_lb_memory_split;
+    float mem_bw, peak_disp_bw;
+    float min_mem_eff = 0.8; /* XXX: taken from legacy method */
+    float pix_clk, pix_clk2; /* in MHz */
+
+    /*
+     * Set display0/1 priority up in the memory controller for
+     * modes if the user specifies HIGH for displaypriority
+     * option.
+     */
+    if (info->DispPriority == 2) {
+	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)
+	    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);
+	mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT);
+
+	if (pRADEONEnt->pCrtc[1]->enabled)
+	    mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); /* display 1 */
+	if (pRADEONEnt->pCrtc[0]->enabled)
+	    mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); /* display 0 */
+
+	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)
+	    OUTMC(pScrn, RS690_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
+    }
+
+    /* XXX: fix me for AVIVO
+     * Determine if there is enough bandwidth for current display mode
+     */
+    mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1);
+
+    pix_clk = 0;
+    pix_clk2 = 0;
+    peak_disp_bw = 0;
+    if (mode1) {
+	pix_clk = mode1->Clock/1000.0;
+	peak_disp_bw += (pix_clk * pixel_bytes1);
+    }
+    if (mode2) {
+	pix_clk2 = mode2->Clock/1000.0;
+	peak_disp_bw += (pix_clk2 * pixel_bytes2);
+    }
+
+    if (peak_disp_bw >= mem_bw * min_mem_eff) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "You may not have enough display bandwidth for current mode\n"
+		   "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
+    }
+
+    /*
+     * Line Buffer Setup
+     * There is a single line buffer shared by both display controllers.
+     * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between the display
+     * controllers.  The paritioning can either be done manually or via one of four
+     * preset allocations specified in bits 1:0:
+     * 0 - line buffer is divided in half and shared between each display controller
+     * 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4
+     * 2 - D1 gets the whole buffer
+     * 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4
+     * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual allocation mode.
+     * In manual allocation mode, D1 always starts at 0, D1 end/2 is specified in bits
+     * 14:4; D2 allocation follows D1.
+     */
+
+    /* is auto or manual better ? */
+    dc_lb_memory_split = INREG(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK;
+    dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
+#if 1
+    /* auto */
+    if (mode1 && mode2) {
+	if (mode1->HDisplay > mode2->HDisplay) {
+	    if (mode1->HDisplay > 2560)
+		dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;
+	    else
+		dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
+	} else if (mode2->HDisplay > mode1->HDisplay) {
+	    if (mode2->HDisplay > 2560)
+		dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
+	    else
+		dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
+	} else
+	    dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
+    } else if (mode1) {
+	dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY;
+    } else if (mode2) {
+	dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
+    }
+#else
+    /* manual */
+    dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
+    dc_lb_memory_split &= ~(AVIVO_DC_LB_DISP1_END_ADR_MASK << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
+    if (mode1) {
+	dc_lb_memory_split |= ((((mode1->HDisplay / 2) + 64 /*???*/) & AVIVO_DC_LB_DISP1_END_ADR_MASK)
+			       << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
+    } else if (mode2) {
+	dc_lb_memory_split |= (0 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
+    }
+    OUTREG(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split);
+#endif
+
+    /*
+     * Watermark setup
+     * TODO...
+     * Unforunately, I haven't been able to dig up the avivo watermark programming
+     * guide yet. -AGD
+     */
+
+}
diff --git a/src/atombios_output.c b/src/atombios_output.c
index 51be301..83b86a7 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -78,7 +78,7 @@ atombios_output_dac1_setup(xf86OutputPtr output, DisplayModePtr mode)
 	}
     }
 
-    disp_data.usPixelClock = mode->Clock / 10;
+    disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10);
     data.exec.index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
     data.exec.dataSpace = (void *)&space;
     data.exec.pspace = &disp_data;
@@ -128,7 +128,7 @@ atombios_output_dac2_setup(xf86OutputPtr output, DisplayModePtr mode)
 	}
     }
 
-    disp_data.usPixelClock = mode->Clock / 10;
+    disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10);
     data.exec.index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
     data.exec.dataSpace = (void *)&space;
     data.exec.pspace = &disp_data;
@@ -188,7 +188,7 @@ atombios_output_tv1_setup(xf86OutputPtr output, DisplayModePtr mode)
 	}
     }
 
-    disp_data.sTVEncoder.usPixelClock = mode->Clock / 10;
+    disp_data.sTVEncoder.usPixelClock = cpu_to_le16(mode->Clock / 10);
     data.exec.index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
     data.exec.dataSpace = (void *)&space;
     data.exec.pspace = &disp_data;
@@ -243,7 +243,7 @@ atombios_output_ddia_setup(xf86OutputPtr output, DisplayModePtr mode)
     unsigned char *space;
 
     disp_data.sDVOEncoder.ucAction = ATOM_ENABLE;
-    disp_data.sDVOEncoder.usPixelClock = mode->Clock / 10;
+    disp_data.sDVOEncoder.usPixelClock = cpu_to_le16(mode->Clock / 10);
 
     if (mode->Clock > 165000)
 	disp_data.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL;
@@ -276,7 +276,7 @@ atombios_output_tmds1_setup(xf86OutputPtr output, DisplayModePtr mode)
 	disp_data.ucMisc = 1;
     else
 	disp_data.ucMisc = 0;
-    disp_data.usPixelClock = mode->Clock / 10;
+    disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10);
     data.exec.index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
     data.exec.dataSpace = (void *)&space;
     data.exec.pspace = &disp_data;
@@ -304,7 +304,7 @@ atombios_output_tmds2_setup(xf86OutputPtr output, DisplayModePtr mode)
 	disp_data.ucMisc = 1;
     else
 	disp_data.ucMisc = 0;
-    disp_data.usPixelClock = mode->Clock / 10;
+    disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10);
     data.exec.index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
     data.exec.dataSpace = (void *)&space;
     data.exec.pspace = &disp_data;
@@ -331,7 +331,7 @@ atombios_output_lvds_setup(xf86OutputPtr output, DisplayModePtr mode)
 	disp_data.ucMisc = 1;
     else
 	disp_data.ucMisc = 0;
-    disp_data.usPixelClock = mode->Clock / 10;
+    disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10);
     data.exec.index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
     data.exec.dataSpace = (void *)&space;
     data.exec.pspace = &disp_data;
@@ -355,7 +355,7 @@ atombios_output_dig1_setup(xf86OutputPtr output, DisplayModePtr mode)
     unsigned char *space;
 
     disp_data.ucAction = 1;
-    disp_data.usPixelClock = mode->Clock / 10;
+    disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10);
     disp_data.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER1;
     if (OUTPUT_IS_DVI || (radeon_output->type == OUTPUT_HDMI)) {
 	if (radeon_output->coherent_mode) {
@@ -406,7 +406,7 @@ atombios_output_dig1_transmitter_setup(xf86OutputPtr output, DisplayModePtr mode
     unsigned char *space;
 
     disp_data.ucAction = ATOM_TRANSMITTER_ACTION_ENABLE;
-    disp_data.usPixelClock = mode->Clock / 10;
+    disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10);
     disp_data.ucConfig = ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER | ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
 
     if (info->IsIGP && (radeon_output->TMDSType == TMDS_UNIPHY)) {
@@ -464,7 +464,7 @@ atombios_output_dig2_setup(xf86OutputPtr output, DisplayModePtr mode)
     unsigned char *space;
 
     disp_data.ucAction = 1;
-    disp_data.usPixelClock = mode->Clock / 10;
+    disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10);
     disp_data.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER2;
     if (OUTPUT_IS_DVI || (radeon_output->type == OUTPUT_HDMI)) {
 	if (radeon_output->coherent_mode) {
@@ -515,7 +515,7 @@ atombios_output_dig2_transmitter_setup(xf86OutputPtr output, DisplayModePtr mode
     unsigned char *space;
 
     disp_data.ucAction = ATOM_TRANSMITTER_ACTION_ENABLE;
-    disp_data.usPixelClock = mode->Clock / 10;
+    disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10);
     disp_data.ucConfig = ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER | ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
 
     if (info->IsIGP && (radeon_output->TMDSType == TMDS_UNIPHY)) {
@@ -979,19 +979,19 @@ atom_bios_dac_load_detect(atomBiosHandlePtr atomBIOS, xf86OutputPtr output)
     dac_data.sDacload.ucMisc = 0;
 
     if (radeon_output->devices & ATOM_DEVICE_CRT1_SUPPORT) {
-	dac_data.sDacload.usDeviceID = ATOM_DEVICE_CRT1_SUPPORT;
+	dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
 	if (radeon_output->DACType == DAC_PRIMARY)
 	    dac_data.sDacload.ucDacType = ATOM_DAC_A;
 	else if (radeon_output->DACType == DAC_TVDAC)
 	    dac_data.sDacload.ucDacType = ATOM_DAC_B;
     } else if (radeon_output->devices & ATOM_DEVICE_CRT2_SUPPORT) {
-	dac_data.sDacload.usDeviceID = ATOM_DEVICE_CRT2_SUPPORT;
+	dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
 	if (radeon_output->DACType == DAC_PRIMARY)
 	    dac_data.sDacload.ucDacType = ATOM_DAC_A;
 	else if (radeon_output->DACType == DAC_TVDAC)
 	    dac_data.sDacload.ucDacType = ATOM_DAC_B;
     } else if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) {
-	dac_data.sDacload.usDeviceID = ATOM_DEVICE_CV_SUPPORT;
+	dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
 	if (radeon_output->DACType == DAC_PRIMARY)
 	    dac_data.sDacload.ucDacType = ATOM_DAC_A;
 	else if (radeon_output->DACType == DAC_TVDAC)
@@ -999,7 +999,7 @@ atom_bios_dac_load_detect(atomBiosHandlePtr atomBIOS, xf86OutputPtr output)
 	if (IS_DCE3_VARIANT)
 	    dac_data.sDacload.ucMisc = 1;
     } else if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) {
-	dac_data.sDacload.usDeviceID = ATOM_DEVICE_TV1_SUPPORT;
+	dac_data.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
 	if (radeon_output->DACType == DAC_PRIMARY)
 	    dac_data.sDacload.ucDacType = ATOM_DAC_A;
 	else if (radeon_output->DACType == DAC_TVDAC)
diff --git a/src/bicubic_table.h b/src/bicubic_table.h
new file mode 100644
index 0000000..765cfff
--- /dev/null
+++ b/src/bicubic_table.h
@@ -0,0 +1,646 @@
+static const uint16_t bicubic_tex_512[] = {
+	0xb266, 0x3c00, 0x3aaa, 0x3155,
+	0xb287, 0x3bf0, 0x3aa2, 0x3175,
+	0xb2a9, 0x3be0, 0x3a9a, 0x3196,
+	0xb2cc, 0x3bd0, 0x3a92, 0x31b7,
+	0xb2ee, 0x3bc0, 0x3a89, 0x31d9,
+	0xb312, 0x3bb0, 0x3a81, 0x31fb,
+	0xb335, 0x3ba0, 0x3a78, 0x321e,
+	0xb359, 0x3b90, 0x3a6f, 0x3241,
+	0xb37d, 0x3b80, 0x3a66, 0x3264,
+	0xb3a2, 0x3b70, 0x3a5d, 0x3288,
+	0xb3c7, 0x3b60, 0x3a54, 0x32ad,
+	0xb3ed, 0x3b51, 0x3a4b, 0x32d1,
+	0xb409, 0x3b41, 0x3a42, 0x32f7,
+	0xb41c, 0x3b31, 0x3a38, 0x331c,
+	0xb42f, 0x3b21, 0x3a2f, 0x3342,
+	0xb443, 0x3b12, 0x3a25, 0x3369,
+	0xb456, 0x3b02, 0x3a1c, 0x3390,
+	0xb46a, 0x3af3, 0x3a12, 0x33b7,
+	0xb47e, 0x3ae3, 0x3a08, 0x33de,
+	0xb492, 0x3ad4, 0x39fe, 0x3403,
+	0xb4a6, 0x3ac5, 0x39f4, 0x3417,
+	0xb4bb, 0x3ab5, 0x39ea, 0x342b,
+	0xb4cf, 0x3aa6, 0x39df, 0x3440,
+	0xb4e4, 0x3a97, 0x39d5, 0x3454,
+	0xb4f9, 0x3a88, 0x39cb, 0x3469,
+	0xb50e, 0x3a79, 0x39c0, 0x347e,
+	0xb523, 0x3a6a, 0x39b6, 0x3493,
+	0xb539, 0x3a5a, 0x39ab, 0x34a8,
+	0xb54e, 0x3a4c, 0x39a0, 0x34be,
+	0xb564, 0x3a3d, 0x3996, 0x34d3,
+	0xb57a, 0x3a2e, 0x398b, 0x34e9,
+	0xb590, 0x3a1f, 0x3980, 0x34ff,
+	0xb5a6, 0x3a10, 0x3975, 0x3515,
+	0xb5bc, 0x3a02, 0x396a, 0x352b,
+	0xb5d2, 0x39f3, 0x395f, 0x3541,
+	0xb5e9, 0x39e4, 0x3954, 0x3557,
+	0xb5ff, 0x39d6, 0x3948, 0x356e,
+	0xb616, 0x39c7, 0x393d, 0x3584,
+	0xb62d, 0x39b9, 0x3932, 0x359b,
+	0xb644, 0x39ab, 0x3926, 0x35b2,
+	0xb65b, 0x399c, 0x391b, 0x35c9,
+	0xb672, 0x398e, 0x3910, 0x35df,
+	0xb68a, 0x3980, 0x3904, 0x35f6,
+	0xb6a1, 0x3972, 0x38f8, 0x360e,
+	0xb6b9, 0x3964, 0x38ed, 0x3625,
+	0xb6d1, 0x3956, 0x38e1, 0x363c,
+	0xb6e8, 0x3948, 0x38d6, 0x3653,
+	0xb700, 0x393a, 0x38ca, 0x366b,
+	0xb719, 0x392c, 0x38be, 0x3682,
+	0xb731, 0x391e, 0x38b2, 0x369a,
+	0xb749, 0x3910, 0x38a7, 0x36b1,
+	0xb762, 0x3902, 0x389b, 0x36c9,
+	0xb77a, 0x38f5, 0x388f, 0x36e1,
+	0xb793, 0x38e7, 0x3883, 0x36f8,
+	0xb7ac, 0x38da, 0x3877, 0x3710,
+	0xb7c5, 0x38cc, 0x386b, 0x3728,
+	0xb7de, 0x38bf, 0x385f, 0x3740,
+	0xb7f7, 0x38b1, 0x3853, 0x3758,
+	0xb808, 0x38a4, 0x3847, 0x3770,
+	0xb815, 0x3897, 0x383b, 0x3788,
+	0xb821, 0x3889, 0x382f, 0x37a0,
+	0xb82e, 0x387c, 0x3823, 0x37b8,
+	0xb83b, 0x386f, 0x3817, 0x37d0,
+	0xb848, 0x3862, 0x380b, 0x37e8,
+	0xb855, 0x3855, 0x3800, 0x3800,
+	0xb862, 0x3848, 0x37e8, 0x380b,
+	0xb86f, 0x383b, 0x37d0, 0x3817,
+	0xb87c, 0x382e, 0x37b8, 0x3823,
+	0xb889, 0x3821, 0x37a0, 0x382f,
+	0xb897, 0x3815, 0x3788, 0x383b,
+	0xb8a4, 0x3808, 0x3770, 0x3847,
+	0xb8b1, 0x37f7, 0x3758, 0x3853,
+	0xb8bf, 0x37de, 0x3740, 0x385f,
+	0xb8cc, 0x37c5, 0x3728, 0x386b,
+	0xb8da, 0x37ac, 0x3710, 0x3877,
+	0xb8e7, 0x3793, 0x36f8, 0x3883,
+	0xb8f5, 0x377a, 0x36e1, 0x388f,
+	0xb902, 0x3762, 0x36c9, 0x389b,
+	0xb910, 0x3749, 0x36b1, 0x38a7,
+	0xb91e, 0x3731, 0x369a, 0x38b2,
+	0xb92c, 0x3719, 0x3682, 0x38be,
+	0xb93a, 0x3700, 0x366b, 0x38ca,
+	0xb948, 0x36e8, 0x3653, 0x38d6,
+	0xb956, 0x36d1, 0x363c, 0x38e1,
+	0xb964, 0x36b9, 0x3625, 0x38ed,
+	0xb972, 0x36a1, 0x360e, 0x38f8,
+	0xb980, 0x368a, 0x35f6, 0x3904,
+	0xb98e, 0x3672, 0x35df, 0x3910,
+	0xb99c, 0x365b, 0x35c9, 0x391b,
+	0xb9ab, 0x3644, 0x35b2, 0x3926,
+	0xb9b9, 0x362d, 0x359b, 0x3932,
+	0xb9c7, 0x3616, 0x3584, 0x393d,
+	0xb9d6, 0x35ff, 0x356e, 0x3948,
+	0xb9e4, 0x35e9, 0x3557, 0x3954,
+	0xb9f3, 0x35d2, 0x3541, 0x395f,
+	0xba02, 0x35bc, 0x352b, 0x396a,
+	0xba10, 0x35a6, 0x3515, 0x3975,
+	0xba1f, 0x3590, 0x34ff, 0x3980,
+	0xba2e, 0x357a, 0x34e9, 0x398b,
+	0xba3d, 0x3564, 0x34d3, 0x3996,
+	0xba4c, 0x354e, 0x34be, 0x39a0,
+	0xba5a, 0x3539, 0x34a8, 0x39ab,
+	0xba6a, 0x3523, 0x3493, 0x39b6,
+	0xba79, 0x350e, 0x347e, 0x39c0,
+	0xba88, 0x34f9, 0x3469, 0x39cb,
+	0xba97, 0x34e4, 0x3454, 0x39d5,
+	0xbaa6, 0x34cf, 0x3440, 0x39df,
+	0xbab5, 0x34bb, 0x342b, 0x39ea,
+	0xbac5, 0x34a6, 0x3417, 0x39f4,
+	0xbad4, 0x3492, 0x3403, 0x39fe,
+	0xbae3, 0x347e, 0x33de, 0x3a08,
+	0xbaf3, 0x346a, 0x33b7, 0x3a12,
+	0xbb02, 0x3456, 0x3390, 0x3a1c,
+	0xbb12, 0x3443, 0x3369, 0x3a25,
+	0xbb21, 0x342f, 0x3342, 0x3a2f,
+	0xbb31, 0x341c, 0x331c, 0x3a38,
+	0xbb41, 0x3409, 0x32f7, 0x3a42,
+	0xbb51, 0x33ed, 0x32d1, 0x3a4b,
+	0xbb60, 0x33c7, 0x32ad, 0x3a54,
+	0xbb70, 0x33a2, 0x3288, 0x3a5d,
+	0xbb80, 0x337d, 0x3264, 0x3a66,
+	0xbb90, 0x3359, 0x3241, 0x3a6f,
+	0xbba0, 0x3335, 0x321e, 0x3a78,
+	0xbbb0, 0x3312, 0x31fb, 0x3a81,
+	0xbbc0, 0x32ee, 0x31d9, 0x3a89,
+	0xbbd0, 0x32cc, 0x31b7, 0x3a92,
+	0xbbe0, 0x32a9, 0x3196, 0x3a9a,
+	0xbbf0, 0x3287, 0x3175, 0x3aa2,
+	0 };
+
+static const uint16_t bicubic_tex_2048[] = {
+	0xb266, 0x3c00, 0x3aaa, 0x3155,
+	0xb26e, 0x3bfc, 0x3aa8, 0x315d,
+	0xb277, 0x3bf8, 0x3aa6, 0x3165,
+	0xb27f, 0x3bf4, 0x3aa4, 0x316d,
+	0xb287, 0x3bf0, 0x3aa2, 0x3175,
+	0xb290, 0x3bec, 0x3aa0, 0x317d,
+	0xb298, 0x3be8, 0x3a9e, 0x3185,
+	0xb2a1, 0x3be4, 0x3a9c, 0x318e,
+	0xb2a9, 0x3be0, 0x3a9a, 0x3196,
+	0xb2b2, 0x3bdc, 0x3a98, 0x319e,
+	0xb2ba, 0x3bd8, 0x3a96, 0x31a6,
+	0xb2c3, 0x3bd4, 0x3a94, 0x31af,
+	0xb2cc, 0x3bd0, 0x3a92, 0x31b7,
+	0xb2d4, 0x3bcc, 0x3a90, 0x31bf,
+	0xb2dd, 0x3bc8, 0x3a8d, 0x31c8,
+	0xb2e6, 0x3bc4, 0x3a8b, 0x31d0,
+	0xb2ee, 0x3bc0, 0x3a89, 0x31d9,
+	0xb2f7, 0x3bbc, 0x3a87, 0x31e1,
+	0xb300, 0x3bb8, 0x3a85, 0x31ea,
+	0xb309, 0x3bb4, 0x3a83, 0x31f2,
+	0xb312, 0x3bb0, 0x3a81, 0x31fb,
+	0xb31a, 0x3bac, 0x3a7e, 0x3204,
+	0xb323, 0x3ba8, 0x3a7c, 0x320c,
+	0xb32c, 0x3ba4, 0x3a7a, 0x3215,
+	0xb335, 0x3ba0, 0x3a78, 0x321e,
+	0xb33e, 0x3b9c, 0x3a76, 0x3226,
+	0xb347, 0x3b98, 0x3a74, 0x322f,
+	0xb350, 0x3b94, 0x3a71, 0x3238,
+	0xb359, 0x3b90, 0x3a6f, 0x3241,
+	0xb362, 0x3b8c, 0x3a6d, 0x3249,
+	0xb36b, 0x3b88, 0x3a6b, 0x3252,
+	0xb374, 0x3b84, 0x3a69, 0x325b,
+	0xb37d, 0x3b80, 0x3a66, 0x3264,
+	0xb387, 0x3b7c, 0x3a64, 0x326d,
+	0xb390, 0x3b78, 0x3a62, 0x3276,
+	0xb399, 0x3b74, 0x3a60, 0x327f,
+	0xb3a2, 0x3b70, 0x3a5d, 0x3288,
+	0xb3ab, 0x3b6c, 0x3a5b, 0x3291,
+	0xb3b5, 0x3b68, 0x3a59, 0x329a,
+	0xb3be, 0x3b64, 0x3a57, 0x32a3,
+	0xb3c7, 0x3b60, 0x3a54, 0x32ad,
+	0xb3d0, 0x3b5c, 0x3a52, 0x32b6,
+	0xb3da, 0x3b58, 0x3a50, 0x32bf,
+	0xb3e3, 0x3b54, 0x3a4d, 0x32c8,
+	0xb3ed, 0x3b51, 0x3a4b, 0x32d1,
+	0xb3f6, 0x3b4d, 0x3a49, 0x32db,
+	0xb3ff, 0x3b49, 0x3a46, 0x32e4,
+	0xb404, 0x3b45, 0x3a44, 0x32ed,
+	0xb409, 0x3b41, 0x3a42, 0x32f7,
+	0xb40e, 0x3b3d, 0x3a3f, 0x3300,
+	0xb412, 0x3b39, 0x3a3d, 0x3309,
+	0xb417, 0x3b35, 0x3a3b, 0x3313,
+	0xb41c, 0x3b31, 0x3a38, 0x331c,
+	0xb421, 0x3b2d, 0x3a36, 0x3326,
+	0xb426, 0x3b29, 0x3a34, 0x332f,
+	0xb42a, 0x3b25, 0x3a31, 0x3339,
+	0xb42f, 0x3b21, 0x3a2f, 0x3342,
+	0xb434, 0x3b1e, 0x3a2c, 0x334c,
+	0xb439, 0x3b1a, 0x3a2a, 0x3355,
+	0xb43e, 0x3b16, 0x3a28, 0x335f,
+	0xb443, 0x3b12, 0x3a25, 0x3369,
+	0xb448, 0x3b0e, 0x3a23, 0x3372,
+	0xb44d, 0x3b0a, 0x3a20, 0x337c,
+	0xb451, 0x3b06, 0x3a1e, 0x3386,
+	0xb456, 0x3b02, 0x3a1c, 0x3390,
+	0xb45b, 0x3afe, 0x3a19, 0x3399,
+	0xb460, 0x3afb, 0x3a17, 0x33a3,
+	0xb465, 0x3af7, 0x3a14, 0x33ad,
+	0xb46a, 0x3af3, 0x3a12, 0x33b7,
+	0xb46f, 0x3aef, 0x3a0f, 0x33c1,
+	0xb474, 0x3aeb, 0x3a0d, 0x33ca,
+	0xb479, 0x3ae7, 0x3a0a, 0x33d4,
+	0xb47e, 0x3ae3, 0x3a08, 0x33de,
+	0xb483, 0x3ae0, 0x3a05, 0x33e8,
+	0xb488, 0x3adc, 0x3a03, 0x33f2,
+	0xb48d, 0x3ad8, 0x3a00, 0x33fc,
+	0xb492, 0x3ad4, 0x39fe, 0x3403,
+	0xb497, 0x3ad0, 0x39fb, 0x3408,
+	0xb49c, 0x3acc, 0x39f9, 0x340d,
+	0xb4a1, 0x3ac8, 0x39f6, 0x3412,
+	0xb4a6, 0x3ac5, 0x39f4, 0x3417,
+	0xb4ac, 0x3ac1, 0x39f1, 0x341c,
+	0xb4b1, 0x3abd, 0x39ef, 0x3421,
+	0xb4b6, 0x3ab9, 0x39ec, 0x3426,
+	0xb4bb, 0x3ab5, 0x39ea, 0x342b,
+	0xb4c0, 0x3ab1, 0x39e7, 0x3430,
+	0xb4c5, 0x3aae, 0x39e5, 0x3435,
+	0xb4ca, 0x3aaa, 0x39e2, 0x343b,
+	0xb4cf, 0x3aa6, 0x39df, 0x3440,
+	0xb4d5, 0x3aa2, 0x39dd, 0x3445,
+	0xb4da, 0x3a9e, 0x39da, 0x344a,
+	0xb4df, 0x3a9b, 0x39d8, 0x344f,
+	0xb4e4, 0x3a97, 0x39d5, 0x3454,
+	0xb4e9, 0x3a93, 0x39d2, 0x345a,
+	0xb4ef, 0x3a8f, 0x39d0, 0x345f,
+	0xb4f4, 0x3a8b, 0x39cd, 0x3464,
+	0xb4f9, 0x3a88, 0x39cb, 0x3469,
+	0xb4fe, 0x3a84, 0x39c8, 0x346e,
+	0xb504, 0x3a80, 0x39c5, 0x3474,
+	0xb509, 0x3a7c, 0x39c3, 0x3479,
+	0xb50e, 0x3a79, 0x39c0, 0x347e,
+	0xb513, 0x3a75, 0x39be, 0x3483,
+	0xb519, 0x3a71, 0x39bb, 0x3489,
+	0xb51e, 0x3a6d, 0x39b8, 0x348e,
+	0xb523, 0x3a6a, 0x39b6, 0x3493,
+	0xb529, 0x3a66, 0x39b3, 0x3499,
+	0xb52e, 0x3a62, 0x39b0, 0x349e,
+	0xb533, 0x3a5e, 0x39ae, 0x34a3,
+	0xb539, 0x3a5a, 0x39ab, 0x34a8,
+	0xb53e, 0x3a57, 0x39a8, 0x34ae,
+	0xb543, 0x3a53, 0x39a6, 0x34b3,
+	0xb549, 0x3a4f, 0x39a3, 0x34b9,
+	0xb54e, 0x3a4c, 0x39a0, 0x34be,
+	0xb554, 0x3a48, 0x399e, 0x34c3,
+	0xb559, 0x3a44, 0x399b, 0x34c9,
+	0xb55e, 0x3a40, 0x3998, 0x34ce,
+	0xb564, 0x3a3d, 0x3996, 0x34d3,
+	0xb569, 0x3a39, 0x3993, 0x34d9,
+	0xb56f, 0x3a35, 0x3990, 0x34de,
+	0xb574, 0x3a32, 0x398d, 0x34e4,
+	0xb57a, 0x3a2e, 0x398b, 0x34e9,
+	0xb57f, 0x3a2a, 0x3988, 0x34ef,
+	0xb585, 0x3a26, 0x3985, 0x34f4,
+	0xb58a, 0x3a23, 0x3983, 0x34f9,
+	0xb590, 0x3a1f, 0x3980, 0x34ff,
+	0xb595, 0x3a1b, 0x397d, 0x3504,
+	0xb59b, 0x3a18, 0x397a, 0x350a,
+	0xb5a0, 0x3a14, 0x3978, 0x350f,
+	0xb5a6, 0x3a10, 0x3975, 0x3515,
+	0xb5ab, 0x3a0d, 0x3972, 0x351a,
+	0xb5b1, 0x3a09, 0x396f, 0x3520,
+	0xb5b6, 0x3a05, 0x396d, 0x3525,
+	0xb5bc, 0x3a02, 0x396a, 0x352b,
+	0xb5c1, 0x39fe, 0x3967, 0x3530,
+	0xb5c7, 0x39fa, 0x3964, 0x3536,
+	0xb5cd, 0x39f7, 0x3961, 0x353c,
+	0xb5d2, 0x39f3, 0x395f, 0x3541,
+	0xb5d8, 0x39ef, 0x395c, 0x3547,
+	0xb5dd, 0x39ec, 0x3959, 0x354c,
+	0xb5e3, 0x39e8, 0x3956, 0x3552,
+	0xb5e9, 0x39e4, 0x3954, 0x3557,
+	0xb5ee, 0x39e1, 0x3951, 0x355d,
+	0xb5f4, 0x39dd, 0x394e, 0x3563,
+	0xb5fa, 0x39d9, 0x394b, 0x3568,
+	0xb5ff, 0x39d6, 0x3948, 0x356e,
+	0xb605, 0x39d2, 0x3946, 0x3573,
+	0xb60b, 0x39cf, 0x3943, 0x3579,
+	0xb610, 0x39cb, 0x3940, 0x357f,
+	0xb616, 0x39c7, 0x393d, 0x3584,
+	0xb61c, 0x39c4, 0x393a, 0x358a,
+	0xb621, 0x39c0, 0x3937, 0x3590,
+	0xb627, 0x39bd, 0x3935, 0x3595,
+	0xb62d, 0x39b9, 0x3932, 0x359b,
+	0xb633, 0x39b5, 0x392f, 0x35a1,
+	0xb638, 0x39b2, 0x392c, 0x35a6,
+	0xb63e, 0x39ae, 0x3929, 0x35ac,
+	0xb644, 0x39ab, 0x3926, 0x35b2,
+	0xb64a, 0x39a7, 0x3924, 0x35b7,
+	0xb64f, 0x39a3, 0x3921, 0x35bd,
+	0xb655, 0x39a0, 0x391e, 0x35c3,
+	0xb65b, 0x399c, 0x391b, 0x35c9,
+	0xb661, 0x3999, 0x3918, 0x35ce,
+	0xb667, 0x3995, 0x3915, 0x35d4,
+	0xb66c, 0x3992, 0x3912, 0x35da,
+	0xb672, 0x398e, 0x3910, 0x35df,
+	0xb678, 0x398a, 0x390d, 0x35e5,
+	0xb67e, 0x3987, 0x390a, 0x35eb,
+	0xb684, 0x3983, 0x3907, 0x35f1,
+	0xb68a, 0x3980, 0x3904, 0x35f6,
+	0xb68f, 0x397c, 0x3901, 0x35fc,
+	0xb695, 0x3979, 0x38fe, 0x3602,
+	0xb69b, 0x3975, 0x38fb, 0x3608,
+	0xb6a1, 0x3972, 0x38f8, 0x360e,
+	0xb6a7, 0x396e, 0x38f6, 0x3613,
+	0xb6ad, 0x396b, 0x38f3, 0x3619,
+	0xb6b3, 0x3967, 0x38f0, 0x361f,
+	0xb6b9, 0x3964, 0x38ed, 0x3625,
+	0xb6bf, 0x3960, 0x38ea, 0x362b,
+	0xb6c5, 0x395d, 0x38e7, 0x3630,
+	0xb6cb, 0x3959, 0x38e4, 0x3636,
+	0xb6d1, 0x3956, 0x38e1, 0x363c,
+	0xb6d6, 0x3952, 0x38de, 0x3642,
+	0xb6dc, 0x394f, 0x38db, 0x3648,
+	0xb6e2, 0x394b, 0x38d9, 0x364d,
+	0xb6e8, 0x3948, 0x38d6, 0x3653,
+	0xb6ee, 0x3944, 0x38d3, 0x3659,
+	0xb6f4, 0x3941, 0x38d0, 0x365f,
+	0xb6fa, 0x393d, 0x38cd, 0x3665,
+	0xb700, 0x393a, 0x38ca, 0x366b,
+	0xb706, 0x3936, 0x38c7, 0x3671,
+	0xb70c, 0x3933, 0x38c4, 0x3676,
+	0xb712, 0x392f, 0x38c1, 0x367c,
+	0xb719, 0x392c, 0x38be, 0x3682,
+	0xb71f, 0x3928, 0x38bb, 0x3688,
+	0xb725, 0x3925, 0x38b8, 0x368e,
+	0xb72b, 0x3921, 0x38b5, 0x3694,
+	0xb731, 0x391e, 0x38b2, 0x369a,
+	0xb737, 0x391a, 0x38af, 0x36a0,
+	0xb73d, 0x3917, 0x38ad, 0x36a5,
+	0xb743, 0x3914, 0x38aa, 0x36ab,
+	0xb749, 0x3910, 0x38a7, 0x36b1,
+	0xb74f, 0x390d, 0x38a4, 0x36b7,
+	0xb755, 0x3909, 0x38a1, 0x36bd,
+	0xb75b, 0x3906, 0x389e, 0x36c3,
+	0xb762, 0x3902, 0x389b, 0x36c9,
+	0xb768, 0x38ff, 0x3898, 0x36cf,
+	0xb76e, 0x38fc, 0x3895, 0x36d5,
+	0xb774, 0x38f8, 0x3892, 0x36db,
+	0xb77a, 0x38f5, 0x388f, 0x36e1,
+	0xb780, 0x38f1, 0x388c, 0x36e7,
+	0xb787, 0x38ee, 0x3889, 0x36ec,
+	0xb78d, 0x38eb, 0x3886, 0x36f2,
+	0xb793, 0x38e7, 0x3883, 0x36f8,
+	0xb799, 0x38e4, 0x3880, 0x36fe,
+	0xb79f, 0x38e0, 0x387d, 0x3704,
+	0xb7a5, 0x38dd, 0x387a, 0x370a,
+	0xb7ac, 0x38da, 0x3877, 0x3710,
+	0xb7b2, 0x38d6, 0x3874, 0x3716,
+	0xb7b8, 0x38d3, 0x3871, 0x371c,
+	0xb7be, 0x38cf, 0x386e, 0x3722,
+	0xb7c5, 0x38cc, 0x386b, 0x3728,
+	0xb7cb, 0x38c9, 0x3868, 0x372e,
+	0xb7d1, 0x38c5, 0x3865, 0x3734,
+	0xb7d7, 0x38c2, 0x3862, 0x373a,
+	0xb7de, 0x38bf, 0x385f, 0x3740,
+	0xb7e4, 0x38bb, 0x385c, 0x3746,
+	0xb7ea, 0x38b8, 0x3859, 0x374c,
+	0xb7f1, 0x38b5, 0x3856, 0x3752,
+	0xb7f7, 0x38b1, 0x3853, 0x3758,
+	0xb7fd, 0x38ae, 0x3850, 0x375e,
+	0xb801, 0x38aa, 0x384d, 0x3764,
+	0xb805, 0x38a7, 0x384a, 0x376a,
+	0xb808, 0x38a4, 0x3847, 0x3770,
+	0xb80b, 0x38a0, 0x3844, 0x3776,
+	0xb80e, 0x389d, 0x3841, 0x377c,
+	0xb811, 0x389a, 0x383e, 0x3782,
+	0xb815, 0x3897, 0x383b, 0x3788,
+	0xb818, 0x3893, 0x3838, 0x378e,
+	0xb81b, 0x3890, 0x3835, 0x3794,
+	0xb81e, 0x388d, 0x3832, 0x379a,
+	0xb821, 0x3889, 0x382f, 0x37a0,
+	0xb824, 0x3886, 0x382c, 0x37a6,
+	0xb828, 0x3883, 0x3829, 0x37ac,
+	0xb82b, 0x387f, 0x3826, 0x37b2,
+	0xb82e, 0x387c, 0x3823, 0x37b8,
+	0xb831, 0x3879, 0x3820, 0x37be,
+	0xb835, 0x3876, 0x381d, 0x37c4,
+	0xb838, 0x3872, 0x381a, 0x37ca,
+	0xb83b, 0x386f, 0x3817, 0x37d0,
+	0xb83e, 0x386c, 0x3814, 0x37d6,
+	0xb841, 0x3868, 0x3811, 0x37dc,
+	0xb845, 0x3865, 0x380e, 0x37e2,
+	0xb848, 0x3862, 0x380b, 0x37e8,
+	0xb84b, 0x385f, 0x3808, 0x37ee,
+	0xb84e, 0x385b, 0x3806, 0x37f4,
+	0xb852, 0x3858, 0x3803, 0x37fa,
+	0xb855, 0x3855, 0x3800, 0x3800,
+	0xb858, 0x3852, 0x37fa, 0x3803,
+	0xb85b, 0x384e, 0x37f4, 0x3806,
+	0xb85f, 0x384b, 0x37ee, 0x3808,
+	0xb862, 0x3848, 0x37e8, 0x380b,
+	0xb865, 0x3845, 0x37e2, 0x380e,
+	0xb868, 0x3841, 0x37dc, 0x3811,
+	0xb86c, 0x383e, 0x37d6, 0x3814,
+	0xb86f, 0x383b, 0x37d0, 0x3817,
+	0xb872, 0x3838, 0x37ca, 0x381a,
+	0xb876, 0x3835, 0x37c4, 0x381d,
+	0xb879, 0x3831, 0x37be, 0x3820,
+	0xb87c, 0x382e, 0x37b8, 0x3823,
+	0xb87f, 0x382b, 0x37b2, 0x3826,
+	0xb883, 0x3828, 0x37ac, 0x3829,
+	0xb886, 0x3824, 0x37a6, 0x382c,
+	0xb889, 0x3821, 0x37a0, 0x382f,
+	0xb88d, 0x381e, 0x379a, 0x3832,
+	0xb890, 0x381b, 0x3794, 0x3835,
+	0xb893, 0x3818, 0x378e, 0x3838,
+	0xb897, 0x3815, 0x3788, 0x383b,
+	0xb89a, 0x3811, 0x3782, 0x383e,
+	0xb89d, 0x380e, 0x377c, 0x3841,
+	0xb8a0, 0x380b, 0x3776, 0x3844,
+	0xb8a4, 0x3808, 0x3770, 0x3847,
+	0xb8a7, 0x3805, 0x376a, 0x384a,
+	0xb8aa, 0x3801, 0x3764, 0x384d,
+	0xb8ae, 0x37fd, 0x375e, 0x3850,
+	0xb8b1, 0x37f7, 0x3758, 0x3853,
+	0xb8b5, 0x37f1, 0x3752, 0x3856,
+	0xb8b8, 0x37ea, 0x374c, 0x3859,
+	0xb8bb, 0x37e4, 0x3746, 0x385c,
+	0xb8bf, 0x37de, 0x3740, 0x385f,
+	0xb8c2, 0x37d7, 0x373a, 0x3862,
+	0xb8c5, 0x37d1, 0x3734, 0x3865,
+	0xb8c9, 0x37cb, 0x372e, 0x3868,
+	0xb8cc, 0x37c5, 0x3728, 0x386b,
+	0xb8cf, 0x37be, 0x3722, 0x386e,
+	0xb8d3, 0x37b8, 0x371c, 0x3871,
+	0xb8d6, 0x37b2, 0x3716, 0x3874,
+	0xb8da, 0x37ac, 0x3710, 0x3877,
+	0xb8dd, 0x37a5, 0x370a, 0x387a,
+	0xb8e0, 0x379f, 0x3704, 0x387d,
+	0xb8e4, 0x3799, 0x36fe, 0x3880,
+	0xb8e7, 0x3793, 0x36f8, 0x3883,
+	0xb8eb, 0x378d, 0x36f2, 0x3886,
+	0xb8ee, 0x3787, 0x36ec, 0x3889,
+	0xb8f1, 0x3780, 0x36e7, 0x388c,
+	0xb8f5, 0x377a, 0x36e1, 0x388f,
+	0xb8f8, 0x3774, 0x36db, 0x3892,
+	0xb8fc, 0x376e, 0x36d5, 0x3895,
+	0xb8ff, 0x3768, 0x36cf, 0x3898,
+	0xb902, 0x3762, 0x36c9, 0x389b,
+	0xb906, 0x375b, 0x36c3, 0x389e,
+	0xb909, 0x3755, 0x36bd, 0x38a1,
+	0xb90d, 0x374f, 0x36b7, 0x38a4,
+	0xb910, 0x3749, 0x36b1, 0x38a7,
+	0xb914, 0x3743, 0x36ab, 0x38aa,
+	0xb917, 0x373d, 0x36a5, 0x38ad,
+	0xb91a, 0x3737, 0x36a0, 0x38af,
+	0xb91e, 0x3731, 0x369a, 0x38b2,
+	0xb921, 0x372b, 0x3694, 0x38b5,
+	0xb925, 0x3725, 0x368e, 0x38b8,
+	0xb928, 0x371f, 0x3688, 0x38bb,
+	0xb92c, 0x3719, 0x3682, 0x38be,
+	0xb92f, 0x3712, 0x367c, 0x38c1,
+	0xb933, 0x370c, 0x3676, 0x38c4,
+	0xb936, 0x3706, 0x3671, 0x38c7,
+	0xb93a, 0x3700, 0x366b, 0x38ca,
+	0xb93d, 0x36fa, 0x3665, 0x38cd,
+	0xb941, 0x36f4, 0x365f, 0x38d0,
+	0xb944, 0x36ee, 0x3659, 0x38d3,
+	0xb948, 0x36e8, 0x3653, 0x38d6,
+	0xb94b, 0x36e2, 0x364d, 0x38d9,
+	0xb94f, 0x36dc, 0x3648, 0x38db,
+	0xb952, 0x36d6, 0x3642, 0x38de,
+	0xb956, 0x36d1, 0x363c, 0x38e1,
+	0xb959, 0x36cb, 0x3636, 0x38e4,
+	0xb95d, 0x36c5, 0x3630, 0x38e7,
+	0xb960, 0x36bf, 0x362b, 0x38ea,
+	0xb964, 0x36b9, 0x3625, 0x38ed,
+	0xb967, 0x36b3, 0x361f, 0x38f0,
+	0xb96b, 0x36ad, 0x3619, 0x38f3,
+	0xb96e, 0x36a7, 0x3613, 0x38f6,
+	0xb972, 0x36a1, 0x360e, 0x38f8,
+	0xb975, 0x369b, 0x3608, 0x38fb,
+	0xb979, 0x3695, 0x3602, 0x38fe,
+	0xb97c, 0x368f, 0x35fc, 0x3901,
+	0xb980, 0x368a, 0x35f6, 0x3904,
+	0xb983, 0x3684, 0x35f1, 0x3907,
+	0xb987, 0x367e, 0x35eb, 0x390a,
+	0xb98a, 0x3678, 0x35e5, 0x390d,
+	0xb98e, 0x3672, 0x35df, 0x3910,
+	0xb992, 0x366c, 0x35da, 0x3912,
+	0xb995, 0x3667, 0x35d4, 0x3915,
+	0xb999, 0x3661, 0x35ce, 0x3918,
+	0xb99c, 0x365b, 0x35c9, 0x391b,
+	0xb9a0, 0x3655, 0x35c3, 0x391e,
+	0xb9a3, 0x364f, 0x35bd, 0x3921,
+	0xb9a7, 0x364a, 0x35b7, 0x3924,
+	0xb9ab, 0x3644, 0x35b2, 0x3926,
+	0xb9ae, 0x363e, 0x35ac, 0x3929,
+	0xb9b2, 0x3638, 0x35a6, 0x392c,
+	0xb9b5, 0x3633, 0x35a1, 0x392f,
+	0xb9b9, 0x362d, 0x359b, 0x3932,
+	0xb9bd, 0x3627, 0x3595, 0x3935,
+	0xb9c0, 0x3621, 0x3590, 0x3937,
+	0xb9c4, 0x361c, 0x358a, 0x393a,
+	0xb9c7, 0x3616, 0x3584, 0x393d,
+	0xb9cb, 0x3610, 0x357f, 0x3940,
+	0xb9cf, 0x360b, 0x3579, 0x3943,
+	0xb9d2, 0x3605, 0x3573, 0x3946,
+	0xb9d6, 0x35ff, 0x356e, 0x3948,
+	0xb9d9, 0x35fa, 0x3568, 0x394b,
+	0xb9dd, 0x35f4, 0x3563, 0x394e,
+	0xb9e1, 0x35ee, 0x355d, 0x3951,
+	0xb9e4, 0x35e9, 0x3557, 0x3954,
+	0xb9e8, 0x35e3, 0x3552, 0x3956,
+	0xb9ec, 0x35dd, 0x354c, 0x3959,
+	0xb9ef, 0x35d8, 0x3547, 0x395c,
+	0xb9f3, 0x35d2, 0x3541, 0x395f,
+	0xb9f7, 0x35cd, 0x353c, 0x3961,
+	0xb9fa, 0x35c7, 0x3536, 0x3964,
+	0xb9fe, 0x35c1, 0x3530, 0x3967,
+	0xba02, 0x35bc, 0x352b, 0x396a,
+	0xba05, 0x35b6, 0x3525, 0x396d,
+	0xba09, 0x35b1, 0x3520, 0x396f,
+	0xba0d, 0x35ab, 0x351a, 0x3972,
+	0xba10, 0x35a6, 0x3515, 0x3975,
+	0xba14, 0x35a0, 0x350f, 0x3978,
+	0xba18, 0x359b, 0x350a, 0x397a,
+	0xba1b, 0x3595, 0x3504, 0x397d,
+	0xba1f, 0x3590, 0x34ff, 0x3980,
+	0xba23, 0x358a, 0x34f9, 0x3983,
+	0xba26, 0x3585, 0x34f4, 0x3985,
+	0xba2a, 0x357f, 0x34ef, 0x3988,
+	0xba2e, 0x357a, 0x34e9, 0x398b,
+	0xba32, 0x3574, 0x34e4, 0x398d,
+	0xba35, 0x356f, 0x34de, 0x3990,
+	0xba39, 0x3569, 0x34d9, 0x3993,
+	0xba3d, 0x3564, 0x34d3, 0x3996,
+	0xba40, 0x355e, 0x34ce, 0x3998,
+	0xba44, 0x3559, 0x34c9, 0x399b,
+	0xba48, 0x3554, 0x34c3, 0x399e,
+	0xba4c, 0x354e, 0x34be, 0x39a0,
+	0xba4f, 0x3549, 0x34b9, 0x39a3,
+	0xba53, 0x3543, 0x34b3, 0x39a6,
+	0xba57, 0x353e, 0x34ae, 0x39a8,
+	0xba5a, 0x3539, 0x34a8, 0x39ab,
+	0xba5e, 0x3533, 0x34a3, 0x39ae,
+	0xba62, 0x352e, 0x349e, 0x39b0,
+	0xba66, 0x3529, 0x3499, 0x39b3,
+	0xba6a, 0x3523, 0x3493, 0x39b6,
+	0xba6d, 0x351e, 0x348e, 0x39b8,
+	0xba71, 0x3519, 0x3489, 0x39bb,
+	0xba75, 0x3513, 0x3483, 0x39be,
+	0xba79, 0x350e, 0x347e, 0x39c0,
+	0xba7c, 0x3509, 0x3479, 0x39c3,
+	0xba80, 0x3504, 0x3474, 0x39c5,
+	0xba84, 0x34fe, 0x346e, 0x39c8,
+	0xba88, 0x34f9, 0x3469, 0x39cb,
+	0xba8b, 0x34f4, 0x3464, 0x39cd,
+	0xba8f, 0x34ef, 0x345f, 0x39d0,
+	0xba93, 0x34e9, 0x345a, 0x39d2,
+	0xba97, 0x34e4, 0x3454, 0x39d5,
+	0xba9b, 0x34df, 0x344f, 0x39d8,
+	0xba9e, 0x34da, 0x344a, 0x39da,
+	0xbaa2, 0x34d5, 0x3445, 0x39dd,
+	0xbaa6, 0x34cf, 0x3440, 0x39df,
+	0xbaaa, 0x34ca, 0x343b, 0x39e2,
+	0xbaae, 0x34c5, 0x3435, 0x39e5,
+	0xbab1, 0x34c0, 0x3430, 0x39e7,
+	0xbab5, 0x34bb, 0x342b, 0x39ea,
+	0xbab9, 0x34b6, 0x3426, 0x39ec,
+	0xbabd, 0x34b1, 0x3421, 0x39ef,
+	0xbac1, 0x34ac, 0x341c, 0x39f1,
+	0xbac5, 0x34a6, 0x3417, 0x39f4,
+	0xbac8, 0x34a1, 0x3412, 0x39f6,
+	0xbacc, 0x349c, 0x340d, 0x39f9,
+	0xbad0, 0x3497, 0x3408, 0x39fb,
+	0xbad4, 0x3492, 0x3403, 0x39fe,
+	0xbad8, 0x348d, 0x33fc, 0x3a00,
+	0xbadc, 0x3488, 0x33f2, 0x3a03,
+	0xbae0, 0x3483, 0x33e8, 0x3a05,
+	0xbae3, 0x347e, 0x33de, 0x3a08,
+	0xbae7, 0x3479, 0x33d4, 0x3a0a,
+	0xbaeb, 0x3474, 0x33ca, 0x3a0d,
+	0xbaef, 0x346f, 0x33c1, 0x3a0f,
+	0xbaf3, 0x346a, 0x33b7, 0x3a12,
+	0xbaf7, 0x3465, 0x33ad, 0x3a14,
+	0xbafb, 0x3460, 0x33a3, 0x3a17,
+	0xbafe, 0x345b, 0x3399, 0x3a19,
+	0xbb02, 0x3456, 0x3390, 0x3a1c,
+	0xbb06, 0x3451, 0x3386, 0x3a1e,
+	0xbb0a, 0x344d, 0x337c, 0x3a20,
+	0xbb0e, 0x3448, 0x3372, 0x3a23,
+	0xbb12, 0x3443, 0x3369, 0x3a25,
+	0xbb16, 0x343e, 0x335f, 0x3a28,
+	0xbb1a, 0x3439, 0x3355, 0x3a2a,
+	0xbb1e, 0x3434, 0x334c, 0x3a2c,
+	0xbb21, 0x342f, 0x3342, 0x3a2f,
+	0xbb25, 0x342a, 0x3339, 0x3a31,
+	0xbb29, 0x3426, 0x332f, 0x3a34,
+	0xbb2d, 0x3421, 0x3326, 0x3a36,
+	0xbb31, 0x341c, 0x331c, 0x3a38,
+	0xbb35, 0x3417, 0x3313, 0x3a3b,
+	0xbb39, 0x3412, 0x3309, 0x3a3d,
+	0xbb3d, 0x340e, 0x3300, 0x3a3f,
+	0xbb41, 0x3409, 0x32f7, 0x3a42,
+	0xbb45, 0x3404, 0x32ed, 0x3a44,
+	0xbb49, 0x33ff, 0x32e4, 0x3a46,
+	0xbb4d, 0x33f6, 0x32db, 0x3a49,
+	0xbb51, 0x33ed, 0x32d1, 0x3a4b,
+	0xbb54, 0x33e3, 0x32c8, 0x3a4d,
+	0xbb58, 0x33da, 0x32bf, 0x3a50,
+	0xbb5c, 0x33d0, 0x32b6, 0x3a52,
+	0xbb60, 0x33c7, 0x32ad, 0x3a54,
+	0xbb64, 0x33be, 0x32a3, 0x3a57,
+	0xbb68, 0x33b5, 0x329a, 0x3a59,
+	0xbb6c, 0x33ab, 0x3291, 0x3a5b,
+	0xbb70, 0x33a2, 0x3288, 0x3a5d,
+	0xbb74, 0x3399, 0x327f, 0x3a60,
+	0xbb78, 0x3390, 0x3276, 0x3a62,
+	0xbb7c, 0x3387, 0x326d, 0x3a64,
+	0xbb80, 0x337d, 0x3264, 0x3a66,
+	0xbb84, 0x3374, 0x325b, 0x3a69,
+	0xbb88, 0x336b, 0x3252, 0x3a6b,
+	0xbb8c, 0x3362, 0x3249, 0x3a6d,
+	0xbb90, 0x3359, 0x3241, 0x3a6f,
+	0xbb94, 0x3350, 0x3238, 0x3a71,
+	0xbb98, 0x3347, 0x322f, 0x3a74,
+	0xbb9c, 0x333e, 0x3226, 0x3a76,
+	0xbba0, 0x3335, 0x321e, 0x3a78,
+	0xbba4, 0x332c, 0x3215, 0x3a7a,
+	0xbba8, 0x3323, 0x320c, 0x3a7c,
+	0xbbac, 0x331a, 0x3204, 0x3a7e,
+	0xbbb0, 0x3312, 0x31fb, 0x3a81,
+	0xbbb4, 0x3309, 0x31f2, 0x3a83,
+	0xbbb8, 0x3300, 0x31ea, 0x3a85,
+	0xbbbc, 0x32f7, 0x31e1, 0x3a87,
+	0xbbc0, 0x32ee, 0x31d9, 0x3a89,
+	0xbbc4, 0x32e6, 0x31d0, 0x3a8b,
+	0xbbc8, 0x32dd, 0x31c8, 0x3a8d,
+	0xbbcc, 0x32d4, 0x31bf, 0x3a90,
+	0xbbd0, 0x32cc, 0x31b7, 0x3a92,
+	0xbbd4, 0x32c3, 0x31af, 0x3a94,
+	0xbbd8, 0x32ba, 0x31a6, 0x3a96,
+	0xbbdc, 0x32b2, 0x319e, 0x3a98,
+	0xbbe0, 0x32a9, 0x3196, 0x3a9a,
+	0xbbe4, 0x32a1, 0x318e, 0x3a9c,
+	0xbbe8, 0x3298, 0x3185, 0x3a9e,
+	0xbbec, 0x3290, 0x317d, 0x3aa0,
+	0xbbf0, 0x3287, 0x3175, 0x3aa2,
+	0xbbf4, 0x327f, 0x316d, 0x3aa4,
+	0xbbf8, 0x3277, 0x3165, 0x3aa6,
+	0xbbfc, 0x326e, 0x315d, 0x3aa8,
+	0 };
+
diff --git a/src/bicubic_table.py b/src/bicubic_table.py
new file mode 100755
index 0000000..232ccb7
--- /dev/null
+++ b/src/bicubic_table.py
@@ -0,0 +1,72 @@
+#!/usr/bin/python
+
+import struct
+
+def half(i):
+ fs, fe, fm = ((i >> 31) & 0x1, (i >> 23) & 0xff, i & 0x7fffff)
+ s, e, m = (fs, 0, 0)
+
+ if (fe == 0x0):
+  pass
+ if ((fe == 0xff) and (fm == 0x0)):
+  e = 31
+ elif (fe == 0xff):
+  m = 1
+  e = 31
+ else:
+  exp = fe - 127;
+  if (exp < -24):
+   pass
+  elif (exp < -14):
+   temp = 10 - (-14 - exp)
+   m = 2**temp + (m >> (23 - temp))
+  elif (exp > 15):
+   e = 31
+  else:
+   e = exp + 15
+   m = fm >> 13
+
+ return ((s << 15) | (e << 10) | m)
+
+def texgen(pix):
+
+ tex = []
+
+ for i in range(0,pix,4):
+
+  a = i / float(pix)
+  a2 = a ** 2
+  a3 = a ** 3
+
+  w0 = 1 / 6.0 * (-a3 + 3 * a2 + -3 * a + 1)
+  w1 = 1 / 6.0 * (3 * a3 + -6 * a2 + 4)
+  w2 = 1 / 6.0 * (-3 * a3 + 3 * a2 + 3 * a + 1)
+  w3 = 1 / 6.0 * a3
+
+  tex.append(-(1 - (w1 / (w0 + w1)) + a))
+  tex.append(1 + (w3 / (w2 + w3)) - a)
+  tex.append(w0 + w1)
+  tex.append(w2 + w3)
+
+ return tex
+
+def printrow(l, offset):
+
+ seq = [ struct.unpack('<I',struct.pack('f',i))[0] for i in l[offset:offset+4] ]
+ seq = [ hex(half(i)) for i in seq ]
+ return "\t" + ", ".join(seq) + ","
+
+def maketable(pix):
+
+ l = texgen(pix)
+
+ print "static const uint16_t bicubic_tex_" + str(pix) + "[] = {"
+
+ for i in range(0, pix, 4):
+
+  print printrow(l, i)
+
+ print "\t0 };\n"
+
+maketable(512)
+maketable(2048)
diff --git a/src/legacy_crtc.c b/src/legacy_crtc.c
index 3df61a7..8995679 100644
--- a/src/legacy_crtc.c
+++ b/src/legacy_crtc.c
@@ -625,6 +625,9 @@ radeon_crtc_modeset_ioctl(xf86CrtcPtr crtc, Bool post)
     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
     struct drm_modeset_ctl modeset;
 
+    if (!info->directRenderingEnabled)
+	return;
+
     modeset.crtc = radeon_crtc->crtc_id;
     modeset.cmd = post ? _DRM_POST_MODESET : _DRM_PRE_MODESET;
 
@@ -1327,9 +1330,12 @@ radeon_update_tv_routing(ScrnInfoPtr pScrn, RADEONSavePtr restore)
 }
 
 /* Calculate display buffer watermark to prevent buffer underflow */
-static void
-RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, int pixel_bytes2, DisplayModePtr mode1, DisplayModePtr mode2)
+void
+RADEONInitDispBandwidthLegacy(ScrnInfoPtr pScrn,
+			      DisplayModePtr mode1, int pixel_bytes1,
+			      DisplayModePtr mode2, int pixel_bytes2)
 {
+    RADEONInfoPtr info = RADEONPTR(pScrn);
     RADEONEntPtr pRADEONEnt   = RADEONEntPriv(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
 
@@ -1352,10 +1358,10 @@ RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, int pixel_bytes2
     float min_mem_eff = 0.8;
     float sclk_eff, sclk_delay;
     float mc_latency_mclk, mc_latency_sclk, cur_latency_mclk, cur_latency_sclk;
-    float disp_latency, disp_latency_overhead, disp_drain_rate, disp_drain_rate2;
+    float disp_latency, disp_latency_overhead, disp_drain_rate = 0, disp_drain_rate2;
     float pix_clk, pix_clk2; /* in MHz */
     int cur_size = 16;       /* in octawords */
-    int critical_point, critical_point2;
+    int critical_point = 0, critical_point2;
     int stop_req, max_stop_req;
     float read_return_rate, time_disp1_drop_priority;
 
@@ -1366,15 +1372,15 @@ RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, int pixel_bytes2
      */
     if ((info->DispPriority == 2) && IS_R300_VARIANT) {
 	uint32_t mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER);
-	if (pRADEONEnt->pCrtc[1]->enabled) {
-	    mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */
-	} else {
-	    mc_init_misc_lat_timer |= 0x0100; /* display 0 only */
-	}
+	mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT);
+	mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT);
+	if (pRADEONEnt->pCrtc[1]->enabled)
+	    mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); /* display 1 */
+	if (pRADEONEnt->pCrtc[0]->enabled)
+	    mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); /* display 0 */
 	OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
     }
 
-
     /* R420 and RV410 family not supported yet */
     if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) return; 
 
@@ -1383,15 +1389,17 @@ RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, int pixel_bytes2
      */
     mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1);
 
-    pix_clk = mode1->Clock/1000.0;
-    if (mode2)
+    pix_clk = 0;
+    pix_clk2 = 0;
+    peak_disp_bw = 0;
+    if (mode1) {
+	pix_clk = mode1->Clock/1000.0;
+	peak_disp_bw += (pix_clk * pixel_bytes1);
+    }
+    if (mode2) {
 	pix_clk2 = mode2->Clock/1000.0;
-    else
-	pix_clk2 = 0;
-
-    peak_disp_bw = (pix_clk * info->CurrentLayout.pixel_bytes);
-    if (pixel_bytes2)
-      peak_disp_bw += (pix_clk2 * pixel_bytes2);
+	peak_disp_bw += (pix_clk2 * pixel_bytes2);
+    }
 
     if (peak_disp_bw >= mem_bw * min_mem_eff) {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
@@ -1399,20 +1407,6 @@ RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, int pixel_bytes2
 		   "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
     }
 
-    /*  CRTC1
-        Set GRPH_BUFFER_CNTL register using h/w defined optimal values.
-	GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ]
-    */
-    stop_req = mode1->HDisplay * info->CurrentLayout.pixel_bytes / 16;
-
-    /* setup Max GRPH_STOP_REQ default value */
-    if (IS_RV100_VARIANT)
-	max_stop_req = 0x5c;
-    else
-	max_stop_req  = 0x7c;
-    if (stop_req > max_stop_req)
-	stop_req = max_stop_req;
-
     /*  Get values from the EXT_MEM_CNTL register...converting its contents. */
     temp = INREG(RADEON_MEM_TIMING_CNTL);
     if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */
@@ -1435,9 +1429,8 @@ RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, int pixel_bytes2
     }
 
     if (IS_R300_VARIANT) {
-
 	/* on the R300, Tcas is included in Trbs.
-	*/
+	 */
 	temp = INREG(RADEON_MEM_CNTL);
 	data = (R300_MEM_NUM_CHANNELS_MASK & temp);
 	if (data == 1) {
@@ -1473,7 +1466,8 @@ RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, int pixel_bytes2
 	    sclk_eff = info->sclk;
     }
 
-    /* Find the memory controller latency for the display client.
+    /*
+      Find the memory controller latency for the display client.
     */
     if (IS_R300_VARIANT) {
 	/*not enough for R350 ???*/
@@ -1527,89 +1521,107 @@ RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, int pixel_bytes2
     mc_latency_sclk = mc_latency_sclk + disp_latency_overhead + cur_latency_sclk;
     disp_latency = MAX(mc_latency_mclk, mc_latency_sclk);
 
-    /*
-      Find the drain rate of the display buffer.
-    */
-    disp_drain_rate = pix_clk / (16.0/info->CurrentLayout.pixel_bytes);
-    if (pixel_bytes2)
-	disp_drain_rate2 = pix_clk2 / (16.0/pixel_bytes2);
+    /* setup Max GRPH_STOP_REQ default value */
+    if (IS_RV100_VARIANT)
+	max_stop_req = 0x5c;
     else
-	disp_drain_rate2 = 0;
+	max_stop_req  = 0x7c;
 
-    /*
-      Find the critical point of the display buffer.
-    */
-    critical_point= (uint32_t)(disp_drain_rate * disp_latency + 0.5);
+    if (mode1) {
+	/*  CRTC1
+	    Set GRPH_BUFFER_CNTL register using h/w defined optimal values.
+	    GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ]
+	*/
+	stop_req = mode1->HDisplay * pixel_bytes1 / 16;
 
-    /* ???? */
-    /*
-    temp = (info->SavedReg.grph_buffer_cntl & RADEON_GRPH_CRITICAL_POINT_MASK) >> RADEON_GRPH_CRITICAL_POINT_SHIFT;
-    if (critical_point < temp) critical_point = temp;
-    */
-    if (info->DispPriority == 2) {
-	critical_point = 0;
-    }
+	if (stop_req > max_stop_req)
+	    stop_req = max_stop_req;
 
-    /*
-      The critical point should never be above max_stop_req-4.  Setting
-      GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time.
-    */
-    if (max_stop_req - critical_point < 4) critical_point = 0;
+	/*
+	  Find the drain rate of the display buffer.
+	*/
+	disp_drain_rate = pix_clk / (16.0/pixel_bytes1);
 
-    if (critical_point == 0 && mode2 && info->ChipFamily == CHIP_FAMILY_R300) {
-	/* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/
-	critical_point = 0x10;
-    }
+	/*
+	  Find the critical point of the display buffer.
+	*/
+	critical_point= (uint32_t)(disp_drain_rate * disp_latency + 0.5);
 
-    temp = info->SavedReg->grph_buffer_cntl;
-    temp &= ~(RADEON_GRPH_STOP_REQ_MASK);
-    temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
-    temp &= ~(RADEON_GRPH_START_REQ_MASK);
-    if ((info->ChipFamily == CHIP_FAMILY_R350) &&
-	(stop_req > 0x15)) {
-	stop_req -= 0x10;
-    }
-    temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
+	/* ???? */
+	/*
+	  temp = (info->SavedReg.grph_buffer_cntl & RADEON_GRPH_CRITICAL_POINT_MASK) >> RADEON_GRPH_CRITICAL_POINT_SHIFT;
+	  if (critical_point < temp) critical_point = temp;
+	*/
+	if (info->DispPriority == 2) {
+	    critical_point = 0;
+	}
 
-    temp |= RADEON_GRPH_BUFFER_SIZE;
-    temp &= ~(RADEON_GRPH_CRITICAL_CNTL   |
-	      RADEON_GRPH_CRITICAL_AT_SOF |
-	      RADEON_GRPH_STOP_CNTL);
-    /*
-      Write the result into the register.
-    */
-    OUTREG(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
-				     (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
+	/*
+	  The critical point should never be above max_stop_req-4.  Setting
+	  GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time.
+	*/
+	if (max_stop_req - critical_point < 4) critical_point = 0;
+
+	if (critical_point == 0 && mode2 && info->ChipFamily == CHIP_FAMILY_R300) {
+	    /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/
+	    critical_point = 0x10;
+	}
+
+	temp = info->SavedReg->grph_buffer_cntl;
+	temp &= ~(RADEON_GRPH_STOP_REQ_MASK);
+	temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
+	temp &= ~(RADEON_GRPH_START_REQ_MASK);
+	if ((info->ChipFamily == CHIP_FAMILY_R350) &&
+	    (stop_req > 0x15)) {
+	    stop_req -= 0x10;
+	}
+	temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
+
+	temp |= RADEON_GRPH_BUFFER_SIZE;
+	temp &= ~(RADEON_GRPH_CRITICAL_CNTL   |
+		  RADEON_GRPH_CRITICAL_AT_SOF |
+		  RADEON_GRPH_STOP_CNTL);
+	/*
+	  Write the result into the register.
+	*/
+	OUTREG(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
+					 (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
 
 #if 0
-    if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
-	(info->ChipFamily == CHIP_FAMILY_RS480)) {
-	/* attempt to program RS400 disp regs correctly ??? */
-	temp = info->SavedReg->disp1_req_cntl1;
-	temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK |
-		  RS400_DISP1_STOP_REQ_LEVEL_MASK);
-	OUTREG(RS400_DISP1_REQ_CNTL1, (temp |
-				       (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) |
-				       (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT)));
-	temp = info->SavedReg->dmif_mem_cntl1;
-	temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK |
-		  RS400_DISP1_CRITICAL_POINT_STOP_MASK);
-	OUTREG(RS400_DMIF_MEM_CNTL1, (temp |
-				      (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) |
-				      (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT)));
-    }
+	if ((info->ChipFamily == CHIP_FAMILY_RS400) ||
+	    (info->ChipFamily == CHIP_FAMILY_RS480)) {
+	    /* attempt to program RS400 disp regs correctly ??? */
+	    temp = info->SavedReg->disp1_req_cntl1;
+	    temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK |
+		      RS400_DISP1_STOP_REQ_LEVEL_MASK);
+	    OUTREG(RS400_DISP1_REQ_CNTL1, (temp |
+					   (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) |
+					   (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT)));
+	    temp = info->SavedReg->dmif_mem_cntl1;
+	    temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK |
+		      RS400_DISP1_CRITICAL_POINT_STOP_MASK);
+	    OUTREG(RS400_DMIF_MEM_CNTL1, (temp |
+					  (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) |
+					  (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT)));
+	}
 #endif
 
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-		   "GRPH_BUFFER_CNTL from %x to %x\n",
-		   (unsigned int)info->SavedReg->grph_buffer_cntl,
-		   (unsigned int)INREG(RADEON_GRPH_BUFFER_CNTL));
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+		       "GRPH_BUFFER_CNTL from %x to %x\n",
+		       (unsigned int)info->SavedReg->grph_buffer_cntl,
+		       (unsigned int)INREG(RADEON_GRPH_BUFFER_CNTL));
+    }
 
     if (mode2) {
 	stop_req = mode2->HDisplay * pixel_bytes2 / 16;
 
 	if (stop_req > max_stop_req) stop_req = max_stop_req;
 
+	/*
+	  Find the drain rate of the display buffer.
+	*/
+	disp_drain_rate2 = pix_clk2 / (16.0/pixel_bytes2);
+
 	temp = info->SavedReg->grph2_buffer_cntl;
 	temp &= ~(RADEON_GRPH_STOP_REQ_MASK);
 	temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
@@ -1629,7 +1641,10 @@ RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, int pixel_bytes2
 	    critical_point2 = 0;
 	else {
 	    read_return_rate = MIN(info->sclk, info->mclk*(info->RamWidth*(info->IsDDR+1)/128));
-	    time_disp1_drop_priority = critical_point / (read_return_rate - disp_drain_rate);
+	    if (mode1)
+		time_disp1_drop_priority = critical_point / (read_return_rate - disp_drain_rate);
+	    else
+		time_disp1_drop_priority = 0;
 
 	    critical_point2 = (uint32_t)((disp_latency + time_disp1_drop_priority + 
 					disp_latency) * disp_drain_rate2 + 0.5);
@@ -1681,45 +1696,6 @@ RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, int pixel_bytes2
 }
 
 void
-RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
-{
-    RADEONInfoPtr info = RADEONPTR(pScrn);
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    DisplayModePtr mode1, mode2;
-    int pixel_bytes2 = 0;
-
-    if (info->IsPrimary || info->IsSecondary)
-	mode1 = &xf86_config->crtc[0]->mode;
-    else
-	mode1 = info->CurrentLayout.mode;
-    mode2 = NULL;
-    pixel_bytes2 = info->CurrentLayout.pixel_bytes;
-
-    if (xf86_config->num_crtc == 2) {
-      pixel_bytes2 = 0;
-      mode2 = NULL;
-
-      if (xf86_config->crtc[1]->enabled && xf86_config->crtc[0]->enabled) {
-	pixel_bytes2 = info->CurrentLayout.pixel_bytes;
-	mode1 = &xf86_config->crtc[0]->mode;
-	mode2 = &xf86_config->crtc[1]->mode;
-      } else if (xf86_config->crtc[0]->enabled) {
-	mode1 = &xf86_config->crtc[0]->mode;
-      } else if (xf86_config->crtc[1]->enabled) {
-	mode1 = &xf86_config->crtc[1]->mode;
-      } else
-	return;
-    } else {
-	if (xf86_config->crtc[0]->enabled)
-	    mode1 = &xf86_config->crtc[0]->mode;
-	else
-	    return;
-    }
-
-    RADEONInitDispBandwidth2(pScrn, info, pixel_bytes2, mode1, mode2);
-}
-
-void
 legacy_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 		     DisplayModePtr adjusted_mode, int x, int y)
 {
@@ -1729,10 +1705,15 @@ legacy_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
     RADEONInfoPtr info = RADEONPTR(pScrn);
     int i = 0;
     double dot_clock = 0;
-    int pll_flags = RADEON_PLL_LEGACY | RADEON_PLL_PREFER_LOW_REF_DIV;
+    int pll_flags = RADEON_PLL_LEGACY;
     Bool update_tv_routing = FALSE;
     Bool tilingChanged = FALSE;
 
+    if (adjusted_mode->Clock > 120000) /* range limits??? */
+	pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+    else
+	pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+
     if (info->allowColorTiling) {
 	radeon_crtc->can_tile = (adjusted_mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE;
 	tilingChanged = RADEONSetTiling(pScrn);
diff --git a/src/legacy_output.c b/src/legacy_output.c
index 9c9ebb9..e5ddf1f 100644
--- a/src/legacy_output.c
+++ b/src/legacy_output.c
@@ -48,6 +48,8 @@
 #include "radeon_tv.h"
 #include "radeon_atombios.h"
 
+#include "ati_pciids_gen.h"
+
 static RADEONMonitorType radeon_detect_tv(ScrnInfoPtr pScrn);
 static RADEONMonitorType radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color);
 static RADEONMonitorType radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color);
@@ -277,16 +279,12 @@ static void
 RADEONRestoreDVOChip(ScrnInfoPtr pScrn, xf86OutputPtr output)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
 
     if (!radeon_output->DVOChip)
 	return;
 
-    OUTREG(radeon_output->dvo_i2c.mask_clk_reg,
-	   INREG(radeon_output->dvo_i2c.mask_clk_reg) &
-	   (uint32_t)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1));
-
+    RADEONI2CDoLock(output, TRUE);
     if (!RADEONInitExtTMDSInfoFromBIOS(output)) {
 	if (radeon_output->DVOChip) {
 	    switch(info->ext_tmds_chip) {
@@ -316,6 +314,7 @@ RADEONRestoreDVOChip(ScrnInfoPtr pScrn, xf86OutputPtr output)
 	    }
 	}
     }
+    RADEONI2CDoLock(output, FALSE);
 }
 
 #if 0
@@ -727,14 +726,6 @@ RADEONEnableDisplay(xf86OutputPtr output, BOOL bEnable)
 		    save->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
 		}
 		tv_dac_change = 1;
-		/* IGP chips seem to use a mix of Primary and TVDAC controls */
-		if (info->IsIGP) {
-		    tmp = INREG(RADEON_CRTC_EXT_CNTL);
-		    tmp |= RADEON_CRTC_CRT_ON;
-		    OUTREG(RADEON_CRTC_EXT_CNTL, tmp);
-		    save->crtc_ext_cntl |= RADEON_CRTC_CRT_ON;
-		    RADEONDacPowerSet(pScrn, bEnable, TRUE);
-		}
 	    }
 	} else if (radeon_output->MonType == MT_DFP) {
 	    if (radeon_output->TMDSType == TMDS_INT) {
@@ -815,14 +806,6 @@ RADEONEnableDisplay(xf86OutputPtr output, BOOL bEnable)
 			save->crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
 		    }
 		}
-		/* IGP chips seem to use a mix of Primary and TVDAC controls */
-		if (info->IsIGP) {
-		    tmp = INREG(RADEON_CRTC_EXT_CNTL);
-		    tmp &= ~RADEON_CRTC_CRT_ON;
-		    OUTREG(RADEON_CRTC_EXT_CNTL, tmp);
-		    save->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON;
-		    RADEONDacPowerSet(pScrn, bEnable, TRUE);
-		}
 	    }
 	} else if (radeon_output->MonType == MT_DFP) {
 	    if (radeon_output->TMDSType == TMDS_INT) {
@@ -1033,9 +1016,14 @@ RADEONInitFP2Registers(xf86OutputPtr output, RADEONSavePtr save,
 			    RADEON_FP2_DVO_RATE_SEL_SDR);
 
 
-    /* XXX: these may be oem specific */
+    /* XXX: these are oem specific */
     if (IS_R300_VARIANT) {
-	save->fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE;
+	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 */
+	else
+	    save->fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE;
 #if 0
 	if (mode->Clock > 165000)
 	    save->fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;
@@ -1383,7 +1371,6 @@ RADEONInitOutputRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
 {
     Bool IsPrimary = crtc_num == 0 ? TRUE : FALSE;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
-    RADEONInfoPtr info = RADEONPTR(pScrn);
 
     if (crtc_num == 0)
 	RADEONInitRMXRegisters(output, save, mode);
@@ -1393,9 +1380,6 @@ RADEONInitOutputRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
 	    RADEONInitDACRegisters(output, save, mode, IsPrimary);
 	} else {
 	    RADEONInitDAC2Registers(output, save, mode, IsPrimary);
-	    /* IGP chips seem to use a mix of primary and TVDAC controls */
-	    if (info->IsIGP)
-		RADEONInitDACRegisters(output, save, mode, IsPrimary);
 	}
     } else if (radeon_output->MonType == MT_LCD) {
 	RADEONInitLVDSRegisters(output, save, mode, IsPrimary);
@@ -1456,8 +1440,8 @@ legacy_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
 		}
 		OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
 	    } else {
-		RADEONRestoreDVOChip(pScrn, output);
 		RADEONRestoreFP2Registers(pScrn, info->ModeReg);
+		RADEONRestoreDVOChip(pScrn, output);
 	    }
 	}
 	break;
diff --git a/src/pcidb/ati_pciids.csv b/src/pcidb/ati_pciids.csv
index 1f6fa82..07e71a3 100644
--- a/src/pcidb/ati_pciids.csv
+++ b/src/pcidb/ati_pciids.csv
@@ -1,5 +1,6 @@
 "#pciid","define","family","mobility","igp","nocrtc2","Nointtvout","singledac","name"
 "0x3150","RV380_3150","RV380",1,,,,,"ATI Radeon Mobility X600 (M24) 3150 (PCIE)"
+"0x3151","RV380_3151","RV380",,,,,,"ATI FireMV 2400 (PCI)"
 "0x3152","RV380_3152","RV380",1,,,,,"ATI Radeon Mobility X300 (M24) 3152 (PCIE)"
 "0x3154","RV380_3154","RV380",1,,,,,"ATI FireGL M24 GL 3154 (PCIE)"
 "0x3E50","RV380_3E50","RV380",,,,,,"ATI Radeon X600 (RV380) 3E50 (PCIE)"
@@ -331,6 +332,9 @@
 "0x940A","R600_940A","R600",,,,,,"ATI FireGL V8650"
 "0x940B","R600_940B","R600",,,,,,"ATI FireGL V8600"
 "0x940F","R600_940F","R600",,,,,,"ATI FireGL V7600"
+"0x9440","RV770_9440","RV770",,,,,,"ATI Radeon 4800 Series"
+"0x9441","RV770_9441","RV770",,,,,,"ATI Radeon HD 4870 x2"
+"0x9442","RV770_9442","RV770",,,,,,"ATI Radeon 4800 Series"
 "0x94C0","RV610_94C0","RV610",,,,,,"ATI RV610"
 "0x94C1","RV610_94C1","RV610",,,,,,"ATI Radeon HD 2400 XT"
 "0x94C3","RV610_94C3","RV610",,,,,,"ATI Radeon HD 2400 Pro"
@@ -348,6 +352,7 @@
 "0x9507","RV670_9507","RV670",,,,,,"ATI RV670"
 "0x950F","RV670_950F","RV670",,,,,,"ATI Radeon HD3870 X2"
 "0x9511","RV670_9511","RV670",,,,,,"ATI FireGL V7700"
+"0x9515","RV670_9515","RV670",,,,,,"ATI Radeon HD3850"
 "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.h b/src/radeon.h
index 4f77c3b..2348e7c 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -98,6 +98,36 @@
 #define MIN(a,b) ((a)>(b)?(b):(a))
 #endif
 
+#if HAVE_BYTESWAP_H
+#include <byteswap.h>
+#elif defined(USE_SYS_ENDIAN_H)
+#include <sys/endian.h>
+#else
+#define bswap_16(value)  \
+        ((((value) & 0xff) << 8) | ((value) >> 8))
+
+#define bswap_32(value) \
+        (((uint32_t)bswap_16((uint16_t)((value) & 0xffff)) << 16) | \
+        (uint32_t)bswap_16((uint16_t)((value) >> 16)))
+ 
+#define bswap_64(value) \
+        (((uint64_t)bswap_32((uint32_t)((value) & 0xffffffff)) \
+            << 32) | \
+        (uint64_t)bswap_32((uint32_t)((value) >> 32)))
+#endif
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+#define le32_to_cpu(x) bswap_32(x)
+#define le16_to_cpu(x) bswap_16(x)
+#define cpu_to_le32(x) bswap_32(x)
+#define cpu_to_le16(x) bswap_16(x)
+#else
+#define le32_to_cpu(x) (x)
+#define le16_to_cpu(x) (x)
+#define cpu_to_le32(x) (x)
+#define cpu_to_le16(x) (x)
+#endif
+
 /* Provide substitutes for gcc's __FUNCTION__ on other compilers */
 #if !defined(__GNUC__) && !defined(__FUNCTION__)
 # define __FUNCTION__ __func__		/* C99 */
@@ -220,7 +250,12 @@ typedef struct {
 #define RADEON_PLL_NO_ODD_POST_DIV (1 << 1)
 #define RADEON_PLL_USE_REF_DIV     (1 << 2)
 #define RADEON_PLL_LEGACY          (1 << 3)
-#define RADEON_PLL_PREFER_LOW_REF_DIV (1 << 4)
+#define RADEON_PLL_PREFER_LOW_REF_DIV   (1 << 4)
+#define RADEON_PLL_PREFER_HIGH_REF_DIV  (1 << 5)
+#define RADEON_PLL_PREFER_LOW_FB_DIV    (1 << 6)
+#define RADEON_PLL_PREFER_HIGH_FB_DIV   (1 << 7)
+#define RADEON_PLL_PREFER_LOW_POST_DIV  (1 << 8)
+#define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9)
 
 typedef struct {
     uint16_t          reference_freq;
@@ -287,6 +322,7 @@ typedef enum {
     CHIP_FAMILY_RV620,
     CHIP_FAMILY_RV635,
     CHIP_FAMILY_RS780,
+    CHIP_FAMILY_RV770,
     CHIP_FAMILY_LAST
 } RADEONChipFamily;
 
@@ -567,7 +603,6 @@ typedef struct {
     Bool              CPRuns;           /* CP is running */
     Bool              CPInUse;          /* CP has been used by X server */
     Bool              CPStarted;        /* CP has started */
-    int               CPMode;           /* CP mode that server/clients use */
     int               CPFifoSize;       /* Size of the CP command FIFO */
     int               CPusecTimeout;    /* CP timeout in usecs */
     Bool              needCacheFlush;
@@ -640,17 +675,6 @@ typedef struct {
     FBAreaPtr         depthTexArea;
 #endif
 
-				/* Saved scissor values */
-    uint32_t          sc_left;
-    uint32_t          sc_right;
-    uint32_t          sc_top;
-    uint32_t          sc_bottom;
-
-    uint32_t          re_top_left;
-    uint32_t          re_width_height;
-
-    uint32_t          aux_sc_cntl;
-
     int               irq;
 
     Bool              DMAForXv;
@@ -787,7 +811,6 @@ do {									\
 extern void legacy_crtc_dpms(xf86CrtcPtr crtc, int mode);
 extern void legacy_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 				 DisplayModePtr adjusted_mode, int x, int y);
-extern void RADEONInitDispBandwidth(ScrnInfoPtr pScrn);
 extern void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn,
 					 RADEONSavePtr restore);
 extern void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn,
@@ -872,6 +895,7 @@ extern Bool RADEONGetTMDSInfoFromBIOS(xf86OutputPtr output);
 extern Bool RADEONGetTVInfoFromBIOS(xf86OutputPtr output);
 extern Bool RADEONInitExtTMDSInfoFromBIOS (xf86OutputPtr output);
 extern Bool RADEONPostCardFromBIOSTables(ScrnInfoPtr pScrn);
+extern Bool radeon_card_posted(ScrnInfoPtr pScrn);
 
 /* radeon_commonfuncs.c */
 #ifdef XF86DRI
@@ -894,6 +918,7 @@ extern DisplayModePtr RADEONCrtcFindClosestMode(xf86CrtcPtr crtc,
 						DisplayModePtr pMode);
 extern void RADEONUnblank(ScrnInfoPtr pScrn);
 extern Bool RADEONSetTiling(ScrnInfoPtr pScrn);
+extern void RADEONInitDispBandwidth(ScrnInfoPtr pScrn);
 
 /* radeon_cursor.c */
 extern Bool RADEONCursorInit(ScreenPtr pScreen);
@@ -983,6 +1008,8 @@ extern void RADEONPrintPortMap(ScrnInfoPtr pScrn);
 extern void RADEONSetOutputType(ScrnInfoPtr pScrn,
 				RADEONOutputPrivatePtr radeon_output);
 extern Bool RADEONSetupConnectors(ScrnInfoPtr pScrn);
+extern Bool RADEONI2CDoLock(xf86OutputPtr output, Bool lock_state);
+
 
 /* radeon_tv.c */
 extern void RADEONSaveTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save);
@@ -1046,13 +1073,11 @@ do {									\
 
 #define RADEONCP_RESET(pScrn, info)					\
 do {									\
-    if (RADEONCP_USE_RING_BUFFER(info->CPMode)) {			\
 	int _ret = drmCommandNone(info->drmFD, DRM_RADEON_CP_RESET);	\
 	if (_ret) {							\
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,			\
 		       "%s: CP reset %d\n", __FUNCTION__, _ret);	\
 	}								\
-    }									\
 } while (0)
 
 #define RADEONCP_REFRESH(pScrn, info)					\
@@ -1064,18 +1089,6 @@ do {									\
 	    info->needCacheFlush = FALSE;				\
 	}								\
 	RADEON_WAIT_UNTIL_IDLE();					\
-        if (info->ChipFamily <= CHIP_FAMILY_RV280) {                    \
-	    BEGIN_RING(6);						\
-	    OUT_RING_REG(RADEON_RE_TOP_LEFT,     info->re_top_left);	\
-	    OUT_RING_REG(RADEON_RE_WIDTH_HEIGHT, info->re_width_height); \
-	    OUT_RING_REG(RADEON_AUX_SC_CNTL,     info->aux_sc_cntl);	\
-	    ADVANCE_RING();						\
-        } else {                                                        \
-            BEGIN_RING(4);                                              \
-            OUT_RING_REG(R300_SC_SCISSOR0, info->re_top_left);          \
-	    OUT_RING_REG(R300_SC_SCISSOR1, info->re_width_height);      \
-            ADVANCE_RING();                                             \
-	}                                                               \
 	info->CPInUse = TRUE;						\
     }									\
 } while (0)
diff --git a/src/radeon_accel.c b/src/radeon_accel.c
index 65ad33d..e617fd5 100644
--- a/src/radeon_accel.c
+++ b/src/radeon_accel.c
@@ -469,23 +469,6 @@ void RADEONEngineInit(ScrnInfoPtr pScrn)
 	 | RADEON_GMC_CLR_CMP_CNTL_DIS
 	 | RADEON_GMC_DST_PITCH_OFFSET_CNTL);
 
-#ifdef XF86DRI
-    info->sc_left         = 0x00000000;
-    info->sc_right        = RADEON_DEFAULT_SC_RIGHT_MAX;
-    info->sc_top          = 0x00000000;
-    info->sc_bottom       = RADEON_DEFAULT_SC_BOTTOM_MAX;
-
-    info->re_top_left     = 0x00000000;
-    if (info->ChipFamily <= CHIP_FAMILY_RV280)
-	info->re_width_height = ((0x7ff << RADEON_RE_WIDTH_SHIFT) |
-				 (0x7ff << RADEON_RE_HEIGHT_SHIFT));
-    else
-	info->re_width_height = ((8191 << R300_SCISSOR_X_SHIFT) |
-				 (8191 << R300_SCISSOR_Y_SHIFT));
-
-    info->aux_sc_cntl     = 0x00000000;
-#endif
-
     RADEONEngineRestore(pScrn);
 }
 
@@ -1046,18 +1029,6 @@ RADEONSetupMemXAA_DRI(int scrnIndex, ScreenPtr pScreen)
     depthSize = ((((pScrn->virtualY + 15) & ~15) * info->depthPitch
 		  * depthCpp + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN);
 
-    switch (info->CPMode) {
-    case RADEON_DEFAULT_CP_PIO_MODE:
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in PIO mode\n");
-	break;
-    case RADEON_DEFAULT_CP_BM_MODE:
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in BM mode\n");
-	break;
-    default:
-        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in UNKNOWN mode\n");
-	break;
-    }
-
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	       "Using %d MB GART aperture\n", info->gartSize);
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index 20aa722..f0a3a31 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -501,11 +501,11 @@ rhdAtomASICInit(atomBiosHandlePtr handle)
     RHDAtomBiosFunc(handle->scrnIndex, handle,
 		    GET_DEFAULT_ENGINE_CLOCK,
 		    &data);
-    asicInit.sASICInitClocks.ulDefaultEngineClock = data.val / 10;/*in 10 Khz*/
+    asicInit.sASICInitClocks.ulDefaultEngineClock = cpu_to_le32(data.val / 10);/*in 10 Khz*/
     RHDAtomBiosFunc(handle->scrnIndex, handle,
 		    GET_DEFAULT_MEMORY_CLOCK,
 		    &data);
-    asicInit.sASICInitClocks.ulDefaultMemoryClock = data.val / 10;/*in 10 Khz*/
+    asicInit.sASICInitClocks.ulDefaultMemoryClock = cpu_to_le32(data.val / 10);/*in 10 Khz*/
     data.exec.dataSpace = NULL;
     data.exec.index = 0x0;
     data.exec.pspace = &asicInit;
@@ -609,17 +609,6 @@ rhdAtomInit(atomBiosHandlePtr unused1, AtomBiosRequestID unused2,
 #endif
     handle->BIOSImageSize = BIOSImageSize;
 
-# if ATOM_BIOS_PARSER
-    /* Try to find out if BIOS has been posted (either by system or int10 */
-    if (!rhdAtomGetFbBaseAndSize(handle, NULL, NULL)) {
-	/* run AsicInit */
-	if (!rhdAtomASICInit(handle))
-	    xf86DrvMsg(scrnIndex, X_WARNING,
-		       "%s: AsicInit failed. Won't be able to obtain in VRAM "
-		       "FB scratch space\n",__func__);
-    }
-# endif
-
     data->atomhandle = handle;
     return ATOM_SUCCESS;
 
@@ -654,12 +643,18 @@ rhdAtomVramInfoQuery(atomBiosHandlePtr handle, AtomBiosRequestID func,
 
     switch (func) {
 	case GET_FW_FB_START:
-	    *val = le32_to_cpu(atomDataPtr->VRAM_UsageByFirmware
-			       ->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware);
+	    if (atomDataPtr->VRAM_UsageByFirmware)
+		*val = le32_to_cpu(atomDataPtr->VRAM_UsageByFirmware
+				   ->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware);
+	    else
+		return ATOM_NOT_IMPLEMENTED;
 	    break;
 	case GET_FW_FB_SIZE:
-	    *val =  le16_to_cpu(atomDataPtr->VRAM_UsageByFirmware
-				->asFirmwareVramReserveInfo[0].usFirmwareUseInKb);
+	    if (atomDataPtr->VRAM_UsageByFirmware)
+		*val =  le16_to_cpu(atomDataPtr->VRAM_UsageByFirmware
+				    ->asFirmwareVramReserveInfo[0].usFirmwareUseInKb);
+	    else
+		return ATOM_NOT_IMPLEMENTED;
 	    break;
 	default:
 	    return ATOM_NOT_IMPLEMENTED;
@@ -1391,36 +1386,6 @@ const int object_connector_convert[] =
       CONNECTOR_DISPLAY_PORT,
     };
 
-static void
-rhdAtomParseI2CRecord(atomBiosHandlePtr handle,
-			ATOM_I2C_RECORD *Record, int *ddc_line)
-{
-    ErrorF(" %s:  I2C Record: %s[%x] EngineID: %x I2CAddr: %x\n",
-	     __func__,
-	     Record->sucI2cId.bfHW_Capable ? "HW_Line" : "GPIO_ID",
-	     Record->sucI2cId.bfI2C_LineMux,
-	     Record->sucI2cId.bfHW_EngineID,
-	     Record->ucI2CAddr);
-
-    if (!*(unsigned char *)&(Record->sucI2cId))
-	*ddc_line = 0;
-    else {
-	if (Record->ucI2CAddr != 0)
-	    return;
-
-	if (Record->sucI2cId.bfHW_Capable) {
-	    switch(Record->sucI2cId.bfI2C_LineMux) {
-	    case 0: *ddc_line = 0x7e40; break;
-	    case 1: *ddc_line = 0x7e50; break;
-	    case 2: *ddc_line = 0x7e30; break;
-	    default: break;
-	    }
-	    return;
-	} else {
-	    /* add GPIO pin parsing */
-	}
-    }
-}
 
 static RADEONI2CBusRec
 RADEONLookupGPIOLineForDDC(ScrnInfoPtr pScrn, uint8_t id)
@@ -1450,12 +1415,16 @@ RADEONLookupGPIOLineForDDC(ScrnInfoPtr pScrn, uint8_t id)
     i2c.put_data_reg = le16_to_cpu(gpio.usDataEnRegisterIndex) * 4;
     i2c.get_clk_reg = le16_to_cpu(gpio.usClkY_RegisterIndex) * 4;
     i2c.get_data_reg = le16_to_cpu(gpio.usDataY_RegisterIndex) * 4;
+    i2c.a_clk_reg = le16_to_cpu(gpio.usClkA_RegisterIndex) * 4;
+    i2c.a_data_reg = le16_to_cpu(gpio.usDataA_RegisterIndex) * 4;
     i2c.mask_clk_mask = (1 << gpio.ucClkMaskShift);
     i2c.mask_data_mask = (1 << gpio.ucDataMaskShift);
     i2c.put_clk_mask = (1 << gpio.ucClkEnShift);
     i2c.put_data_mask = (1 << gpio.ucDataEnShift);
     i2c.get_clk_mask = (1 << gpio.ucClkY_Shift);
     i2c.get_data_mask = (1 <<  gpio.ucDataY_Shift);
+    i2c.a_clk_mask = (1 << gpio.ucClkA_Shift);
+    i2c.a_data_mask = (1 <<  gpio.ucDataA_Shift);
     i2c.valid = TRUE;
 
 #if 0
@@ -1465,21 +1434,28 @@ RADEONLookupGPIOLineForDDC(ScrnInfoPtr pScrn, uint8_t id)
     ErrorF("put_data_reg: 0x%x\n", gpio.usDataEnRegisterIndex * 4);
     ErrorF("get_clk_reg: 0x%x\n", gpio.usClkY_RegisterIndex * 4);
     ErrorF("get_data_reg: 0x%x\n", gpio.usDataY_RegisterIndex * 4);
-    ErrorF("other_clk_reg: 0x%x\n", gpio.usClkA_RegisterIndex * 4);
-    ErrorF("other_data_reg: 0x%x\n", gpio.usDataA_RegisterIndex * 4);
+    ErrorF("a_clk_reg: 0x%x\n", gpio.usClkA_RegisterIndex * 4);
+    ErrorF("a_data_reg: 0x%x\n", gpio.usDataA_RegisterIndex * 4);
     ErrorF("mask_clk_mask: %d\n", gpio.ucClkMaskShift);
     ErrorF("mask_data_mask: %d\n", gpio.ucDataMaskShift);
     ErrorF("put_clk_mask: %d\n", gpio.ucClkEnShift);
     ErrorF("put_data_mask: %d\n", gpio.ucDataEnShift);
     ErrorF("get_clk_mask: %d\n", gpio.ucClkY_Shift);
     ErrorF("get_data_mask: %d\n", gpio.ucDataY_Shift);
-    ErrorF("other_clk_mask: %d\n", gpio.ucClkA_Shift);
-    ErrorF("other_data_mask: %d\n", gpio.ucDataA_Shift);
+    ErrorF("a_clk_mask: %d\n", gpio.ucClkA_Shift);
+    ErrorF("a_data_mask: %d\n", gpio.ucDataA_Shift);
 #endif
 
     return i2c;
 }
 
+static RADEONI2CBusRec
+rhdAtomParseI2CRecord(ScrnInfoPtr pScrn, atomBiosHandlePtr handle,
+			ATOM_I2C_RECORD *Record)
+{
+    return RADEONLookupGPIOLineForDDC(pScrn, Record->sucI2cId.bfI2C_LineMux);
+}
+
 Bool
 RADEONGetATOMConnectorInfoFromBIOSObject (ScrnInfoPtr pScrn)
 {
@@ -1489,7 +1465,7 @@ RADEONGetATOMConnectorInfoFromBIOSObject (ScrnInfoPtr pScrn)
     atomDataTablesPtr atomDataPtr;
     ATOM_CONNECTOR_OBJECT_TABLE *con_obj;
     ATOM_INTEGRATED_SYSTEM_INFO_V2 *igp_obj = NULL;
-    int i, j, ddc_line = 0;
+    int i, j;
 
     atomDataPtr = info->atomBIOS->atomDataPtr;
     if (!rhdAtomGetTableRevisionAndSize((ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->Object_Header), &crev, &frev, &size))
@@ -1617,10 +1593,8 @@ RADEONGetATOMConnectorInfoFromBIOSObject (ScrnInfoPtr pScrn)
 	    ErrorF("record type %d\n", Record->ucRecordType);
 	    switch (Record->ucRecordType) {
 		case ATOM_I2C_RECORD_TYPE:
-		    rhdAtomParseI2CRecord(info->atomBIOS,
-					  (ATOM_I2C_RECORD *)Record,
-					  &ddc_line);
-		    info->BiosConnector[i].ddc_i2c = atom_setup_i2c_bus(ddc_line);
+		    info->BiosConnector[i].ddc_i2c = rhdAtomParseI2CRecord(pScrn, info->atomBIOS,
+									   (ATOM_I2C_RECORD *)Record);
 		    break;
 		case ATOM_HPD_INT_RECORD_TYPE:
 		    break;
@@ -1751,6 +1725,15 @@ static void RADEONApplyATOMQuirks(ScrnInfoPtr pScrn, int index)
 	}
     }
 
+    /* Falcon NW laptop lists vga ddc line for LVDS */
+    if ((info->Chipset == PCI_CHIP_RV410_5653) &&
+	(PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1462) &&
+	(PCI_SUB_DEVICE_ID(info->PciInfo) == 0x0291)) {
+	if (info->BiosConnector[index].ConnectorType == CONNECTOR_LVDS) {
+	    info->BiosConnector[index].ddc_i2c.valid = FALSE;
+	}
+    }
+
 }
 
 Bool
@@ -2027,9 +2010,12 @@ RHDAtomBiosFunc(int scrnIndex, atomBiosHandlePtr handle,
 VOID*
 CailAllocateMemory(VOID *CAIL,UINT16 size)
 {
+    void *ret;
     CAILFUNC(CAIL);
 
-    return malloc(size);
+    ret = malloc(size);
+    memset(ret, 0, size);
+    return ret;
 }
 
 VOID
@@ -2256,4 +2242,15 @@ atombios_get_command_table_version(atomBiosHandlePtr atomBIOS, int index, int *m
 }
 
 
+UINT16 ATOM_BSWAP16(UINT16 x)
+{
+    return bswap_16(x);
+}
+
+UINT32 ATOM_BSWAP32(UINT32 x)
+{
+    return bswap_32(x);
+}
+
+
 #endif /* ATOM_BIOS */
diff --git a/src/radeon_atomwrapper.c b/src/radeon_atomwrapper.c
index 3e7ae01..bed1471 100644
--- a/src/radeon_atomwrapper.c
+++ b/src/radeon_atomwrapper.c
@@ -31,6 +31,7 @@
 
 #define INT32 INT32
 #include "CD_Common_Types.h"
+#include "atombios.h"
 #include "CD_Definitions.h"
 
 
diff --git a/src/radeon_bios.c b/src/radeon_bios.c
index 529dda7..b34a421 100644
--- a/src/radeon_bios.c
+++ b/src/radeon_bios.c
@@ -266,6 +266,26 @@ radeon_read_unposted_bios(ScrnInfoPtr pScrn)
     return ret;
 }
 
+Bool
+radeon_card_posted(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr info     = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    uint32_t reg;
+
+    if (IS_AVIVO_VARIANT) {
+	reg = INREG(AVIVO_D1CRTC_CONTROL) | INREG(AVIVO_D2CRTC_CONTROL);
+	if (reg & AVIVO_CRTC_EN)
+	    return TRUE;
+    } else {
+	reg = INREG(RADEON_CRTC_GEN_CNTL) | INREG(RADEON_CRTC2_GEN_CNTL);
+	if (reg & RADEON_CRTC_EN)
+	    return TRUE;
+    }
+
+    return FALSE;
+}
+
 /* Read the Video BIOS block and the FP registers (if applicable). */
 Bool
 RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr  pInt10)
@@ -273,6 +293,7 @@ RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr  pInt10)
     RADEONInfoPtr info     = RADEONPTR(pScrn);
     int tmp;
     unsigned short dptr;
+    Bool posted = TRUE;
 
 #ifdef XSERVER_LIBPCIACCESS
     int size = info->PciInfo->rom_size > RADEON_VBIOS_SIZE ? info->PciInfo->rom_size : RADEON_VBIOS_SIZE;
@@ -291,6 +312,7 @@ RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr  pInt10)
 			 RADEON_VBIOS_SIZE);
 	} else if (!radeon_read_bios(pScrn)) {
 	    (void)radeon_read_unposted_bios(pScrn);
+	    posted = FALSE;
 	}
     }
 
@@ -326,7 +348,7 @@ RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr  pInt10)
 	info->VBIOS = NULL;
 	return FALSE;
     }
- 
+
     tmp = info->ROMHeaderStart + 4;
     if ((RADEON_BIOS8(tmp)   == 'A' &&
 	 RADEON_BIOS8(tmp+1) == 'T' &&
@@ -344,51 +366,65 @@ RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr  pInt10)
 	       info->IsAtomBios ? "ATOM":"Legacy");
 
     if (info->IsAtomBios) {
-        AtomBiosArgRec atomBiosArg;
+	AtomBiosArgRec atomBiosArg;
 
-        if (RHDAtomBiosFunc(pScrn->scrnIndex, NULL, ATOMBIOS_INIT, &atomBiosArg)
-            == ATOM_SUCCESS) {
-            info->atomBIOS = atomBiosArg.atomhandle;
-        }
+	if (RHDAtomBiosFunc(pScrn->scrnIndex, NULL, ATOMBIOS_INIT, &atomBiosArg)
+	    == ATOM_SUCCESS) {
+	    info->atomBIOS = atomBiosArg.atomhandle;
+	}
 
-        atomBiosArg.fb.start = info->FbFreeStart;
-        atomBiosArg.fb.size = info->FbFreeSize;
-        if (RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, ATOMBIOS_ALLOCATE_FB_SCRATCH,
+	atomBiosArg.fb.start = info->FbFreeStart;
+	atomBiosArg.fb.size = info->FbFreeSize;
+	if (RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, ATOMBIOS_ALLOCATE_FB_SCRATCH,
 			    &atomBiosArg) == ATOM_SUCCESS) {
 
 	    info->FbFreeStart = atomBiosArg.fb.start;
 	    info->FbFreeSize = atomBiosArg.fb.size;
-        }
-
-        RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, GET_DEFAULT_ENGINE_CLOCK,
-                        &atomBiosArg);
-        RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, GET_DEFAULT_MEMORY_CLOCK,
-                        &atomBiosArg);
-        RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS,
-                        GET_MAX_PIXEL_CLOCK_PLL_OUTPUT, &atomBiosArg);
-        RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS,
-                        GET_MIN_PIXEL_CLOCK_PLL_OUTPUT, &atomBiosArg);
-        RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS,
-                        GET_MAX_PIXEL_CLOCK_PLL_INPUT, &atomBiosArg);
-        RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS,
+	}
+
+	RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, GET_DEFAULT_ENGINE_CLOCK,
+			&atomBiosArg);
+	RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, GET_DEFAULT_MEMORY_CLOCK,
+			&atomBiosArg);
+	RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS,
+			GET_MAX_PIXEL_CLOCK_PLL_OUTPUT, &atomBiosArg);
+	RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS,
+			GET_MIN_PIXEL_CLOCK_PLL_OUTPUT, &atomBiosArg);
+	RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS,
+			GET_MAX_PIXEL_CLOCK_PLL_INPUT, &atomBiosArg);
+	RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS,
 			GET_MIN_PIXEL_CLOCK_PLL_INPUT, &atomBiosArg);
-        RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS,
+	RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS,
 			GET_MAX_PIXEL_CLK, &atomBiosArg);
-        RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS,
-                        GET_REF_CLOCK, &atomBiosArg);
+	RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS,
+			GET_REF_CLOCK, &atomBiosArg);
 
 	info->MasterDataStart = RADEON_BIOS16 (info->ROMHeaderStart + 32);
     }
+
+    /* We are a bit too quick at using this "unposted" to re-post the
+     * card. This causes some problems with VT switch on some machines,
+     * so let's work around this for now by only POSTing if none of the
+     * CRTCs are enabled
+     */
+    if ((!posted) && info->VBIOS) {
+	posted = radeon_card_posted(pScrn);
+    }
+
+    if ((!posted) && info->VBIOS) {
+	if (info->IsAtomBios) {
+	    if (!rhdAtomASICInit(info->atomBIOS))
+		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			   "%s: AsicInit failed.\n",__func__);
+	} else {
 #if 0
-    else {
-	/* non-primary card may need posting */
-	if (!pInt10) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Attempting to POST via BIOS tables\n");
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Attempting to POST via legacy BIOS tables\n");
 	    RADEONGetBIOSInitTableOffsets(pScrn);
 	    RADEONPostCardFromBIOSTables(pScrn);
+#endif
 	}
     }
-#endif
+
     return TRUE;
 }
 
@@ -397,7 +433,7 @@ static Bool RADEONGetATOMConnectorInfoFromBIOS (ScrnInfoPtr pScrn)
     RADEONInfoPtr info = RADEONPTR (pScrn);
 
     if (!info->VBIOS) return FALSE;
-    
+
     if (RADEONGetATOMConnectorInfoFromBIOSObject(pScrn))
 	return TRUE;
 
@@ -411,28 +447,41 @@ static void RADEONApplyLegacyQuirks(ScrnInfoPtr pScrn, int index)
 {
     RADEONInfoPtr info = RADEONPTR (pScrn);
 
-    /* on XPRESS chips, CRT2_DDC and MONID_DCC both use the 
-     * MONID gpio, but use different pins.
-     * CRT2_DDC uses the standard pinout, MONID_DDC uses
-     * something else.
+    /* For RS300/RS350/RS400 chips, there is no primary DAC. Force VGA port to use TVDAC
+     * Also there is no internal TMDS
      */
+    if ((info->ChipFamily == CHIP_FAMILY_RS300) ||
+	(info->ChipFamily == CHIP_FAMILY_RS400) ||
+	(info->ChipFamily == CHIP_FAMILY_RS480)) {
+	info->BiosConnector[index].DACType = DAC_TVDAC;
+	info->BiosConnector[index].TMDSType = TMDS_EXT;
+    }
+
+    /* XPRESS DDC quirks */
     if ((info->ChipFamily == CHIP_FAMILY_RS400 ||
 	 info->ChipFamily == CHIP_FAMILY_RS480) &&
-	info->BiosConnector[index].ConnectorType == CONNECTOR_VGA &&
 	info->BiosConnector[index].ddc_i2c.mask_clk_reg == RADEON_GPIO_CRT2_DDC) {
 	info->BiosConnector[index].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID);
-    }
-
-    /* XPRESS desktop chips seem to have a proprietary connector listed for
-     * DVI-D, try and do the right thing here.
-     */
-    if ((!info->IsMobility) &&
-	(info->BiosConnector[index].ConnectorType == CONNECTOR_LVDS)) {
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "Proprietary connector found, assuming DVI-D\n");
-	info->BiosConnector[index].DACType = DAC_NONE;
-	info->BiosConnector[index].TMDSType = TMDS_EXT;
-	info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_D;
+    } else if ((info->ChipFamily == CHIP_FAMILY_RS400 ||
+		info->ChipFamily == CHIP_FAMILY_RS480) &&
+	       info->BiosConnector[index].ddc_i2c.mask_clk_reg == RADEON_GPIO_MONID) {
+	info->BiosConnector[index].ddc_i2c.valid = TRUE;
+	info->BiosConnector[index].ddc_i2c.mask_clk_mask = (0x20 << 8);
+	info->BiosConnector[index].ddc_i2c.mask_data_mask = 0x80;
+	info->BiosConnector[index].ddc_i2c.a_clk_mask = (0x20 << 8);
+	info->BiosConnector[index].ddc_i2c.a_data_mask = 0x80;
+	info->BiosConnector[index].ddc_i2c.put_clk_mask = (0x20 << 8);
+	info->BiosConnector[index].ddc_i2c.put_data_mask = 0x80;
+	info->BiosConnector[index].ddc_i2c.get_clk_mask = (0x20 << 8);
+	info->BiosConnector[index].ddc_i2c.get_data_mask = 0x80;
+	info->BiosConnector[index].ddc_i2c.mask_clk_reg = RADEON_GPIOPAD_MASK;
+	info->BiosConnector[index].ddc_i2c.mask_data_reg = RADEON_GPIOPAD_MASK;
+	info->BiosConnector[index].ddc_i2c.a_clk_reg = RADEON_GPIOPAD_A;
+	info->BiosConnector[index].ddc_i2c.a_data_reg = RADEON_GPIOPAD_A;
+	info->BiosConnector[index].ddc_i2c.put_clk_reg = RADEON_GPIOPAD_EN;
+	info->BiosConnector[index].ddc_i2c.put_data_reg = RADEON_GPIOPAD_EN;
+	info->BiosConnector[index].ddc_i2c.get_clk_reg = RADEON_LCD_GPIO_Y_REG;
+	info->BiosConnector[index].ddc_i2c.get_data_reg = RADEON_LCD_GPIO_Y_REG;
     }
 
     /* Certain IBM chipset RN50s have a BIOS reporting two VGAs,
@@ -454,6 +503,16 @@ static void RADEONApplyLegacyQuirks(ScrnInfoPtr pScrn, int index)
 	}
     }
 
+    /* X300 card with extra non-existent DVI port */
+    if (info->Chipset == PCI_CHIP_RV370_5B60 &&
+	PCI_SUB_VENDOR_ID(info->PciInfo) == 0x17af &&
+	PCI_SUB_DEVICE_ID(info->PciInfo) == 0x201e &&
+	index == 2) {
+	if (info->BiosConnector[index].ConnectorType == CONNECTOR_DVI_I) {
+	    info->BiosConnector[index].valid = FALSE;
+	}
+    }
+
 }
 
 static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn)
@@ -479,7 +538,7 @@ static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn)
 	    ConnectorType = (tmp >> 12) & 0xf;
 	    switch (ConnectorType) {
 	    case CONNECTOR_PROPRIETARY_LEGACY:
-		info->BiosConnector[i].ConnectorType = CONNECTOR_LVDS;
+		info->BiosConnector[i].ConnectorType = CONNECTOR_DVI_D;
 		break;
 	    case CONNECTOR_CRT_LEGACY:
 		info->BiosConnector[i].ConnectorType = CONNECTOR_VGA;
@@ -528,10 +587,6 @@ static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn)
 	    else
 		info->BiosConnector[i].DACType = DAC_PRIMARY;
 
-	    /* For RS300/RS350/RS400 chips, there is no primary DAC. Force VGA port to use TVDAC*/
-	    if (info->IsIGP)
-		info->BiosConnector[i].DACType = DAC_TVDAC;
-
 	    if ((tmp >> 4) & 0x1)
 		info->BiosConnector[i].TMDSType = TMDS_EXT;
 	    else
@@ -560,7 +615,10 @@ static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn)
     }
 
     /* check LVDS table */
-    if (info->IsMobility) {
+    /* RS4xx can be mobile or desktop so check the connectors */
+    if (info->IsMobility ||
+	info->ChipFamily == CHIP_FAMILY_RS400 ||
+	info->ChipFamily == CHIP_FAMILY_RS480) {
 	offset = RADEON_BIOS16(info->ROMHeaderStart + 0x40);
 	if (offset) {
 	    info->BiosConnector[4].valid = TRUE;
@@ -591,10 +649,10 @@ static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn)
 			    break;
 			case DDC_LCD:
 			    info->BiosConnector[4].ddc_i2c = legacy_setup_i2c_bus(RADEON_LCD_GPIO_MASK);
-			    info->BiosConnector[4].ddc_i2c.mask_clk_mask =
-				RADEON_BIOS32(tmp0 + 0x03) | RADEON_BIOS32(tmp0 + 0x07);
-			    info->BiosConnector[4].ddc_i2c.mask_data_mask =
-				RADEON_BIOS32(tmp0 + 0x03) | RADEON_BIOS32(tmp0 + 0x07);
+			    info->BiosConnector[4].ddc_i2c.mask_clk_mask = RADEON_BIOS32(tmp0 + 0x03);
+			    info->BiosConnector[4].ddc_i2c.mask_data_mask = RADEON_BIOS32(tmp0 + 0x07);
+			    info->BiosConnector[4].ddc_i2c.a_clk_mask = RADEON_BIOS32(tmp0 + 0x03);
+			    info->BiosConnector[4].ddc_i2c.a_data_mask = RADEON_BIOS32(tmp0 + 0x07);
 			    info->BiosConnector[4].ddc_i2c.put_clk_mask = RADEON_BIOS32(tmp0 + 0x03);
 			    info->BiosConnector[4].ddc_i2c.put_data_mask = RADEON_BIOS32(tmp0 + 0x07);
 			    info->BiosConnector[4].ddc_i2c.get_clk_mask = RADEON_BIOS32(tmp0 + 0x03);
@@ -602,10 +660,10 @@ static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn)
 			    break;
 			case DDC_GPIO:
 			    info->BiosConnector[4].ddc_i2c = legacy_setup_i2c_bus(RADEON_MDGPIO_EN_REG);
-			    info->BiosConnector[4].ddc_i2c.mask_clk_mask =
-				RADEON_BIOS32(tmp0 + 0x03) | RADEON_BIOS32(tmp0 + 0x07);
-			    info->BiosConnector[4].ddc_i2c.mask_data_mask =
-				RADEON_BIOS32(tmp0 + 0x03) | RADEON_BIOS32(tmp0 + 0x07);
+			    info->BiosConnector[4].ddc_i2c.mask_clk_mask =  RADEON_BIOS32(tmp0 + 0x03);
+			    info->BiosConnector[4].ddc_i2c.mask_data_mask = RADEON_BIOS32(tmp0 + 0x07);
+			    info->BiosConnector[4].ddc_i2c.a_clk_mask = RADEON_BIOS32(tmp0 + 0x03);
+			    info->BiosConnector[4].ddc_i2c.a_data_mask = RADEON_BIOS32(tmp0 + 0x07);
 			    info->BiosConnector[4].ddc_i2c.put_clk_mask = RADEON_BIOS32(tmp0 + 0x03);
 			    info->BiosConnector[4].ddc_i2c.put_data_mask = RADEON_BIOS32(tmp0 + 0x07);
 			    info->BiosConnector[4].ddc_i2c.get_clk_mask = RADEON_BIOS32(tmp0 + 0x03);
@@ -1118,6 +1176,50 @@ Bool RADEONGetTMDSInfoFromBIOS (xf86OutputPtr output)
     return FALSE;
 }
 
+static RADEONI2CBusRec
+RADEONLookupI2CBlock(ScrnInfoPtr pScrn, int id)
+{
+    RADEONInfoPtr info = RADEONPTR (pScrn);
+    int offset, blocks, i;
+    RADEONI2CBusRec i2c;
+
+    memset(&i2c, 0, sizeof(RADEONI2CBusRec));
+    i2c.valid = FALSE;
+
+    offset = RADEON_BIOS16(info->ROMHeaderStart + 0x70);
+    if (offset) {
+	blocks = RADEON_BIOS8(offset + 2);
+	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);
+
+		i2c.mask_clk_mask = (1 << clock_shift);
+		i2c.mask_data_mask = (1 << data_shift);
+		i2c.a_clk_mask = (1 << clock_shift);
+		i2c.a_data_mask = (1 << data_shift);
+		i2c.put_clk_mask = (1 << clock_shift);
+		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.valid = TRUE;
+		break;
+	    }
+	}
+    }
+    return i2c;
+}
+
 Bool RADEONGetExtTMDSInfoFromBIOS (xf86OutputPtr output)
 {
     ScrnInfoPtr pScrn = output->scrn;
@@ -1129,6 +1231,52 @@ Bool RADEONGetExtTMDSInfoFromBIOS (xf86OutputPtr output)
 
     if (info->IsAtomBios) {
 	return FALSE;
+    } else if (info->IsIGP) {
+	/* RS4xx TMDS stuff is in the mobile table */
+	offset = RADEON_BIOS16(info->ROMHeaderStart + 0x42);
+	if (offset) {
+	    int rev = RADEON_BIOS8(offset);
+	    if (rev >= 6) {
+		offset = RADEON_BIOS16(offset + 0x17);
+		if (offset) {
+		    offset = RADEON_BIOS16(offset + 2);
+		    rev = RADEON_BIOS8(offset);
+		    if (offset && (rev > 1)) {
+			int blocks = RADEON_BIOS8(offset + 3);
+			int index = offset + 4;
+			radeon_output->dvo_i2c.valid = FALSE;
+			while (blocks > 0) {
+			    int id = RADEON_BIOS16(index);
+			    index += 2;
+			    switch (id >> 13) {
+			    case 0:
+				index += 6;
+				break;
+			    case 2:
+				index += 10;
+				break;
+			    case 3:
+				index += 2;
+				break;
+			    case 4:
+				index += 2;
+				break;
+			    case 6:
+				radeon_output->dvo_i2c_slave_addr =
+				    RADEON_BIOS16(index) & 0xff;
+				index += 2;
+				radeon_output->dvo_i2c =
+				    RADEONLookupI2CBlock(pScrn, RADEON_BIOS8(index));
+				return TRUE;
+			    default:
+				break;
+			    }
+			    blocks--;
+			}
+		    }
+		}
+	    }
+	}
     } else {
 	offset = RADEON_BIOS16(info->ROMHeaderStart + 0x58);
 	if (offset) {
@@ -1148,10 +1296,11 @@ Bool RADEONGetExtTMDSInfoFromBIOS (xf86OutputPtr output)
 		radeon_output->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
 	    else if (gpio_reg == 4)
 		radeon_output->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
-	    else if (gpio_reg == 5)
+	    else if (gpio_reg == 5) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			   "unsupported MM gpio_reg\n");
-	    else {
+		return FALSE;
+	    } else {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 			   "Unknown gpio reg: %d\n", gpio_reg);
 		return FALSE;
@@ -1179,12 +1328,82 @@ Bool RADEONInitExtTMDSInfoFromBIOS (xf86OutputPtr output)
     unsigned char *RADEONMMIO = info->MMIO;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
     int offset, index, id;
-    uint32_t val, reg, andmask, ormask;
+    uint32_t val, reg, and_mask, or_mask;
 
     if (!info->VBIOS) return FALSE;
 
     if (info->IsAtomBios) {
 	return FALSE;
+    } else if (info->IsIGP) {
+	/* RS4xx TMDS stuff is in the mobile table */
+	offset = RADEON_BIOS16(info->ROMHeaderStart + 0x42);
+	if (offset) {
+	    int rev = RADEON_BIOS8(offset);
+	    if (rev >= 6) {
+		offset = RADEON_BIOS16(offset + 0x17);
+		if (offset) {
+		    offset = RADEON_BIOS16(offset + 2);
+		    rev = RADEON_BIOS8(offset);
+		    if (offset && (rev > 1)) {
+			int blocks = RADEON_BIOS8(offset + 3);
+			index = offset + 4;
+			while (blocks > 0) {
+			    id = RADEON_BIOS16(index);
+			    index += 2;
+			    switch (id >> 13) {
+			    case 0:
+				reg = (id & 0x1fff) * 4;
+				val = RADEON_BIOS32(index);
+				index += 4;
+				ErrorF("MMIO: 0x%x 0x%x\n",
+				       (unsigned)reg, (unsigned)val);
+				OUTREG(reg, val);
+				break;
+			    case 2:
+				reg = (id & 0x1fff) * 4;
+				and_mask = RADEON_BIOS32(index);
+				index += 4;
+				or_mask = RADEON_BIOS32(index);
+				index += 4;
+				ErrorF("MMIO mask: 0x%x 0x%x 0x%x\n",
+				       (unsigned)reg, (unsigned)and_mask, (unsigned)or_mask);
+				val = INREG(reg);
+				val = (val & and_mask) | or_mask;
+				OUTREG(reg, val);
+				break;
+			    case 3:
+				val = RADEON_BIOS16(index);
+				index += 2;
+				ErrorF("delay: %u\n", (unsigned)val);
+				usleep(val);
+				break;
+			    case 4:
+				val = RADEON_BIOS16(index);
+				index += 2;
+				ErrorF("delay: %u\n", (unsigned)val * 1000);
+				usleep(val * 1000);
+				break;
+			    case 6:
+				index++;
+				reg = RADEON_BIOS8(index);
+				index++;
+				val = RADEON_BIOS8(index);
+				index++;
+				ErrorF("i2c write: 0x%x, 0x%x\n", (unsigned)reg,
+				       (unsigned)val);
+				RADEONDVOWriteByte(radeon_output->DVOChip, reg, val);
+				break;
+			    default:
+				ErrorF("unknown id %d\n", id>>13);
+				return FALSE;
+			    }
+			    blocks--;
+			}
+			return TRUE;
+		    }
+		}
+	    }
+	}
     } else {
 	offset = RADEON_BIOS16(info->ROMHeaderStart + 0x58);
 	if (offset) {
@@ -1194,24 +1413,24 @@ Bool RADEONInitExtTMDSInfoFromBIOS (xf86OutputPtr output)
 		index += 2;
 		switch(id >> 13) {
 		case 0:
-		    reg = id & 0x1fff;
+		    reg = (id & 0x1fff) * 4;
 		    val = RADEON_BIOS32(index);
 		    index += 4;
-		    ErrorF("WRITE INDEXED: 0x%x 0x%x\n",
+		    ErrorF("MMIO: 0x%x 0x%x\n",
 			   (unsigned)reg, (unsigned)val);
-		    /*OUTREG(reg, val);*/
+		    OUTREG(reg, val);
 		    break;
 		case 2:
-		    reg = id & 0x1fff;
-		    andmask = RADEON_BIOS32(index);
+		    reg = (id & 0x1fff) * 4;
+		    and_mask = RADEON_BIOS32(index);
 		    index += 4;
-		    ormask = RADEON_BIOS32(index);
+		    or_mask = RADEON_BIOS32(index);
 		    index += 4;
 		    val = INREG(reg);
-		    val = (val & andmask) | ormask;
-		    ErrorF("MASK DIRECT: 0x%x 0x%x 0x%x\n",
-			   (unsigned)reg, (unsigned)andmask, (unsigned)ormask);
-		    /*OUTREG(reg, val);*/
+		    val = (val & and_mask) | or_mask;
+		    ErrorF("MMIO mask: 0x%x 0x%x 0x%x\n",
+			   (unsigned)reg, (unsigned)and_mask, (unsigned)or_mask);
+		    OUTREG(reg, val);
 		    break;
 		case 4:
 		    val = RADEON_BIOS16(index);
@@ -1221,15 +1440,15 @@ Bool RADEONInitExtTMDSInfoFromBIOS (xf86OutputPtr output)
 		    break;
 		case 5:
 		    reg = id & 0x1fff;
-		    andmask = RADEON_BIOS32(index);
+		    and_mask = RADEON_BIOS32(index);
 		    index += 4;
-		    ormask = RADEON_BIOS32(index);
+		    or_mask = RADEON_BIOS32(index);
 		    index += 4;
-		    ErrorF("MASK PLL: 0x%x 0x%x 0x%x\n",
-			   (unsigned)reg, (unsigned)andmask, (unsigned)ormask);
-		    /*val = INPLL(pScrn, reg);
-		    val = (val & andmask) | ormask;
-		    OUTPLL(pScrn, reg, val);*/
+		    ErrorF("PLL mask: 0x%x 0x%x 0x%x\n",
+			   (unsigned)reg, (unsigned)and_mask, (unsigned)or_mask);
+		    val = INPLL(pScrn, reg);
+		    val = (val & and_mask) | or_mask;
+		    OUTPLL(pScrn, reg, val);
 		    break;
 		case 6:
 		    reg = id & 0x1fff;
diff --git a/src/radeon_chipinfo_gen.h b/src/radeon_chipinfo_gen.h
index ed3174a..daaf717 100644
--- a/src/radeon_chipinfo_gen.h
+++ b/src/radeon_chipinfo_gen.h
@@ -1,6 +1,7 @@
 /* This file is autogenerated please do not edit */
 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 },
  { 0x3154, CHIP_FAMILY_RV380, 1, 0, 0, 0, 0 },
  { 0x3E50, CHIP_FAMILY_RV380, 0, 0, 0, 0, 0 },
@@ -250,6 +251,9 @@ RADEONCardInfo RADEONCards[] = {
  { 0x940A, CHIP_FAMILY_R600, 0, 0, 0, 0, 0 },
  { 0x940B, CHIP_FAMILY_R600, 0, 0, 0, 0, 0 },
  { 0x940F, CHIP_FAMILY_R600, 0, 0, 0, 0, 0 },
+ { 0x9440, CHIP_FAMILY_RV770, 0, 0, 0, 0, 0 },
+ { 0x9441, CHIP_FAMILY_RV770, 0, 0, 0, 0, 0 },
+ { 0x9442, CHIP_FAMILY_RV770, 0, 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 },
@@ -267,6 +271,7 @@ RADEONCardInfo RADEONCards[] = {
  { 0x9507, CHIP_FAMILY_RV670, 0, 0, 0, 0, 0 },
  { 0x950F, CHIP_FAMILY_RV670, 0, 0, 0, 0, 0 },
  { 0x9511, CHIP_FAMILY_RV670, 0, 0, 0, 0, 0 },
+ { 0x9515, CHIP_FAMILY_RV670, 0, 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 d1761d2..79b094a 100644
--- a/src/radeon_chipset_gen.h
+++ b/src/radeon_chipset_gen.h
@@ -1,6 +1,7 @@
 /* This file is autogenerated please do not edit */
 static SymTabRec RADEONChipsets[] = {
   { PCI_CHIP_RV380_3150, "ATI Radeon Mobility X600 (M24) 3150 (PCIE)" },
+  { PCI_CHIP_RV380_3151, "ATI FireMV 2400 (PCI)" },
   { PCI_CHIP_RV380_3152, "ATI Radeon Mobility X300 (M24) 3152 (PCIE)" },
   { PCI_CHIP_RV380_3154, "ATI FireGL M24 GL 3154 (PCIE)" },
   { PCI_CHIP_RV380_3E50, "ATI Radeon X600 (RV380) 3E50 (PCIE)" },
@@ -250,6 +251,9 @@ static SymTabRec RADEONChipsets[] = {
   { PCI_CHIP_R600_940A, "ATI FireGL V8650" },
   { PCI_CHIP_R600_940B, "ATI FireGL V8600" },
   { PCI_CHIP_R600_940F, "ATI FireGL V7600" },
+  { PCI_CHIP_RV770_9440, "ATI Radeon 4800 Series" },
+  { PCI_CHIP_RV770_9441, "ATI Radeon HD 4870 x2" },
+  { PCI_CHIP_RV770_9442, "ATI Radeon 4800 Series" },
   { PCI_CHIP_RV610_94C0, "ATI RV610" },
   { PCI_CHIP_RV610_94C1, "ATI Radeon HD 2400 XT" },
   { PCI_CHIP_RV610_94C3, "ATI Radeon HD 2400 Pro" },
@@ -267,6 +271,7 @@ static SymTabRec RADEONChipsets[] = {
   { PCI_CHIP_RV670_9507, "ATI RV670" },
   { PCI_CHIP_RV670_950F, "ATI Radeon HD3870 X2" },
   { PCI_CHIP_RV670_9511, "ATI FireGL V7700" },
+  { PCI_CHIP_RV670_9515, "ATI Radeon HD3850" },
   { 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_commonfuncs.c b/src/radeon_commonfuncs.c
index 58fe306..1de6bf8 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -158,13 +158,14 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 	if (info->ChipFamily == CHIP_FAMILY_RV515)
 	    vap_cntl |= (2 << R300_PVS_NUM_FPUS_SHIFT);
 	else if ((info->ChipFamily == CHIP_FAMILY_RV530) ||
-		 (info->ChipFamily == CHIP_FAMILY_RV560))
+		 (info->ChipFamily == CHIP_FAMILY_RV560) ||
+		 (info->ChipFamily == CHIP_FAMILY_RV570))
 	    vap_cntl |= (5 << R300_PVS_NUM_FPUS_SHIFT);
-	else if (info->ChipFamily == CHIP_FAMILY_R420)
+	else if ((info->ChipFamily == CHIP_FAMILY_RV410) ||
+		 (info->ChipFamily == CHIP_FAMILY_R420))
 	    vap_cntl |= (6 << R300_PVS_NUM_FPUS_SHIFT);
 	else if ((info->ChipFamily == CHIP_FAMILY_R520) ||
-		 (info->ChipFamily == CHIP_FAMILY_R580) ||
-		 (info->ChipFamily == CHIP_FAMILY_RV570))
+		 (info->ChipFamily == CHIP_FAMILY_R580))
 	    vap_cntl |= (8 << R300_PVS_NUM_FPUS_SHIFT);
 	else
 	    vap_cntl |= (4 << R300_PVS_NUM_FPUS_SHIFT);
@@ -218,7 +219,7 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 
 	/* pre-load the vertex shaders */
 	if (info->has_tcl) {
-	    /* exa mask shader program */
+	    /* exa mask/Xv bicubic shader program */
 	    BEGIN_ACCEL(13);
 	    OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_INDX_REG, 0);
 	    /* PVS inst 0 */
@@ -498,14 +499,14 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 	if (IS_R300_3D) {
 	    BEGIN_ACCEL(2);
 	    /* tex inst for src texture */
-	    OUT_ACCEL_REG(R300_US_TEX_INST_0,
+	    OUT_ACCEL_REG(R300_US_TEX_INST(0),
 			  (R300_TEX_SRC_ADDR(0) |
 			   R300_TEX_DST_ADDR(0) |
 			   R300_TEX_ID(0) |
 			   R300_TEX_INST(R300_TEX_INST_LD)));
 
 	    /* tex inst for mask texture */
-	    OUT_ACCEL_REG(R300_US_TEX_INST_1,
+	    OUT_ACCEL_REG(R300_US_TEX_INST(1),
 			  (R300_TEX_SRC_ADDR(1) |
 			   R300_TEX_DST_ADDR(1) |
 			   R300_TEX_ID(1) |
@@ -514,9 +515,8 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 	}
 
 	if (IS_R300_3D) {
-	    BEGIN_ACCEL(9);
+	    BEGIN_ACCEL(8);
 	    OUT_ACCEL_REG(R300_US_CONFIG, (0 << R300_NLEVEL_SHIFT) | R300_FIRST_TEX);
-	    OUT_ACCEL_REG(R300_US_PIXSIZE, 1); /* highest temp used */
 	    OUT_ACCEL_REG(R300_US_CODE_ADDR_0,
 			  (R300_ALU_START(0) |
 			   R300_ALU_SIZE(0) |
@@ -533,9 +533,8 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 			   R300_TEX_START(0) |
 			   R300_TEX_SIZE(0)));
 	} else {
-	    BEGIN_ACCEL(7);
+	    BEGIN_ACCEL(6);
 	    OUT_ACCEL_REG(R300_US_CONFIG, R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO);
-	    OUT_ACCEL_REG(R300_US_PIXSIZE, 1); /* highest temp used */
 	    OUT_ACCEL_REG(R500_US_FC_CTRL, 0);
 	}
 	OUT_ACCEL_REG(R300_US_W_FMT, 0);
diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c
index c63b650..5ab00c1 100644
--- a/src/radeon_crtc.c
+++ b/src/radeon_crtc.c
@@ -58,6 +58,14 @@ extern void atombios_crtc_mode_set(xf86CrtcPtr crtc,
 				   DisplayModePtr adjusted_mode,
 				   int x, int y);
 extern void atombios_crtc_dpms(xf86CrtcPtr crtc, int mode);
+extern void
+RADEONInitDispBandwidthLegacy(ScrnInfoPtr pScrn,
+			      DisplayModePtr mode1, int pixel_bytes1,
+			      DisplayModePtr mode2, int pixel_bytes2);
+extern void
+RADEONInitDispBandwidthAVIVO(ScrnInfoPtr pScrn,
+			     DisplayModePtr mode1, int pixel_bytes1,
+			     DisplayModePtr mode2, int pixel_bytes2);
 
 void
 radeon_crtc_dpms(xf86CrtcPtr crtc, int mode)
@@ -220,7 +228,12 @@ RADEONComputePLL(RADEONPLLPtr pll,
 			best_freq = current_freq;
 			best_error = error;
 			best_vco_diff = vco_diff;
-		    } else if ((flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) {
+		    } else if (((flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) ||
+			       ((flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) ||
+			       ((flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) ||
+			       ((flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) ||
+			       ((flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) ||
+			       ((flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) {
 			best_post_div = post_div;
 			best_ref_div = ref_div;
 			best_feedback_div = feedback_div;
@@ -567,6 +580,43 @@ static const xf86CrtcFuncsRec radeon_crtc_funcs = {
     .destroy = NULL, /* XXX */
 };
 
+void
+RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    DisplayModePtr mode1 = NULL, mode2 = NULL;
+    int pixel_bytes1 = info->CurrentLayout.pixel_bytes;
+    int pixel_bytes2 = info->CurrentLayout.pixel_bytes;
+
+    if (xf86_config->num_crtc == 2) {
+	if (xf86_config->crtc[1]->enabled &&
+	    xf86_config->crtc[0]->enabled) {
+	    mode1 = &xf86_config->crtc[0]->mode;
+	    mode2 = &xf86_config->crtc[1]->mode;
+	} else if (xf86_config->crtc[0]->enabled) {
+	    mode1 = &xf86_config->crtc[0]->mode;
+	} else if (xf86_config->crtc[1]->enabled) {
+	    mode2 = &xf86_config->crtc[1]->mode;
+	} else
+	    return;
+    } else {
+	if (info->IsPrimary)
+	    mode1 = &xf86_config->crtc[0]->mode;
+	else if (info->IsSecondary)
+	    mode2 = &xf86_config->crtc[0]->mode;
+	else if (xf86_config->crtc[0]->enabled)
+	    mode1 = &xf86_config->crtc[0]->mode;
+	else
+	    return;
+    }
+
+    if (IS_AVIVO_VARIANT)
+	RADEONInitDispBandwidthAVIVO(pScrn, mode1, pixel_bytes1, mode2, pixel_bytes2);
+    else
+	RADEONInitDispBandwidthLegacy(pScrn, mode1, pixel_bytes1, mode2, pixel_bytes2);
+}
+
 Bool RADEONAllocateControllers(ScrnInfoPtr pScrn, int mask)
 {
     RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
diff --git a/src/radeon_cursor.c b/src/radeon_cursor.c
index c4472db..13c2b9c 100644
--- a/src/radeon_cursor.c
+++ b/src/radeon_cursor.c
@@ -209,21 +209,23 @@ radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
     if (xorigin >= CURSOR_WIDTH)  xorigin = CURSOR_WIDTH - 1;
     if (yorigin >= CURSOR_HEIGHT) yorigin = CURSOR_HEIGHT - 1;
 
-    if (mode->Flags & V_INTERLACE)
-	y /= 2;
-    else if (mode->Flags & V_DBLSCAN)
-	y *= 2;
-
     if (IS_AVIVO_VARIANT) {
 	/* avivo cursor spans the full fb width */
-	x += crtc->x;
-	y += crtc->y;
+	if (crtc->rotatedData == NULL) {
+	    x += crtc->x;
+	    y += crtc->y;
+	}
 	avivo_lock_cursor(crtc, TRUE);
 	OUTREG(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, ((xorigin ? 0 : x) << 16)
 	       | (yorigin ? 0 : y));
 	OUTREG(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
 	avivo_lock_cursor(crtc, FALSE);
     } else {
+	if (mode->Flags & V_INTERLACE)
+	    y /= 2;
+	else if (mode->Flags & V_DBLSCAN)
+	    y *= 2;
+
 	if (crtc_id == 0) {
 	    OUTREG(RADEON_CUR_HORZ_VERT_OFF,  (RADEON_CUR_LOCK
 					       | (xorigin << 16)
diff --git a/src/radeon_dri.c b/src/radeon_dri.c
index 0fc03e4..a192811 100644
--- a/src/radeon_dri.c
+++ b/src/radeon_dri.c
@@ -1103,7 +1103,7 @@ static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen)
 
     drmInfo.sarea_priv_offset   = sizeof(XF86DRISAREARec);
     drmInfo.is_pci              = (info->cardType!=CARD_AGP);
-    drmInfo.cp_mode             = info->CPMode;
+    drmInfo.cp_mode             = RADEON_CSQ_PRIBM_INDBM;
     drmInfo.gart_size           = info->gartSize*1024*1024;
     drmInfo.ring_size           = info->ringSize*1024*1024;
     drmInfo.usec_timeout        = info->CPusecTimeout;
@@ -1211,6 +1211,12 @@ static void RADEONDRIIrqInit(RADEONInfoPtr info, ScreenPtr pScreen)
 	} else {
 	    unsigned char *RADEONMMIO = info->MMIO;
 	    info->ModeReg->gen_int_cntl = INREG( RADEON_GEN_INT_CNTL );
+
+	    /* Let the DRM know it can safely disable the vblank interrupts */
+	    radeon_crtc_modeset_ioctl(XF86_CRTC_CONFIG_PTR(pScrn)->crtc[0],
+				      FALSE);
+	    radeon_crtc_modeset_ioctl(XF86_CRTC_CONFIG_PTR(pScrn)->crtc[0],
+				      TRUE);
 	}
     }
 
@@ -1453,10 +1459,9 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen)
 		PCI_DEV_DEV(info->PciInfo),
 		PCI_DEV_FUNC(info->PciInfo));
     }
-    pDRIInfo->ddxDriverMajorVersion      = info->allowColorTiling ?
-    				RADEON_VERSION_MAJOR_TILED : RADEON_VERSION_MAJOR;
-    pDRIInfo->ddxDriverMinorVersion      = RADEON_VERSION_MINOR;
-    pDRIInfo->ddxDriverPatchVersion      = RADEON_VERSION_PATCH;
+    pDRIInfo->ddxDriverMajorVersion      = info->allowColorTiling ? 5 : 4;
+    pDRIInfo->ddxDriverMinorVersion      = 3;
+    pDRIInfo->ddxDriverPatchVersion      = 0;
     pDRIInfo->frameBufferPhysicalAddress = (void *)info->LinearAddr + info->frontOffset;
     pDRIInfo->frameBufferSize            = info->FbMapSize - info->FbSecureSize;
     pDRIInfo->frameBufferStride          = (pScrn->displayWidth *
diff --git a/src/radeon_dri.h b/src/radeon_dri.h
index 67892a6..6e3ad62 100644
--- a/src/radeon_dri.h
+++ b/src/radeon_dri.h
@@ -39,9 +39,8 @@
 #include "xf86drm.h"
 
 /* DRI Driver defaults */
-#define RADEON_DEFAULT_CP_PIO_MODE    RADEON_CSQ_PRIPIO_INDPIO
-#define RADEON_DEFAULT_CP_BM_MODE     RADEON_CSQ_PRIBM_INDBM
 #define RADEON_DEFAULT_GART_SIZE      8 /* MB (must be 2^n and > 4MB) */
+#define R300_DEFAULT_GART_SIZE        32 /* MB (for R300 and above) */
 #define RADEON_DEFAULT_RING_SIZE      1 /* MB (must be page aligned) */
 #define RADEON_DEFAULT_BUFFER_SIZE    2 /* MB (must be page aligned) */
 #define RADEON_DEFAULT_GART_TEX_SIZE  1 /* MB (must be page aligned) */
@@ -52,10 +51,6 @@
 
 #define RADEON_CARD_TYPE_RADEON       1
 
-#define RADEONCP_USE_RING_BUFFER(m)					\
-    (((m) == RADEON_CSQ_PRIBM_INDDIS) ||				\
-     ((m) == RADEON_CSQ_PRIBM_INDBM))
-
 typedef struct {
     /* DRI screen private data */
     int           deviceID;	/* PCI device ID */
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index f18ad99..45d2c2f 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -669,7 +669,14 @@ static void radeon_write_mc_fb_agp_location(ScrnInfoPtr pScrn, int mask, uint32_
     RADEONInfoPtr  info       = RADEONPTR(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
 
-    if (info->ChipFamily >= CHIP_FAMILY_R600) {
+    if (info->ChipFamily >= CHIP_FAMILY_RV770) {
+	if (mask & LOC_FB)
+	    OUTREG(R700_MC_VM_FB_LOCATION, fb_loc);
+	if (mask & LOC_AGP) {
+	    OUTREG(R600_MC_VM_AGP_BOT, agp_loc);
+	    OUTREG(R600_MC_VM_AGP_TOP, agp_loc_hi);
+	}
+    } else if (info->ChipFamily >= CHIP_FAMILY_R600) {
 	if (mask & LOC_FB)
 	    OUTREG(R600_MC_VM_FB_LOCATION, fb_loc);
 	if (mask & LOC_AGP) {
@@ -712,7 +719,14 @@ static void radeon_read_mc_fb_agp_location(ScrnInfoPtr pScrn, int mask, uint32_t
     RADEONInfoPtr  info       = RADEONPTR(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
 
-    if (info->ChipFamily >= CHIP_FAMILY_R600) {
+    if (info->ChipFamily >= CHIP_FAMILY_RV770) {
+	if (mask & LOC_FB)
+	    *fb_loc = INREG(R700_MC_VM_FB_LOCATION);
+	if (mask & LOC_AGP) {
+	    *agp_loc = INREG(R600_MC_VM_AGP_BOT);
+	    *agp_loc_hi = INREG(R600_MC_VM_AGP_TOP);
+	}
+    } else if (info->ChipFamily >= CHIP_FAMILY_R600) {
 	if (mask & LOC_FB)
 	    *fb_loc = INREG(R600_MC_VM_FB_LOCATION);
 	if (mask & LOC_AGP) {
@@ -2032,16 +2046,22 @@ static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn)
 
 static Bool RADEONPreInitInt10(ScrnInfoPtr pScrn, xf86Int10InfoPtr *ppInt10)
 {
-#if !defined(__powerpc__) && !defined(__sparc__)
+#if (!defined(__powerpc__) && !defined(__sparc__)) || \
+    (defined(XSERVER_LIBPCIACCESS) && HAVE_PCI_DEVICE_ENABLE)
     RADEONInfoPtr  info = RADEONPTR(pScrn);
+#endif
+#if !defined(__powerpc__) && !defined(__sparc__)
     unsigned char *RADEONMMIO = info->MMIO;
     uint32_t       fp2_gen_ctl_save   = 0;
+#endif
 
 #ifdef XSERVER_LIBPCIACCESS
 #if HAVE_PCI_DEVICE_ENABLE
     pci_device_enable(info->PciInfo);
 #endif
 #endif
+
+#if !defined(__powerpc__) && !defined(__sparc__)
     /* don't need int10 on atom cards.
      * in theory all radeons, but the older stuff
      * isn't 100% yet
@@ -2106,19 +2126,16 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn)
 
     if (info->Chipset == PCI_CHIP_RN50_515E ||
 	info->Chipset == PCI_CHIP_RN50_5969 ||
-	info->Chipset == PCI_CHIP_RC410_5A61 ||
-	info->Chipset == PCI_CHIP_RC410_5A62 ||
-	info->Chipset == PCI_CHIP_RS485_5975 ||
 	info->ChipFamily == CHIP_FAMILY_RS600 ||
 	info->ChipFamily >= CHIP_FAMILY_R600) {
 	if (xf86ReturnOptValBool(info->Options, OPTION_DRI, FALSE)) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		"Direct rendering for RN50/RC410/RS485/RS600/R600 forced on -- "
+		"Direct rendering for RN50/RS600/R600 forced on -- "
 		"This is NOT officially supported at the hardware level "
 		"and may cause instability or lockups\n");
 	} else {
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		"Direct rendering not officially supported on RN50/RC410/R600\n");
+		"Direct rendering not officially supported on RN50/RS600/R600\n");
 	    return FALSE;
 	}
     }
@@ -2167,14 +2184,11 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn)
 	"Direct rendering experimental on RS400/Xpress 200 enabled\n");
     }
 
-    if (xf86ReturnOptValBool(info->Options, OPTION_CP_PIO, FALSE)) {
-	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing CP into PIO mode\n");
-	info->CPMode = RADEON_DEFAULT_CP_PIO_MODE;
-    } else {
-	info->CPMode = RADEON_DEFAULT_CP_BM_MODE;
-    }
+    if (info->ChipFamily >= CHIP_FAMILY_R300)
+	info->gartSize      = R300_DEFAULT_GART_SIZE;
+    else
+	info->gartSize      = RADEON_DEFAULT_GART_SIZE;
 
-    info->gartSize      = RADEON_DEFAULT_GART_SIZE;
     info->ringSize      = RADEON_DEFAULT_RING_SIZE;
     info->bufSize       = RADEON_DEFAULT_BUFFER_SIZE;
     info->gartTexSize   = RADEON_DEFAULT_GART_TEX_SIZE;
@@ -4178,6 +4192,7 @@ avivo_save(ScrnInfoPtr pScrn, RADEONSavePtr save)
 
     state->crtc_master_en = INREG(AVIVO_DC_CRTC_MASTER_EN);
     state->crtc_tv_control = INREG(AVIVO_DC_CRTC_TV_CONTROL);
+    state->dc_lb_memory_split = INREG(AVIVO_DC_LB_MEMORY_SPLIT);
 
     state->pll1.ref_div_src = INREG(AVIVO_EXT1_PPLL_REF_DIV_SRC);
     state->pll1.ref_div = INREG(AVIVO_EXT1_PPLL_REF_DIV);
@@ -4233,8 +4248,10 @@ avivo_save(ScrnInfoPtr pScrn, RADEONSavePtr save)
     state->grph1.x_end = INREG(AVIVO_D1GRPH_X_END);
     state->grph1.y_end = INREG(AVIVO_D1GRPH_Y_END);
 
+    state->grph1.desktop_height = INREG(AVIVO_D1MODE_DESKTOP_HEIGHT);
     state->grph1.viewport_start = INREG(AVIVO_D1MODE_VIEWPORT_START);
     state->grph1.viewport_size = INREG(AVIVO_D1MODE_VIEWPORT_SIZE);
+    state->grph1.mode_data_format = INREG(AVIVO_D1MODE_DATA_FORMAT);
 
     state->crtc2.pll_source = INREG(AVIVO_PCLK_CRTC2_CNTL);
 
@@ -4272,8 +4289,10 @@ avivo_save(ScrnInfoPtr pScrn, RADEONSavePtr save)
     state->grph2.x_end = INREG(AVIVO_D2GRPH_X_END);
     state->grph2.y_end = INREG(AVIVO_D2GRPH_Y_END);
 
+    state->grph2.desktop_height = INREG(AVIVO_D2MODE_DESKTOP_HEIGHT);
     state->grph2.viewport_start = INREG(AVIVO_D2MODE_VIEWPORT_START);
     state->grph2.viewport_size = INREG(AVIVO_D2MODE_VIEWPORT_SIZE);
+    state->grph2.mode_data_format = INREG(AVIVO_D2MODE_DATA_FORMAT);
 
     if (IS_DCE3_VARIANT) {
 	/* save DVOA regs */
@@ -4477,14 +4496,71 @@ avivo_restore(ScrnInfoPtr pScrn, RADEONSavePtr restore)
     struct avivo_state *state = &restore->avivo;
     int i, j;
 
-    //    OUTMC(pScrn, AVIVO_MC_MEMORY_MAP, state->mc_memory_map);
-    //    OUTREG(AVIVO_VGA_MEMORY_BASE, state->vga_memory_base);
-    //    OUTREG(AVIVO_VGA_FB_START, state->vga_fb_start);
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "avivo_restore !\n");
+
+    /* Disable VGA control for now.. maybe needs to be changed */
+    OUTREG(AVIVO_D1VGA_CONTROL, 0);
+    OUTREG(AVIVO_D2VGA_CONTROL, 0);
+
+    /* Disable CRTCs */
+    OUTREG(AVIVO_D1CRTC_CONTROL,
+	   (INREG(AVIVO_D1CRTC_CONTROL) & ~0x300) | 0x01000000);
+    OUTREG(AVIVO_D2CRTC_CONTROL,
+	   (INREG(AVIVO_D2CRTC_CONTROL) & ~0x300) | 0x01000000);
+    OUTREG(AVIVO_D1CRTC_CONTROL,
+	   INREG(AVIVO_D1CRTC_CONTROL) & ~0x1);
+    OUTREG(AVIVO_D2CRTC_CONTROL,
+	   INREG(AVIVO_D2CRTC_CONTROL) & ~0x1);
+    OUTREG(AVIVO_D1CRTC_CONTROL,
+	   INREG(AVIVO_D1CRTC_CONTROL) | 0x100);
+    OUTREG(AVIVO_D2CRTC_CONTROL,
+	   INREG(AVIVO_D2CRTC_CONTROL) | 0x100);
+
+    /* Lock graph registers */
+    OUTREG(AVIVO_D1GRPH_UPDATE, AVIVO_D1GRPH_UPDATE_LOCK);
+    OUTREG(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS, state->grph1.prim_surf_addr);
+    OUTREG(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS, state->grph1.sec_surf_addr);
+    OUTREG(AVIVO_D1GRPH_CONTROL, state->grph1.control);
+    OUTREG(AVIVO_D1GRPH_SURFACE_OFFSET_X, state->grph1.x_offset);
+    OUTREG(AVIVO_D1GRPH_SURFACE_OFFSET_Y, state->grph1.y_offset);
+    OUTREG(AVIVO_D1GRPH_X_START, state->grph1.x_start);
+    OUTREG(AVIVO_D1GRPH_Y_START, state->grph1.y_start);
+    OUTREG(AVIVO_D1GRPH_X_END, state->grph1.x_end);
+    OUTREG(AVIVO_D1GRPH_Y_END, state->grph1.y_end);
+    OUTREG(AVIVO_D1GRPH_PITCH, state->grph1.pitch);
+    OUTREG(AVIVO_D1GRPH_ENABLE, state->grph1.enable);
+    OUTREG(AVIVO_D1GRPH_UPDATE, 0);
+
+    OUTREG(AVIVO_D2GRPH_UPDATE, AVIVO_D1GRPH_UPDATE_LOCK);
+    OUTREG(AVIVO_D2GRPH_PRIMARY_SURFACE_ADDRESS, state->grph2.prim_surf_addr);
+    OUTREG(AVIVO_D2GRPH_SECONDARY_SURFACE_ADDRESS, state->grph2.sec_surf_addr);
+    OUTREG(AVIVO_D2GRPH_CONTROL, state->grph2.control);
+    OUTREG(AVIVO_D2GRPH_SURFACE_OFFSET_X, state->grph2.x_offset);
+    OUTREG(AVIVO_D2GRPH_SURFACE_OFFSET_Y, state->grph2.y_offset);
+    OUTREG(AVIVO_D2GRPH_X_START, state->grph2.x_start);
+    OUTREG(AVIVO_D2GRPH_Y_START, state->grph2.y_start);
+    OUTREG(AVIVO_D2GRPH_X_END, state->grph2.x_end);
+    OUTREG(AVIVO_D2GRPH_Y_END, state->grph2.y_end);
+    OUTREG(AVIVO_D2GRPH_PITCH, state->grph2.pitch);
+    OUTREG(AVIVO_D2GRPH_ENABLE, state->grph2.enable);
+    OUTREG(AVIVO_D2GRPH_UPDATE, 0);
 
+    /* Whack some mode regs too */
+    OUTREG(AVIVO_D1SCL_UPDATE, AVIVO_D1SCL_UPDATE_LOCK);
+    OUTREG(AVIVO_D1MODE_DESKTOP_HEIGHT, state->grph1.desktop_height);
+    OUTREG(AVIVO_D1MODE_VIEWPORT_START, state->grph1.viewport_start);
+    OUTREG(AVIVO_D1MODE_VIEWPORT_SIZE, state->grph1.viewport_size);
+    OUTREG(AVIVO_D1MODE_DATA_FORMAT, state->grph1.mode_data_format);
+    OUTREG(AVIVO_D1SCL_UPDATE, 0);
 
-    OUTREG(AVIVO_DC_CRTC_MASTER_EN, state->crtc_master_en);
-    OUTREG(AVIVO_DC_CRTC_TV_CONTROL, state->crtc_tv_control);
+    OUTREG(AVIVO_D2SCL_UPDATE, AVIVO_D1SCL_UPDATE_LOCK);
+    OUTREG(AVIVO_D2MODE_DESKTOP_HEIGHT, state->grph2.desktop_height);
+    OUTREG(AVIVO_D2MODE_VIEWPORT_START, state->grph2.viewport_start);
+    OUTREG(AVIVO_D2MODE_VIEWPORT_SIZE, state->grph2.viewport_size);
+    OUTREG(AVIVO_D2MODE_DATA_FORMAT, state->grph2.mode_data_format);
+    OUTREG(AVIVO_D2SCL_UPDATE, 0);
 
+    /* Set the PLL */
     OUTREG(AVIVO_EXT1_PPLL_REF_DIV_SRC, state->pll1.ref_div_src);
     OUTREG(AVIVO_EXT1_PPLL_REF_DIV, state->pll1.ref_div);
     OUTREG(AVIVO_EXT1_PPLL_FB_DIV, state->pll1.fb_div);
@@ -4504,7 +4580,9 @@ avivo_restore(ScrnInfoPtr pScrn, RADEONSavePtr restore)
     OUTREG(AVIVO_P2PLL_INT_SS_CNTL, state->pll2.int_ss_cntl);
 
     OUTREG(AVIVO_PCLK_CRTC1_CNTL, state->crtc1.pll_source);
+    OUTREG(AVIVO_PCLK_CRTC2_CNTL, state->crtc2.pll_source);
 
+    /* Set the CRTC */
     OUTREG(AVIVO_D1CRTC_H_TOTAL, state->crtc1.h_total);
     OUTREG(AVIVO_D1CRTC_H_BLANK_START_END, state->crtc1.h_blank_start_end);
     OUTREG(AVIVO_D1CRTC_H_SYNC_A, state->crtc1.h_sync_a);
@@ -4519,29 +4597,12 @@ avivo_restore(ScrnInfoPtr pScrn, RADEONSavePtr restore)
     OUTREG(AVIVO_D1CRTC_V_SYNC_B, state->crtc1.v_sync_b);
     OUTREG(AVIVO_D1CRTC_V_SYNC_B_CNTL, state->crtc1.v_sync_b_cntl);
 
-    OUTREG(AVIVO_D1CRTC_CONTROL, state->crtc1.control);
-    OUTREG(AVIVO_D1CRTC_BLANK_CONTROL, state->crtc1.blank_control);
     OUTREG(AVIVO_D1CRTC_INTERLACE_CONTROL, state->crtc1.interlace_control);
     OUTREG(AVIVO_D1CRTC_STEREO_CONTROL, state->crtc1.stereo_control);
 
     OUTREG(AVIVO_D1CUR_CONTROL, state->crtc1.cursor_control);
 
-    OUTREG(AVIVO_D1GRPH_ENABLE, state->grph1.enable);
-    OUTREG(AVIVO_D1GRPH_CONTROL, state->grph1.control);
-    OUTREG(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS, state->grph1.prim_surf_addr);
-    OUTREG(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS, state->grph1.sec_surf_addr);
-    OUTREG(AVIVO_D1GRPH_PITCH, state->grph1.pitch);
-    OUTREG(AVIVO_D1GRPH_SURFACE_OFFSET_X, state->grph1.x_offset);
-    OUTREG(AVIVO_D1GRPH_SURFACE_OFFSET_Y, state->grph1.y_offset);
-    OUTREG(AVIVO_D1GRPH_X_START, state->grph1.x_start);
-    OUTREG(AVIVO_D1GRPH_Y_START, state->grph1.y_start);
-    OUTREG(AVIVO_D1GRPH_X_END, state->grph1.x_end);
-    OUTREG(AVIVO_D1GRPH_Y_END, state->grph1.y_end);
-
-    OUTREG(AVIVO_D1MODE_VIEWPORT_START, state->grph1.viewport_start);
-    OUTREG(AVIVO_D1MODE_VIEWPORT_SIZE, state->grph1.viewport_size);
-
-    OUTREG(AVIVO_PCLK_CRTC2_CNTL, state->crtc2.pll_source);
+    /* XXX Fix scaler */
 
     OUTREG(AVIVO_D2CRTC_H_TOTAL, state->crtc2.h_total);
     OUTREG(AVIVO_D2CRTC_H_BLANK_START_END, state->crtc2.h_blank_start_end);
@@ -4557,29 +4618,11 @@ avivo_restore(ScrnInfoPtr pScrn, RADEONSavePtr restore)
     OUTREG(AVIVO_D2CRTC_V_SYNC_B, state->crtc2.v_sync_b);
     OUTREG(AVIVO_D2CRTC_V_SYNC_B_CNTL, state->crtc2.v_sync_b_cntl);
 
-    OUTREG(AVIVO_D2CRTC_CONTROL, state->crtc2.control);
-    OUTREG(AVIVO_D2CRTC_BLANK_CONTROL, state->crtc2.blank_control);
     OUTREG(AVIVO_D2CRTC_INTERLACE_CONTROL, state->crtc2.interlace_control);
     OUTREG(AVIVO_D2CRTC_STEREO_CONTROL, state->crtc2.stereo_control);
 
     OUTREG(AVIVO_D2CUR_CONTROL, state->crtc2.cursor_control);
 
-    OUTREG(AVIVO_D2GRPH_ENABLE, state->grph2.enable);
-    OUTREG(AVIVO_D2GRPH_CONTROL, state->grph2.control);
-    OUTREG(AVIVO_D2GRPH_PRIMARY_SURFACE_ADDRESS, state->grph2.prim_surf_addr);
-    OUTREG(AVIVO_D2GRPH_SECONDARY_SURFACE_ADDRESS, state->grph2.sec_surf_addr);
-    OUTREG(AVIVO_D2GRPH_PITCH, state->grph2.pitch);
-    OUTREG(AVIVO_D2GRPH_SURFACE_OFFSET_X, state->grph2.x_offset);
-    OUTREG(AVIVO_D2GRPH_SURFACE_OFFSET_Y, state->grph2.y_offset);
-    OUTREG(AVIVO_D2GRPH_X_START, state->grph2.x_start);
-    OUTREG(AVIVO_D2GRPH_Y_START, state->grph2.y_start);
-    OUTREG(AVIVO_D2GRPH_X_END, state->grph2.x_end);
-    OUTREG(AVIVO_D2GRPH_Y_END, state->grph2.y_end);
-
-    OUTREG(AVIVO_D2MODE_VIEWPORT_START, state->grph2.viewport_start);
-    OUTREG(AVIVO_D2MODE_VIEWPORT_SIZE, state->grph2.viewport_size);
-
-
     if (IS_DCE3_VARIANT) {
 	/* DVOA regs */
 	OUTREG(0x7080, state->dvoa[0]);
@@ -4699,7 +4742,7 @@ avivo_restore(ScrnInfoPtr pScrn, RADEONSavePtr restore)
 	}
 
 	j = 0;
-	/* DAC regs */
+	/* DAC regs */ /* -- MIGHT NEED ORDERING FIX & DELAYS -- */
 	for (i = 0x7800; i <= 0x782c; i += 4) {
 	    OUTREG(i, state->daca[j]);
 	    OUTREG((i + 0x200), state->dacb[j]);
@@ -4766,8 +4809,31 @@ avivo_restore(ScrnInfoPtr pScrn, RADEONSavePtr restore)
     OUTREG(0x6e30, state->dxscl[6]);
     OUTREG(0x6e34, state->dxscl[7]);
 
+    /* Enable CRTCs */
+    if (state->crtc1.control & 1) {
+	    OUTREG(AVIVO_D1CRTC_CONTROL, 0x01000101);
+	    INREG(AVIVO_D1CRTC_CONTROL);
+	    OUTREG(AVIVO_D1CRTC_CONTROL, 0x00010101);
+    }
+    if (state->crtc2.control & 1) {
+	    OUTREG(AVIVO_D2CRTC_CONTROL, 0x01000101);
+	    INREG(AVIVO_D2CRTC_CONTROL);
+	    OUTREG(AVIVO_D2CRTC_CONTROL, 0x00010101);
+    }
+
+    /* Where should that go ? */
+    OUTREG(AVIVO_DC_CRTC_TV_CONTROL, state->crtc_tv_control);
+    OUTREG(AVIVO_DC_LB_MEMORY_SPLIT, state->dc_lb_memory_split);
+
+    /* Need fixing too ? */
+    OUTREG(AVIVO_D1CRTC_BLANK_CONTROL, state->crtc1.blank_control);
+    OUTREG(AVIVO_D2CRTC_BLANK_CONTROL, state->crtc2.blank_control);
+
+    /* Dbl check */
     OUTREG(AVIVO_D1VGA_CONTROL, state->vga1_cntl);
     OUTREG(AVIVO_D2VGA_CONTROL, state->vga2_cntl);
+
+    /* Should only enable outputs here */
 }
 
 static void avivo_restore_vga_regs(ScrnInfoPtr pScrn, RADEONSavePtr restore)
@@ -5318,26 +5384,18 @@ Bool RADEONEnterVT(int scrnIndex, int flags)
 {
     ScrnInfoPtr    pScrn = xf86Screens[scrnIndex];
     RADEONInfoPtr  info  = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    uint32_t mem_size;
     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
     int i;
 
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "RADEONEnterVT\n");
 
-    if (info->ChipFamily >= CHIP_FAMILY_R600)
-	mem_size = INREG(R600_CONFIG_MEMSIZE);
-    else
-	mem_size = INREG(RADEON_CONFIG_MEMSIZE);
-
-    if (mem_size == 0) { /* Softboot V_BIOS */
+    if (!radeon_card_posted(pScrn)) { /* Softboot V_BIOS */
 	if (info->IsAtomBios) {
 	    rhdAtomASICInit(info->atomBIOS);
 	} else {
 	    xf86Int10InfoPtr pInt;
-	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		       "zero MEMSIZE, probably at D3cold. Re-POSTing via int10.\n");
+
 	    pInt = xf86InitInt10 (info->pEnt->index);
 	    if (pInt) {
 		pInt->num = 0xe6;
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index f461f3c..02fd4fc 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -413,14 +413,16 @@ Bool RADEONSetupMemEXA (ScreenPtr pScreen)
     /* Reserve static area for hardware cursor */
     if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
 	int cursor_size = 64 * 4 * 64;
+	int align = IS_AVIVO_VARIANT ? 4096 : 256;
 	int c;
 
 	for (c = 0; c < xf86_config->num_crtc; c++) {
 	    xf86CrtcPtr crtc = xf86_config->crtc[c];
 	    RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
 
-	    radeon_crtc->cursor_offset = info->exa->offScreenBase;
-	    info->exa->offScreenBase += cursor_size;
+	    radeon_crtc->cursor_offset =
+		RADEON_ALIGN(info->exa->offScreenBase, align);
+	    info->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size;
 
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		       "Will use %d kb for hardware cursor %d at offset 0x%08x\n",
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 4736e4f..043b0d4 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -1419,7 +1419,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 
 
 	/* setup the rasterizer, load FS */
-	BEGIN_ACCEL(9);
+	BEGIN_ACCEL(10);
 	if (pMask) {
 	    /* 4 components: 2 for tex0, 2 for tex1 */
 	    OUT_ACCEL_REG(R300_RS_COUNT,
@@ -1461,6 +1461,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 			   R300_RGBA_OUT));
 	}
 
+	OUT_ACCEL_REG(R300_US_PIXSIZE, 1); /* highest temp used */
 	/* shader output swizzling */
 	OUT_ACCEL_REG(R300_US_OUT_FMT_0, output_fmt);
 
@@ -1474,7 +1475,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 	 * R300_ALU_RGB_OMASK - output components to write
 	 * R300_ALU_RGB_TARGET_A - render target
 	 */
-	OUT_ACCEL_REG(R300_US_ALU_RGB_ADDR_0,
+	OUT_ACCEL_REG(R300_US_ALU_RGB_ADDR(0),
 		      (R300_ALU_RGB_ADDR0(0) |
 		       R300_ALU_RGB_ADDR1(1) |
 		       R300_ALU_RGB_ADDR2(0) |
@@ -1486,7 +1487,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 	/* RGB inst
 	 * ALU operation
 	 */
-	OUT_ACCEL_REG(R300_US_ALU_RGB_INST_0,
+	OUT_ACCEL_REG(R300_US_ALU_RGB_INST(0),
 		      (R300_ALU_RGB_SEL_A(src_color) |
 		       R300_ALU_RGB_MOD_A(R300_ALU_RGB_MOD_NOP) |
 		       R300_ALU_RGB_SEL_B(mask_color) |
@@ -1503,7 +1504,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 	 * R300_ALU_ALPHA_OMASK - output components to write
 	 * R300_ALU_ALPHA_TARGET_A - render target
 	 */
-	OUT_ACCEL_REG(R300_US_ALU_ALPHA_ADDR_0,
+	OUT_ACCEL_REG(R300_US_ALU_ALPHA_ADDR(0),
 		      (R300_ALU_ALPHA_ADDR0(0) |
 		       R300_ALU_ALPHA_ADDR1(1) |
 		       R300_ALU_ALPHA_ADDR2(0) |
@@ -1514,7 +1515,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 	/* Alpha inst
 	 * ALU operation
 	 */
-	OUT_ACCEL_REG(R300_US_ALU_ALPHA_INST_0,
+	OUT_ACCEL_REG(R300_US_ALU_ALPHA_INST(0),
 		      (R300_ALU_ALPHA_SEL_A(src_alpha) |
 		       R300_ALU_ALPHA_MOD_A(R300_ALU_ALPHA_MOD_NOP) |
 		       R300_ALU_ALPHA_SEL_B(mask_alpha) |
@@ -1633,7 +1634,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 	    break;
 	}
 
-	BEGIN_ACCEL(6);
+	BEGIN_ACCEL(7);
 	if (pMask) {
 	    /* 4 components: 2 for tex0, 2 for tex1 */
 	    OUT_ACCEL_REG(R300_RS_COUNT,
@@ -1662,12 +1663,13 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 	    OUT_ACCEL_REG(R500_US_CODE_OFFSET, 0);
 	}
 
+	OUT_ACCEL_REG(R300_US_PIXSIZE, 1); /* highest temp used */
 	OUT_ACCEL_REG(R300_US_OUT_FMT_0, output_fmt);
 	FINISH_ACCEL();
 
 	if (pMask) {
 	    BEGIN_ACCEL(19);
-	    OUT_ACCEL_REG(R500_GA_US_VECTOR_INDEX, 0);
+	    OUT_ACCEL_REG(R500_GA_US_VECTOR_INDEX, R500_US_VECTOR_INST_INDEX(0));
 	    /* tex inst for src texture */
 	    OUT_ACCEL_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_TEX |
 						   R500_INST_RGB_WMASK_R |
@@ -1739,7 +1741,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 	    OUT_ACCEL_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
 	} else {
 	    BEGIN_ACCEL(13);
-	    OUT_ACCEL_REG(R500_GA_US_VECTOR_INDEX, 0);
+	    OUT_ACCEL_REG(R500_GA_US_VECTOR_INDEX, R500_US_VECTOR_INST_INDEX(0));
 	    /* tex inst for src texture */
 	    OUT_ACCEL_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_TEX |
 						   R500_INST_TEX_SEM_WAIT |
@@ -1962,9 +1964,9 @@ static void FUNC_NAME(RadeonCompositeTile)(PixmapPtr pDst,
 
 #ifdef ACCEL_CP
     if (info->ChipFamily < CHIP_FAMILY_R200) {
-	BEGIN_RING(4 * vtx_count + 3);
+	BEGIN_RING(3 * vtx_count + 3);
 	OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD,
-			    4 * vtx_count + 1));
+			    3 * vtx_count + 1));
 	if (has_mask)
 	    OUT_RING(RADEON_CP_VC_FRMT_XY |
 		     RADEON_CP_VC_FRMT_ST0 |
@@ -1972,11 +1974,11 @@ static void FUNC_NAME(RadeonCompositeTile)(PixmapPtr pDst,
 	else
 	    OUT_RING(RADEON_CP_VC_FRMT_XY |
 		     RADEON_CP_VC_FRMT_ST0);
-	OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
+	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 |
-		 (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
+		 (3 << RADEON_CP_VC_CNTL_NUM_SHIFT));
     } else {
 	if (IS_R300_3D || IS_R500_3D)
 	    BEGIN_RING(4 * vtx_count + 4);
@@ -1985,7 +1987,7 @@ static void FUNC_NAME(RadeonCompositeTile)(PixmapPtr pDst,
 
 	OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
 			    4 * vtx_count));
-	OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
+	OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_QUAD_LIST |
 		 RADEON_CP_VC_CNTL_PRIM_WALK_RING |
 		 (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
     }
@@ -1993,25 +1995,29 @@ static void FUNC_NAME(RadeonCompositeTile)(PixmapPtr pDst,
 #else /* ACCEL_CP */
     if (IS_R300_3D || IS_R500_3D)
 	BEGIN_ACCEL(2 + vtx_count * 4);
+    else if (info->ChipFamily < CHIP_FAMILY_R200)
+	BEGIN_ACCEL(1 + vtx_count * 3);
     else
 	BEGIN_ACCEL(1 + vtx_count * 4);
 
     if (info->ChipFamily < CHIP_FAMILY_R200) {
-	OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_TRIANGLE_FAN |
+	OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_RECTANGLE_LIST |
 					  RADEON_VF_PRIM_WALK_DATA |
 					  RADEON_VF_RADEON_MODE |
-					  4 << RADEON_VF_NUM_VERTICES_SHIFT));
+					  (3 << RADEON_VF_NUM_VERTICES_SHIFT)));
     } else {
 	OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_QUAD_LIST |
 					  RADEON_VF_PRIM_WALK_DATA |
-					  4 << RADEON_VF_NUM_VERTICES_SHIFT));
+					  (4 << RADEON_VF_NUM_VERTICES_SHIFT)));
     }
 #endif
 
     if (has_mask) {
-	VTX_OUT_MASK((float)dstX,                                      (float)dstY,
-		xFixedToFloat(srcTopLeft.x) / info->texW[0],      xFixedToFloat(srcTopLeft.y) / info->texH[0],
-		xFixedToFloat(maskTopLeft.x) / info->texW[1],     xFixedToFloat(maskTopLeft.y) / info->texH[1]);
+	if (info->ChipFamily >= CHIP_FAMILY_R200) {
+	    VTX_OUT_MASK((float)dstX,                                      (float)dstY,
+			 xFixedToFloat(srcTopLeft.x) / info->texW[0],      xFixedToFloat(srcTopLeft.y) / info->texH[0],
+			 xFixedToFloat(maskTopLeft.x) / info->texW[1],     xFixedToFloat(maskTopLeft.y) / info->texH[1]);
+	}
 	VTX_OUT_MASK((float)dstX,                                      (float)(dstY + h),
 		xFixedToFloat(srcBottomLeft.x) / info->texW[0],   xFixedToFloat(srcBottomLeft.y) / info->texH[0],
 		xFixedToFloat(maskBottomLeft.x) / info->texW[1],  xFixedToFloat(maskBottomLeft.y) / info->texH[1]);
@@ -2022,8 +2028,10 @@ static void FUNC_NAME(RadeonCompositeTile)(PixmapPtr pDst,
 		xFixedToFloat(srcTopRight.x) / info->texW[0],     xFixedToFloat(srcTopRight.y) / info->texH[0],
 		xFixedToFloat(maskTopRight.x) / info->texW[1],    xFixedToFloat(maskTopRight.y) / info->texH[1]);
     } else {
-	VTX_OUT((float)dstX,                                      (float)dstY,
-		xFixedToFloat(srcTopLeft.x) / info->texW[0],      xFixedToFloat(srcTopLeft.y) / info->texH[0]);
+	if (info->ChipFamily >= CHIP_FAMILY_R200) {
+	    VTX_OUT((float)dstX,                                      (float)dstY,
+		    xFixedToFloat(srcTopLeft.x) / info->texW[0],      xFixedToFloat(srcTopLeft.y) / info->texH[0]);
+	}
 	VTX_OUT((float)dstX,                                      (float)(dstY + h),
 		xFixedToFloat(srcBottomLeft.x) / info->texW[0],   xFixedToFloat(srcBottomLeft.y) / info->texH[0]);
 	VTX_OUT((float)(dstX + w),                                (float)(dstY + h),
diff --git a/src/radeon_macros.h b/src/radeon_macros.h
index afe442e..f19bc3e 100644
--- a/src/radeon_macros.h
+++ b/src/radeon_macros.h
@@ -51,32 +51,6 @@
 
 #include "compiler.h"
 
-#if HAVE_BYTESWAP_H
-#include <byteswap.h>
-#elif defined(USE_SYS_ENDIAN_H)
-#include <sys/endian.h>
-#else
-#define	bswap_16(value)  \
- 	((((value) & 0xff) << 8) | ((value) >> 8))
-
-#define	bswap_32(value)	\
- 	(((uint32_t)bswap_16((uint16_t)((value) & 0xffff)) << 16) | \
- 	(uint32_t)bswap_16((uint16_t)((value) >> 16)))
- 
-#define	bswap_64(value)	\
- 	(((uint64_t)bswap_32((uint32_t)((value) & 0xffffffff)) \
- 	    << 32) | \
- 	(uint64_t)bswap_32((uint32_t)((value) >> 32)))
-#endif
-
-#if X_BYTE_ORDER == X_BIG_ENDIAN
-#define le32_to_cpu(x) bswap_32(x)
-#define le16_to_cpu(x) bswap_16(x)
-#else
-#define le32_to_cpu(x) (x)
-#define le16_to_cpu(x) (x)
-#endif
-
 #define RADEON_BIOS8(v)  (info->VBIOS[v])
 #define RADEON_BIOS16(v) (info->VBIOS[v] | \
                           (info->VBIOS[(v) + 1] << 8))
diff --git a/src/radeon_output.c b/src/radeon_output.c
index 7b89d66..2cc38a5 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -173,9 +173,6 @@ static const uint32_t default_tvdac_adj [CHIP_FAMILY_LAST] =
 
 static void RADEONUpdatePanelSize(xf86OutputPtr output);
 static void RADEONGetTMDSInfoFromTable(xf86OutputPtr output);
-#define AVIVO_I2C_DISABLE 0
-#define AVIVO_I2C_ENABLE 1
-static Bool AVIVOI2CDoLock(xf86OutputPtr output, int lock_state);
 
 extern void atombios_output_mode_set(xf86OutputPtr output,
 				     DisplayModePtr mode,
@@ -183,6 +180,8 @@ extern void atombios_output_mode_set(xf86OutputPtr output,
 extern void atombios_output_dpms(xf86OutputPtr output, int mode);
 extern RADEONMonitorType atombios_dac_detect(ScrnInfoPtr pScrn, xf86OutputPtr output);
 extern int atombios_external_tmds_setup(xf86OutputPtr output, DisplayModePtr mode);
+extern AtomBiosResult
+atombios_lock_crtc(atomBiosHandlePtr atomBIOS, int crtc, int lock);
 static void
 radeon_bios_output_dpms(xf86OutputPtr output, int mode);
 static void
@@ -213,88 +212,6 @@ void RADEONPrintPortMap(ScrnInfoPtr pScrn)
 
 }
 
-static xf86MonPtr
-radeon_do_ddc(xf86OutputPtr output)
-{
-    RADEONInfoPtr info = RADEONPTR(output->scrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    uint32_t DDCReg;
-    xf86MonPtr MonInfo = NULL;
-    RADEONOutputPrivatePtr radeon_output = output->driver_private;
-    int i, j;
-
-    if (radeon_output->pI2CBus) {
-	DDCReg = radeon_output->ddc_i2c.mask_clk_reg;
-
-	if (IS_AVIVO_VARIANT) {
-	    AVIVOI2CDoLock(output, AVIVO_I2C_ENABLE);
-	    MonInfo = xf86OutputGetEDID(output, radeon_output->pI2CBus);
-	    AVIVOI2CDoLock(output, AVIVO_I2C_DISABLE);
-	} else if ((DDCReg == RADEON_LCD_GPIO_MASK) || (DDCReg == RADEON_MDGPIO_EN_REG)) {
-	    MonInfo = xf86OutputGetEDID(output, radeon_output->pI2CBus);
-	} else {
-	    OUTREG(DDCReg, INREG(DDCReg) &
-		   (uint32_t)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1));
-
-	    /* For some old monitors (like Compaq Presario FP500), we need
-	     * following process to initialize/stop DDC
-	     */
-	    OUTREG(DDCReg, INREG(DDCReg) & ~(RADEON_GPIO_EN_1));
-	    for (j = 0; j < 3; j++) {
-		OUTREG(DDCReg,
-		       INREG(DDCReg) & ~(RADEON_GPIO_EN_0));
-		usleep(13000);
-
-		OUTREG(DDCReg,
-		       INREG(DDCReg) & ~(RADEON_GPIO_EN_1));
-		for (i = 0; i < 10; i++) {
-		    usleep(15000);
-		    if (INREG(DDCReg) & RADEON_GPIO_Y_1)
-			break;
-		}
-		if (i == 10) continue;
-
-		usleep(15000);
-
-		OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_0);
-		usleep(15000);
-
-		OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_1);
-		usleep(15000);
-		OUTREG(DDCReg,
-		       INREG(DDCReg) & ~(RADEON_GPIO_EN_0));
-		usleep(15000);
-
-		MonInfo = xf86OutputGetEDID(output, radeon_output->pI2CBus);
-
-		OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_1);
-		OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_0);
-		usleep(15000);
-		OUTREG(DDCReg,
-		       INREG(DDCReg) & ~(RADEON_GPIO_EN_1));
-		for (i = 0; i < 5; i++) {
-		    usleep(15000);
-		    if (INREG(DDCReg) & RADEON_GPIO_Y_1)
-			break;
-		}
-		usleep(15000);
-		OUTREG(DDCReg,
-		       INREG(DDCReg) & ~(RADEON_GPIO_EN_0));
-		usleep(15000);
-
-		OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_1);
-		OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_0);
-		usleep(15000);
-		if (MonInfo)  break;
-	    }
-	    OUTREG(DDCReg, INREG(DDCReg) &
-		   ~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1));
-	}
-    }
-
-    return MonInfo;
-}
-
 static RADEONMonitorType
 radeon_ddc_connected(xf86OutputPtr output)
 {
@@ -304,8 +221,11 @@ radeon_ddc_connected(xf86OutputPtr output)
     xf86MonPtr MonInfo = NULL;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
 
-    if (radeon_output->pI2CBus)
-	MonInfo = radeon_do_ddc(output);
+    if (radeon_output->pI2CBus) {
+	RADEONI2CDoLock(output, TRUE);
+	MonInfo = xf86OutputGetEDID(output, radeon_output->pI2CBus);
+	RADEONI2CDoLock(output, FALSE);
+    }
     if (MonInfo) {
 	if (!xf86ReturnOptValBool(info->Options, OPTION_IGNORE_EDID, FALSE))
 	    xf86OutputSetEDID(output, MonInfo);
@@ -317,13 +237,14 @@ radeon_ddc_connected(xf86OutputPtr output)
 	    MonType = MT_DFP;
 	else if (radeon_output->type == OUTPUT_DP)
 	    MonType = MT_DFP;
-	else if (radeon_output->type == OUTPUT_DVI_I && (MonInfo->rawData[0x14] & 0x80)) /* if it's digital and DVI */
+	else if (radeon_output->type == OUTPUT_DVI_I &&
+		 (MonInfo->rawData[0x14] & 0x80)) /* if it's digital and DVI */
 	    MonType = MT_DFP;
 	else
 	    MonType = MT_CRT;
     } else
 	MonType = MT_NONE;
-    
+
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	       "Output: %s, Detected Monitor Type: %d\n", output->name, MonType);
 
@@ -537,7 +458,7 @@ radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 		if (IS_AVIVO_VARIANT) {
 		    /* set to the panel's native mode */
 		    adjusted_mode->HDisplay = radeon_output->PanelXRes;
-		    adjusted_mode->HDisplay = radeon_output->PanelYRes;
+		    adjusted_mode->VDisplay = radeon_output->PanelYRes;
 		    adjusted_mode->HTotal = radeon_output->PanelXRes + radeon_output->HBlank;
 		    adjusted_mode->HSyncStart = radeon_output->PanelXRes + radeon_output->HOverPlus;
 		    adjusted_mode->HSyncEnd = adjusted_mode->HSyncStart + radeon_output->HSyncWidth;
@@ -580,12 +501,20 @@ radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 	}
     }
 
+    if (IS_AVIVO_VARIANT) {
+	/* hw bug */
+	if ((mode->Flags & V_INTERLACE)
+	    && (mode->CrtcVSyncStart < (mode->CrtcVDisplay + 2)))
+	    adjusted_mode->CrtcVSyncStart = adjusted_mode->CrtcVDisplay + 2;
+    }
+
     return TRUE;
 }
 
 static void
 radeon_mode_prepare(xf86OutputPtr output)
 {
+    RADEONInfoPtr info = RADEONPTR(output->scrn);
     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR (output->scrn);
     int o;
 
@@ -595,9 +524,12 @@ radeon_mode_prepare(xf86OutputPtr output)
 	    continue;
 	else if (loop_output->crtc) {
 	    xf86CrtcPtr other_crtc = loop_output->crtc;
+	    RADEONCrtcPrivatePtr other_radeon_crtc = other_crtc->driver_private;
 	    if (other_crtc->enabled) {
-		radeon_dpms(loop_output, DPMSModeOff);
 		radeon_crtc_dpms(other_crtc, DPMSModeOff);
+		if (IS_AVIVO_VARIANT)
+		    atombios_lock_crtc(info->atomBIOS, other_radeon_crtc->crtc_id, 1);
+		radeon_dpms(loop_output, DPMSModeOff);
 	    }
 	}
     }
@@ -625,6 +557,7 @@ radeon_mode_set(xf86OutputPtr output, DisplayModePtr mode,
 static void
 radeon_mode_commit(xf86OutputPtr output)
 {
+    RADEONInfoPtr info = RADEONPTR(output->scrn);
     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR (output->scrn);
     int o;
 
@@ -634,9 +567,12 @@ radeon_mode_commit(xf86OutputPtr output)
 	    continue;
 	else if (loop_output->crtc) {
 	    xf86CrtcPtr other_crtc = loop_output->crtc;
+	    RADEONCrtcPrivatePtr other_radeon_crtc = other_crtc->driver_private;
 	    if (other_crtc->enabled) {
-		radeon_dpms(loop_output, DPMSModeOn);		
 		radeon_crtc_dpms(other_crtc, DPMSModeOn);
+		if (IS_AVIVO_VARIANT)
+		    atombios_lock_crtc(info->atomBIOS, other_radeon_crtc->crtc_id, 0);
+		radeon_dpms(loop_output, DPMSModeOn);
 	    }
 	}
     }
@@ -1682,8 +1618,8 @@ Bool AVIVOI2CReset(ScrnInfoPtr pScrn)
 }
 #endif
 
-static
-Bool AVIVOI2CDoLock(xf86OutputPtr output, int lock_state)
+Bool
+RADEONI2CDoLock(xf86OutputPtr output, int lock_state)
 {
     ScrnInfoPtr pScrn = output->scrn;
     RADEONInfoPtr  info       = RADEONPTR(pScrn);
@@ -1692,19 +1628,29 @@ Bool AVIVOI2CDoLock(xf86OutputPtr output, int lock_state)
     unsigned char *RADEONMMIO = info->MMIO;
     uint32_t temp;
 
+    if (lock_state) {
+	temp = INREG(pRADEONI2CBus->a_clk_reg);
+	temp &= ~(pRADEONI2CBus->a_clk_mask);
+	OUTREG(pRADEONI2CBus->a_clk_reg, temp);
+
+	temp = INREG(pRADEONI2CBus->a_data_reg);
+	temp &= ~(pRADEONI2CBus->a_data_mask);
+	OUTREG(pRADEONI2CBus->a_data_reg, temp);
+    }
+
     temp = INREG(pRADEONI2CBus->mask_clk_reg);
-    if (lock_state == AVIVO_I2C_ENABLE)
-	temp |= (pRADEONI2CBus->put_clk_mask);
+    if (lock_state)
+	temp |= (pRADEONI2CBus->mask_clk_mask);
     else
-	temp &= ~(pRADEONI2CBus->put_clk_mask);
+	temp &= ~(pRADEONI2CBus->mask_clk_mask);
     OUTREG(pRADEONI2CBus->mask_clk_reg, temp);
     temp = INREG(pRADEONI2CBus->mask_clk_reg);
 
     temp = INREG(pRADEONI2CBus->mask_data_reg);
-    if (lock_state == AVIVO_I2C_ENABLE)
-	temp |= (pRADEONI2CBus->put_data_mask);
+    if (lock_state)
+	temp |= (pRADEONI2CBus->mask_data_mask);
     else
-	temp &= ~(pRADEONI2CBus->put_data_mask);
+	temp &= ~(pRADEONI2CBus->mask_data_mask);
     OUTREG(pRADEONI2CBus->mask_data_reg, temp);
     temp = INREG(pRADEONI2CBus->mask_data_reg);
 
@@ -1786,8 +1732,10 @@ legacy_setup_i2c_bus(int ddc_line)
 {
     RADEONI2CBusRec i2c;
 
-    i2c.mask_clk_mask = RADEON_GPIO_EN_1 | RADEON_GPIO_Y_1;
-    i2c.mask_data_mask =  RADEON_GPIO_EN_0 | RADEON_GPIO_Y_0;
+    i2c.mask_clk_mask = RADEON_GPIO_EN_1;
+    i2c.mask_data_mask = RADEON_GPIO_EN_0;
+    i2c.a_clk_mask = RADEON_GPIO_A_1;
+    i2c.a_data_mask = RADEON_GPIO_A_0;
     i2c.put_clk_mask = RADEON_GPIO_EN_1;
     i2c.put_data_mask = RADEON_GPIO_EN_0;
     i2c.get_clk_mask = RADEON_GPIO_Y_1;
@@ -1796,6 +1744,8 @@ legacy_setup_i2c_bus(int ddc_line)
 	(ddc_line == RADEON_MDGPIO_EN_REG)) {
 	i2c.mask_clk_reg = ddc_line;
 	i2c.mask_data_reg = ddc_line;
+	i2c.a_clk_reg = ddc_line;
+	i2c.a_data_reg = ddc_line;
 	i2c.put_clk_reg = ddc_line;
 	i2c.put_data_reg = ddc_line;
 	i2c.get_clk_reg = ddc_line + 4;
@@ -1803,6 +1753,8 @@ legacy_setup_i2c_bus(int ddc_line)
     } else {
 	i2c.mask_clk_reg = ddc_line;
 	i2c.mask_data_reg = ddc_line;
+	i2c.a_clk_reg = ddc_line;
+	i2c.a_data_reg = ddc_line;
 	i2c.put_clk_reg = ddc_line;
 	i2c.put_data_reg = ddc_line;
 	i2c.get_clk_reg = ddc_line;
@@ -1829,6 +1781,8 @@ atom_setup_i2c_bus(int ddc_line)
 	i2c.get_data_mask = (1 << 18);
 	i2c.mask_clk_mask = (1 << 19);
 	i2c.mask_data_mask = (1 << 18);
+	i2c.a_clk_mask = (1 << 19);
+	i2c.a_data_mask = (1 << 18);
     } else {
 	i2c.put_clk_mask = (1 << 0);
 	i2c.put_data_mask = (1 << 8);
@@ -1836,9 +1790,13 @@ atom_setup_i2c_bus(int ddc_line)
 	i2c.get_data_mask = (1 << 8);
 	i2c.mask_clk_mask = (1 << 0);
 	i2c.mask_data_mask = (1 << 8);
+	i2c.a_clk_mask = (1 << 0);
+	i2c.a_data_mask = (1 << 8);
     }
     i2c.mask_clk_reg = ddc_line;
     i2c.mask_data_reg = ddc_line;
+    i2c.a_clk_reg = ddc_line + 0x4;
+    i2c.a_data_reg = ddc_line + 0x4;
     i2c.put_clk_reg = ddc_line + 0x8;
     i2c.put_data_reg = ddc_line + 0x8;
     i2c.get_clk_reg = ddc_line + 0xc;
@@ -2301,13 +2259,13 @@ static Bool RADEONSetupAppleConnectors(ScrnInfoPtr pScrn)
 	info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
 	info->BiosConnector[0].DACType = DAC_NONE;
 	info->BiosConnector[0].TMDSType = TMDS_NONE;
-	info->BiosConnector[0].ConnectorType = CONNECTOR_VGA;
+	info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS;
 	info->BiosConnector[0].valid = TRUE;
 
 	info->BiosConnector[1].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
 	info->BiosConnector[1].DACType = DAC_PRIMARY;
-	info->BiosConnector[1].TMDSType = TMDS_INT;
-	info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_I;
+	info->BiosConnector[1].TMDSType = TMDS_NONE;
+	info->BiosConnector[1].ConnectorType = CONNECTOR_VGA;
 	info->BiosConnector[1].valid = TRUE;
 
 	info->BiosConnector[2].ConnectorType = CONNECTOR_STV;
@@ -2677,7 +2635,6 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn)
 {
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     RADEONInfoPtr info       = RADEONPTR(pScrn);
-    RADEONEntPtr pRADEONEnt  = RADEONEntPriv(pScrn);
     xf86OutputPtr output;
     char *optstr;
     int i = 0;
@@ -2742,13 +2699,6 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn)
 	    RADEONSetupGenericConnectors(pScrn);
     }
 
-    if (!pRADEONEnt->HasCRTC2) {
-	for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) {
-	    if (info->BiosConnector[i].ConnectorType == CONNECTOR_VGA)
-		info->BiosConnector[i].DACType = DAC_PRIMARY;
-	}
-    }
-
     /* parse connector table option */
     optstr = (char *)xf86GetOptValString(info->Options, OPTION_CONNECTORTABLE);
 
diff --git a/src/radeon_pci_chipset_gen.h b/src/radeon_pci_chipset_gen.h
index 39adb5e..ff1801f 100644
--- a/src/radeon_pci_chipset_gen.h
+++ b/src/radeon_pci_chipset_gen.h
@@ -1,6 +1,7 @@
 /* This file is autogenerated please do not edit */
 PciChipsets RADEONPciChipsets[] = {
  { PCI_CHIP_RV380_3150, PCI_CHIP_RV380_3150, RES_SHARED_VGA },
+ { PCI_CHIP_RV380_3151, PCI_CHIP_RV380_3151, RES_SHARED_VGA },
  { PCI_CHIP_RV380_3152, PCI_CHIP_RV380_3152, RES_SHARED_VGA },
  { PCI_CHIP_RV380_3154, PCI_CHIP_RV380_3154, RES_SHARED_VGA },
  { PCI_CHIP_RV380_3E50, PCI_CHIP_RV380_3E50, RES_SHARED_VGA },
@@ -250,6 +251,9 @@ PciChipsets RADEONPciChipsets[] = {
  { PCI_CHIP_R600_940A, PCI_CHIP_R600_940A, RES_SHARED_VGA },
  { PCI_CHIP_R600_940B, PCI_CHIP_R600_940B, RES_SHARED_VGA },
  { PCI_CHIP_R600_940F, PCI_CHIP_R600_940F, RES_SHARED_VGA },
+ { PCI_CHIP_RV770_9440, PCI_CHIP_RV770_9440, RES_SHARED_VGA },
+ { PCI_CHIP_RV770_9441, PCI_CHIP_RV770_9441, RES_SHARED_VGA },
+ { PCI_CHIP_RV770_9442, PCI_CHIP_RV770_9442, 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 },
@@ -267,6 +271,7 @@ PciChipsets RADEONPciChipsets[] = {
  { PCI_CHIP_RV670_9507, PCI_CHIP_RV670_9507, RES_SHARED_VGA },
  { PCI_CHIP_RV670_950F, PCI_CHIP_RV670_950F, RES_SHARED_VGA },
  { PCI_CHIP_RV670_9511, PCI_CHIP_RV670_9511, RES_SHARED_VGA },
+ { PCI_CHIP_RV670_9515, PCI_CHIP_RV670_9515, 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 d81cbe3..d650f9f 100644
--- a/src/radeon_pci_device_match_gen.h
+++ b/src/radeon_pci_device_match_gen.h
@@ -1,6 +1,7 @@
 /* This file is autogenerated please do not edit */
 static const struct pci_id_match radeon_device_match[] = {
  ATI_DEVICE_MATCH( PCI_CHIP_RV380_3150, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV380_3151, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV380_3152, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV380_3154, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV380_3E50, 0 ),
@@ -250,6 +251,9 @@ static const struct pci_id_match radeon_device_match[] = {
  ATI_DEVICE_MATCH( PCI_CHIP_R600_940A, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_R600_940B, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_R600_940F, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV770_9440, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV770_9441, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV770_9442, 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 ),
@@ -267,6 +271,7 @@ static const struct pci_id_match radeon_device_match[] = {
  ATI_DEVICE_MATCH( PCI_CHIP_RV670_9507, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV670_950F, 0 ),
  ATI_DEVICE_MATCH( PCI_CHIP_RV670_9511, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_RV670_9515, 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 ),
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index 24af52b..3770abf 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -166,6 +166,8 @@ typedef struct
     Bool   valid;
     uint32_t mask_clk_reg;
     uint32_t mask_data_reg;
+    uint32_t a_clk_reg;
+    uint32_t a_data_reg;
     uint32_t put_clk_reg;
     uint32_t put_data_reg;
     uint32_t get_clk_reg;
@@ -176,6 +178,8 @@ typedef struct
     uint32_t put_data_mask;
     uint32_t get_clk_mask;
     uint32_t get_data_mask;
+    uint32_t a_clk_mask;
+    uint32_t a_data_mask;
 } RADEONI2CBusRec, *RADEONI2CBusPtr;
 
 typedef struct _RADEONCrtcPrivateRec {
@@ -310,8 +314,10 @@ struct avivo_grph_state {
     uint32_t x_end;
     uint32_t y_end;
 
+    uint32_t desktop_height;
     uint32_t viewport_start;
     uint32_t viewport_size;
+    uint32_t mode_data_format;
 };
 
 struct avivo_state
@@ -326,6 +332,7 @@ struct avivo_state
 
     uint32_t crtc_master_en;
     uint32_t crtc_tv_control;
+    uint32_t dc_lb_memory_split;
 
     struct avivo_pll_state pll1;
     struct avivo_pll_state pll2;
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index 59e2f12..19f9869 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -1032,6 +1032,10 @@
 #define RADEON_OV0_BASE_ADDR                0x43c
 #define RADEON_NB_TOM                       0x15c
 #define R300_MC_INIT_MISC_LAT_TIMER         0x180
+#       define R300_MC_DISP0R_INIT_LAT_SHIFT 8
+#       define R300_MC_DISP0R_INIT_LAT_MASK  0xf
+#       define R300_MC_DISP1R_INIT_LAT_SHIFT 12
+#       define R300_MC_DISP1R_INIT_LAT_MASK  0xf
 #define RADEON_MCLK_CNTL                    0x0012 /* PLL */
 #       define RADEON_FORCEON_MCLKA         (1 << 16)
 #       define RADEON_FORCEON_MCLKB         (1 << 17)
@@ -3185,6 +3189,7 @@
 #define RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST       0x00000008
 #define RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST 0x00000009
 #define RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST  0x0000000a
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_QUAD_LIST       0x0000000d
 #define RADEON_CP_VC_CNTL_PRIM_WALK_IND             0x00000010
 #define RADEON_CP_VC_CNTL_PRIM_WALK_LIST            0x00000020
 #define RADEON_CP_VC_CNTL_PRIM_WALK_RING            0x00000030
@@ -3418,6 +3423,7 @@
 #define RS690_MC_AGP_LOCATION			0x101
 #define RS690_MC_AGP_BASE			0x102
 #define RS690_MC_AGP_BASE_2                     0x103
+#define RS690_MC_INIT_MISC_LAT_TIMER            0x104
 #define RS690_MC_STATUS                         0x90
 #define RS690_MC_STATUS_IDLE                    (1 << 0)
 
@@ -3431,12 +3437,13 @@
 #define RS600_MC_STATUS                         0x0
 #define RS600_MC_STATUS_IDLE                    (1 << 0)
 
-#define AVIVO_MC_INDEX						0x0070
-#define R520_MC_STATUS 0x00
-#define R520_MC_STATUS_IDLE (1<<1)
-#define RV515_MC_STATUS 0x08
-#define RV515_MC_STATUS_IDLE (1<<4)
-#define AVIVO_MC_DATA						0x0074
+#define AVIVO_MC_INDEX				0x0070
+#define R520_MC_STATUS                          0x00
+#       define R520_MC_STATUS_IDLE              (1 << 1)
+#define RV515_MC_STATUS                         0x08
+#       define RV515_MC_STATUS_IDLE             (1 << 4)
+#define RV515_MC_INIT_MISC_LAT_TIMER            0x09
+#define AVIVO_MC_DATA				0x0074
 
 #define RV515_MC_FB_LOCATION   0x1
 #define RV515_MC_AGP_LOCATION  0x2
@@ -3598,8 +3605,20 @@
 #define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN        0x64d4
 #define AVIVO_DC_LUTA_WHITE_OFFSET_RED          0x64d8
 
-
-#define AVIVO_D1MODE_DESKTOP_HEIGHT             0x652C
+#define AVIVO_DC_LB_MEMORY_SPLIT                0x6520
+#       define AVIVO_DC_LB_MEMORY_SPLIT_MASK    0x3
+#       define AVIVO_DC_LB_MEMORY_SPLIT_SHIFT   0
+#       define AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF  0
+#       define AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q    1
+#       define AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY        2
+#       define AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q    3
+#       define AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE (1 << 2)
+#       define AVIVO_DC_LB_DISP1_END_ADR_SHIFT  4
+#       define AVIVO_DC_LB_DISP1_END_ADR_MASK   0x7ff
+
+#define AVIVO_D1MODE_DATA_FORMAT                0x6528
+#       define AVIVO_D1MODE_INTERLEAVE_EN       (1 << 0)
+#define AVIVO_D1MODE_DESKTOP_HEIGHT             0x652c
 #define AVIVO_D1MODE_VIEWPORT_START             0x6580
 #define AVIVO_D1MODE_VIEWPORT_SIZE              0x6584
 #define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT    0x6588
@@ -3651,6 +3670,8 @@
 #define AVIVO_D2CUR_SIZE                        0x6c10
 #define AVIVO_D2CUR_POSITION                    0x6c14
 
+#define AVIVO_D2MODE_DATA_FORMAT                0x6d28
+#define AVIVO_D2MODE_DESKTOP_HEIGHT             0x6d2c
 #define AVIVO_D2MODE_VIEWPORT_START             0x6d80
 #define AVIVO_D2MODE_VIEWPORT_SIZE              0x6d84
 #define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT    0x6d88
@@ -3658,6 +3679,7 @@
 
 #define AVIVO_D2SCL_SCALER_ENABLE               0x6d90
 #define AVIVO_D2SCL_SCALER_TAP_CONTROL	 	0x6d94
+#define AVIVO_D2SCL_UPDATE                      0x6dcc
 
 #define AVIVO_DDIA_BIT_DEPTH_CONTROL				0x7214
 
@@ -3918,6 +3940,8 @@
 #define R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR                       0x2194
 #define R600_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR                    0x2198
 
+#define R700_MC_VM_FB_LOCATION                                     0x2024
+
 #define R600_HDP_NONSURFACE_BASE                                0x2c04
 
 #define R600_BUS_CNTL                                           0x5420
@@ -4234,7 +4258,7 @@
 #define R300_PVS_SRC_ADDR_SEL(x)                        (x << 29)
 #define R300_PVS_SRC_ADDR_MODE_1                        (1 << 31)
 
-#define R300_VAP_PVS_FLOW_CNTL_OPC		        0x22DC
+#define R300_VAP_PVS_FLOW_CNTL_OPC		        0x22dc
 #define R300_VAP_OUT_VTX_FMT_0			        0x2090
 #       define R300_VTX_POS_PRESENT                     (1 << 0)
 #       define R300_VTX_COLOR_0_PRESENT                 (1 << 1)
@@ -4322,6 +4346,7 @@
 
 #define R300_TX_INVALTAGS				0x4100
 #define R300_TX_FILTER0_0				0x4400
+#define R300_TX_FILTER0_1				0x4404
 #       define R300_TX_CLAMP_S(x)                       (x << 0)
 #       define R300_TX_CLAMP_T(x)                       (x << 3)
 #       define R300_TX_CLAMP_R(x)                       (x << 6)
@@ -4339,7 +4364,9 @@
 #       define R300_TX_MIN_FILTER_LINEAR                (2 << 11)
 #       define R300_TX_ID_SHIFT                         28
 #define R300_TX_FILTER1_0				0x4440
+#define R300_TX_FILTER1_1				0x4444
 #define R300_TX_FORMAT0_0				0x4480
+#define R300_TX_FORMAT0_1				0x4484
 #       define R300_TXWIDTH_SHIFT                       0
 #       define R300_TXHEIGHT_SHIFT                      11
 #       define R300_NUM_LEVELS_SHIFT                    26
@@ -4347,6 +4374,7 @@
 #       define R300_TXPROJECTED                         (1 << 30)
 #       define R300_TXPITCH_EN                          (1 << 31)
 #define R300_TX_FORMAT1_0				0x44c0
+#define R300_TX_FORMAT1_1				0x44c4
 #	define R300_TX_FORMAT_X8		    0x0
 #	define R300_TX_FORMAT_X16		    0x1
 #	define R300_TX_FORMAT_Y4X4		    0x2
@@ -4420,10 +4448,12 @@
 #       define R300_TX_FORMAT_SWAP_YUV                 (1 << 24)
 
 #define R300_TX_FORMAT2_0				0x4500
+#define R300_TX_FORMAT2_1				0x4504
 #       define R500_TXWIDTH_11                          (1 << 15)
 #       define R500_TXHEIGHT_11                         (1 << 16)
 
 #define R300_TX_OFFSET_0				0x4540
+#define R300_TX_OFFSET_1				0x4544
 #       define R300_ENDIAN_SWAP_16_BIT                  (1 << 0)
 #       define R300_ENDIAN_SWAP_32_BIT                  (2 << 0)
 #       define R300_ENDIAN_SWAP_HALF_DWORD              (3 << 0)
@@ -4500,6 +4530,7 @@
 #define R300_US_TEX_INST_0				0x4620
 #define R300_US_TEX_INST_1				0x4624
 #define R300_US_TEX_INST_2				0x4628
+#define R300_US_TEX_INST(x)			        (R300_US_TEX_INST_0 + (x)*4)
 #       define R300_TEX_SRC_ADDR(x)                     (x << 0)
 #       define R300_TEX_DST_ADDR(x)                     (x << 6)
 #       define R300_TEX_ID(x)                           (x << 11)
@@ -4512,11 +4543,13 @@
 #define R300_US_ALU_RGB_ADDR_0			        0x46c0
 #define R300_US_ALU_RGB_ADDR_1			        0x46c4
 #define R300_US_ALU_RGB_ADDR_2			        0x46c8
+#define R300_US_ALU_RGB_ADDR(x)			        (R300_US_ALU_RGB_ADDR_0 + (x)*4)
 /* for ADDR0-2, values 0-31 specify a location in the pixel stack,
    values 32-63 specify a constant */
 #       define R300_ALU_RGB_ADDR0(x)                    (x << 0)
 #       define R300_ALU_RGB_ADDR1(x)                    (x << 6)
 #       define R300_ALU_RGB_ADDR2(x)                    (x << 12)
+#       define R300_ALU_RGB_CONST(x)                    ((x) | (1 << 5))
 /* ADDRD - where on the pixel stack the result of this instruction
    will be written */
 #       define R300_ALU_RGB_ADDRD(x)                    (x << 18)
@@ -4526,6 +4559,7 @@
 #       define R300_ALU_RGB_MASK_R                      1
 #       define R300_ALU_RGB_MASK_G                      2
 #       define R300_ALU_RGB_MASK_B                      4
+#       define R300_ALU_RGB_MASK_RGB                    7
 #       define R300_ALU_RGB_TARGET_A                    (0 << 29)
 #       define R300_ALU_RGB_TARGET_B                    (1 << 29)
 #       define R300_ALU_RGB_TARGET_C                    (2 << 29)
@@ -4533,6 +4567,7 @@
 #define R300_US_ALU_RGB_INST_0			        0x48c0
 #define R300_US_ALU_RGB_INST_1			        0x48c4
 #define R300_US_ALU_RGB_INST_2			        0x48c8
+#define R300_US_ALU_RGB_INST(x)			        (R300_US_ALU_RGB_INST_0 + (x)*4)
 #       define R300_ALU_RGB_SEL_A(x)                    (x << 0)
 #       define R300_ALU_RGB_SRC0_RGB                    0
 #       define R300_ALU_RGB_SRC0_RRR                    1
@@ -4604,11 +4639,13 @@
 #define R300_US_ALU_ALPHA_ADDR_0		        0x47c0
 #define R300_US_ALU_ALPHA_ADDR_1		        0x47c4
 #define R300_US_ALU_ALPHA_ADDR_2		        0x47c8
+#define R300_US_ALU_ALPHA_ADDR(x)		        (R300_US_ALU_ALPHA_ADDR_0 + (x)*4)
 /* for ADDR0-2, values 0-31 specify a location in the pixel stack,
    values 32-63 specify a constant */
 #       define R300_ALU_ALPHA_ADDR0(x)                  (x << 0)
 #       define R300_ALU_ALPHA_ADDR1(x)                  (x << 6)
 #       define R300_ALU_ALPHA_ADDR2(x)                  (x << 12)
+#       define R300_ALU_ALPHA_CONST(x)                  ((x) | (1 << 5))
 /* ADDRD - where on the pixel stack the result of this instruction
    will be written */
 #       define R300_ALU_ALPHA_ADDRD(x)                  (x << 18)
@@ -4624,6 +4661,7 @@
 #define R300_US_ALU_ALPHA_INST_0		        0x49c0
 #define R300_US_ALU_ALPHA_INST_1		        0x49c4
 #define R300_US_ALU_ALPHA_INST_2		        0x49c8
+#define R300_US_ALU_ALPHA_INST(x)		        (R300_US_ALU_ALPHA_INST_0 + (x)*4)
 #       define R300_ALU_ALPHA_SEL_A(x)                  (x << 0)
 #       define R300_ALU_ALPHA_SRC0_R                    0
 #       define R300_ALU_ALPHA_SRC0_G                    1
@@ -4680,6 +4718,15 @@
 #       define R300_ALU_ALPHA_OMOD_DIV_8                6
 #       define R300_ALU_ALPHA_CLAMP                     (1 << 30)
 
+#define R300_US_ALU_CONST_R_0                           0x4c00
+#define R300_US_ALU_CONST_R(x)                          (R300_US_ALU_CONST_R_0 + (x)*16)
+#define R300_US_ALU_CONST_G_0                           0x4c04
+#define R300_US_ALU_CONST_G(x)                          (R300_US_ALU_CONST_G_0 + (x)*16)
+#define R300_US_ALU_CONST_B_0                           0x4c08
+#define R300_US_ALU_CONST_B(x)                          (R300_US_ALU_CONST_B_0 + (x)*16)
+#define R300_US_ALU_CONST_A_0                           0x4c0c
+#define R300_US_ALU_CONST_A(x)                          (R300_US_ALU_CONST_A_0 + (x)*16)
+
 #define R300_FG_DEPTH_SRC				0x4bd8
 #define R300_FG_FOG_BLEND				0x4bc0
 #define R300_FG_ALPHA_FUNC				0x4bd4
@@ -4759,10 +4806,11 @@
 
 /* R500 US has to be loaded through an index/data pair */
 #define R500_GA_US_VECTOR_INDEX				0x4250
-#   define R500_US_VECTOR_INDEX(x)			(x << 0)
 #   define R500_US_VECTOR_TYPE_INST			(0 << 16)
 #   define R500_US_VECTOR_TYPE_CONST			(1 << 16)
 #   define R500_US_VECTOR_CLAMP				(1 << 17)
+#   define R500_US_VECTOR_INST_INDEX(x)			((x) | R500_US_VECTOR_TYPE_INST)
+#   define R500_US_VECTOR_CONST_INDEX(x)		((x) | R500_US_VECTOR_TYPE_CONST)
 #define R500_GA_US_VECTOR_DATA				0x4254
 
 /*
diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c
index cfa349d..da1d60f 100644
--- a/src/radeon_textured_video.c
+++ b/src/radeon_textured_video.c
@@ -93,6 +93,7 @@ static __inline__ uint32_t F_TO_DW(float val)
 #undef VIDEO_PREAMBLE
 #undef BEGIN_VIDEO
 #undef OUT_VIDEO_REG
+#undef OUT_VIDEO_REG_F
 #undef FINISH_VIDEO
 
 #ifdef XF86DRI
@@ -103,6 +104,7 @@ static __inline__ uint32_t F_TO_DW(float val)
     RADEONCP_REFRESH(pScrn, info)
 #define BEGIN_VIDEO(n)		BEGIN_RING(2*(n))
 #define OUT_VIDEO_REG(reg, val)	OUT_RING_REG(reg, val)
+#define OUT_VIDEO_REG_F(reg, val)	OUT_VIDEO_REG(reg, F_TO_DW(val))
 #define FINISH_VIDEO()		ADVANCE_RING()
 #define OUT_VIDEO_RING_F(x) OUT_RING(F_TO_DW(x))
 
@@ -199,6 +201,18 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
 	    return BadAlloc;
     }
 
+    /* Bicubic filter loading */
+    if (!IS_R500_3D)
+	pPriv->bicubic_enabled = FALSE;
+    if (pPriv->bicubic_memory == NULL && pPriv->bicubic_enabled) {
+	pPriv->bicubic_offset = RADEONAllocateMemory(pScrn,
+					&pPriv->bicubic_memory,
+					sizeof(bicubic_tex_512));
+	pPriv->bicubic_src_offset = pPriv->bicubic_offset + info->fbLocation + pScrn->fbOffset;
+	if (pPriv->bicubic_offset == 0)
+		pPriv->bicubic_enabled = FALSE;
+    }
+
     if (pDraw->type == DRAWABLE_WINDOW)
 	pPriv->pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
     else
@@ -267,6 +281,10 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
 	break;
     }
 
+    /* Upload bicubic filter tex */
+    if (pPriv->bicubic_enabled)
+	RADEONCopyData(pScrn, (uint8_t *)bicubic_tex_512, (uint8_t *)(info->FB + pPriv->bicubic_offset), 1024, 1024, 1, 512, 2);
+
     /* update cliplist */
     if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
 	REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
@@ -320,12 +338,16 @@ static XF86VideoFormatRec Formats[NUM_FORMATS] =
     {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
 };
 
-#define NUM_ATTRIBUTES 0
+#define NUM_ATTRIBUTES 1
 
-static XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
+static XF86AttributeRec Attributes[NUM_ATTRIBUTES+1] =
 {
+    {XvSettable | XvGettable, 0, 1, "XV_BICUBIC"},
+    {0, 0, 0, NULL}
 };
 
+static Atom xvBicubic;
+
 #define NUM_IMAGES 4
 
 static XF86ImageRec Images[NUM_IMAGES] =
@@ -336,6 +358,44 @@ static XF86ImageRec Images[NUM_IMAGES] =
     XVIMAGE_UYVY
 };
 
+int
+RADEONGetTexPortAttribute(ScrnInfoPtr  pScrn,
+		       Atom	    attribute,
+		       INT32	    *value,
+		       pointer	    data)
+{
+    RADEONInfoPtr	info = RADEONPTR(pScrn);
+    RADEONPortPrivPtr	pPriv = (RADEONPortPrivPtr)data;
+
+    if (info->accelOn) RADEON_SYNC(info, pScrn);
+
+    if (attribute == xvBicubic)
+	*value = pPriv->bicubic_enabled ? 1 : 0;
+    else
+	return BadMatch;
+
+    return Success;
+}
+
+int
+RADEONSetTexPortAttribute(ScrnInfoPtr  pScrn,
+		       Atom	    attribute,
+		       INT32	    value,
+		       pointer	    data)
+{
+    RADEONInfoPtr	info = RADEONPTR(pScrn);
+    RADEONPortPrivPtr	pPriv = (RADEONPortPrivPtr)data;
+
+    RADEON_SYNC(info, pScrn);
+
+    if (attribute == xvBicubic)
+	pPriv->bicubic_enabled = ClipValue (value, 0, 1);
+    else
+	return BadMatch;
+
+    return Success;
+}
+
 XF86VideoAdaptorPtr
 RADEONSetupImageTexturedVideo(ScreenPtr pScreen)
 {
@@ -351,6 +411,8 @@ RADEONSetupImageTexturedVideo(ScreenPtr pScreen)
     if (adapt == NULL)
 	return NULL;
 
+    xvBicubic         = MAKE_ATOM("XV_BICUBIC");
+
     adapt->type = XvWindowMask | XvInputMask | XvImageMask;
     adapt->flags = 0;
     adapt->name = "Radeon Textured Video";
@@ -367,8 +429,13 @@ RADEONSetupImageTexturedVideo(ScreenPtr pScreen)
     pPortPriv =
 	(RADEONPortPrivPtr)(&adapt->pPortPrivates[num_texture_ports]);
 
-    adapt->nAttributes = NUM_ATTRIBUTES;
-    adapt->pAttributes = Attributes;
+    if (IS_R500_3D) {
+	adapt->nAttributes = NUM_ATTRIBUTES;
+	adapt->pAttributes = Attributes;
+    } else {
+	adapt->nAttributes = 0;
+	adapt->pAttributes = NULL;
+    }
     adapt->pImages = Images;
     adapt->nImages = NUM_IMAGES;
     adapt->PutVideo = NULL;
@@ -376,8 +443,8 @@ RADEONSetupImageTexturedVideo(ScreenPtr pScreen)
     adapt->GetVideo = NULL;
     adapt->GetStill = NULL;
     adapt->StopVideo = RADEONStopVideo;
-    adapt->SetPortAttribute = RADEONSetPortAttribute;
-    adapt->GetPortAttribute = RADEONGetPortAttribute;
+    adapt->SetPortAttribute = RADEONSetTexPortAttribute;
+    adapt->GetPortAttribute = RADEONGetTexPortAttribute;
     adapt->QueryBestSize = RADEONQueryBestSize;
     adapt->PutImage = RADEONPutImageTextured;
     adapt->ReputImage = NULL;
@@ -390,6 +457,7 @@ RADEONSetupImageTexturedVideo(ScreenPtr pScreen)
 	pPriv->videoStatus = 0;
 	pPriv->currentBuffer = 0;
 	pPriv->doubleBuffer = 0;
+	pPriv->bicubic_enabled = (info->ChipFamily >= CHIP_FAMILY_RV515);
 
 	/* 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 277d9b2..b53e114 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -45,10 +45,21 @@
 #endif
 #endif
 
+#define VTX_DWORD_COUNT_FILTER 6
 #define VTX_DWORD_COUNT 4
 
 #ifdef ACCEL_CP
 
+#define VTX_OUT_FILTER(_dstX, _dstY, _srcX, _srcY, _maskX, _maskY)	\
+do {									\
+    OUT_VIDEO_RING_F(_dstX);						\
+    OUT_VIDEO_RING_F(_dstY);						\
+    OUT_VIDEO_RING_F(_srcX);						\
+    OUT_VIDEO_RING_F(_srcY);						\
+    OUT_VIDEO_RING_F(_maskX);						\
+    OUT_VIDEO_RING_F(_maskY);						\
+} while (0)
+
 #define VTX_OUT(_dstX, _dstY, _srcX, _srcY)	\
 do {								\
     OUT_VIDEO_RING_F(_dstX);						\
@@ -59,6 +70,16 @@ do {								\
 
 #else /* ACCEL_CP */
 
+#define VTX_OUT_FILTER(_dstX, _dstY, _srcX, _srcY, _maskX, _maskY)	\
+do {									\
+    OUT_VIDEO_REG_F(RADEON_SE_PORT_DATA0, _dstX);			\
+    OUT_VIDEO_REG_F(RADEON_SE_PORT_DATA0, _dstY);			\
+    OUT_VIDEO_REG_F(RADEON_SE_PORT_DATA0, _srcX);			\
+    OUT_VIDEO_REG_F(RADEON_SE_PORT_DATA0, _srcY);			\
+    OUT_VIDEO_REG_F(RADEON_SE_PORT_DATA0, _maskX);			\
+    OUT_VIDEO_REG_F(RADEON_SE_PORT_DATA0, _maskY);			\
+} while (0)
+
 #define VTX_OUT(_dstX, _dstY, _srcX, _srcY)	\
 do {								\
     OUT_VIDEO_REG_F(RADEON_SE_PORT_DATA0, _dstX);		\
@@ -79,7 +100,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
     uint32_t dst_offset, dst_pitch, dst_format;
     uint32_t txenable, colorpitch;
     uint32_t blendcntl;
-    int dstxoff, dstyoff, pixel_shift;
+    int dstxoff, dstyoff, pixel_shift, vtx_count;
     BoxPtr pBox = REGION_RECTS(&pPriv->clip);
     int nBox = REGION_NUM_RECTS(&pPriv->clip);
     VIDEO_PREAMBLE();
@@ -123,6 +144,11 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		  RADEON_WAIT_DMA_GUI_IDLE);
     FINISH_VIDEO();
 
+    if (pPriv->bicubic_enabled)
+	vtx_count = VTX_DWORD_COUNT_FILTER;
+    else
+	vtx_count = VTX_DWORD_COUNT;
+
     if (IS_R300_3D || IS_R500_3D) {
 	uint32_t output_fmt;
 
@@ -160,16 +186,17 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	txformat1 |= R300_TX_FORMAT_YUV_TO_RGB_CLAMP;
 
 	txformat0 = ((((pPriv->w - 1) & 0x7ff) << R300_TXWIDTH_SHIFT) |
-		     (((pPriv->h - 1) & 0x7ff) << R300_TXHEIGHT_SHIFT));
-
-	txformat0 |= R300_TXPITCH_EN;
+		     (((pPriv->h - 1) & 0x7ff) << R300_TXHEIGHT_SHIFT) |
+		     R300_TXPITCH_EN);
 
 	info->texW[0] = pPriv->w;
 	info->texH[0] = pPriv->h;
 
 	txfilter = (R300_TX_CLAMP_S(R300_TX_CLAMP_CLAMP_LAST) |
 		    R300_TX_CLAMP_T(R300_TX_CLAMP_CLAMP_LAST) |
-		    R300_TX_MAG_FILTER_LINEAR | R300_TX_MIN_FILTER_LINEAR);
+		    R300_TX_MAG_FILTER_LINEAR |
+		    R300_TX_MIN_FILTER_LINEAR |
+		    (0 << R300_TX_ID_SHIFT));
 
 	/* pitch is in pixels */
 	txpitch = pPriv->src_pitch / 2;
@@ -194,11 +221,47 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 
 	txenable = R300_TEX_0_ENABLE;
 
+	if (pPriv->bicubic_enabled) {
+		/* Size is 128x1 */
+		txformat0 = ((0x7f << R300_TXWIDTH_SHIFT) |
+			     (0x0 << R300_TXHEIGHT_SHIFT) |
+			     R300_TXPITCH_EN);
+		/* Format is 32-bit floats, 4bpp */
+		txformat1 = R300_EASY_TX_FORMAT(Z, Y, X, W, FL_R16G16B16A16);
+		/* Pitch is 127 (128-1) */
+		txpitch = 0x7f;
+		/* Tex filter */
+		txfilter = (R300_TX_CLAMP_S(R300_TX_CLAMP_WRAP) |
+			    R300_TX_CLAMP_T(R300_TX_CLAMP_WRAP) |
+			    R300_TX_MIN_FILTER_NEAREST |
+			    R300_TX_MAG_FILTER_NEAREST |
+			    (1 << R300_TX_ID_SHIFT));
+
+		BEGIN_VIDEO(6);
+		OUT_VIDEO_REG(R300_TX_FILTER0_1, txfilter);
+		OUT_VIDEO_REG(R300_TX_FILTER1_1, 0);
+		OUT_VIDEO_REG(R300_TX_FORMAT0_1, txformat0);
+		OUT_VIDEO_REG(R300_TX_FORMAT1_1, txformat1);
+		OUT_VIDEO_REG(R300_TX_FORMAT2_1, txpitch);
+		OUT_VIDEO_REG(R300_TX_OFFSET_1, pPriv->bicubic_src_offset);
+		FINISH_VIDEO();
+
+		/* Enable tex 1 */
+		txenable |= R300_TEX_1_ENABLE;
+	}
+
 	/* setup the VAP */
-	if (info->has_tcl)
-	    BEGIN_VIDEO(6);
-	else
-	    BEGIN_VIDEO(4);
+	if (info->has_tcl) {
+	    if (pPriv->bicubic_enabled)
+		BEGIN_VIDEO(7);
+	    else
+		BEGIN_VIDEO(6);
+	} else {
+	    if (pPriv->bicubic_enabled)
+		BEGIN_VIDEO(5);
+	    else
+		BEGIN_VIDEO(4);
+	}
 
 	/* These registers define the number, type, and location of data submitted
 	 * to the PVS unit of GA input (when PVS is disabled)
@@ -213,42 +276,74 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	 * Textures 0-7
 	 * Fog
 	 */
-	OUT_VIDEO_REG(R300_VAP_PROG_STREAM_CNTL_0,
-		      ((R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_0_SHIFT) |
-		       (0 << R300_SKIP_DWORDS_0_SHIFT) |
-		       (0 << R300_DST_VEC_LOC_0_SHIFT) |
-		       R300_SIGNED_0 |
-		       (R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_1_SHIFT) |
-		       (0 << R300_SKIP_DWORDS_1_SHIFT) |
-		       (6 << R300_DST_VEC_LOC_1_SHIFT) |
-		       R300_LAST_VEC_1 |
-		       R300_SIGNED_1));
+	if (pPriv->bicubic_enabled) {
+	    OUT_VIDEO_REG(R300_VAP_PROG_STREAM_CNTL_0,
+			  ((R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_0_SHIFT) |
+			   (0 << R300_SKIP_DWORDS_0_SHIFT) |
+			   (0 << R300_DST_VEC_LOC_0_SHIFT) |
+			   R300_SIGNED_0 |
+			   (R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_1_SHIFT) |
+			   (0 << R300_SKIP_DWORDS_1_SHIFT) |
+			   (6 << R300_DST_VEC_LOC_1_SHIFT) |
+			   R300_SIGNED_1));
+	    OUT_VIDEO_REG(R300_VAP_PROG_STREAM_CNTL_1,
+			  ((R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_2_SHIFT) |
+			   (0 << R300_SKIP_DWORDS_2_SHIFT) |
+			   (7 << R300_DST_VEC_LOC_2_SHIFT) |
+			   R300_LAST_VEC_2 |
+			   R300_SIGNED_2));
+	} else {
+	    OUT_VIDEO_REG(R300_VAP_PROG_STREAM_CNTL_0,
+			  ((R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_0_SHIFT) |
+			   (0 << R300_SKIP_DWORDS_0_SHIFT) |
+			   (0 << R300_DST_VEC_LOC_0_SHIFT) |
+			   R300_SIGNED_0 |
+			   (R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_1_SHIFT) |
+			   (0 << R300_SKIP_DWORDS_1_SHIFT) |
+			   (6 << R300_DST_VEC_LOC_1_SHIFT) |
+			   R300_LAST_VEC_1 |
+			   R300_SIGNED_1));
+	}
 
 	/* load the vertex shader
 	 * We pre-load vertex programs in RADEONInit3DEngine():
+	 * - exa mask/Xv bicubic
 	 * - exa no mask
-	 * - exa mask
 	 * - Xv
 	 * Here we select the offset of the vertex program we want to use
 	 */
 	if (info->has_tcl) {
-	    OUT_VIDEO_REG(R300_VAP_PVS_CODE_CNTL_0,
-			  ((5 << R300_PVS_FIRST_INST_SHIFT) |
-			   (6 << R300_PVS_XYZW_VALID_INST_SHIFT) |
-			   (6 << R300_PVS_LAST_INST_SHIFT)));
-	    OUT_VIDEO_REG(R300_VAP_PVS_CODE_CNTL_1,
-			  (6 << R300_PVS_LAST_VTX_SRC_INST_SHIFT));
+	    if (pPriv->bicubic_enabled) {
+		OUT_VIDEO_REG(R300_VAP_PVS_CODE_CNTL_0,
+			      ((0 << R300_PVS_FIRST_INST_SHIFT) |
+			       (2 << R300_PVS_XYZW_VALID_INST_SHIFT) |
+			       (2 << R300_PVS_LAST_INST_SHIFT)));
+		OUT_VIDEO_REG(R300_VAP_PVS_CODE_CNTL_1,
+			      (2 << R300_PVS_LAST_VTX_SRC_INST_SHIFT));
+	    } else {
+		OUT_VIDEO_REG(R300_VAP_PVS_CODE_CNTL_0,
+			      ((5 << R300_PVS_FIRST_INST_SHIFT) |
+			       (6 << R300_PVS_XYZW_VALID_INST_SHIFT) |
+			       (6 << R300_PVS_LAST_INST_SHIFT)));
+		OUT_VIDEO_REG(R300_VAP_PVS_CODE_CNTL_1,
+			      (6 << R300_PVS_LAST_VTX_SRC_INST_SHIFT));
+	    }
 	}
 
 	/* Position and one set of 2 texture coordinates */
 	OUT_VIDEO_REG(R300_VAP_OUT_VTX_FMT_0, R300_VTX_POS_PRESENT);
-	OUT_VIDEO_REG(R300_VAP_OUT_VTX_FMT_1, (2 << R300_TEX_0_COMP_CNT_SHIFT));
+	if (pPriv->bicubic_enabled)
+	    OUT_VIDEO_REG(R300_VAP_OUT_VTX_FMT_1, ((2 << R300_TEX_0_COMP_CNT_SHIFT) |
+						   (2 << R300_TEX_1_COMP_CNT_SHIFT)));
+	else
+	    OUT_VIDEO_REG(R300_VAP_OUT_VTX_FMT_1, (2 << R300_TEX_0_COMP_CNT_SHIFT));
+
 	OUT_VIDEO_REG(R300_US_OUT_FMT_0, output_fmt);
 	FINISH_VIDEO();
 
 	/* setup pixel shader */
 	if (IS_R300_3D) {
-	    BEGIN_VIDEO(8);
+	    BEGIN_VIDEO(9);
 	    /* 2 components: 2 for tex0 */
 	    OUT_VIDEO_REG(R300_RS_COUNT,
 			  ((2 << R300_RS_COUNT_IT_COUNT_SHIFT) |
@@ -256,6 +351,8 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	    /* R300_INST_COUNT_RS - highest RS instruction used */
 	    OUT_VIDEO_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0) | R300_TX_OFFSET_RS(6));
 
+	    OUT_VIDEO_REG(R300_US_PIXSIZE, 0); /* highest temp used */
+
 	    OUT_VIDEO_REG(R300_US_CODE_OFFSET,
 			  (R300_ALU_CODE_OFFSET(0) |
 			   R300_ALU_CODE_SIZE(1) |
@@ -313,102 +410,577 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 			   R300_ALU_ALPHA_CLAMP));
 	    FINISH_VIDEO();
 	} else {
-	    BEGIN_VIDEO(18);
-	    /* 2 components: 2 for tex0 */
-	    OUT_VIDEO_REG(R300_RS_COUNT,
-			  ((2 << R300_RS_COUNT_IT_COUNT_SHIFT) |
-			   R300_RS_COUNT_HIRES_EN));
-
-	    /* R300_INST_COUNT_RS - highest RS instruction used */
-	    OUT_VIDEO_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0) | R300_TX_OFFSET_RS(6));
-
-	    OUT_VIDEO_REG(R500_US_CODE_ADDR, (R500_US_CODE_START_ADDR(0) |
-					      R500_US_CODE_END_ADDR(1)));
-	    OUT_VIDEO_REG(R500_US_CODE_RANGE, (R500_US_CODE_RANGE_ADDR(0) |
-					       R500_US_CODE_RANGE_SIZE(1)));
-	    OUT_VIDEO_REG(R500_US_CODE_OFFSET, 0);
-	    OUT_VIDEO_REG(R500_GA_US_VECTOR_INDEX, 0);
-
-	    /* tex inst */
-	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_TEX |
-						   R500_INST_TEX_SEM_WAIT |
-						   R500_INST_RGB_WMASK_R |
-						   R500_INST_RGB_WMASK_G |
-						   R500_INST_RGB_WMASK_B |
-						   R500_INST_ALPHA_WMASK |
-						   R500_INST_RGB_CLAMP |
-						   R500_INST_ALPHA_CLAMP));
-
-	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_ID(0) |
-						   R500_TEX_INST_LD |
-						   R500_TEX_SEM_ACQUIRE |
-						   R500_TEX_IGNORE_UNCOVERED));
-
-	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_SRC_ADDR(0) |
-						   R500_TEX_SRC_S_SWIZ_R |
-						   R500_TEX_SRC_T_SWIZ_G |
-						   R500_TEX_DST_ADDR(0) |
-						   R500_TEX_DST_R_SWIZ_R |
-						   R500_TEX_DST_G_SWIZ_G |
-						   R500_TEX_DST_B_SWIZ_B |
-						   R500_TEX_DST_A_SWIZ_A));
-	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_DX_ADDR(0) |
-						   R500_DX_S_SWIZ_R |
-						   R500_DX_T_SWIZ_R |
-						   R500_DX_R_SWIZ_R |
-						   R500_DX_Q_SWIZ_R |
-						   R500_DY_ADDR(0) |
-						   R500_DY_S_SWIZ_R |
-						   R500_DY_T_SWIZ_R |
-						   R500_DY_R_SWIZ_R |
-						   R500_DY_Q_SWIZ_R));
-	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
-	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
-
-	    /* ALU inst */
-	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_OUT |
-						   R500_INST_TEX_SEM_WAIT |
-						   R500_INST_LAST |
-						   R500_INST_RGB_OMASK_R |
-						   R500_INST_RGB_OMASK_G |
-						   R500_INST_RGB_OMASK_B |
-						   R500_INST_ALPHA_OMASK |
-						   R500_INST_RGB_CLAMP |
-						   R500_INST_ALPHA_CLAMP));
-
-	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_RGB_ADDR0(0) |
-						   R500_RGB_ADDR1(0) |
-						   R500_RGB_ADDR1_CONST |
-						   R500_RGB_ADDR2(0) |
-						   R500_RGB_ADDR2_CONST));
-	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDR0(0) |
-						   R500_ALPHA_ADDR1(0) |
-						   R500_ALPHA_ADDR1_CONST |
-						   R500_ALPHA_ADDR2(0) |
-						   R500_ALPHA_ADDR2_CONST));
-
-	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGB_SEL_A_SRC0 |
-						   R500_ALU_RGB_R_SWIZ_A_R |
-						   R500_ALU_RGB_G_SWIZ_A_G |
-						   R500_ALU_RGB_B_SWIZ_A_B |
-						   R500_ALU_RGB_SEL_B_SRC0 |
-						   R500_ALU_RGB_R_SWIZ_B_1 |
-						   R500_ALU_RGB_B_SWIZ_B_1 |
-						   R500_ALU_RGB_G_SWIZ_B_1));
-
-	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_OP_MAD |
-						   R500_ALPHA_SWIZ_A_A |
-						   R500_ALPHA_SWIZ_B_1));
-
-	    OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGBA_OP_MAD |
-						   R500_ALU_RGBA_R_SWIZ_0 |
-						   R500_ALU_RGBA_G_SWIZ_0 |
-						   R500_ALU_RGBA_B_SWIZ_0 |
-						   R500_ALU_RGBA_A_SWIZ_0));
-	    FINISH_VIDEO();
+	    if (pPriv->bicubic_enabled) {
+		BEGIN_VIDEO(7);
+
+		/* 4 components: 2 for tex0 and 2 for tex1 */
+		OUT_VIDEO_REG(R300_RS_COUNT,
+			      ((4 << R300_RS_COUNT_IT_COUNT_SHIFT) |
+			       R300_RS_COUNT_HIRES_EN));
+
+		/* R300_INST_COUNT_RS - highest RS instruction used */
+		OUT_VIDEO_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(1) | R300_TX_OFFSET_RS(6));
+
+		/* Pixel stack frame size. */
+		OUT_VIDEO_REG(R300_US_PIXSIZE, 5);
+
+		/* FP length. */
+		OUT_VIDEO_REG(R500_US_CODE_ADDR, (R500_US_CODE_START_ADDR(0) |
+						  R500_US_CODE_END_ADDR(13)));
+		OUT_VIDEO_REG(R500_US_CODE_RANGE, (R500_US_CODE_RANGE_ADDR(0) |
+						   R500_US_CODE_RANGE_SIZE(13)));
+
+		/* Prepare for FP emission. */
+		OUT_VIDEO_REG(R500_US_CODE_OFFSET, 0);
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_INDEX, R500_US_VECTOR_INST_INDEX(0));
+		FINISH_VIDEO();
+
+		BEGIN_VIDEO(89);
+		/* Pixel shader.
+		 * I've gone ahead and annotated each instruction, since this
+		 * thing is MASSIVE. :3
+		 * Note: In order to avoid buggies with temps and multiple
+		 * inputs, all temps are offset by 2. temp0 -> register2. */
+
+		/* TEX temp2, input1.xxxx, tex1, 1D */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_TEX |
+						       R500_INST_RGB_WMASK_R |
+						       R500_INST_RGB_WMASK_G |
+						       R500_INST_RGB_WMASK_B));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_ID(1) |
+						       R500_TEX_INST_LD |
+						       R500_TEX_IGNORE_UNCOVERED));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_SRC_ADDR(1) |
+						       R500_TEX_SRC_S_SWIZ_R |
+						       R500_TEX_SRC_T_SWIZ_R |
+						       R500_TEX_SRC_R_SWIZ_R |
+						       R500_TEX_SRC_Q_SWIZ_R |
+						       R500_TEX_DST_ADDR(2) |
+						       R500_TEX_DST_R_SWIZ_R |
+						       R500_TEX_DST_G_SWIZ_G |
+						       R500_TEX_DST_B_SWIZ_B |
+						       R500_TEX_DST_A_SWIZ_A));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+
+		/* TEX temp5, input1.yyyy, tex1, 1D */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_TEX |
+						       R500_INST_TEX_SEM_WAIT |
+						       R500_INST_RGB_WMASK_R |
+						       R500_INST_RGB_WMASK_G |
+						       R500_INST_RGB_WMASK_B));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_ID(1) |
+						       R500_TEX_INST_LD |
+						       R500_TEX_SEM_ACQUIRE |
+						       R500_TEX_IGNORE_UNCOVERED));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_SRC_ADDR(1) |
+						       R500_TEX_SRC_S_SWIZ_G |
+						       R500_TEX_SRC_T_SWIZ_G |
+						       R500_TEX_SRC_R_SWIZ_G |
+						       R500_TEX_SRC_Q_SWIZ_G |
+						       R500_TEX_DST_ADDR(5) |
+						       R500_TEX_DST_R_SWIZ_R |
+						       R500_TEX_DST_G_SWIZ_G |
+						       R500_TEX_DST_B_SWIZ_B |
+						       R500_TEX_DST_A_SWIZ_A));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+
+		/* MUL temp4, const0.x0x0, temp2.yyxx */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_ALU |
+						       R500_INST_TEX_SEM_WAIT |
+						       R500_INST_RGB_WMASK_R |
+						       R500_INST_RGB_WMASK_G |
+						       R500_INST_RGB_WMASK_B |
+						       R500_INST_ALPHA_WMASK));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_RGB_ADDR0(0) |
+						       R500_RGB_ADDR0_CONST |
+						       R500_RGB_ADDR1(2)));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDR0(0) |
+						       R500_ALPHA_ADDR0_CONST |
+						       R500_ALPHA_ADDR1(2)));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGB_SEL_A_SRC0 |
+						       R500_ALU_RGB_R_SWIZ_A_R |
+						       R500_ALU_RGB_G_SWIZ_A_0 |
+						       R500_ALU_RGB_B_SWIZ_A_R |
+						       R500_ALU_RGB_SEL_B_SRC1 |
+						       R500_ALU_RGB_R_SWIZ_B_G |
+						       R500_ALU_RGB_G_SWIZ_B_G |
+						       R500_ALU_RGB_B_SWIZ_B_R));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDRD(4) |
+						       R500_ALPHA_OP_MAD |
+						       R500_ALPHA_SEL_A_SRC0 |
+						       R500_ALPHA_SWIZ_A_0 |
+						       R500_ALPHA_SEL_B_SRC1 |
+						       R500_ALPHA_SWIZ_B_R));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGBA_ADDRD(4) |
+						       R500_ALU_RGBA_OP_MAD |
+						       R500_ALU_RGBA_R_SWIZ_0 |
+						       R500_ALU_RGBA_G_SWIZ_0 |
+						       R500_ALU_RGBA_B_SWIZ_0 |
+						       R500_ALU_RGBA_A_SWIZ_0));
+
+		/* MAD temp3, const0.0y0y, temp5.xxxx, temp4 */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_ALU |
+						       R500_INST_RGB_WMASK_R |
+						       R500_INST_RGB_WMASK_G |
+						       R500_INST_RGB_WMASK_B |
+						       R500_INST_ALPHA_WMASK));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_RGB_ADDR0(0) |
+						       R500_RGB_ADDR0_CONST |
+						       R500_RGB_ADDR1(5) |
+						       R500_RGB_ADDR2(4)));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDR0(0) |
+						       R500_ALPHA_ADDR0_CONST |
+						       R500_ALPHA_ADDR1(5) |
+						       R500_ALPHA_ADDR2(4)));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGB_SEL_A_SRC0 |
+						       R500_ALU_RGB_R_SWIZ_A_0 |
+						       R500_ALU_RGB_G_SWIZ_A_G |
+						       R500_ALU_RGB_B_SWIZ_A_0 |
+						       R500_ALU_RGB_SEL_B_SRC1 |
+						       R500_ALU_RGB_R_SWIZ_B_R |
+						       R500_ALU_RGB_G_SWIZ_B_R |
+						       R500_ALU_RGB_B_SWIZ_B_R));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDRD(3) |
+						       R500_ALPHA_OP_MAD |
+						       R500_ALPHA_SEL_A_SRC0 |
+						       R500_ALPHA_SWIZ_A_G |
+						       R500_ALPHA_SEL_B_SRC1 |
+						       R500_ALPHA_SWIZ_B_R));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGBA_ADDRD(3) |
+						       R500_ALU_RGBA_OP_MAD |
+						       R500_ALU_RGBA_SEL_C_SRC2 |
+						       R500_ALU_RGBA_R_SWIZ_R |
+						       R500_ALU_RGBA_G_SWIZ_G |
+						       R500_ALU_RGBA_B_SWIZ_B |
+						       R500_ALU_RGBA_A_SWIZ_A));
+
+		/* ADD temp3, temp3, input0.xyxy */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_ALU |
+						       R500_INST_RGB_WMASK_R |
+						       R500_INST_RGB_WMASK_G |
+						       R500_INST_RGB_WMASK_B |
+						       R500_INST_ALPHA_WMASK));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_RGB_ADDR1(3) |
+						       R500_RGB_ADDR2(0)));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDR1(3) |
+						       R500_ALPHA_ADDR2(0)));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGB_R_SWIZ_A_1 |
+						       R500_ALU_RGB_G_SWIZ_A_1 |
+						       R500_ALU_RGB_B_SWIZ_A_1 |
+						       R500_ALU_RGB_SEL_B_SRC1 |
+						       R500_ALU_RGB_R_SWIZ_B_R |
+						       R500_ALU_RGB_G_SWIZ_B_G |
+						       R500_ALU_RGB_B_SWIZ_B_B));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDRD(3) |
+						       R500_ALPHA_OP_MAD |
+						       R500_ALPHA_SWIZ_A_1 |
+						       R500_ALPHA_SEL_B_SRC1 |
+						       R500_ALPHA_SWIZ_B_A));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGBA_ADDRD(3) |
+						       R500_ALU_RGBA_OP_MAD |
+						       R500_ALU_RGBA_SEL_C_SRC2 |
+						       R500_ALU_RGBA_R_SWIZ_R |
+						       R500_ALU_RGBA_G_SWIZ_G |
+						       R500_ALU_RGBA_B_SWIZ_R |
+						       R500_ALU_RGBA_A_SWIZ_G));
+
+		/* TEX temp1, temp3.zwxy, tex0, 1D */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_TEX |
+						       R500_INST_RGB_WMASK_R |
+						       R500_INST_RGB_WMASK_G |
+						       R500_INST_RGB_WMASK_B |
+						       R500_INST_ALPHA_WMASK));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_ID(0) |
+						       R500_TEX_INST_LD |
+						       R500_TEX_IGNORE_UNCOVERED));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_SRC_ADDR(3) |
+						       R500_TEX_SRC_S_SWIZ_B |
+						       R500_TEX_SRC_T_SWIZ_A |
+						       R500_TEX_SRC_R_SWIZ_R |
+						       R500_TEX_SRC_Q_SWIZ_G |
+						       R500_TEX_DST_ADDR(1) |
+						       R500_TEX_DST_R_SWIZ_R |
+						       R500_TEX_DST_G_SWIZ_G |
+						       R500_TEX_DST_B_SWIZ_B |
+						       R500_TEX_DST_A_SWIZ_A));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+
+		/* TEX temp3, temp3.xyzw, tex0, 1D */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_TEX |
+						       R500_INST_TEX_SEM_WAIT |
+						       R500_INST_RGB_WMASK_R |
+						       R500_INST_RGB_WMASK_G |
+						       R500_INST_RGB_WMASK_B |
+						       R500_INST_ALPHA_WMASK));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_ID(0) |
+						       R500_TEX_INST_LD |
+						       R500_TEX_SEM_ACQUIRE |
+						       R500_TEX_IGNORE_UNCOVERED));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_SRC_ADDR(3) |
+						       R500_TEX_SRC_S_SWIZ_R |
+						       R500_TEX_SRC_T_SWIZ_G |
+						       R500_TEX_SRC_R_SWIZ_B |
+						       R500_TEX_SRC_Q_SWIZ_A |
+						       R500_TEX_DST_ADDR(3) |
+						       R500_TEX_DST_R_SWIZ_R |
+						       R500_TEX_DST_G_SWIZ_G |
+						       R500_TEX_DST_B_SWIZ_B |
+						       R500_TEX_DST_A_SWIZ_A));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+
+		/* MAD temp4, const1.0y0y, temp5.yyyy, temp4 */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_ALU |
+						       R500_INST_RGB_WMASK_R |
+						       R500_INST_RGB_WMASK_G |
+						       R500_INST_RGB_WMASK_B |
+						       R500_INST_ALPHA_WMASK));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_RGB_ADDR0(0) |
+						       R500_RGB_ADDR0_CONST |
+						       R500_RGB_ADDR1(5) |
+						       R500_RGB_ADDR2(4)));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDR0(0) |
+						       R500_ALPHA_ADDR0_CONST |
+						       R500_ALPHA_ADDR1(5) |
+						       R500_ALPHA_ADDR2(4)));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGB_SEL_A_SRC0 |
+						       R500_ALU_RGB_R_SWIZ_A_0 |
+						       R500_ALU_RGB_G_SWIZ_A_G |
+						       R500_ALU_RGB_B_SWIZ_A_0 |
+						       R500_ALU_RGB_SEL_B_SRC1 |
+						       R500_ALU_RGB_R_SWIZ_B_G |
+						       R500_ALU_RGB_G_SWIZ_B_G |
+						       R500_ALU_RGB_B_SWIZ_B_G));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDRD(4) |
+						       R500_ALPHA_OP_MAD |
+						       R500_ALPHA_SEL_A_SRC0 |
+						       R500_ALPHA_SWIZ_A_G |
+						       R500_ALPHA_SEL_B_SRC1 |
+						       R500_ALPHA_SWIZ_B_G));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGBA_ADDRD(4) |
+						       R500_ALU_RGBA_OP_MAD |
+						       R500_ALU_RGBA_SEL_C_SRC2 |
+						       R500_ALU_RGBA_R_SWIZ_R |
+						       R500_ALU_RGBA_G_SWIZ_G |
+						       R500_ALU_RGBA_B_SWIZ_B |
+						       R500_ALU_RGBA_A_SWIZ_A));
+
+		/* ADD temp0, temp4, input0.xyxy */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_ALU |
+						       R500_INST_RGB_WMASK_R |
+						       R500_INST_RGB_WMASK_G |
+						       R500_INST_RGB_WMASK_B |
+						       R500_INST_ALPHA_WMASK));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_RGB_ADDR1(4) |
+						       R500_RGB_ADDR2(0)));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDR1(4) |
+						       R500_ALPHA_ADDR2(0)));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGB_R_SWIZ_A_1 |
+						       R500_ALU_RGB_G_SWIZ_A_1 |
+						       R500_ALU_RGB_B_SWIZ_A_1 |
+						       R500_ALU_RGB_SEL_B_SRC1 |
+						       R500_ALU_RGB_R_SWIZ_B_R |
+						       R500_ALU_RGB_G_SWIZ_B_G |
+						       R500_ALU_RGB_B_SWIZ_B_B));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDRD(0) |
+						       R500_ALPHA_OP_MAD |
+						       R500_ALPHA_SWIZ_A_1 |
+						       R500_ALPHA_SEL_B_SRC1 |
+						       R500_ALPHA_SWIZ_B_A));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGBA_ADDRD(0) |
+						       R500_ALU_RGBA_OP_MAD |
+						       R500_ALU_RGBA_SEL_C_SRC2 |
+						       R500_ALU_RGBA_R_SWIZ_R |
+						       R500_ALU_RGBA_G_SWIZ_G |
+						       R500_ALU_RGBA_B_SWIZ_R |
+						       R500_ALU_RGBA_A_SWIZ_G));
+
+		/* TEX temp4, temp0.zwzw, tex0, 1D */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_TEX |
+						       R500_INST_TEX_SEM_WAIT |
+						       R500_INST_RGB_WMASK_R |
+						       R500_INST_RGB_WMASK_G |
+						       R500_INST_RGB_WMASK_B |
+						       R500_INST_ALPHA_WMASK));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_ID(0) |
+						       R500_TEX_INST_LD |
+						       R500_TEX_IGNORE_UNCOVERED));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_SRC_ADDR(0) |
+						       R500_TEX_SRC_S_SWIZ_B |
+						       R500_TEX_SRC_T_SWIZ_A |
+						       R500_TEX_SRC_R_SWIZ_B |
+						       R500_TEX_SRC_Q_SWIZ_A |
+						       R500_TEX_DST_ADDR(4) |
+						       R500_TEX_DST_R_SWIZ_R |
+						       R500_TEX_DST_G_SWIZ_G |
+						       R500_TEX_DST_B_SWIZ_B |
+						       R500_TEX_DST_A_SWIZ_A));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+
+		/* TEX temp0, temp0.xyzw, tex0, 1D */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_TEX |
+						       R500_INST_TEX_SEM_WAIT |
+						       R500_INST_RGB_WMASK_R |
+						       R500_INST_RGB_WMASK_G |
+						       R500_INST_RGB_WMASK_B |
+						   R500_INST_ALPHA_WMASK));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_ID(0) |
+						       R500_TEX_INST_LD |
+						       R500_TEX_SEM_ACQUIRE |
+						       R500_TEX_IGNORE_UNCOVERED));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_SRC_ADDR(0) |
+						       R500_TEX_SRC_S_SWIZ_R |
+						       R500_TEX_SRC_T_SWIZ_G |
+						       R500_TEX_SRC_R_SWIZ_B |
+						       R500_TEX_SRC_Q_SWIZ_A |
+						       R500_TEX_DST_ADDR(0) |
+						       R500_TEX_DST_R_SWIZ_R |
+						       R500_TEX_DST_G_SWIZ_G |
+						       R500_TEX_DST_B_SWIZ_B |
+						       R500_TEX_DST_A_SWIZ_A));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+
+		/* LRP temp3, temp2.zzzz, temp1, temp3 ->
+		 * - PRESUB temps, temp1 - temp3
+		 * - MAD temp2.zzzz, temps, temp3 */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_ALU |
+						       R500_INST_RGB_WMASK_R |
+						       R500_INST_RGB_WMASK_G |
+						       R500_INST_RGB_WMASK_B |
+						       R500_INST_ALPHA_WMASK));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_RGB_ADDR0(3) |
+						       R500_RGB_SRCP_OP_RGB1_MINUS_RGB0 |
+						       R500_RGB_ADDR1(1) |
+						       R500_RGB_ADDR2(2)));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDR0(3) |
+						       R500_ALPHA_SRCP_OP_A1_MINUS_A0 |
+						       R500_ALPHA_ADDR1(1) |
+						       R500_ALPHA_ADDR2(2)));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGB_SEL_A_SRC2 |
+						       R500_ALU_RGB_R_SWIZ_A_B |
+						       R500_ALU_RGB_G_SWIZ_A_B |
+						       R500_ALU_RGB_B_SWIZ_A_B |
+						       R500_ALU_RGB_SEL_B_SRCP |
+						       R500_ALU_RGB_R_SWIZ_B_R |
+						       R500_ALU_RGB_G_SWIZ_B_G |
+						       R500_ALU_RGB_B_SWIZ_B_B));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDRD(3) |
+						       R500_ALPHA_OP_MAD |
+						       R500_ALPHA_SEL_A_SRC2 |
+						       R500_ALPHA_SWIZ_A_B |
+						       R500_ALPHA_SEL_B_SRCP |
+						       R500_ALPHA_SWIZ_B_A));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGBA_ADDRD(3) |
+						       R500_ALU_RGBA_OP_MAD |
+						       R500_ALU_RGBA_SEL_C_SRC0 |
+						       R500_ALU_RGBA_R_SWIZ_R |
+						       R500_ALU_RGBA_G_SWIZ_G |
+						       R500_ALU_RGBA_B_SWIZ_B |
+						       R500_ALU_RGBA_A_SWIZ_A));
+
+		/* LRP temp0, temp2.zzzz, temp4, temp0 ->
+		 * - PRESUB temps, temp4 - temp1
+		 * - MAD temp2.zzzz, temps, temp0 */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_ALU |
+						       R500_INST_TEX_SEM_WAIT |
+						       R500_INST_RGB_WMASK_R |
+						       R500_INST_RGB_WMASK_G |
+						       R500_INST_RGB_WMASK_B |
+						       R500_INST_ALPHA_WMASK));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_RGB_ADDR0(0) |
+						       R500_RGB_SRCP_OP_RGB1_MINUS_RGB0 |
+						       R500_RGB_ADDR1(4) |
+						       R500_RGB_ADDR2(2)));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDR0(0) |
+						       R500_ALPHA_SRCP_OP_A1_MINUS_A0 |
+						       R500_ALPHA_ADDR1(4) |
+						       R500_ALPHA_ADDR2(2)));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGB_SEL_A_SRC2 |
+						       R500_ALU_RGB_R_SWIZ_A_B |
+						       R500_ALU_RGB_G_SWIZ_A_B |
+						       R500_ALU_RGB_B_SWIZ_A_B |
+						       R500_ALU_RGB_SEL_B_SRCP |
+						       R500_ALU_RGB_R_SWIZ_B_R |
+						       R500_ALU_RGB_G_SWIZ_B_G |
+						       R500_ALU_RGB_B_SWIZ_B_B));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDRD(0) |
+						       R500_ALPHA_OP_MAD |
+						       R500_ALPHA_SEL_A_SRC2 |
+						       R500_ALPHA_SWIZ_A_B |
+						       R500_ALPHA_SEL_B_SRCP |
+						       R500_ALPHA_SWIZ_B_A));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGBA_ADDRD(0) |
+						       R500_ALU_RGBA_OP_MAD |
+						       R500_ALU_RGBA_SEL_C_SRC0 |
+						       R500_ALU_RGBA_R_SWIZ_R |
+						       R500_ALU_RGBA_G_SWIZ_G |
+						       R500_ALU_RGBA_B_SWIZ_B |
+						       R500_ALU_RGBA_A_SWIZ_A));
+
+		/* LRP output, temp5.zzzz, temp3, temp0 ->
+		 * - PRESUB temps, temp3 - temp0
+		 * - MAD temp5.zzzz, temps, temp0 */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_OUT |
+						       R500_INST_LAST |
+						       R500_INST_TEX_SEM_WAIT |
+						       R500_INST_RGB_WMASK_R |
+						       R500_INST_RGB_WMASK_G |
+						       R500_INST_RGB_WMASK_B |
+						       R500_INST_ALPHA_WMASK |
+						       R500_INST_RGB_OMASK_R |
+						       R500_INST_RGB_OMASK_G |
+						       R500_INST_RGB_OMASK_B |
+						       R500_INST_ALPHA_OMASK));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_RGB_ADDR0(0) |
+						       R500_RGB_SRCP_OP_RGB1_MINUS_RGB0 |
+						       R500_RGB_ADDR1(3) |
+						       R500_RGB_ADDR2(5)));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDR0(0) |
+						       R500_ALPHA_SRCP_OP_A1_MINUS_A0 |
+						       R500_ALPHA_ADDR1(3) |
+						       R500_ALPHA_ADDR2(5)));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGB_SEL_A_SRC2 |
+						       R500_ALU_RGB_R_SWIZ_A_B |
+						       R500_ALU_RGB_G_SWIZ_A_B |
+						       R500_ALU_RGB_B_SWIZ_A_B |
+						       R500_ALU_RGB_SEL_B_SRCP |
+						       R500_ALU_RGB_R_SWIZ_B_R |
+						       R500_ALU_RGB_G_SWIZ_B_G |
+						       R500_ALU_RGB_B_SWIZ_B_B));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDRD(0) |
+						       R500_ALPHA_OP_MAD |
+						       R500_ALPHA_SEL_A_SRC2 |
+						       R500_ALPHA_SWIZ_A_B |
+						       R500_ALPHA_SEL_B_SRCP |
+						       R500_ALPHA_SWIZ_B_A));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGBA_ADDRD(0) |
+						       R500_ALU_RGBA_OP_MAD |
+						       R500_ALU_RGBA_SEL_C_SRC0 |
+						       R500_ALU_RGBA_R_SWIZ_R |
+						       R500_ALU_RGBA_G_SWIZ_G |
+						       R500_ALU_RGBA_B_SWIZ_B |
+						       R500_ALU_RGBA_A_SWIZ_A));
+
+		/* Shader constants. */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_INDEX, R500_US_VECTOR_CONST_INDEX(0));
+
+		/* const0 = {1 / texture[0].width, 0, 0, 0} */
+		OUT_VIDEO_REG_F(R500_GA_US_VECTOR_DATA, (1.0/(float)pPriv->w));
+		OUT_VIDEO_REG_F(R500_GA_US_VECTOR_DATA, (1.0/(float)pPriv->h));
+		OUT_VIDEO_REG_F(R500_GA_US_VECTOR_DATA, 0x0);
+		OUT_VIDEO_REG_F(R500_GA_US_VECTOR_DATA, 0x0);
+
+		FINISH_VIDEO();
+
+	    } else {
+		BEGIN_VIDEO(19);
+		/* 2 components: 2 for tex0 */
+		OUT_VIDEO_REG(R300_RS_COUNT,
+			      ((2 << R300_RS_COUNT_IT_COUNT_SHIFT) |
+			       R300_RS_COUNT_HIRES_EN));
+
+		/* R300_INST_COUNT_RS - highest RS instruction used */
+		OUT_VIDEO_REG(R300_RS_INST_COUNT, R300_INST_COUNT_RS(0) | R300_TX_OFFSET_RS(6));
+
+		/* Pixel stack frame size. */
+		OUT_VIDEO_REG(R300_US_PIXSIZE, 0); /* highest temp used */
+
+		/* FP length. */
+		OUT_VIDEO_REG(R500_US_CODE_ADDR, (R500_US_CODE_START_ADDR(0) |
+						  R500_US_CODE_END_ADDR(1)));
+		OUT_VIDEO_REG(R500_US_CODE_RANGE, (R500_US_CODE_RANGE_ADDR(0) |
+						   R500_US_CODE_RANGE_SIZE(1)));
+
+		/* Prepare for FP emission. */
+		OUT_VIDEO_REG(R500_US_CODE_OFFSET, 0);
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_INDEX, R500_US_VECTOR_INST_INDEX(0));
+
+		/* tex inst */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_TEX |
+						       R500_INST_TEX_SEM_WAIT |
+						       R500_INST_RGB_WMASK_R |
+						       R500_INST_RGB_WMASK_G |
+						       R500_INST_RGB_WMASK_B |
+						       R500_INST_ALPHA_WMASK |
+						       R500_INST_RGB_CLAMP |
+						       R500_INST_ALPHA_CLAMP));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_ID(0) |
+						       R500_TEX_INST_LD |
+						       R500_TEX_SEM_ACQUIRE |
+						       R500_TEX_IGNORE_UNCOVERED));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_TEX_SRC_ADDR(0) |
+						       R500_TEX_SRC_S_SWIZ_R |
+						       R500_TEX_SRC_T_SWIZ_G |
+						       R500_TEX_DST_ADDR(0) |
+						       R500_TEX_DST_R_SWIZ_R |
+						       R500_TEX_DST_G_SWIZ_G |
+						       R500_TEX_DST_B_SWIZ_B |
+						       R500_TEX_DST_A_SWIZ_A));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_DX_ADDR(0) |
+						       R500_DX_S_SWIZ_R |
+						       R500_DX_T_SWIZ_R |
+						       R500_DX_R_SWIZ_R |
+						       R500_DX_Q_SWIZ_R |
+						       R500_DY_ADDR(0) |
+						       R500_DY_S_SWIZ_R |
+						       R500_DY_T_SWIZ_R |
+						       R500_DY_R_SWIZ_R |
+						       R500_DY_Q_SWIZ_R));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, 0x00000000);
+
+		/* ALU inst */
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_INST_TYPE_OUT |
+						       R500_INST_TEX_SEM_WAIT |
+						       R500_INST_LAST |
+						       R500_INST_RGB_OMASK_R |
+						       R500_INST_RGB_OMASK_G |
+						       R500_INST_RGB_OMASK_B |
+						       R500_INST_ALPHA_OMASK |
+						       R500_INST_RGB_CLAMP |
+						       R500_INST_ALPHA_CLAMP));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_RGB_ADDR0(0) |
+						       R500_RGB_ADDR1(0) |
+						       R500_RGB_ADDR1_CONST |
+						       R500_RGB_ADDR2(0) |
+						       R500_RGB_ADDR2_CONST));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_ADDR0(0) |
+						       R500_ALPHA_ADDR1(0) |
+						       R500_ALPHA_ADDR1_CONST |
+						       R500_ALPHA_ADDR2(0) |
+						       R500_ALPHA_ADDR2_CONST));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGB_SEL_A_SRC0 |
+						       R500_ALU_RGB_R_SWIZ_A_R |
+						       R500_ALU_RGB_G_SWIZ_A_G |
+						       R500_ALU_RGB_B_SWIZ_A_B |
+						       R500_ALU_RGB_SEL_B_SRC0 |
+						       R500_ALU_RGB_R_SWIZ_B_1 |
+						       R500_ALU_RGB_B_SWIZ_B_1 |
+						       R500_ALU_RGB_G_SWIZ_B_1));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALPHA_OP_MAD |
+						       R500_ALPHA_SWIZ_A_A |
+						       R500_ALPHA_SWIZ_B_1));
+		OUT_VIDEO_REG(R500_GA_US_VECTOR_DATA, (R500_ALU_RGBA_OP_MAD |
+						       R500_ALU_RGBA_R_SWIZ_0 |
+						       R500_ALU_RGBA_G_SWIZ_0 |
+						       R500_ALU_RGBA_B_SWIZ_0 |
+						       R500_ALU_RGBA_A_SWIZ_0));
+		FINISH_VIDEO();
+	    }
 	}
 
-	BEGIN_VIDEO(5);
+	BEGIN_VIDEO(6);
 	OUT_VIDEO_REG(R300_TX_INVALTAGS, 0);
 	OUT_VIDEO_REG(R300_TX_ENABLE, txenable);
 
@@ -418,10 +990,8 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	blendcntl = RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO;
 	/* no need to enable blending */
 	OUT_VIDEO_REG(R300_RB3D_BLENDCNTL, blendcntl);
-	FINISH_VIDEO();
 
-	BEGIN_VIDEO(1);
-	OUT_VIDEO_REG(R300_VAP_VTX_SIZE, VTX_DWORD_COUNT);
+	OUT_VIDEO_REG(R300_VAP_VTX_SIZE, vtx_count);
 	FINISH_VIDEO();
 
     } else {
@@ -456,15 +1026,15 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	BEGIN_VIDEO(5);
 
 	OUT_VIDEO_REG(RADEON_PP_CNTL,
-		    RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE);
+		      RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE);
 	OUT_VIDEO_REG(RADEON_RB3D_CNTL,
-		    dst_format | RADEON_ALPHA_BLEND_ENABLE);
+		      dst_format | RADEON_ALPHA_BLEND_ENABLE);
 	OUT_VIDEO_REG(RADEON_RB3D_COLOROFFSET, dst_offset);
 
 	OUT_VIDEO_REG(RADEON_RB3D_COLORPITCH, colorpitch);
 
 	OUT_VIDEO_REG(RADEON_RB3D_BLENDCNTL,
-		    RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO);
+		      RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO);
 
 	FINISH_VIDEO();
 
@@ -481,35 +1051,37 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 
 	    OUT_VIDEO_REG(R200_SE_VTX_FMT_0, R200_VTX_XY);
 	    OUT_VIDEO_REG(R200_SE_VTX_FMT_1,
-			(2 << R200_VTX_TEX0_COMP_CNT_SHIFT));
+			  (2 << R200_VTX_TEX0_COMP_CNT_SHIFT));
 
 	    OUT_VIDEO_REG(R200_PP_TXFILTER_0,
-			R200_MAG_FILTER_LINEAR |
-			R200_MIN_FILTER_LINEAR |
-			R200_YUV_TO_RGB);
+			  R200_MAG_FILTER_LINEAR |
+			  R200_MIN_FILTER_LINEAR |
+			  R200_CLAMP_S_CLAMP_LAST |
+			  R200_CLAMP_T_CLAMP_LAST |
+			  R200_YUV_TO_RGB);
 	    OUT_VIDEO_REG(R200_PP_TXFORMAT_0, txformat);
 	    OUT_VIDEO_REG(R200_PP_TXFORMAT_X_0, 0);
 	    OUT_VIDEO_REG(R200_PP_TXSIZE_0,
-			(pPriv->w - 1) |
-			((pPriv->h - 1) << RADEON_TEX_VSIZE_SHIFT));
+			  (pPriv->w - 1) |
+			  ((pPriv->h - 1) << RADEON_TEX_VSIZE_SHIFT));
 	    OUT_VIDEO_REG(R200_PP_TXPITCH_0, pPriv->src_pitch - 32);
 
 	    OUT_VIDEO_REG(R200_PP_TXOFFSET_0, pPriv->src_offset);
 
 	    OUT_VIDEO_REG(R200_PP_TXCBLEND_0,
-			R200_TXC_ARG_A_ZERO |
-			R200_TXC_ARG_B_ZERO |
-			R200_TXC_ARG_C_R0_COLOR |
-			R200_TXC_OP_MADD);
+			  R200_TXC_ARG_A_ZERO |
+			  R200_TXC_ARG_B_ZERO |
+			  R200_TXC_ARG_C_R0_COLOR |
+			  R200_TXC_OP_MADD);
 	    OUT_VIDEO_REG(R200_PP_TXCBLEND2_0,
-			R200_TXC_CLAMP_0_1 | R200_TXC_OUTPUT_REG_R0);
+			  R200_TXC_CLAMP_0_1 | R200_TXC_OUTPUT_REG_R0);
 	    OUT_VIDEO_REG(R200_PP_TXABLEND_0,
-			R200_TXA_ARG_A_ZERO |
-			R200_TXA_ARG_B_ZERO |
-			R200_TXA_ARG_C_R0_ALPHA |
-			R200_TXA_OP_MADD);
+			  R200_TXA_ARG_A_ZERO |
+			  R200_TXA_ARG_B_ZERO |
+			  R200_TXA_ARG_C_R0_ALPHA |
+			  R200_TXA_OP_MADD);
 	    OUT_VIDEO_REG(R200_PP_TXABLEND2_0,
-			R200_TXA_CLAMP_0_1 | R200_TXA_OUTPUT_REG_R0);
+			  R200_TXA_CLAMP_0_1 | R200_TXA_OUTPUT_REG_R0);
 	    FINISH_VIDEO();
 	} else {
 
@@ -518,32 +1090,35 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 
 	    BEGIN_VIDEO(8);
 
-	    OUT_VIDEO_REG(RADEON_SE_VTX_FMT, RADEON_SE_VTX_FMT_XY |
-			RADEON_SE_VTX_FMT_ST0);
+	    OUT_VIDEO_REG(RADEON_SE_VTX_FMT, (RADEON_SE_VTX_FMT_XY |
+					      RADEON_SE_VTX_FMT_ST0));
 
-	    OUT_VIDEO_REG(RADEON_PP_TXFILTER_0, RADEON_MAG_FILTER_LINEAR |
-			RADEON_MIN_FILTER_LINEAR |
-			RADEON_YUV_TO_RGB);
+	    OUT_VIDEO_REG(RADEON_PP_TXFILTER_0,
+			  RADEON_MAG_FILTER_LINEAR |
+			  RADEON_MIN_FILTER_LINEAR |
+			  RADEON_CLAMP_S_CLAMP_LAST |
+			  RADEON_CLAMP_T_CLAMP_LAST |
+			  RADEON_YUV_TO_RGB);
 	    OUT_VIDEO_REG(RADEON_PP_TXFORMAT_0, txformat);
 	    OUT_VIDEO_REG(RADEON_PP_TXOFFSET_0, pPriv->src_offset);
 	    OUT_VIDEO_REG(RADEON_PP_TXCBLEND_0,
-			RADEON_COLOR_ARG_A_ZERO |
-			RADEON_COLOR_ARG_B_ZERO |
-			RADEON_COLOR_ARG_C_T0_COLOR |
-			RADEON_BLEND_CTL_ADD |
-			RADEON_CLAMP_TX);
+			  RADEON_COLOR_ARG_A_ZERO |
+			  RADEON_COLOR_ARG_B_ZERO |
+			  RADEON_COLOR_ARG_C_T0_COLOR |
+			  RADEON_BLEND_CTL_ADD |
+			  RADEON_CLAMP_TX);
 	    OUT_VIDEO_REG(RADEON_PP_TXABLEND_0,
-			RADEON_ALPHA_ARG_A_ZERO |
-			RADEON_ALPHA_ARG_B_ZERO |
-			RADEON_ALPHA_ARG_C_T0_ALPHA |
-			RADEON_BLEND_CTL_ADD |
-			RADEON_CLAMP_TX);
+			  RADEON_ALPHA_ARG_A_ZERO |
+			  RADEON_ALPHA_ARG_B_ZERO |
+			  RADEON_ALPHA_ARG_C_T0_ALPHA |
+			  RADEON_BLEND_CTL_ADD |
+			  RADEON_CLAMP_TX);
 
 	    OUT_VIDEO_REG(RADEON_PP_TEX_SIZE_0,
-			(pPriv->w - 1) |
-			((pPriv->h - 1) << RADEON_TEX_VSIZE_SHIFT));
+			  (pPriv->w - 1) |
+			  ((pPriv->h - 1) << RADEON_TEX_VSIZE_SHIFT));
 	    OUT_VIDEO_REG(RADEON_PP_TEX_PITCH_0,
-			pPriv->src_pitch - 32);
+			  pPriv->src_pitch - 32);
 	    FINISH_VIDEO();
 	}
     }
@@ -582,53 +1157,71 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 
 #ifdef ACCEL_CP
 	if (info->ChipFamily < CHIP_FAMILY_R200) {
-	    BEGIN_RING(4 * VTX_DWORD_COUNT + 3);
+	    BEGIN_RING(3 * vtx_count + 3);
 	    OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD,
-				4 * VTX_DWORD_COUNT + 1));
+				3 * vtx_count + 1));
 	    OUT_RING(RADEON_CP_VC_FRMT_XY |
 		     RADEON_CP_VC_FRMT_ST0);
-	    OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
+	    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 |
-		     (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
+		     (3 << RADEON_CP_VC_CNTL_NUM_SHIFT));
 	} else {
 	    if (IS_R300_3D || IS_R500_3D)
-		BEGIN_RING(4 * VTX_DWORD_COUNT + 4);
+		BEGIN_RING(4 * vtx_count + 4);
 	    else
-		BEGIN_RING(4 * VTX_DWORD_COUNT + 2);
+		BEGIN_RING(4 * vtx_count + 2);
 	    OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
-				4 * VTX_DWORD_COUNT));
-	    OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
+				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));
 	}
 #else /* ACCEL_CP */
 	if (IS_R300_3D || IS_R500_3D)
-	    BEGIN_VIDEO(2 + VTX_DWORD_COUNT * 4);
+	    BEGIN_VIDEO(2 + vtx_count * 4);
+	else if (info->ChipFamily < CHIP_FAMILY_R200)
+	    BEGIN_VIDEO(1 + vtx_count * 3);
 	else
-	    BEGIN_VIDEO(1 + VTX_DWORD_COUNT * 4);
+	    BEGIN_VIDEO(1 + vtx_count * 4);
 
-	if (info->ChipFamily < CHIP_FAMILY_R200) {
-	    OUT_VIDEO_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_TRIANGLE_FAN |
+	if (info->ChipFamily < CHIP_FAMILY_R200)
+	    OUT_VIDEO_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_RECTANGLE_LIST |
 					      RADEON_VF_PRIM_WALK_DATA |
 					      RADEON_VF_RADEON_MODE |
-					      4 << RADEON_VF_NUM_VERTICES_SHIFT));
-	} else {
+					      (3 << RADEON_VF_NUM_VERTICES_SHIFT)));
+	else
 	    OUT_VIDEO_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_QUAD_LIST |
 					      RADEON_VF_PRIM_WALK_DATA |
-					      4 << RADEON_VF_NUM_VERTICES_SHIFT));
-	}
-#endif
+					      (4 << RADEON_VF_NUM_VERTICES_SHIFT)));
 
-	VTX_OUT((float)dstX,                                      (float)dstY,
-		xFixedToFloat(srcTopLeft.x) / info->texW[0],      xFixedToFloat(srcTopLeft.y) / info->texH[0]);
-	VTX_OUT((float)dstX,                                      (float)(dstY + dsth),
+#endif
+	if (pPriv->bicubic_enabled) {
+		VTX_OUT_FILTER((float)dstX,                       (float)dstY,
+		xFixedToFloat(srcTopLeft.x) / info->texW[0],      xFixedToFloat(srcTopLeft.y) / info->texH[0],
+		xFixedToFloat(srcTopLeft.x) + 0.5,                xFixedToFloat(srcTopLeft.y) + 0.5);
+		VTX_OUT_FILTER((float)dstX,                       (float)(dstY + dsth),
+		xFixedToFloat(srcBottomLeft.x) / info->texW[0],   xFixedToFloat(srcBottomLeft.y) / info->texH[0],
+		xFixedToFloat(srcBottomLeft.x) + 0.5,             xFixedToFloat(srcBottomLeft.y) + 0.5);
+		VTX_OUT_FILTER((float)(dstX + dstw),              (float)(dstY + dsth),
+		xFixedToFloat(srcBottomRight.x) / info->texW[0],  xFixedToFloat(srcBottomRight.y) / info->texH[0],
+		xFixedToFloat(srcBottomRight.x) + 0.5,            xFixedToFloat(srcBottomRight.y) + 0.5);
+		VTX_OUT_FILTER((float)(dstX + dstw),              (float)dstY,
+		xFixedToFloat(srcTopRight.x) / info->texW[0],     xFixedToFloat(srcTopRight.y) / info->texH[0],
+		xFixedToFloat(srcTopRight.x) + 0.5,               xFixedToFloat(srcTopRight.y) + 0.5);
+	} else {
+		if (info->ChipFamily >= CHIP_FAMILY_R200) {
+			VTX_OUT((float)dstX,                              (float)dstY,
+			xFixedToFloat(srcTopLeft.x) / info->texW[0],      xFixedToFloat(srcTopLeft.y) / info->texH[0]);
+		}
+		VTX_OUT((float)dstX,                              (float)(dstY + dsth),
 		xFixedToFloat(srcBottomLeft.x) / info->texW[0],   xFixedToFloat(srcBottomLeft.y) / info->texH[0]);
-	VTX_OUT((float)(dstX + dstw),                                (float)(dstY + dsth),
+		VTX_OUT((float)(dstX + dstw),                     (float)(dstY + dsth),
 		xFixedToFloat(srcBottomRight.x) / info->texW[0],  xFixedToFloat(srcBottomRight.y) / info->texH[0]);
-	VTX_OUT((float)(dstX + dstw),                                (float)dstY,
+		VTX_OUT((float)(dstX + dstw),                     (float)dstY,
 		xFixedToFloat(srcTopRight.x) / info->texW[0],     xFixedToFloat(srcTopRight.y) / info->texH[0]);
+	}
 
 	if (IS_R300_3D || IS_R500_3D)
 	    /* flushing is pipelined, free/finish is not */
@@ -655,4 +1248,5 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 }
 
 #undef VTX_OUT
+#undef VTX_OUT_FILTER
 #undef FUNC_NAME
diff --git a/src/radeon_tv.c b/src/radeon_tv.c
index 90020b3..90d1ac9 100644
--- a/src/radeon_tv.c
+++ b/src/radeon_tv.c
@@ -140,7 +140,7 @@ static const uint16_t vert_timing_PAL[] =
  **********************************************************************/
 static const TVModeConstants availableTVModes[] =
 {
-    {
+    {   /* NTSC timing for 27 Mhz ref clk */
 	800,                /* horResolution */
 	600,                /* verResolution */
 	TV_STD_NTSC,        /* standard */
@@ -155,7 +155,7 @@ static const TVModeConstants availableTVModes[] =
 	4,                  /* crtcPLL_postDiv */
 	1022,               /* pixToTV */
     },
-    {
+    {   /* PAL timing for 27 Mhz ref clk */
 	800,               /* horResolution */
 	600,               /* verResolution */
 	TV_STD_PAL,        /* standard */
@@ -169,7 +169,22 @@ static const TVModeConstants availableTVModes[] =
 	231,               /* crtcPLL_M */
 	4,                 /* crtcPLL_postDiv */
 	759,               /* pixToTV */
-    }
+    },
+    {   /* NTSC timing for 14 Mhz ref clk */
+	800,                /* horResolution */
+	600,                /* verResolution */
+	TV_STD_NTSC,        /* standard */
+	1018,               /* horTotal */
+	727,                /* verTotal */
+	813,                /* horStart */
+	840,                /* horSyncStart */
+	633,                /* verSyncStart */
+	630627,             /* defRestart */
+	347,                /* crtcPLL_N */
+	14,                 /* crtcPLL_M */
+	8,                  /* crtcPLL_postDiv */
+	1022,               /* pixToTV */
+    },
 };
 
 #define N_AVAILABLE_MODES (sizeof(availableModes) / sizeof(availableModes[ 0 ]))
@@ -582,6 +597,8 @@ static Bool RADEONInitTVRestarts(xf86OutputPtr output, RADEONSavePtr save,
 				 DisplayModePtr mode)
 {
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    RADEONInfoPtr  info       = RADEONPTR(output->scrn);
+    RADEONPLLPtr pll = &info->pll;
     int restart;
     unsigned hTotal;
     unsigned vTotal;
@@ -597,14 +614,21 @@ static Bool RADEONInitTVRestarts(xf86OutputPtr output, RADEONSavePtr save,
     /* FIXME: need to revisit this when we add more modes */
     if (radeon_output->tvStd == TV_STD_NTSC ||
 	radeon_output->tvStd == TV_STD_NTSC_J ||
-        radeon_output->tvStd == TV_STD_PAL_M)
-	constPtr = &availableTVModes[0];
-    else
-	constPtr = &availableTVModes[1];
+	radeon_output->tvStd == TV_STD_PAL_M) {
+	if (pll->reference_freq == 2700)
+	    constPtr = &availableTVModes[0];
+	else
+	    constPtr = &availableTVModes[2];
+    } else {
+	if (pll->reference_freq == 2700)
+	    constPtr = &availableTVModes[1];
+	else
+	    constPtr = &availableTVModes[1]; /* FIXME */
+    }
 
     hTotal = constPtr->horTotal;
     vTotal = constPtr->verTotal;
-    
+
     if (radeon_output->tvStd == TV_STD_NTSC ||
 	radeon_output->tvStd == TV_STD_NTSC_J ||
         radeon_output->tvStd == TV_STD_PAL_M ||
@@ -696,6 +720,8 @@ void RADEONInitTVRegisters(xf86OutputPtr output, RADEONSavePtr save,
     ScrnInfoPtr pScrn = output->scrn;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
     RADEONInfoPtr  info = RADEONPTR(pScrn);
+    RADEONPLLPtr pll = &info->pll;
+    unsigned m, n, p;
     unsigned i;
     unsigned long vert_space, flicker_removal;
     uint32_t tmp;
@@ -703,14 +729,20 @@ void RADEONInitTVRegisters(xf86OutputPtr output, RADEONSavePtr save,
     const uint16_t *hor_timing;
     const uint16_t *vert_timing;
 
-
     /* FIXME: need to revisit this when we add more modes */
     if (radeon_output->tvStd == TV_STD_NTSC ||
 	radeon_output->tvStd == TV_STD_NTSC_J ||
-	radeon_output->tvStd == TV_STD_PAL_M)
-	constPtr = &availableTVModes[0];
-    else
-	constPtr = &availableTVModes[1];
+	radeon_output->tvStd == TV_STD_PAL_M) {
+	if (pll->reference_freq == 2700)
+	    constPtr = &availableTVModes[0];
+	else
+	    constPtr = &availableTVModes[2];
+    } else {
+	if (pll->reference_freq == 2700)
+	    constPtr = &availableTVModes[1];
+	else
+	    constPtr = &availableTVModes[1]; /* FIXME */
+    }
 
     save->tv_crc_cntl = 0;
 
@@ -796,7 +828,10 @@ void RADEONInitTVRegisters(xf86OutputPtr output, RADEONSavePtr save,
     save->tv_vscaler_cntl1 = RADEON_Y_W_EN;
     save->tv_vscaler_cntl1 =
 	(save->tv_vscaler_cntl1 & 0xe3ff0000) | (vert_space * (1 << FRAC_BITS) / 10000);
-    save->tv_vscaler_cntl1 |= RADEON_RESTART_FIELD;
+
+    if (pll->reference_freq == 2700)
+	save->tv_vscaler_cntl1 |= RADEON_RESTART_FIELD;
+
     if (constPtr->horResolution == 1024)
 	save->tv_vscaler_cntl1 |= (4 << RADEON_Y_DEL_W_SIG_SHIFT);
     else
@@ -873,18 +908,33 @@ void RADEONInitTVRegisters(xf86OutputPtr output, RADEONSavePtr save,
 #endif
 
     if (radeon_output->tvStd == TV_STD_NTSC ||
-        radeon_output->tvStd == TV_STD_NTSC_J)
-	save->tv_pll_cntl = (NTSC_TV_PLL_M & RADEON_TV_M0LO_MASK) |
-	    (((NTSC_TV_PLL_M >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) |
-	    ((NTSC_TV_PLL_N & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) |
-	    (((NTSC_TV_PLL_N >> 9) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) |
-	    ((NTSC_TV_PLL_P & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT);
-    else
-	save->tv_pll_cntl = (PAL_TV_PLL_M & RADEON_TV_M0LO_MASK) |
-	    (((PAL_TV_PLL_M >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) |
-	    ((PAL_TV_PLL_N & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) |
-	    (((PAL_TV_PLL_N >> 9) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) |
-	    ((PAL_TV_PLL_P & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT);
+	radeon_output->tvStd == TV_STD_NTSC_J) {
+	if (pll->reference_freq == 2700) {
+	    m = NTSC_TV_PLL_M_27;
+	    n = NTSC_TV_PLL_N_27;
+	    p = NTSC_TV_PLL_P_27;
+	} else {
+	    m = NTSC_TV_PLL_M_14;
+	    n = NTSC_TV_PLL_N_14;
+	    p = NTSC_TV_PLL_P_14;
+	}
+    } else {
+	if (pll->reference_freq == 2700) {
+	    m = PAL_TV_PLL_M_27;
+	    n = PAL_TV_PLL_N_27;
+	    p = PAL_TV_PLL_P_27;
+	} else {
+	    /* FIXME */
+	    m = PAL_TV_PLL_M_27;
+	    n = PAL_TV_PLL_N_27;
+	    p = PAL_TV_PLL_P_27;
+	}
+    }
+    save->tv_pll_cntl = (m & RADEON_TV_M0LO_MASK) |
+	(((m >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) |
+	((n & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) |
+	(((n >> 9) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) |
+	((p & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT);
 
     save->tv_pll_cntl1 =  (((4 & RADEON_TVPCP_MASK)<< RADEON_TVPCP_SHIFT) |
 			   ((4 & RADEON_TVPVG_MASK) << RADEON_TVPVG_SHIFT) |
@@ -999,14 +1049,23 @@ void RADEONAdjustCrtcRegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save,
 {
     const TVModeConstants *constPtr;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    RADEONPLLPtr pll = &info->pll;
 
     /* FIXME: need to revisit this when we add more modes */
     if (radeon_output->tvStd == TV_STD_NTSC ||
 	radeon_output->tvStd == TV_STD_NTSC_J ||
-        radeon_output->tvStd == TV_STD_PAL_M)
-	constPtr = &availableTVModes[0];
-    else
-	constPtr = &availableTVModes[1];
+	radeon_output->tvStd == TV_STD_PAL_M) {
+	if (pll->reference_freq == 2700)
+	    constPtr = &availableTVModes[0];
+	else
+	    constPtr = &availableTVModes[2];
+    } else {
+	if (pll->reference_freq == 2700)
+	    constPtr = &availableTVModes[1];
+	else
+	    constPtr = &availableTVModes[1]; /* FIXME */
+    }
 
     save->crtc_h_total_disp = (((constPtr->horResolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) |
 	(((constPtr->horTotal / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT);
@@ -1030,14 +1089,23 @@ void RADEONAdjustPLLRegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save,
     unsigned postDiv;
     const TVModeConstants *constPtr;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    RADEONPLLPtr pll = &info->pll;
 
     /* FIXME: need to revisit this when we add more modes */
     if (radeon_output->tvStd == TV_STD_NTSC ||
 	radeon_output->tvStd == TV_STD_NTSC_J ||
-        radeon_output->tvStd == TV_STD_PAL_M)
-	constPtr = &availableTVModes[0];
-    else
-	constPtr = &availableTVModes[1];
+	radeon_output->tvStd == TV_STD_PAL_M) {
+	if (pll->reference_freq == 2700)
+	    constPtr = &availableTVModes[0];
+	else
+	    constPtr = &availableTVModes[2];
+    } else {
+	if (pll->reference_freq == 2700)
+	    constPtr = &availableTVModes[1];
+	else
+	    constPtr = &availableTVModes[1]; /* FIXME */
+    }
 
     save->htotal_cntl = (constPtr->horTotal & 0x7 /*0xf*/) | RADEON_HTOT_CNTL_VGA_EN;
 
@@ -1083,14 +1151,23 @@ void RADEONAdjustCrtc2RegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save,
 {
     const TVModeConstants *constPtr;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    RADEONPLLPtr pll = &info->pll;
 
     /* FIXME: need to revisit this when we add more modes */
     if (radeon_output->tvStd == TV_STD_NTSC ||
 	radeon_output->tvStd == TV_STD_NTSC_J ||
-        radeon_output->tvStd == TV_STD_PAL_M)
-	constPtr = &availableTVModes[0];
-    else
-	constPtr = &availableTVModes[1];
+	radeon_output->tvStd == TV_STD_PAL_M) {
+	if (pll->reference_freq == 2700)
+	    constPtr = &availableTVModes[0];
+	else
+	    constPtr = &availableTVModes[2];
+    } else {
+	if (pll->reference_freq == 2700)
+	    constPtr = &availableTVModes[1];
+	else
+	    constPtr = &availableTVModes[1]; /* FIXME */
+    }
 
     save->crtc2_h_total_disp = (((constPtr->horResolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) |
 	(((constPtr->horTotal / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT);
@@ -1114,14 +1191,23 @@ void RADEONAdjustPLL2RegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save,
     unsigned postDiv;
     const TVModeConstants *constPtr;
     RADEONOutputPrivatePtr radeon_output = output->driver_private;
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    RADEONPLLPtr pll = &info->pll;
 
     /* FIXME: need to revisit this when we add more modes */
     if (radeon_output->tvStd == TV_STD_NTSC ||
 	radeon_output->tvStd == TV_STD_NTSC_J ||
-        radeon_output->tvStd == TV_STD_PAL_M)
-	constPtr = &availableTVModes[0];
-    else
-	constPtr = &availableTVModes[1];
+	radeon_output->tvStd == TV_STD_PAL_M) {
+	if (pll->reference_freq == 2700)
+	    constPtr = &availableTVModes[0];
+	else
+	    constPtr = &availableTVModes[2];
+    } else {
+	if (pll->reference_freq == 2700)
+	    constPtr = &availableTVModes[1];
+	else
+	    constPtr = &availableTVModes[1]; /* FIXME */
+    }
 
     save->htotal_cntl2 = (constPtr->horTotal & 0x7); /* 0xf */
 
diff --git a/src/radeon_tv.h b/src/radeon_tv.h
index c4b7838..8d77a77 100644
--- a/src/radeon_tv.h
+++ b/src/radeon_tv.h
@@ -27,24 +27,31 @@
 #define MAX_H_SIZE 5 /* Range: [-5..5], negative is smaller, positive is larger */
 
 /* tv standard constants */
-#define NTSC_TV_PLL_M 22
-#define NTSC_TV_PLL_N 175
-#define NTSC_TV_PLL_P 5
 #define NTSC_TV_CLOCK_T 233
 #define NTSC_TV_VFTOTAL 1
 #define NTSC_TV_LINES_PER_FRAME 525
 #define NTSC_TV_ZERO_H_SIZE 479166
 #define NTSC_TV_H_SIZE_UNIT 9478
 
-#define PAL_TV_PLL_M 113
-#define PAL_TV_PLL_N 668
-#define PAL_TV_PLL_P 3
 #define PAL_TV_CLOCK_T 188
 #define PAL_TV_VFTOTAL 3
 #define PAL_TV_LINES_PER_FRAME 625
 #define PAL_TV_ZERO_H_SIZE 473200
 #define PAL_TV_H_SIZE_UNIT 9360
 
+/* tv pll setting for 27 mhz ref clk */
+#define NTSC_TV_PLL_M_27 22
+#define NTSC_TV_PLL_N_27 175
+#define NTSC_TV_PLL_P_27 5
+
+#define PAL_TV_PLL_M_27 113
+#define PAL_TV_PLL_N_27 668
+#define PAL_TV_PLL_P_27 3
+
+/* tv pll setting for 14 mhz ref clk */
+#define NTSC_TV_PLL_M_14 33
+#define NTSC_TV_PLL_N_14 693
+#define NTSC_TV_PLL_P_14 7
 
 #define VERT_LEAD_IN_LINES 2
 #define FRAC_BITS 0xe
diff --git a/src/radeon_version.h b/src/radeon_version.h
index ccc1367..5717ead 100644
--- a/src/radeon_version.h
+++ b/src/radeon_version.h
@@ -39,10 +39,9 @@
 #define R200_DRIVER_NAME     "r200"
 #define R300_DRIVER_NAME     "r300"
 
-#define RADEON_VERSION_MAJOR 4
-#define RADEON_VERSION_MAJOR_TILED 5
-#define RADEON_VERSION_MINOR 3
-#define RADEON_VERSION_PATCH 0
+#define RADEON_VERSION_MAJOR PACKAGE_VERSION_MAJOR
+#define RADEON_VERSION_MINOR PACKAGE_VERSION_MINOR
+#define RADEON_VERSION_PATCH PACKAGE_VERSION_PATCHLEVEL
 
 #ifndef RADEON_VERSION_EXTRA
 #define RADEON_VERSION_EXTRA ""
diff --git a/src/radeon_video.c b/src/radeon_video.c
index ac60166..e71f0f8 100644
--- a/src/radeon_video.c
+++ b/src/radeon_video.c
@@ -89,10 +89,6 @@ static void RADEON_MSP_SetEncoding(RADEONPortPrivPtr pPriv);
 static void RADEON_TDA9885_SetEncoding(RADEONPortPrivPtr pPriv);
 static void RADEON_FI1236_SetEncoding(RADEONPortPrivPtr pPriv);
 
-
-
-#define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
-
 static Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer;
 static Atom xvRedIntensity, xvGreenIntensity, xvBlueIntensity;
 static Atom xvContrast, xvHue, xvColor, xvAutopaintColorkey, xvSetDefaults;
@@ -106,7 +102,6 @@ static Atom xvEncoding, xvFrequency, xvVolume, xvMute,
 	     
 static Atom xvOvAlpha, xvGrAlpha, xvAlphaMode;
 
-
 #define GET_PORT_PRIVATE(pScrn) \
    (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
 
@@ -1678,6 +1673,10 @@ RADEONStopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
 	 RADEONFreeMemory(pScrn, pPriv->video_memory);
 	 pPriv->video_memory = NULL;
      }
+     if (pPriv->bicubic_memory != NULL) {
+	 RADEONFreeMemory(pScrn, pPriv->bicubic_memory);
+	 pPriv->bicubic_memory = NULL;
+     }
      pPriv->videoStatus = 0;
   } else {
      if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
@@ -1699,9 +1698,6 @@ RADEONSetPortAttribute(ScrnInfoPtr  pScrn,
     Bool		setAlpha = FALSE;
     unsigned char *RADEONMMIO = info->MMIO;
 
-    if (pPriv->textured)
-	return BadMatch;
-
     RADEON_SYNC(info, pScrn);
 
 #define RTFSaturation(a)   (1.0 + ((a)*1.0)/1000.0)
@@ -1928,7 +1924,7 @@ RADEONSetPortAttribute(ScrnInfoPtr  pScrn,
 	if(pPriv->fi1236!=NULL){
 		xf86_fi1236_dump_status(pPriv->fi1236);
 		}
-   } 
+   }
    else if(attribute == xvAdjustment) 
    {
   	pPriv->adjustment=value;
@@ -1973,9 +1969,6 @@ RADEONGetPortAttribute(ScrnInfoPtr  pScrn,
     RADEONInfoPtr	info = RADEONPTR(pScrn);
     RADEONPortPrivPtr	pPriv = (RADEONPortPrivPtr)data;
 
-    if (pPriv->textured)
-	return BadMatch;
-
     if (info->accelOn) RADEON_SYNC(info, pScrn);
 
     if(attribute == xvAutopaintColorkey)
@@ -2586,6 +2579,7 @@ RADEONDisplayVideo(
     RADEONOutputPrivatePtr radeon_output;
     xf86OutputPtr output;
     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
+    int base_offset;
 
     is_rgb=0; is_planar=0;
     switch(id){
@@ -2715,6 +2709,22 @@ RADEONDisplayVideo(
         }
 #endif
 
+    /* Make the overlay base address as close to the buffers as possible to
+     * prevent the buffer offsets from exceeding the hardware limit of 128 MB.
+     * The base address must be aligned to a multiple of 4 MB.
+     */
+    base_offset = ((info->fbLocation +
+		    min(offset1, min(offset2, min(offset3, min(offset4,
+			min(offset5, offset6)))))) & (~0 << 22)) -
+	info->fbLocation;
+
+    offset1 -= base_offset;
+    offset2 -= base_offset;
+    offset3 -= base_offset;
+    offset4 -= base_offset;
+    offset5 -= base_offset;
+    offset6 -= base_offset;
+
     /* keep everything in 16.16 */
 
     if (is_planar) {
@@ -2846,6 +2856,10 @@ RADEONDisplayVideo(
 	src_w >>= 1;
     OUTREG(RADEON_OV0_P2_X_START_END, (src_w + leftuv - 1) | (leftuv << 16));
     OUTREG(RADEON_OV0_P3_X_START_END, (src_w + leftuv - 1) | (leftuv << 16));
+    if (info->ModeReg->ov0_base_addr != (info->fbLocation + base_offset)) {
+	info->ModeReg->ov0_base_addr = info->fbLocation + base_offset;
+	OUTREG(RADEON_OV0_BASE_ADDR, info->ModeReg->ov0_base_addr);
+    }
     OUTREG(RADEON_OV0_VID_BUF0_BASE_ADRS, offset1);
     OUTREG(RADEON_OV0_VID_BUF1_BASE_ADRS, offset2);
     OUTREG(RADEON_OV0_VID_BUF2_BASE_ADRS, offset3);
@@ -3236,6 +3250,10 @@ RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now)
 		    RADEONFreeMemory(pScrn, pPriv->video_memory);
 		    pPriv->video_memory = NULL;
 		}
+		if (pPriv->bicubic_memory != NULL) {
+		    RADEONFreeMemory(pScrn, pPriv->bicubic_memory);
+		    pPriv->bicubic_memory = NULL;
+		}
 		pPriv->videoStatus = 0;
 		info->VideoTimerCallback = NULL;
 	    }
diff --git a/src/radeon_video.h b/src/radeon_video.h
index 096de37..b9d900d 100644
--- a/src/radeon_video.h
+++ b/src/radeon_video.h
@@ -13,6 +13,10 @@
 
 #include "xf86Crtc.h"
 
+#include "bicubic_table.h"
+
+#define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
+
 /* Xvideo port struct */
 typedef struct {
    uint32_t	 transform_index;
@@ -37,7 +41,7 @@ typedef struct {
    uint32_t      radeon_N;
    uint32_t      i2c_status;
    uint32_t      i2c_cntl;
-   
+
    FI1236Ptr     fi1236;
    uint8_t       tuner_type;
    MSP3430Ptr    msp3430;
@@ -46,7 +50,7 @@ typedef struct {
 
    /* VIP bus and devices */
    GENERIC_BUS_Ptr  VIP;
-   TheatrePtr       theatre;   
+   TheatrePtr       theatre;
 
    Bool          video_stream_active;
    int           encoding;
@@ -56,7 +60,7 @@ typedef struct {
    int           sap_channel;
    int           v;
    uint32_t      adjustment; /* general purpose variable */
-   
+
 #define METHOD_BOB      0
 #define METHOD_SINGLE   1
 #define METHOD_WEAVE    2
@@ -89,6 +93,12 @@ typedef struct {
    void         *video_memory;
    int           video_offset;
 
+   /* bicubic filtering */
+   void         *bicubic_memory;
+   int           bicubic_offset;
+   Bool          bicubic_enabled;
+   uint32_t      bicubic_src_offset;
+
    Atom          device_id, location_id, instance_id;
 
     /* textured video */
@@ -106,7 +116,6 @@ typedef struct {
     int drw_x, drw_y;
 } RADEONPortPrivRec, *RADEONPortPrivPtr;
 
-
 void RADEONInitI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv);
 void RADEONResetI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv);