6872597 need support for auburndale/havendale chipset
authorNiveditha Rau <Niveditha.Rau@Sun.COM>
Wed, 21 Oct 2009 10:31:36 -0700
changeset 814 b5944ca396d1
parent 813 c07f05811086
child 815 d55936cbc91a
6872597 need support for auburndale/havendale chipset
open-src/driver/xf86-video-intel/6872597.patch
open-src/driver/xf86-video-intel/COPYING
open-src/driver/xf86-video-intel/Makefile
open-src/driver/xf86-video-intel/bugs.patch
open-src/lib/libdrm/Makefile
open-src/lib/mesa/6872597.patch
open-src/lib/mesa/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/open-src/driver/xf86-video-intel/6872597.patch	Wed Oct 21 10:31:36 2009 -0700
@@ -0,0 +1,7191 @@
+
+--- src/common.h	2009-08-18 11:31:33.525169652 +0800
++++ src/common.h	2009-08-18 11:32:03.738267811 +0800
+@@ -311,6 +311,16 @@ extern int I810_DEBUG;
+ #define PCI_CHIP_G41_G_BRIDGE	0x2E30
+ #endif
+ 
++#ifndef PCI_CHIP_IGDNG_D_G
++#define PCI_CHIP_IGDNG_D_G	0x0042
++#define PCI_CHIP_IGDNG_D_G_BRIDGE	0x0040
++#endif
++
++#ifndef PCI_CHIP_IGDNG_M_G
++#define PCI_CHIP_IGDNG_M_G	0x0046
++#define PCI_CHIP_IGDNG_M_G_BRIDGE	0x0044
++#endif
++
+ #if XSERVER_LIBPCIACCESS
+ #define I810_MEMBASE(p,n) (p)->regions[(n)].base_addr
+ #define VENDOR_ID(p)      (p)->vendor_id
+@@ -346,27 +356,30 @@ extern int I810_DEBUG;
+ #define IS_G4X(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_IGD_E_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_G45_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_Q45_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_G41_G || IS_GM45(pI810))
+ #define IS_I965GM(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GM || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GME)
+ #define IS_965_Q(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_Q)
+-#define IS_I965G(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_G35_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_Q || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I946_GZ || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GM || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GME || IS_G4X(pI810))
++#define IS_IGDNG_D(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_IGDNG_D_G)
++#define IS_IGDNG_M(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_IGDNG_M_G)
++#define IS_IGDNG(pI810) (IS_IGDNG_D(pI810) || IS_IGDNG_M(pI810))
++#define IS_I965G(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_G35_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_Q || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I946_GZ || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GM || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GME || IS_G4X(pI810) || IS_IGDNG(pI810))
+ #define IS_G33CLASS(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_G33_G ||\
+  			    DEVICE_ID(pI810->PciInfo) == PCI_CHIP_Q35_G ||\
+  			    DEVICE_ID(pI810->PciInfo) == PCI_CHIP_Q33_G)
+ #define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810) || IS_I965G(pI810) || IS_G33CLASS(pI810))
+ #define IS_I915(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810) || IS_G33CLASS(pI810))
+ 
+-#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810) || IS_I965GM(pI810) || IS_GM45(pI810))
++#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810) || IS_I965GM(pI810) || IS_GM45(pI810) || IS_IGDNG_M(pI810))
+ /* mark chipsets for using gfx VM offset for overlay */
+ #define OVERLAY_NOPHYSICAL(pI810) (IS_G33CLASS(pI810) || IS_I965G(pI810))
+ /* mark chipsets without overlay hw */
+-#define OVERLAY_NOEXIST(pI810) (IS_G4X(pI810))
++#define OVERLAY_NOEXIST(pI810) (IS_G4X(pI810) || IS_IGDNG(pI810))
+ /* chipsets require graphics mem for hardware status page */
+ #define HWS_NEED_GFX(pI810) (!pI810->use_drm_mode && \
+ 			     (IS_G33CLASS(pI810) ||\
+-			      IS_G4X(pI810)))
++			      IS_G4X(pI810) || IS_IGDNG(pI810)))
+ /* chipsets require status page in non stolen memory */
+-#define HWS_NEED_NONSTOLEN(pI810) (IS_G4X(pI810))
+-#define SUPPORTS_INTEGRATED_HDMI(pI810) (IS_G4X(pI810))
++#define HWS_NEED_NONSTOLEN(pI810) (IS_G4X(pI810) || IS_IGDNG(pI810))
++#define SUPPORTS_INTEGRATED_HDMI(pI810) (IS_G4X(pI810) || IS_IGDNG(pI810))
+ /* dsparb controlled by hw only */
+-#define DSPARB_HWCONTROL(pI810) (IS_G4X(pI810))
++#define DSPARB_HWCONTROL(pI810) (IS_G4X(pI810) || IS_IGDNG(pI810))
+ /* supports Y tiled surfaces (pre-965 Mesa isn't ready yet) */
+ #define SUPPORTS_YTILING(pI810) (IS_I965G(pI830))
+ 
+--- src/i810_driver.c	2009-08-18 11:31:33.479949097 +0800
++++ src/i810_driver.c	2009-08-18 11:32:03.739518101 +0800
+@@ -157,6 +157,8 @@ static const struct pci_id_match intel_d
+    INTEL_DEVICE_MATCH (PCI_CHIP_G45_G, 0 ),
+    INTEL_DEVICE_MATCH (PCI_CHIP_Q45_G, 0 ),
+    INTEL_DEVICE_MATCH (PCI_CHIP_G41_G, 0 ),
++   INTEL_DEVICE_MATCH (PCI_CHIP_IGDNG_D_G, 0 ),
++   INTEL_DEVICE_MATCH (PCI_CHIP_IGDNG_M_G, 0 ),
+     { 0, 0, 0 },
+ };
+ 
+@@ -214,6 +216,8 @@ static SymTabRec I810Chipsets[] = {
+    {PCI_CHIP_G45_G,		"G45/G43"},
+    {PCI_CHIP_Q45_G,		"Q45/Q43"},
+    {PCI_CHIP_G41_G,		"G41"},
++   {PCI_CHIP_IGDNG_D_G,		"IGDNG_D"},
++   {PCI_CHIP_IGDNG_M_G,		"IGDNG_M"},
+    {-1,				NULL}
+ };
+ 
+@@ -248,6 +252,8 @@ static PciChipsets I810PciChipsets[] = {
+    {PCI_CHIP_G45_G,		PCI_CHIP_G45_G,		RES_SHARED_VGA},
+    {PCI_CHIP_Q45_G,		PCI_CHIP_Q45_G,		RES_SHARED_VGA},
+    {PCI_CHIP_G41_G,		PCI_CHIP_G41_G,		RES_SHARED_VGA},
++   {PCI_CHIP_IGDNG_D_G,		PCI_CHIP_IGDNG_D_G,	RES_SHARED_VGA},
++   {PCI_CHIP_IGDNG_M_G,		PCI_CHIP_IGDNG_M_G,	RES_SHARED_VGA},
+    {-1,				-1, RES_UNDEFINED }
+ };
+ 
+--- src/i830_driver.c	2009-08-18 11:31:33.477769983 +0800
++++ src/i830_driver.c	2009-08-18 11:32:30.358842938 +0800
+@@ -258,6 +258,8 @@ static SymTabRec I830Chipsets[] = {
+    {PCI_CHIP_G45_G,		"G45/G43"},
+    {PCI_CHIP_Q45_G,		"Q45/Q43"},
+    {PCI_CHIP_G41_G,		"G41"},
++   {PCI_CHIP_IGDNG_D_G,		"IGDNG_D"},
++   {PCI_CHIP_IGDNG_M_G,		"IGDNG_M"},
+    {-1,				NULL}
+ };
+ 
+@@ -286,6 +288,8 @@ static PciChipsets I830PciChipsets[] = {
+    {PCI_CHIP_G45_G,		PCI_CHIP_G45_G,		RES_SHARED_VGA},
+    {PCI_CHIP_Q45_G,		PCI_CHIP_Q45_G,		RES_SHARED_VGA},
+    {PCI_CHIP_G41_G,		PCI_CHIP_G41_G,		RES_SHARED_VGA},
++   {PCI_CHIP_IGDNG_D_G,		PCI_CHIP_IGDNG_D_G,		RES_SHARED_VGA},
++   {PCI_CHIP_IGDNG_M_G,		PCI_CHIP_IGDNG_M_G,		RES_SHARED_VGA},
+    {-1,				-1,			RES_UNDEFINED}
+ };
+ 
+@@ -505,7 +509,7 @@ I830DetectMemory(ScrnInfoPtr pScrn)
+    range = gtt_size + 4;
+ 
+    /* new 4 series hardware has seperate GTT stolen with GFX stolen */
+-   if (IS_G4X(pI830) || IS_GM45(pI830))
++   if (IS_G4X(pI830) || IS_GM45(pI830) || IS_IGDNG(pI830))
+        range = 4;
+ 
+    if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) {
+@@ -640,7 +644,7 @@ I830MapMMIO(ScrnInfoPtr pScrn)
+ 
+       if (IS_I965G(pI830)) 
+       {
+-	 if (IS_G4X(pI830)) {
++	 if (IS_G4X(pI830) || IS_IGDNG(pI830)) {
+ 	     gttaddr = pI830->MMIOAddr + MB(2);
+ 	     pI830->GTTMapSize = MB(2);
+ 	 } else {
+@@ -1374,6 +1378,12 @@ i830_detect_chipset(ScrnInfoPtr pScrn)
+     case PCI_CHIP_G41_G:
+ 	chipname = "G41";
+ 	break;
++    case PCI_CHIP_IGDNG_D_G:
++	chipname = "IGDNG_D";
++	break;
++    case PCI_CHIP_IGDNG_M_G:
++	chipname = "IGDNG_M";
++	break;
+    default:
+ 	chipname = "unknown chipset";
+ 	break;
+
+--- src/i830.h	2009-08-18 14:01:07.320962581 +0800
++++ src/i830.h	2009-08-18 11:41:03.886037545 +0800
+@@ -502,6 +502,7 @@ typedef struct _I830Rec {
+    int Chipset;
+    unsigned long LinearAddr;
+    unsigned long MMIOAddr;
++   unsigned int MMIOSize;
+    IOADDRESS ioBase;
+    EntityInfoPtr pEnt;
+ #if XSERVER_LIBPCIACCESS
+--- src/i830_driver.c	2009-08-18 14:01:07.323530941 +0800
++++ src/i830_driver.c	2009-08-18 14:04:18.838404348 +0800
+@@ -611,7 +611,7 @@ I830MapMMIO(ScrnInfoPtr pScrn)
+    device = pI830->PciInfo;
+    err = pci_device_map_range (device,
+ 			       pI830->MMIOAddr,
+-			       I810_REG_SIZE,
++			       pI830->MMIOSize,
+ 			       PCI_DEV_MAP_FLAG_WRITABLE,
+ 			       (void **) &pI830->MMIOBase);
+    if (err) 
+@@ -731,7 +731,7 @@ I830UnmapMMIO(ScrnInfoPtr pScrn)
+    I830Ptr pI830 = I830PTR(pScrn);
+ 
+ #if XSERVER_LIBPCIACCESS
+-   pci_device_unmap_range (pI830->PciInfo, pI830->MMIOBase, I810_REG_SIZE);
++   pci_device_unmap_range (pI830->PciInfo, pI830->MMIOBase, pI830->MMIOSize);
+ #else
+    xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->MMIOBase,
+ 		   I810_REG_SIZE);
+@@ -1457,6 +1457,7 @@ i830_detect_chipset(ScrnInfoPtr pScrn)
+     if (pI830->pEnt->device->IOBase != 0) {
+ 	pI830->MMIOAddr = pI830->pEnt->device->IOBase;
+ 	from = X_CONFIG;
++	pI830->MMIOSize = I810_REG_SIZE;
+     } else {
+ 	pI830->MMIOAddr = I810_MEMBASE (pI830->PciInfo, mmio_bar);
+ 	if (pI830->MMIOAddr == 0) {
+@@ -1465,10 +1466,11 @@ i830_detect_chipset(ScrnInfoPtr pScrn)
+ 	    PreInitCleanup(pScrn);
+ 	    return FALSE;
+ 	}
++	pI830->MMIOSize = pI830->PciInfo->regions[mmio_bar].size;
+     }
+ 
+-    xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n",
+-	       (unsigned long)pI830->MMIOAddr);
++    xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX size %u\n",
++	       (unsigned long)pI830->MMIOAddr, pI830->MMIOSize);
+ 
+     /* Now figure out mapsize on 8xx chips */
+     if (IS_I830(pI830) || IS_845G(pI830)) {
+
+--- src/i810_reg.h	2009-08-14 16:18:48.325243258 +0800
++++ src/i810_reg.h	2009-08-14 16:46:43.739763594 +0800
+@@ -980,13 +980,18 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  */
+ # define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS	0x003f0000
+ # define DPLL_FPA01_P1_POST_DIV_SHIFT		16
++/* IGDNG */
++# define DPLL_FPA0_P1_POST_DIV_SHIFT		16
++
+ # define PLL_P2_DIVIDE_BY_4			(1 << 23) /* i830, required in DVO non-gang */
+ # define PLL_P1_DIVIDE_BY_TWO			(1 << 21) /* i830 */
+ # define PLL_REF_INPUT_DREFCLK			(0 << 13)
+ # define PLL_REF_INPUT_TVCLKINA			(1 << 13) /* i830 */
++# define PLL_REF_INPUT_SUPER_SSC		(1 << 13) /* IGDNG: 120M SSC */
+ # define PLL_REF_INPUT_TVCLKINBC		(2 << 13) /* SDVO TVCLKIN */
+ # define PLLB_REF_INPUT_SPREADSPECTRUMIN	(3 << 13)
+ # define PLL_REF_INPUT_MASK			(3 << 13)
++# define PLL_REF_INPUT_DMICLK			(5 << 13) /* IGDNG: DMI refclk */
+ # define PLL_LOAD_PULSE_PHASE_SHIFT		9
+ /*
+  * Parallel to Serial Load Pulse phase selection.
+@@ -996,6 +1001,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  */
+ # define PLL_LOAD_PULSE_PHASE_MASK		(0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
+ # define DISPLAY_RATE_SELECT_FPA1		(1 << 8)
++/* IGDNG */
++# define PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT	9
++# define PLL_REF_SDVO_HDMI_MULTIPLIER_MASK	(7 << 9)
++# define PLL_REF_SDVO_HDMI_MULTIPLIER(x)	(((x)-1)<< PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT)
++# define DPLL_FPA1_P1_POST_DIV_SHIFT		0
++# define DPLL_FPA1_P1_POST_DIV_MASK		0xff
++
+ 
+ /**
+  * SDVO multiplier for 945G/GM. Not used on 965.
+@@ -2140,10 +2152,34 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ #define PIPEACONF_PIPE_LOCKED	(1<<25)
+ #define PIPEACONF_PALETTE	0
+ #define PIPEACONF_GAMMA 	(1<<24)
++/* IGDNG: gamma */
++#define PIPECONF_PALETTE_8BIT	(0<<24)
++#define PIPECONF_PALETTE_10BIT	(1<<24)
++#define PIPECONF_PALETTE_12BIT	(2<<24)
+ #define PIPECONF_FORCE_BORDER	(1<<25)
+ #define PIPECONF_PROGRESSIVE	(0 << 21)
+ #define PIPECONF_INTERLACE_W_FIELD_INDICATION	(6 << 21)
+ #define PIPECONF_INTERLACE_FIELD_0_ONLY		(7 << 21)
++/* IGDNG */
++#define PIPECONF_MSA_TIMING_DELAY	(0<<18) /* for eDP */
++#define PIPECONF_NO_DYNAMIC_RATE_CHANGE	(0 << 16)
++#define PIPECONF_NO_ROTATION		(0<<14)
++#define PIPECONF_FULL_COLOR_RANGE	(0<<13)
++#define PIPECONF_CE_COLOR_RANGE		(1<<13)
++#define PIPECONF_COLOR_SPACE_RGB	(0<<11)
++#define PIPECONF_COLOR_SPACE_YUV601	(1<<11)
++#define PIPECONF_COLOR_SPACE_YUV709	(2<<11)
++#define PIPECONF_CONNECT_DEFAULT	(0<<9)
++#define PIPECONF_8BPP			(0<<5)
++#define PIPECONF_10BPP			(1<<5)
++#define PIPECONF_6BPP			(2<<5)
++#define PIPECONF_12BPP			(3<<5)
++#define PIPECONF_ENABLE_DITHER		(1<<4)
++#define PIPECONF_DITHER_SPATIAL		(0<<2)
++#define PIPECONF_DITHER_ST1		(1<<2)
++#define PIPECONF_DITHER_ST2		(2<<2)
++#define PIPECONF_DITHER_TEMPORAL	(3<<2)
++
+ 
+ #define PIPEAGCMAXRED		0x70010
+ #define PIPEAGCMAXGREEN		0x70014
+@@ -2237,13 +2273,23 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ #define DISPPLANE_8BPP				(0x2<<26)
+ #define DISPPLANE_15_16BPP			(0x4<<26)
+ #define DISPPLANE_16BPP				(0x5<<26)
+-#define DISPPLANE_32BPP_NO_ALPHA 		(0x6<<26)
+-#define DISPPLANE_32BPP				(0x7<<26)
++#define DISPPLANE_32BPP_NO_ALPHA 		(0x6<<26) /* IGDNG: BGRX */
++#define DISPPLANE_32BPP				(0x7<<26) /* IGDNG: not support */
++/* IGDNG */
++#define DISPPLANE_32BPP_10			(0x8<<26) /* 2:10:10:10 */
++#define DISPPLANE_32BPP_BGRX			(0xa<<26)
++#define DISPPLANE_64BPP				(0xc<<26)
++#define DISPPLANE_32BPP_RGBX			(0xe<<26)
+ #define DISPPLANE_STEREO_ENABLE			(1<<25)
+ #define DISPPLANE_STEREO_DISABLE		0
+ #define DISPPLANE_SEL_PIPE_MASK			(1<<24)
+ #define DISPPLANE_SEL_PIPE_A			0
+ #define DISPPLANE_SEL_PIPE_B			(1<<24)
++#define DISPPLANE_NORMAL_RANGE			(0<<25)
++#define DISPPLANE_EXT_RANGE			(1<<25)
++/* IGDNG */
++#define DISPPLANE_CSC_BYPASS			(0<<24)
++#define DISPPLANE_CSC_PASSTHROUGH		(1<<24)
+ #define DISPPLANE_SRC_KEY_ENABLE		(1<<22)
+ #define DISPPLANE_SRC_KEY_DISABLE		0
+ #define DISPPLANE_LINE_DOUBLE			(1<<20)
+@@ -2255,11 +2301,18 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ #define DISPPLANE_ALPHA_TRANS_DISABLE		0
+ #define DISPPLANE_SPRITE_ABOVE_DISPLAYA		0
+ #define DISPPLANE_SPRITE_ABOVE_OVERLAY		(1)
++/* IGDNG */
++#define DISPPLANE_X_TILE			(1<<10)
++#define DISPPLANE_LINEAR			(0<<10)
+ 
+ #define DSPABASE		0x70184
++/* IGDNG */
++#define DSPALINOFF		0x70184
+ #define DSPASTRIDE		0x70188
+ 
+ #define DSPBBASE		0x71184
++/* IGDNG */
++#define DSPBLINOFF		0x71184
+ #define DSPBADDR		DSPBBASE
+ #define DSPBSTRIDE		0x71188
+ 
+@@ -2860,4 +2913,439 @@ typedef enum {
+ #define MCHBAR_RENDER_STANDBY	0x111B8
+ #define RENDER_STANDBY_ENABLE	(1 << 30)
+ 
++/* IGDNG */
++
++/* warmup time in us */
++#define WARMUP_PCH_REF_CLK_SSC_MOD	1
++#define WARMUP_PCH_FDI_RECEIVER_PLL	25
++#define WARMUP_PCH_DPLL			50
++#define WARMUP_CPU_DP_PLL		20
++#define WARMUP_CPU_FDI_TRANSMITTER_PLL	10
++#define WARMUP_DMI_LATENCY		20
++#define FDI_TRAIN_PATTERN_1_TIME	0.5
++#define FDI_TRAIN_PATTERN_2_TIME	1.5
++#define FDI_ONE_IDLE_PATTERN_TIME	31
++
++#define CPU_VGACNTRL		0x41000
++
++#define DIGITAL_PORT_HOTPLUG_CNTRL	0x44030
++#define  DIGITAL_PORTA_HOTPLUG_ENABLE		(1 << 4)
++#define  DIGITAL_PORTA_SHORT_PULSE_2MS		(0 << 2)
++#define  DIGITAL_PORTA_SHORT_PULSE_4_5MS	(1 << 2)
++#define  DIGITAL_PORTA_SHORT_PULSE_6MS		(2 << 2)
++#define  DIGITAL_PORTA_SHORT_PULSE_100MS	(3 << 2)
++#define  DIGITAL_PORTA_NO_DETECT		(0 << 0)
++#define  DIGITAL_PORTA_LONG_PULSE_DETECT_MASK	(1 << 1)
++#define  DIGITAL_PORTA_SHORT_PULSE_DETECT_MASK	(1 << 0)
++
++/* refresh rate hardware control */
++#define RR_HW_CTL	0x45300
++#define  RR_HW_LOW_POWER_FRAMES_MASK	0xff
++#define  RR_HW_HIGH_POWER_FRAMES_MASK	0xff00
++
++#define FDI_PLL_BIOS_0			0x46000
++#define FDI_PLL_BIOS_1			0x46004
++#define FDI_PLL_BIOS_2			0x46008
++#define DISPLAY_PORT_PLL_BIOS_0		0x4600c
++#define DISPLAY_PORT_PLL_BIOS_1		0x46010
++#define DISPLAY_PORT_PLL_BIOS_2		0x46014
++
++#define FDI_PLL_FREQ_CTL	0x46030
++#define  FDI_PLL_FREQ_CHANGE_REQUEST	(1<<24)
++#define  FDI_PLL_FREQ_LOCK_LIMIT_MASK	0xfff00
++#define  FDI_PLL_FREQ_DISABLE_COUNT_LIMIT_MASK	0xff
++
++#define PIPEA_DATA_M1		0x60030
++#define  TU_SIZE(x)		(((x)-1) << 25) /* default size 64 */
++#define  TU_SIZE_MASK		0x7e000000
++#define  PIPEA_DATA_M1_OFFSET	0
++#define PIPEA_DATA_N1		0x60034
++#define  PIPEA_DATA_N1_OFFSET	0
++
++#define PIPEA_DATA_M2		0x60038
++#define  PIPEA_DATA_M2_OFFSET	0
++#define PIPEA_DATA_N2		0x6003c
++#define  PIPEA_DATA_N2_OFFSET	0
++
++#define PIPEA_LINK_M1		0x60040
++#define  PIPEA_LINK_M1_OFFSET	0
++#define PIPEA_LINK_N1		0x60044
++#define  PIPEA_LINK_N1_OFFSET	0
++
++#define PIPEA_LINK_M2		0x60048
++#define  PIPEA_LINK_M2_OFFSET	0
++#define PIPEA_LINK_N2		0x6004c
++#define  PIPEA_LINK_N2_OFFSET	0
++
++/* PIPEB timing regs are same start from 0x61000 */
++
++#define PIPEB_DATA_M1		0x61030
++#define  PIPEB_DATA_M1_OFFSET	0
++#define PIPEB_DATA_N1		0x61034
++#define  PIPEB_DATA_N1_OFFSET	0
++
++#define PIPEB_DATA_M2		0x61038
++#define  PIPEB_DATA_M2_OFFSET	0
++#define PIPEB_DATA_N2		0x6103c
++#define  PIPEB_DATA_N2_OFFSET	0
++
++#define PIPEB_LINK_M1		0x61040
++#define  PIPEB_LINK_M1_OFFSET	0
++#define PIPEB_LINK_N1		0x61044
++#define  PIPEB_LINK_N1_OFFSET	0
++
++#define PIPEB_LINK_M2		0x61048
++#define  PIPEB_LINK_M2_OFFSET	0
++#define PIPEB_LINK_N2		0x6104c
++#define  PIPEB_LINK_N2_OFFSET	0
++
++/* PIPECONF for pipe A/B addr is same */
++
++/* cusor A is only connected to pipe A,
++   cursor B is connected to pipe B. Otherwise no change. */
++
++/* Plane A/B, DSPACNTR/DSPBCNTR addr not changed */
++
++/* CPU panel fitter */
++#define PFA_CTL_1		0x68080
++#define PFB_CTL_1		0x68880
++#define  PF_ENABLE		(1<<31)
++
++/* CPU panel fitter */
++#define PFA_CTRL_1		0x68080
++#define PFB_CTRL_1		0x68880
++
++/* legacy palette */
++#define LGC_PALETTE_A		0x4a000
++#define LGC_PALETTE_B		0x4a800
++
++/* interrupts */
++#define DE_MASTER_IRQ_CONTROL	(1 << 31)
++#define DE_SPRITEB_FLIP_DONE	(1 << 29)
++#define DE_SPRITEA_FLIP_DONE	(1 << 28)
++#define DE_PLANEB_FLIP_DONE	(1 << 27)
++#define DE_PLANEA_FLIP_DONE	(1 << 26)
++#define DE_PCU_EVENT		(1 << 25)
++#define DE_GTT_FAULT		(1 << 24)
++#define DE_POISON		(1 << 23)
++#define DE_PERFORM_COUNTER	(1 << 22)
++#define DE_PCH_EVENT		(1 << 21)
++#define DE_AUX_CHANNEL_A	(1 << 20)
++#define DE_DP_A_HOTPLUG		(1 << 19)
++#define DE_GSE			(1 << 18)
++#define DE_PIPEB_VBLANK		(1 << 15)
++#define DE_PIPEB_EVEN_FIELD	(1 << 14)
++#define DE_PIPEB_ODD_FIELD	(1 << 13)
++#define DE_PIPEB_LINE_COMPARE	(1 << 12)
++#define DE_PIPEB_VSYNC		(1 << 11)
++#define DE_PIPEB_FIFO_UNDERRUN	(1 << 8)
++#define DE_PIPEA_VBLANK		(1 << 7)
++#define DE_PIPEA_EVEN_FIELD	(1 << 6)
++#define DE_PIPEA_ODD_FIELD	(1 << 5)
++#define DE_PIPEA_LINE_COMPARE	(1 << 4)
++#define DE_PIPEA_VSYNC		(1 << 3)
++#define DE_PIPEA_FIFO_UNDERRUN	(1 << 0)
++
++#define DEISR	0x44000
++#define DEIMR	0x44004
++#define DEIIR	0x44008
++#define DEIER	0x4400c
++
++/* GT interrupt */
++#define GT_SYNC_STATUS		(1 << 2)
++#define GT_USER_INTERRUPT	(1 << 0)
++
++#define GTISR	0x44010
++#define GTIMR	0x44014
++#define GTIIR	0x44018
++#define GTIER	0x4401c
++
++/* PCH */
++
++/* south display engine interrupt */
++#define SDE_CRT_HOTPLUG		(1 << 11)
++#define SDE_PORTD_HOTPLUG	(1 << 10)
++#define SDE_PORTC_HOTPLUG	(1 << 9)
++#define SDE_PORTB_HOTPLUG	(1 << 8)
++#define SDE_SDVOB_HOTPLUG	(1 << 6)
++
++#define SDEISR	0xc4000
++#define SDEIMR	0xc4004
++#define SDEIIR	0xc4008
++#define SDEIER	0xc400c
++
++/* digital port hotplug */
++#define PCH_PORT_HOTPLUG	0xc4030
++#define PORTD_HOTPLUG_ENABLE		(1 << 20)
++#define PORTD_PULSE_DURATION_2ms	(0)
++#define PORTD_PULSE_DURATION_4_5ms	(1 << 18)
++#define PORTD_PULSE_DURATION_6ms	(2 << 18)
++#define PORTD_PULSE_DURATION_100ms	(3 << 18)
++#define PORTD_HOTPLUG_NO_DETECT		(0)
++#define PORTD_HOTPLUG_SHORT_DETECT	(1 << 16)
++#define PORTD_HOTPLUG_LONG_DETECT	(1 << 17)
++#define PORTC_HOTPLUG_ENABLE		(1 << 12)
++#define PORTC_PULSE_DURATION_2ms	(0)
++#define PORTC_PULSE_DURATION_4_5ms	(1 << 10)
++#define PORTC_PULSE_DURATION_6ms	(2 << 10)
++#define PORTC_PULSE_DURATION_100ms	(3 << 10)
++#define PORTC_HOTPLUG_NO_DETECT		(0)
++#define PORTC_HOTPLUG_SHORT_DETECT	(1 << 8)
++#define PORTC_HOTPLUG_LONG_DETECT	(1 << 9)
++#define PORTB_HOTPLUG_ENABLE		(1 << 4)
++#define PORTB_PULSE_DURATION_2ms	(0)
++#define PORTB_PULSE_DURATION_4_5ms	(1 << 2)
++#define PORTB_PULSE_DURATION_6ms	(2 << 2)
++#define PORTB_PULSE_DURATION_100ms	(3 << 2)
++#define PORTB_HOTPLUG_NO_DETECT		(0)
++#define PORTB_HOTPLUG_SHORT_DETECT	(1 << 0)
++#define PORTB_HOTPLUG_LONG_DETECT	(1 << 1)
++
++#define PCH_GPIOA		0xc5010
++#define PCH_GPIOB		0xc5014
++#define PCH_GPIOC		0xc5018
++#define PCH_GPIOD		0xc501c
++#define PCH_GPIOE		0xc5020
++#define PCH_GPIOF		0xc5024
++#define PCH_GMBUS0		0xc5100
++#define PCH_GMBUS1		0xc5104
++#define PCH_GMBUS2		0xc5108
++#define PCH_GMBUS3		0xc510c
++#define PCH_GMBUS4		0xc5110
++#define PCH_GMBUS5		0xc5120
++
++#define PCH_DPLL_A		0xc6014
++#define PCH_DPLL_B		0xc6018
++
++#define PCH_FPA0		0xc6040
++#define PCH_FPA1		0xc6044
++#define PCH_FPB0		0xc6048
++#define PCH_FPB1		0xc604c
++
++#define PCH_DPLL_TEST		0xc606c
++
++#define PCH_DREF_CONTROL	0xC6200
++#define  DREF_CONTROL_MASK	0x7fc3
++#define  DREF_CPU_SOURCE_OUTPUT_DISABLE		(0<<13)
++#define  DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD	(2<<13)
++#define  DREF_CPU_SOURCE_OUTPUT_NONSPREAD	(3<<13)
++#define  DREF_SSC_SOURCE_DISABLE		(0<<11)
++#define  DREF_SSC_SOURCE_ENABLE			(2<<11)
++#define  DREF_NONSPREAD_SOURCE_DISABLE		(0<<9)
++#define  DREF_NONSPREAD_SOURCE_ENABLE		(2<<9)
++#define  DREF_SUPERSPREAD_SOURCE_DISABLE	(0<<7)
++#define  DREF_SUPERSPREAD_SOURCE_ENABLE		(2<<7)
++#define  DREF_SSC4_DOWNSPREAD			(0<<6)
++#define  DREF_SSC4_CENTERSPREAD			(1<<6)
++#define  DREF_SSC1_DISABLE			(0<<1)
++#define  DREF_SSC1_ENABLE			(1<<1)
++#define  DREF_SSC4_DISABLE			(0)
++#define  DREF_SSC4_ENABLE			(1)
++
++#define PCH_RAWCLK_FREQ		0xc6204
++#define  FDL_TP1_TIMER_SHIFT	12
++#define  FDL_TP1_TIMER_MASK	(3<<12)
++#define  FDL_TP2_TIMER_SHIFT	10
++#define  FDL_TP2_TIMER_MASK	(3<<10)
++#define  RAWCLK_FREQ_MASK	0x3ff
++
++#define PCH_DPLL_TMR_CFG	0xc6208
++
++#define PCH_SSC4_PARMS		0xc6210
++#define PCH_SSC4_AUX_PARMS	0xc6214
++
++/* transcoder */
++
++#define TRANS_HTOTAL_A		0xe0000
++#define  TRANS_HTOTAL_SHIFT	16
++#define  TRANS_HACTIVE_SHIFT	0
++#define TRANS_HBLANK_A		0xe0004
++#define  TRANS_HBLANK_END_SHIFT	16
++#define  TRANS_HBLANK_START_SHIFT 0
++#define TRANS_HSYNC_A		0xe0008
++#define  TRANS_HSYNC_END_SHIFT	16
++#define  TRANS_HSYNC_START_SHIFT 0
++#define TRANS_VTOTAL_A		0xe000c
++#define  TRANS_VTOTAL_SHIFT	16
++#define  TRANS_VACTIVE_SHIFT	0
++#define TRANS_VBLANK_A		0xe0010
++#define  TRANS_VBLANK_END_SHIFT	16
++#define  TRANS_VBLANK_START_SHIFT 0
++#define TRANS_VSYNC_A		0xe0014
++#define  TRANS_VSYNC_END_SHIFT	16
++#define  TRANS_VSYNC_START_SHIFT 0
++
++#define TRANSA_DATA_M1		0xe0030
++#define TRANSA_DATA_N1		0xe0034
++#define TRANSA_DATA_M2		0xe0038
++#define TRANSA_DATA_N2		0xe003c
++#define TRANSA_DP_LINK_M1	0xe0040
++#define TRANSA_DP_LINK_N1	0xe0044
++#define TRANSA_DP_LINK_M2	0xe0048
++#define TRANSA_DP_LINK_N2	0xe004c
++
++#define TRANS_HTOTAL_B		0xe1000
++#define TRANS_HBLANK_B		0xe1004
++#define TRANS_HSYNC_B		0xe1008
++#define TRANS_VTOTAL_B		0xe100c
++#define TRANS_VBLANK_B		0xe1010
++#define TRANS_VSYNC_B		0xe1014
++
++#define TRANSB_DATA_M1		0xe1030
++#define TRANSB_DATA_N1		0xe1034
++#define TRANSB_DATA_M2		0xe1038
++#define TRANSB_DATA_N2		0xe103c
++#define TRANSB_DP_LINK_M1	0xe1040
++#define TRANSB_DP_LINK_N1	0xe1044
++#define TRANSB_DP_LINK_M2	0xe1048
++#define TRANSB_DP_LINK_N2	0xe104c
++
++#define TRANSACONF		0xf0008
++#define TRANSBCONF		0xf1008
++#define  TRANS_DISABLE		(0<<31)
++#define  TRANS_ENABLE		(1<<31)
++#define  TRANS_STATE_MASK	(1<<30)
++#define  TRANS_STATE_DISABLE	(0<<30)
++#define  TRANS_STATE_ENABLE	(1<<30)
++#define  TRANS_FSYNC_DELAY_HB1	(0<<27)
++#define  TRANS_FSYNC_DELAY_HB2	(1<<27)
++#define  TRANS_FSYNC_DELAY_HB3	(2<<27)
++#define  TRANS_FSYNC_DELAY_HB4	(3<<27)
++#define  TRANS_DP_AUDIO_ONLY	(1<<26)
++#define  TRANS_DP_VIDEO_AUDIO	(0<<26)
++#define  TRANS_PROGRESSIVE	(0<<21)
++#define  TRANS_8BPC		(0<<5)
++#define  TRANS_10BPC		(1<<5)
++#define  TRANS_6BPC		(2<<5)
++#define  TRANS_12BPC		(3<<5)
++
++#define FDI_RXA_CHICKEN		0xc200c
++#define FDI_RXB_CHICKEN		0xc2010
++#define  FDI_RX_PHASE_SYNC_POINTER_ENABLE	(1)
++
++/* CPU: FDI_TX */
++#define FDI_TXA_CTL		0x60100
++#define FDI_TXB_CTL		0x61100
++#define  FDI_TX_DISABLE		(0<<31)
++#define  FDI_TX_ENABLE		(1<<31)
++#define  FDI_LINK_TRAIN_PATTERN_1	(0<<28)
++#define  FDI_LINK_TRAIN_PATTERN_2	(1<<28)
++#define  FDI_LINK_TRAIN_PATTERN_IDLE	(2<<28)
++#define  FDI_LINK_TRAIN_NONE		(3<<28)
++#define  FDI_LINK_TRAIN_VOLTAGE_0_4V	(0<<25)
++#define  FDI_LINK_TRAIN_VOLTAGE_0_6V	(1<<25)
++#define  FDI_LINK_TRAIN_VOLTAGE_0_8V	(2<<25)
++#define  FDI_LINK_TRAIN_VOLTAGE_1_2V	(3<<25)
++#define  FDI_LINK_TRAIN_PRE_EMPHASIS_NONE (0<<22)
++#define  FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X (1<<22)
++#define  FDI_LINK_TRAIN_PRE_EMPHASIS_2X	  (2<<22)
++#define  FDI_LINK_TRAIN_PRE_EMPHASIS_3X	  (3<<22)
++#define  FDI_DP_PORT_WIDTH_X1		(0<<19)
++#define  FDI_DP_PORT_WIDTH_X2		(1<<19)
++#define  FDI_DP_PORT_WIDTH_X3		(2<<19)
++#define  FDI_DP_PORT_WIDTH_X4		(3<<19)
++#define  FDI_TX_ENHANCE_FRAME_ENABLE	(1<<18)
++/* IGDNG: hardwired to 1 */
++#define  FDI_TX_PLL_ENABLE		(1<<14)
++/* both Tx and Rx */
++#define  FDI_SCRAMBLING_ENABLE		(0<<7)
++#define  FDI_SCRAMBLING_DISABLE		(1<<7)
++
++/* FDI_RX, FDI_X is hard-wired to Transcoder_X */
++#define FDI_RXA_CTL		0xf000c
++#define FDI_RXB_CTL		0xf100c
++#define  FDI_RX_ENABLE		(1<<31)
++#define  FDI_RX_DISABLE		(0<<31)
++/* train, dp width same as FDI_TX */
++#define  FDI_DP_PORT_WIDTH_X8		(7<<19)
++#define  FDI_8BPC			(0<<16)
++#define  FDI_10BPC			(1<<16)
++#define  FDI_6BPC			(2<<16)
++#define  FDI_12BPC			(3<<16)
++#define  FDI_LINK_REVERSE_OVERWRITE	(1<<15)
++#define  FDI_DMI_LINK_REVERSE_MASK	(1<<14)
++#define  FDI_RX_PLL_ENABLE		(1<<13)
++#define  FDI_FS_ERR_CORRECT_ENABLE	(1<<11)
++#define  FDI_FE_ERR_CORRECT_ENABLE	(1<<10)
++#define  FDI_FS_ERR_REPORT_ENABLE	(1<<9)
++#define  FDI_FE_ERR_REPORT_ENABLE	(1<<8)
++#define  FDI_RX_ENHANCE_FRAME_ENABLE	(1<<6)
++#define  FDI_SEL_RAWCLK			(0<<4)
++#define  FDI_SEL_PCDCLK			(1<<4)
++
++#define FDI_RXA_MISC		0xf0010
++#define FDI_RXB_MISC		0xf1010
++#define FDI_RXA_TUSIZE1		0xf0030
++#define FDI_RXA_TUSIZE2		0xf0038
++#define FDI_RXB_TUSIZE1		0xf1030
++#define FDI_RXB_TUSIZE2		0xf1038
++
++/* FDI_RX interrupt register format */
++#define FDI_RX_INTER_LANE_ALIGN		(1<<10)
++#define FDI_RX_SYMBOL_LOCK		(1<<9) /* train 2 */
++#define FDI_RX_BIT_LOCK			(1<<8) /* train 1 */
++#define FDI_RX_TRAIN_PATTERN_2_FAIL	(1<<7)
++#define FDI_RX_FS_CODE_ERR		(1<<6)
++#define FDI_RX_FE_CODE_ERR		(1<<5)
++#define FDI_RX_SYMBOL_ERR_RATE_ABOVE	(1<<4)
++#define FDI_RX_HDCP_LINK_FAIL		(1<<3)
++#define FDI_RX_PIXEL_FIFO_OVERFLOW	(1<<2)
++#define FDI_RX_CROSS_CLOCK_OVERFLOW	(1<<1)
++#define FDI_RX_SYMBOL_QUEUE_OVERFLOW	(1<<0)
++
++#define FDI_RXA_IIR		0xf0014
++#define FDI_RXA_IMR		0xf0018
++#define FDI_RXB_IIR		0xf1014
++#define FDI_RXB_IMR		0xf1018
++
++#define FDI_PLL_CTL_1		0xfe000
++#define FDI_PLL_CTL_2		0xfe004
++
++/* CRT */
++#define PCH_ADPA		0xe1100
++#define  ADPA_TRANS_SELECT_MASK	(1<<30)
++#define  ADPA_TRANS_A_SELECT	0
++#define  ADPA_TRANS_B_SELECT	(1<<30)
++/* HPD is here */
++#define  ADPA_CRT_HOTPLUG_MASK	0x03ff0000 /* bit 25-16 */
++#define	 ADPA_CRT_HOTPLUG_MONITOR_NONE	(0<<24)
++#define  ADPA_CRT_HOTPLUG_MONITOR_MASK	(3<<24)
++#define  ADPA_CRT_HOTPLUG_MONITOR_COLOR	(3<<24)
++#define  ADPA_CRT_HOTPLUG_MONITOR_MONO	(2<<24)
++#define  ADPA_CRT_HOTPLUG_ENABLE	(1<<23)
++#define  ADPA_CRT_HOTPLUG_PERIOD_64	(0<<22)
++#define  ADPA_CRT_HOTPLUG_PERIOD_128	(1<<22)
++#define  ADPA_CRT_HOTPLUG_WARMUP_5MS	(0<<21)
++#define  ADPA_CRT_HOTPLUG_WARMUP_10MS	(1<<21)
++#define  ADPA_CRT_HOTPLUG_SAMPLE_2S	(0<<20)
++#define  ADPA_CRT_HOTPLUG_SAMPLE_4S	(1<<20)
++#define  ADPA_CRT_HOTPLUG_VOLTAGE_40	(0<<18)
++#define  ADPA_CRT_HOTPLUG_VOLTAGE_50	(1<<18)
++#define  ADPA_CRT_HOTPLUG_VOLTAGE_60	(2<<18)
++#define  ADPA_CRT_HOTPLUG_VOLTAGE_70	(3<<18)
++#define  ADPA_CRT_HOTPLUG_VOLREF_325MV	(0<<17)
++#define  ADPA_CRT_HOTPLUG_VOLREF_475MV	(1<<17)
++#define  ADPA_CRT_HOTPLUG_FORCE_TRIGGER	(1<<16)
++/* polarity control not changed */
++
++/* or SDVOB */
++#define HDMIB	0xe1140
++#define  PORT_ENABLE	(1 << 31)
++#define  TRANSCODER_A	(0)
++#define  TRANSCODER_B	(1 << 30)
++#define  COLOR_FORMAT_8bpc	(0)
++#define  COLOR_FORMAT_12bpc	(3 << 26)
++#define  SDVOB_HOTPLUG_ENABLE	(1 << 23)
++#define  SDVO_ENCODING		(0)
++#define  TMDS_ENCODING		(2 << 10)
++#define  NULL_PACKET_VSYNC_ENABLE	(1 << 9)
++#define  SDVOB_BORDER_ENABLE	(1 << 7)
++#define  AUDIO_ENABLE		(1 << 6)
++#define  VSYNC_ACTIVE_HIGH	(1 << 4)
++#define  HSYNC_ACTIVE_HIGH	(1 << 3)
++#define  PORT_DETECTED		(1 << 2)
++
++#define HDMIC	0xe1150
++#define HDMID	0xe1160
++
+ #endif /* _I810_REG_H */
+
+--- src/Makefile.am	2009-08-27 16:05:51.348546796 +0800
++++ src/Makefile.am	2009-08-27 16:31:50.232148216 +0800
+@@ -138,7 +138,9 @@ intel_drv_la_SOURCES = \
+ 	 i830_render.c \
+ 	 i915_render.c \
+ 	 i965_render.c \
+-	 drmmode_display.c
++	 drmmode_display.c \
++         cpu_display.c \
++         pch_crt.c
+ 
+ INTEL_G4A =				\
+ 	packed_yuv_sf.g4a		\
+--- src/common.h	2009-08-18 11:35:53.921343728 +0800
++++ src/common.h	2009-08-28 10:13:38.356977179 +0800
+@@ -241,6 +241,13 @@ extern int I810_DEBUG;
+ #define PCI_CHIP_I945_GME_BRIDGE 0x27AC
+ #endif
+ 
++#ifndef PCI_CHIP_IGD_GM
++#define PCI_CHIP_IGD_GM		0xA011
++#define PCI_CHIP_IGD_GM_BRIDGE	0xA010
++#define PCI_CHIP_IGD_G		0xA001
++#define PCI_CHIP_IGD_G_BRIDGE	0xA000
++#endif
++
+ #ifndef PCI_CHIP_G35_G
+ #define PCI_CHIP_G35_G		0x2982
+ #define PCI_CHIP_G35_G_BRIDGE 	0x2980
+@@ -352,6 +359,9 @@ extern int I810_DEBUG;
+ #define IS_I915GM(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I915_GM)
+ #define IS_I945G(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I945_G)
+ #define IS_I945GM(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I945_GM || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I945_GME)
++#define IS_IGDGM(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_IGD_GM)
++#define IS_IGDG(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_IGD_G)
++#define IS_IGD(pI810) (IS_IGDG(pI810) || IS_IGDGM(pI810))
+ #define IS_GM45(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_GM45_GM)
+ #define IS_G4X(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_IGD_E_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_G45_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_Q45_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_G41_G || IS_GM45(pI810))
+ #define IS_I965GM(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GM || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GME)
+--- src/cpu_display.c	1970-01-01 08:00:00.000000000 +0800
++++ src/cpu_display.c	2009-08-28 09:53:52.423964098 +0800
+@@ -0,0 +1,1462 @@
++/* -*- c-basic-offset: 4 -*- */
++/*
++ * Copyright ? 2009 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ * Authors:
++ *	Zhenyu Wang <[email protected]>
++ *
++ */
++
++/* This file is for CPU Display engine and PCH display engine, which
++   is connected through FDI, and has different PLLs.
++
++   So the aim of this is to get video data passing from CPU to PCH for
++   specific modes. Other PCH output driver will drive specific outputs */
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include <unistd.h>
++#include <string.h>
++#include <assert.h>
++#include <stdlib.h>
++#include <math.h>
++#include <sys/ioctl.h>
++
++#include "xf86.h"
++#include "i830.h"
++#include "i830_bios.h"
++#include "i830_display.h"
++#include "i830_debug.h"
++#include "xf86Modes.h"
++
++typedef struct {
++    /* given values */
++    int n;
++    int m1, m2;
++    int p1, p2;
++    /* derived values */
++    int	dot;
++    int	vco;
++    int	m;
++    int	p;
++} intel_clock_t;
++
++typedef struct {
++    int	min, max;
++} intel_range_t;
++
++typedef struct {
++    int	dot_limit;
++    int	p2_slow, p2_fast;
++} intel_p2_t;
++
++#define INTEL_P2_NUM		      2
++
++typedef struct intel_limit intel_limit_t;
++struct intel_limit {
++    intel_range_t   dot, vco, n, m, m1, m2, p, p1;
++    intel_p2_t	    p2;
++    Bool (* find_pll)(const intel_limit_t *, xf86CrtcPtr,
++                      int, int, intel_clock_t *);
++};
++
++#define DOT_MIN		25000
++#define DOT_MAX		350000
++#define VCO_MIN		1760000
++#define VCO_MAX		3510000
++#define N_MIN		3
++#define N_MAX		8
++#define M_MIN		79
++#define M_MAX		127
++#define M1_MIN		12
++#define M1_MAX		22
++#define M2_MIN		5
++#define M2_MAX		9
++#define P_SDVO_DAC_MIN	5
++#define P_SDVO_DAC_MAX	80
++#define P_LVDS_MIN	28
++#define P_LVDS_MAX	112
++#define P1_MIN		1
++#define P1_MAX		8
++#define P2_SDVO_DAC_SLOW 10
++#define P2_SDVO_DAC_FAST 5
++#define P2_LVDS_SLOW	14
++#define P2_LVDS_FAST	7
++#define P2_DOT_LIMIT	225000 /* 225Mhz */
++
++#define INTEL_LIMIT_SDVO_DAC    0
++#define INTEL_LIMIT_LVDS	1
++
++static Bool
++intel_find_pll_ilk(const intel_limit_t *, xf86CrtcPtr,
++                             int, int, intel_clock_t *);
++
++static const intel_limit_t intel_limits[] = {
++    { /* INTEL_LIMIT_SDVO_DAC */
++        .dot = { .min = DOT_MIN,		.max = DOT_MAX },
++        .vco = { .min = VCO_MIN,		.max = VCO_MAX },
++        .n   = { .min = N_MIN,			.max = N_MAX },
++        .m   = { .min = M_MIN,			.max = M_MAX },
++        .m1  = { .min = M1_MIN,			.max = M1_MAX },
++        .m2  = { .min = M2_MIN,			.max = M2_MAX },
++        .p   = { .min = P_SDVO_DAC_MIN,		.max = P_SDVO_DAC_MAX },
++        .p1  = { .min = P1_MIN,			.max = P1_MAX },
++	.p2  = { .dot_limit = P2_DOT_LIMIT, .p2_slow = P2_SDVO_DAC_SLOW,
++			.p2_fast = P2_SDVO_DAC_FAST },
++        .find_pll = intel_find_pll_ilk,
++    },
++    { /* INTEL_LIMIT_LVDS */
++        .dot = { .min = DOT_MIN,		.max = DOT_MAX },
++        .vco = { .min = VCO_MIN,		.max = VCO_MAX },
++        .n   = { .min = N_MIN,			.max = N_MAX },
++        .m   = { .min = M_MIN,			.max = M_MAX },
++        .m1  = { .min = M1_MIN,			.max = M1_MAX },
++        .m2  = { .min = M2_MIN,			.max = M2_MAX },
++        .p   = { .min = P_LVDS_MIN,		.max = P_LVDS_MAX },
++        .p1  = { .min = P1_MIN,			.max = P1_MAX },
++	.p2  = { .dot_limit = P2_DOT_LIMIT, .p2_slow = P2_LVDS_SLOW,
++			.p2_fast = P2_LVDS_FAST },
++        .find_pll = intel_find_pll_ilk,
++    }
++};
++
++static const intel_limit_t *intel_limit_ilk (xf86CrtcPtr crtc)
++{
++    const intel_limit_t *limit;
++
++    if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
++	limit = &intel_limits[INTEL_LIMIT_LVDS];
++    else
++        limit = &intel_limits[INTEL_LIMIT_SDVO_DAC];
++
++    return limit;
++}
++
++/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */
++
++static void i9xx_clock(int refclk, intel_clock_t *clock)
++{
++    clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
++    clock->p = clock->p1 * clock->p2;
++    clock->vco = refclk * clock->m / (clock->n + 2);
++    clock->dot = clock->vco / clock->p;
++}
++
++static void intel_clock(I830Ptr pI830, int refclk, intel_clock_t *clock)
++{
++    i9xx_clock (refclk, clock);
++}
++
++static void
++i830PrintPll(ScrnInfoPtr pScrn, char *prefix, intel_clock_t *clock)
++{
++    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
++	       "%s: dotclock %d vco %d ((m %d, m1 %d, m2 %d), n %d, "
++	       "(p %d, p1 %d, p2 %d))\n",
++	       prefix, clock->dot, clock->vco,
++	       clock->m, clock->m1, clock->m2,
++	       clock->n,
++	       clock->p, clock->p1, clock->p2);
++}
++
++#define i830PllInvalid(s)   { /* ErrorF (s) */; return FALSE; }
++/**
++ * Returns whether the given set of divisors are valid for a given refclk with
++ * the given outputs.
++ */
++
++static Bool
++i830PllIsValid(xf86CrtcPtr crtc, intel_clock_t *clock)
++{
++    const intel_limit_t *limit = intel_limit_ilk (crtc);
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830Ptr pI830 = I830PTR(pScrn);
++
++    if (clock->p1  < limit->p1.min  || limit->p1.max  < clock->p1)
++	i830PllInvalid ("p1 out of range\n");
++    if (clock->p   < limit->p.min   || limit->p.max   < clock->p)
++	i830PllInvalid ("p out of range\n");
++    if (clock->m2  < limit->m2.min  || limit->m2.max  < clock->m2)
++	i830PllInvalid ("m2 out of range\n");
++    if (clock->m1  < limit->m1.min  || limit->m1.max  < clock->m1)
++	i830PllInvalid ("m1 out of range\n");
++    if (clock->m1 <= clock->m2 && !IS_IGD(pI830))
++	i830PllInvalid ("m1 <= m2\n");
++    if (clock->m   < limit->m.min   || limit->m.max   < clock->m)
++	i830PllInvalid ("m out of range\n");
++    if (clock->n   < limit->n.min   || limit->n.max   < clock->n)
++	i830PllInvalid ("n out of range\n");
++    if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
++	i830PllInvalid ("vco out of range\n");
++    /* XXX: We may need to be checking "Dot clock" depending on the multiplier,
++     * output, etc., rather than just a single range.
++     */
++    if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
++	i830PllInvalid ("dot out of range\n");
++
++    return TRUE;
++}
++
++static Bool
++intel_find_pll_ilk(const intel_limit_t * limit, xf86CrtcPtr crtc,
++                   int target, int refclk, intel_clock_t *best_clock)
++{
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830Ptr pI830 = I830PTR(pScrn);
++    intel_clock_t clock;
++    int  max_n;
++    Bool found = FALSE;
++    int err_most = target * 0.0048;
++
++    if (target < limit->p2.dot_limit)
++	clock.p2 = limit->p2.p2_slow;
++    else
++	clock.p2 = limit->p2.p2_fast;
++
++    max_n = limit->n.max;
++    /* based on hardware requirement prefer smaller n to precision */
++    for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
++        /* based on hardware requirement prefere larger m1,m2, p1*/
++        for (clock.m1 = limit->m1.max;
++            clock.m1 >= limit->m1.min; clock.m1--) {
++            for (clock.m2 = limit->m2.max;
++                clock.m2 >= limit->m2.min; clock.m2--) {
++                for (clock.p1 = limit->p1.max;
++                    clock.p1 >= limit->p1.min; clock.p1--) {
++                    int this_err;
++
++                    intel_clock (pI830, refclk, &clock);
++                    if (!i830PllIsValid(crtc, &clock))
++                        continue;
++                    this_err = abs(clock.dot - target) ;
++                    if (this_err < err_most) {
++                        memcpy(best_clock, &clock, sizeof(intel_clock_t));
++                        err_most = this_err;
++                        /* prefer smaller n to precision */
++                        max_n = clock.n; /* just may outside cycle return,
++					    true return clock is in 'best_clock' already,
++					    so clock.n++ no problem */
++                        found = TRUE;
++			goto out; /* IGDNG: jump out in first match like vbios does */
++                    }
++                }
++            }
++        }
++    }
++out:
++    return found;
++}
++
++/**
++ * Fine with IGDNG, no change
++ */
++static void
++IlkPipeSetBase(xf86CrtcPtr crtc, int x, int y)
++{
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830Ptr pI830 = I830PTR(pScrn);
++    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
++    int pipe = intel_crtc->pipe;
++    int plane = intel_crtc->plane;
++    unsigned long Start, Offset, Stride;
++    int dsplinoff = (plane == 0 ? DSPALINOFF : DSPBLINOFF);
++    int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF);
++    int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF);
++    int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE;
++
++    Offset = ((y * pScrn->displayWidth + x) * pI830->cpp);
++    Stride = pScrn->displayWidth * pI830->cpp;
++    if (pI830->front_buffer == NULL) {
++	/* During startup we may be called as part of monitor detection while
++	 * there is no memory allocation done, so just supply a dummy base
++	 * address.
++	 */
++	Start = 0;
++    } else if (crtc->rotatedData != NULL) {
++	/* offset is done by shadow painting code, not here */
++	Start = (char *)crtc->rotatedData - (char *)pI830->FbBase;
++	Offset = 0;
++	Stride = intel_crtc->rotate_mem->pitch;
++    } else {
++	Start = pI830->front_buffer->offset;
++    }
++
++    crtc->x = x;
++    crtc->y = y;
++
++    OUTREG(dspstride, Stride);
++    OUTREG(dsplinoff, Offset);
++    POSTING_READ(dsplinoff);
++    OUTREG(dspsurf, Start);
++    POSTING_READ(dspsurf);
++    OUTREG(dsptileoff, (y << 16) | x);
++
++#ifdef XF86DRI
++    if (pI830->directRenderingType == DRI_XF86DRI) {
++	drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
++
++	if (!sPriv)
++	    return;
++
++	switch (pipe) {
++	case 0:
++	    sPriv->pipeA_x = x;
++	    sPriv->pipeA_y = y;
++	    break;
++	case 1:
++	    sPriv->pipeB_x = x;
++	    sPriv->pipeB_y = y;
++	    break;
++	default:
++	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
++		       "Can't update pipe %d in SAREA\n", pipe);
++	    break;
++	}
++    }
++#endif
++}
++
++/* FIXME: use pixmap private instead if possible */
++static Bool
++ilk_display_tiled(xf86CrtcPtr crtc)
++{
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830Ptr pI830 = I830PTR(pScrn);
++
++    /* Rotated data is currently linear, allocated either via XAA or EXA */
++    if (crtc->rotatedData)
++	return FALSE;
++
++    if (pI830->front_buffer && pI830->front_buffer->tiling != TILE_NONE)
++	return TRUE;
++
++    return FALSE;
++}
++
++void
++ilk_disable_vga_plane (xf86CrtcPtr crtc)
++{
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830Ptr pI830 = I830PTR(pScrn);
++    uint32_t vgacntrl = INREG(CPU_VGACNTRL);
++    uint8_t sr01;
++
++    if (vgacntrl & VGA_DISP_DISABLE)
++	return;
++
++    _debug("ilk disable vga plane");
++
++    /*
++       Set bit 5 of SR01;
++       Wait 30us;
++       */
++    OUTREG8(SRX, 1);
++    sr01 = INREG8(SRX + 1);
++    OUTREG8(SRX + 1, sr01 | (1 << 5));
++    usleep(30);
++    /* disable center mode on 965GM and G4X platform */
++    if (IS_I965GM(pI830) || IS_G4X(pI830)
++	    || IS_IGDNG(pI830))
++        vgacntrl &= ~(3 << 24);
++
++    vgacntrl |= VGA_DISP_DISABLE;
++
++    OUTREG(CPU_VGACNTRL, vgacntrl);
++    i830WaitForVblank(pScrn);
++}
++
++static void
++intel_wait_warmup(int w)
++{
++    usleep(w);
++}
++
++void
++cpu_crtc_enable(xf86CrtcPtr crtc)
++{
++    /* enable sequence, link train */
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830Ptr pI830 = I830PTR(pScrn);
++    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
++    int pipe = intel_crtc->pipe;
++    int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
++    int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
++    int fdi_rx_chicken_reg = (pipe == 0) ? FDI_RXA_CHICKEN : FDI_RXB_CHICKEN;
++    int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR;
++    int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
++    int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1;
++    uint32_t temp;
++    int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
++    int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
++    int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
++    int cpu_vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
++    int cpu_vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
++    int cpu_vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
++    int trans_htot_reg = (pipe == 0) ? TRANS_HTOTAL_A : TRANS_HTOTAL_B;
++    int trans_hblank_reg = (pipe == 0) ? TRANS_HBLANK_A : TRANS_HBLANK_B;
++    int trans_hsync_reg = (pipe == 0) ? TRANS_HSYNC_A : TRANS_HSYNC_B;
++    int trans_vtot_reg = (pipe == 0) ? TRANS_VTOTAL_A : TRANS_VTOTAL_B;
++    int trans_vblank_reg = (pipe == 0) ? TRANS_VBLANK_A : TRANS_VBLANK_B;
++    int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B;
++
++    _debug("cpu crtc %d enable", pipe);
++
++    /* enable PCH SSC modulator, looks not needed for CRT */
++
++    /* ignore eDP now */
++
++    /* configure CPU pipe timing, M/N/TU, etc. XXX ->mode_set*/
++
++    /* enable CPU FDI TX and PCH FDI RX */
++
++    temp = INREG(fdi_tx_reg);
++    temp |= FDI_TX_ENABLE;
++    OUTREG(fdi_tx_reg, temp);
++    POSTING_READ(fdi_tx_reg);
++
++    temp = INREG(fdi_rx_reg);
++    OUTREG(fdi_rx_reg, temp | FDI_RX_ENABLE);
++    POSTING_READ(fdi_rx_reg);
++
++    if (ilk_a_stepping()) {
++	temp = INREG(fdi_rx_chicken_reg);
++	OUTREG(fdi_rx_chicken_reg, temp | FDI_RX_PHASE_SYNC_POINTER_ENABLE);
++    }
++
++    intel_wait_warmup(FDI_TRAIN_PATTERN_1_TIME);
++    usleep(150);
++    /* Train FDI ... */
++
++    _debug("train start");
++
++    temp = INREG(fdi_rx_iir_reg);
++    _debug("FDI_RX_IIR 0x%x", temp);
++
++    if ((temp & FDI_RX_BIT_LOCK) == 0) {
++	/* try more times for luck */
++	int tries = 20, j;
++	for (j = 0; j < tries; j++) {
++	    temp = INREG(fdi_rx_iir_reg);
++	    _debug("FDI_RX_IIR 0x%x", temp);
++	    if (temp & FDI_RX_BIT_LOCK)
++		break;
++	    usleep(200);
++	}
++	if (j != tries) {
++	    _debug("train 1 ok 1!");
++	    /* XXX clear it */
++	    /* OUTREG(fdi_rx_iir_reg, temp | FDI_RX_BIT_LOCK); */
++	} else
++	    _debug("train 1 fail");
++    } else {
++	/* XXX clear it */
++	/* OUTREG(fdi_rx_iir_reg, temp | FDI_RX_BIT_LOCK); */
++	_debug("train 1 ok 2!");
++    }
++
++    temp = INREG(fdi_tx_reg);
++    temp &= ~FDI_LINK_TRAIN_NONE;
++    temp |= FDI_LINK_TRAIN_PATTERN_2;
++    OUTREG(fdi_tx_reg, temp);
++
++    temp = INREG(fdi_rx_reg);
++    temp &= ~FDI_LINK_TRAIN_NONE;
++    temp |= FDI_LINK_TRAIN_PATTERN_2;
++    OUTREG(fdi_rx_reg, temp);
++
++    intel_wait_warmup(FDI_TRAIN_PATTERN_2_TIME);
++    usleep(150);
++
++    _debug("train 2 start");
++
++    temp = INREG(fdi_rx_iir_reg);
++    _debug("FDI_RX_IIR 0x%x", temp);
++
++    if ((temp & FDI_RX_SYMBOL_LOCK) == 0) {
++	/* try more times for luck */
++	int tries = 20, j;
++	for (j = 0; j < tries; j++) {
++	    temp = INREG(fdi_rx_iir_reg);
++	    _debug("FDI_RX_IIR 0x%x", temp);
++	    if (temp & FDI_RX_SYMBOL_LOCK)
++		break;
++	    usleep(200);
++	}
++	if (j != tries) {
++	    /* XXX clear it */
++	    /* OUTREG(fdi_rx_iir_reg, temp | FDI_RX_SYMBOL_LOCK); */
++	    _debug("train 2 ok 1!");
++	} else
++	    _debug("train 2 fail");
++    } else {
++	/* XXX clear it */
++	/* OUTREG(fdi_rx_iir_reg, temp | FDI_RX_SYMBOL_LOCK); */
++	_debug("train 2 ok 2!");
++    }
++    _debug("train done");
++
++    /* set transcoder timing */
++    OUTREG(trans_htot_reg, INREG(cpu_htot_reg));
++    OUTREG(trans_hblank_reg, INREG(cpu_hblank_reg));
++    OUTREG(trans_hsync_reg, INREG(cpu_hsync_reg));
++
++    OUTREG(trans_vtot_reg, INREG(cpu_vtot_reg));
++    OUTREG(trans_vblank_reg, INREG(cpu_vblank_reg));
++    OUTREG(trans_vsync_reg, INREG(cpu_vsync_reg));
++
++    /* enable PCH transcoder */
++    temp = INREG(transconf_reg);
++    OUTREG(transconf_reg, temp | TRANS_ENABLE);
++    POSTING_READ(transconf_reg);
++
++    while ((INREG(transconf_reg) & TRANS_STATE_ENABLE) == 0) ;
++
++    /* enable normal */
++
++    temp = INREG(fdi_tx_reg);
++    temp &= ~FDI_LINK_TRAIN_NONE;
++    OUTREG(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE);
++    POSTING_READ(fdi_tx_reg);
++
++    temp = INREG(fdi_rx_reg);
++    temp &= ~FDI_LINK_TRAIN_NONE;
++    OUTREG(fdi_rx_reg, temp | FDI_LINK_TRAIN_NONE | FDI_RX_ENHANCE_FRAME_ENABLE);
++    POSTING_READ(fdi_rx_reg);
++
++    /* wait one idle pattern time */
++    intel_wait_warmup(FDI_ONE_IDLE_PATTERN_TIME);
++
++    /* configure PCH transcoder timing, M/N/TU, etc. XXX->mode_set */
++
++    /* enable CPU panel fitter XXX */
++    temp = INREG(pf_ctl_reg);
++    if ((temp & PF_ENABLE) == 0) {
++	OUTREG(pf_ctl_reg, temp | PF_ENABLE);
++	POSTING_READ(pf_ctl_reg);
++    }
++
++    i830WaitForVblank(pScrn);
++
++    _debug("crtc enable done.");
++}
++
++void
++cpu_crtc_disable(xf86CrtcPtr crtc, Bool disable_pipe)
++{
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830Ptr pI830 = I830PTR(pScrn);
++    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
++    int pipe = intel_crtc->pipe;
++    int plane = intel_crtc->plane;
++    int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
++    int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
++    int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
++    int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
++    int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
++    int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
++    int fdi_rx_chicken_reg = (pipe == 0) ? FDI_RXA_CHICKEN : FDI_RXB_CHICKEN;
++    int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
++    int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1;
++    uint32_t temp;
++
++    _debug("cpu crtc %d disable", pipe);
++
++    /** disable sequence **/
++
++    /* disable cpu pipe, disable after all planes disabled */
++    temp = INREG(pipeconf_reg);
++    if ((temp & PIPEACONF_ENABLE) != 0) {
++	OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
++	POSTING_READ(pipeconf_reg);
++    } else {
++	_debug("pipe %d already disabled", pipe);
++	return;
++    }
++
++    /* disable panel power -> output power down */
++
++    /* disable cpu planes */
++    temp = INREG(dspcntr_reg);
++    if ((temp & DISPLAY_PLANE_ENABLE) != 0)
++    {
++	OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
++	/* Flush the plane changes */
++	OUTREG(dspbase_reg, INREG(dspbase_reg));
++	POSTING_READ(dspbase_reg);
++    }
++
++    ilk_disable_vga_plane (crtc);
++
++    /* wait for cpu pipe off, pipe state */
++    while ((INREG(pipeconf_reg) & I965_PIPECONF_ACTIVE) != 0)
++	;
++
++    /* IGDNG-A : disable cpu panel fitter ? */
++    temp = INREG(pf_ctl_reg);
++    if ((temp & PF_ENABLE) != 0) {
++	OUTREG(pf_ctl_reg, temp & ~PF_ENABLE);
++	POSTING_READ(pf_ctl_reg);
++    }
++
++    /* ignore eDP now */
++
++    /* disable CPU FDI tx and PCH FDI rx */
++    temp = INREG(fdi_tx_reg);
++    OUTREG(fdi_tx_reg, temp & ~FDI_TX_ENABLE);
++    POSTING_READ(fdi_tx_reg);
++
++    temp = INREG(fdi_rx_reg);
++    OUTREG(fdi_rx_reg, temp & ~FDI_RX_ENABLE);
++    POSTING_READ(fdi_rx_reg);
++
++    if (ilk_a_stepping()) {
++	temp = INREG(fdi_rx_chicken_reg);
++	OUTREG(fdi_rx_chicken_reg, temp & ~FDI_RX_PHASE_SYNC_POINTER_ENABLE);
++    }
++
++    /* still set train pattern 1 */
++    temp = INREG(fdi_tx_reg);
++    temp &= ~FDI_LINK_TRAIN_NONE;
++    temp |= FDI_LINK_TRAIN_PATTERN_1;
++    OUTREG(fdi_tx_reg, temp);
++
++    temp = INREG(fdi_rx_reg);
++    temp &= ~FDI_LINK_TRAIN_NONE;
++    temp |= FDI_LINK_TRAIN_PATTERN_1;
++    OUTREG(fdi_rx_reg, temp);
++    /* XXX disable SDVO */
++
++    /* disable PCH transcoder */
++    temp = INREG(transconf_reg);
++    OUTREG(transconf_reg, temp & ~TRANS_ENABLE);
++    POSTING_READ(transconf_reg);
++
++    temp = INREG(fdi_rx_reg);
++    OUTREG(fdi_rx_reg, temp & ~FDI_SEL_PCDCLK);
++    POSTING_READ(fdi_rx_reg);
++
++    /* disable PCH DPLL */
++    temp = INREG(pch_dpll_reg);
++    if ((temp & DPLL_VCO_ENABLE) != 0) {
++	OUTREG(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE);
++	POSTING_READ(pch_dpll_reg);
++    }
++
++    temp = INREG(fdi_rx_reg);
++    if ((temp & FDI_RX_PLL_ENABLE) != 0) {
++	OUTREG(fdi_rx_reg, temp & ~FDI_RX_PLL_ENABLE);
++	POSTING_READ(fdi_rx_reg);
++    }
++
++    /* if SSC no need, disable PCH SSC modulator ??? */
++
++    i830WaitForVblank(pScrn);
++}
++
++/**
++ * Sets the power management mode of the pipe and plane.
++ *
++ * This code should probably grow support for turning the cursor off and back
++ * on appropriately at the same time as we're turning the pipe off/on.
++ */
++static void
++cpu_crtc_dpms(xf86CrtcPtr crtc, int mode)
++{
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830Ptr pI830 = I830PTR(pScrn);
++    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
++    int pipe = intel_crtc->pipe;
++
++    /* XXX: When our outputs are all unaware of DPMS modes other than off and
++     * on, we should map those modes to DPMSModeOff in the CRTC.
++     */
++
++    /* IGDNG: dpms function should do whole enable/disable sequence for
++       cpu pipe/fdi, pch fdi/transcoder, enable with link train, etc.
++       XXX
++       - dpms_off should do whole disable sequence
++       - mode_set will do timing calculate and set CPU/PCH timing
++         (spec says it can be set anytime before enable CPU pipe or PCH transcoder)
++       - dpms_on will do enable sequence, and CPU/PCH timing should have been setup.
++     */
++    if (!pI830->starting && mode == intel_crtc->dpms_mode)
++	return;
++
++    switch (mode) {
++    case DPMSModeOn:
++    case DPMSModeStandby:
++    case DPMSModeSuspend:
++	cpu_crtc_enable(crtc);
++	break;
++    case DPMSModeOff:
++	cpu_crtc_disable(crtc, TRUE);
++	break;
++    }
++
++    intel_crtc->dpms_mode = mode;
++
++#ifdef XF86DRI
++    if (pI830->directRenderingType == DRI_XF86DRI) {
++	drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
++	Bool enabled = crtc->enabled && mode != DPMSModeOff;
++
++	I830DRISetVBlankInterrupt (pScrn, TRUE);
++
++	if (!sPriv)
++	    return;
++
++	switch (pipe) {
++	case 0:
++	    sPriv->pipeA_w = enabled ? crtc->mode.HDisplay : 0;
++	    sPriv->pipeA_h = enabled ? crtc->mode.VDisplay : 0;
++	    break;
++	case 1:
++	    sPriv->pipeB_w = enabled ? crtc->mode.HDisplay : 0;
++	    sPriv->pipeB_h = enabled ? crtc->mode.VDisplay : 0;
++	    break;
++	default:
++	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
++		       "Can't update pipe %d in SAREA\n", pipe);
++	    break;
++	}
++    }
++#endif
++}
++
++static Bool
++ilk_crtc_lock (xf86CrtcPtr crtc)
++{
++   /* Sync the engine before mode switch */
++   i830WaitSync(crtc->scrn);
++
++#ifdef XF86DRI
++    return I830DRILock(crtc->scrn);
++#else
++    return FALSE;
++#endif
++}
++
++static void
++ilk_crtc_unlock (xf86CrtcPtr crtc)
++{
++#ifdef XF86DRI
++    I830DRIUnlock (crtc->scrn);
++#endif
++}
++
++static void
++ilk_crtc_prepare (xf86CrtcPtr crtc)
++{
++    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
++
++    if (intel_crtc->enabled)
++	crtc->funcs->hide_cursor (crtc);
++    crtc->funcs->dpms (crtc, DPMSModeOff);
++}
++
++static void
++ilk_crtc_commit (xf86CrtcPtr crtc)
++{
++    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
++
++    intel_crtc->enabled = TRUE;
++
++    crtc->funcs->dpms (crtc, DPMSModeOn);
++    if (crtc->scrn->pScreen != NULL)
++	xf86_reload_cursors (crtc->scrn->pScreen);
++
++#ifdef XF86DRI
++    /* Tell DRI1 the news about new output config */
++    i830_update_dri_buffers(crtc->scrn);
++#endif
++}
++
++static Bool
++cpu_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
++		     DisplayModePtr adjusted_mode)
++{
++    /* FDI link clock is fixed at 2.7G */
++    if (mode->Clock * 3 > 270000 * 4)
++	return MODE_CLOCK_HIGH;
++    return TRUE;
++}
++
++/* M/N cal, steal from keithp's display-port branch */
++struct ilk_m_n {
++    uint32_t        tu;
++    uint32_t        gmch_m;
++    uint32_t        gmch_n;
++    uint32_t        link_m;
++    uint32_t        link_n;
++};
++
++static void
++ilk_reduce_ratio(uint32_t *num, uint32_t *den)
++{
++    while (*num > 0xffffff || *den > 0xffffff) {
++	*num >>= 1;
++	*den >>= 1;
++    }
++}
++
++#define DATA_N 0x800000
++#define LINK_N 0x80000
++
++static void
++ilk_compute_m_n(int bytes_per_pixel,
++	int nlanes,
++	int pixel_clock,
++	int link_clock,
++	struct ilk_m_n *m_n)
++{
++    uint64_t temp;
++
++    m_n->tu = 64; /* default size */
++
++    temp = (uint64_t) DATA_N * pixel_clock;
++    temp /= link_clock;
++    m_n->gmch_m = temp * bytes_per_pixel / nlanes;
++    m_n->gmch_n = DATA_N;
++    ilk_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
++
++    temp = (uint64_t) LINK_N * pixel_clock;
++    m_n->link_m = temp / link_clock;
++    m_n->link_n = LINK_N;
++    ilk_reduce_ratio(&m_n->link_m, &m_n->link_n);
++}
++
++
++/**
++ * Sets up registers for the given mode/adjusted_mode pair.
++ *
++ * The clocks, CRTCs and outputs attached to this CRTC must be off.
++ *
++ * This shouldn't enable any clocks, CRTCs, or outputs, but they should
++ * be easily turned on/off after this.
++ */
++static void
++cpu_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
++		   DisplayModePtr adjusted_mode,
++		   int x, int y)
++{
++
++    /* set cpu and pch timing, M/U/TU, and PLL */
++
++    ScrnInfoPtr pScrn = crtc->scrn;
++    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
++    I830Ptr pI830 = I830PTR(pScrn);
++    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
++    I830OutputPrivatePtr intel_output;
++    int pipe = intel_crtc->pipe;
++    int plane = intel_crtc->plane;
++    /* CPU */
++    int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
++    int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
++    int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
++    int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
++    int cpu_vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
++    int cpu_vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
++    int cpu_vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
++    int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
++    int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
++    /* it looks vesa setting only affect m1/n1, not m2/n2 */
++    int data_m1_reg = (pipe == 0) ? PIPEA_DATA_M1 : PIPEB_DATA_M1;
++    int data_n1_reg = (pipe == 0) ? PIPEA_DATA_N1 : PIPEB_DATA_N1;
++    int link_m1_reg = (pipe == 0) ? PIPEA_LINK_M1 : PIPEB_LINK_M1;
++    int link_n1_reg = (pipe == 0) ? PIPEA_LINK_N1 : PIPEB_LINK_N1;
++    /* PCH */
++    int pch_fp_reg = (pipe == 0) ? PCH_FPA0 : PCH_FPB0;
++    int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
++    int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
++    uint32_t temp;
++
++    int i, num_outputs = 0;
++    int refclk;
++    intel_clock_t clock;
++    uint32_t dpll = 0, fp = 0, dspcntr, pipeconf, lvds_bits = 0;
++    Bool ok, is_sdvo = FALSE, is_dvo = FALSE;
++    Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
++    const intel_limit_t *limit;
++    int sdvo_pixel_multiply;
++    struct ilk_m_n m_n;
++
++    _debug("crtc mode_set ");
++
++    /* Set up some convenient bools for what outputs are connected to
++     * our pipe, used in DPLL setup.
++     */
++    for (i = 0; i < xf86_config->num_output; i++) {
++	xf86OutputPtr  output = xf86_config->output[i];
++	intel_output = output->driver_private;
++
++	if (output->crtc != crtc)
++	    continue;
++
++	switch (intel_output->type) {
++	case I830_OUTPUT_LVDS:
++	    is_lvds = TRUE;
++	    lvds_bits = intel_output->lvds_bits;
++	    break;
++	case I830_OUTPUT_SDVO:
++	case I830_OUTPUT_HDMI:
++	    is_sdvo = TRUE;
++	    if (intel_output->needs_tv_clock)
++		is_tv = TRUE;
++	    break;
++	case I830_OUTPUT_DVO_TMDS:
++	case I830_OUTPUT_DVO_LVDS:
++	case I830_OUTPUT_DVO_TVOUT:
++	    is_dvo = TRUE;
++	    break;
++	case I830_OUTPUT_TVOUT:
++	    is_tv = TRUE;
++	    break;
++	case I830_OUTPUT_ANALOG:
++	    is_crt = TRUE;
++	    break;
++	}
++
++	num_outputs++;
++    }
++
++    if (num_outputs > 1)
++	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "clone detected, disabling SSC\n");
++
++    /* Don't use SSC when cloned */
++    if (is_lvds && pI830->lvds_use_ssc && num_outputs < 2) {
++	refclk = pI830->lvds_ssc_freq * 1000;
++	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
++		   "using SSC reference clock of %d MHz\n", refclk / 1000);
++    } else if (IS_I9XX(pI830)) {
++	refclk = 120000; /* reference clock at 120Mhz */
++    } else {
++	refclk = 48000;
++    }
++
++    _debug("calculate pll\n");
++    /*
++     * Returns a set of divisors for the desired target clock with the given
++     * refclk, or FALSE.  The returned values represent the clock equation:
++     * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
++     */
++    limit = intel_limit_ilk (crtc);
++    ok = limit->find_pll(limit, crtc, adjusted_mode->Clock, refclk, &clock);
++    if (!ok)
++	FatalError("Couldn't find PLL settings for mode!\n");
++
++    if (fabs(adjusted_mode->Clock - clock.dot) / clock.dot > .02) {
++	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++		   "Chosen PLL clock of %.1f Mhz more than 2%% away from "
++		   "desired %.1f Mhz\n",
++		   (float)clock.dot / 1000,
++		   (float)adjusted_mode->Clock / 1000);
++    }
++
++    fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
++
++    _debug("set m_n");
++    ilk_compute_m_n(3, 4, /* lane num 4 */
++	    adjusted_mode->Clock,
++	    270000, /* lane clock */
++	    &m_n);
++
++    if (is_lvds)
++	dpll |= DPLLB_MODE_LVDS;
++    else
++	dpll |= DPLLB_MODE_DAC_SERIAL;
++    if (is_sdvo)
++	dpll |= DPLL_DVO_HIGH_SPEED;
++
++    /* compute bitmask from p1 value */
++    dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA0_P1_POST_DIV_SHIFT;
++    /* also for FPA1 p1 */
++    dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
++
++    switch (clock.p2) {
++	case 5:
++	    _debug("p2 is 5");
++	    dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
++	    break;
++	case 7:
++	    _debug("p2 is 7");
++	    dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
++	    break;
++	case 10:
++	    _debug("p2 is 10");
++	    dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
++	    break;
++	case 14:
++	    _debug("p2 is 14");
++	    dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
++	    break;
++    }
++
++    if (is_sdvo && is_tv)
++	dpll |= PLL_REF_INPUT_TVCLKINBC;
++    else if (is_tv)
++    {
++	/* XXX: just matching BIOS for now */
++/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
++	dpll |= 3;
++    } /* XXX ssc and super ssc ...*/
++    else if (is_lvds && pI830->lvds_use_ssc && num_outputs < 2)
++	dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
++    else
++	dpll |= PLL_REF_INPUT_DREFCLK;
++
++    /* Set up the display plane register */
++    dspcntr = DISPPLANE_GAMMA_ENABLE;
++    switch (pScrn->bitsPerPixel) {
++    case 8:
++	dspcntr |= DISPPLANE_8BPP;
++	break;
++    case 16:
++	if (pScrn->depth == 15)
++	    dspcntr |= DISPPLANE_15_16BPP;
++	else
++	    dspcntr |= DISPPLANE_16BPP;
++	break;
++    case 32:
++	dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
++	break;
++    default:
++	FatalError("unknown display bpp\n");
++    }
++
++    /* Plane A/B is connected to Pipe A/B only */
++
++    if (ilk_display_tiled(crtc))
++	dspcntr |= DISPLAY_PLANE_TILED;
++
++    /* full rgb color, 8bpc */
++    pipeconf = (PIPECONF_FULL_COLOR_RANGE |
++	    PIPECONF_COLOR_SPACE_RGB |
++	    PIPECONF_8BPP);
++
++    /*
++     * This "shouldn't" be needed as the dpms on code
++     * will be run after the mode is set. On 9xx, it helps.
++     * On 855, it can lock up the chip (and the entire machine)
++     */
++    dspcntr |= DISPLAY_PLANE_ENABLE;
++    pipeconf |= PIPEACONF_ENABLE;
++    dpll |= DPLL_VCO_ENABLE;
++
++    if (pI830->debug_modes) {
++	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
++		   "Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
++	xf86PrintModeline(pScrn->scrnIndex, mode);
++	if (!xf86ModesEqual(mode, adjusted_mode)) {
++	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
++		       "Adjusted mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
++	    xf86PrintModeline(pScrn->scrnIndex, adjusted_mode);
++	}
++	i830PrintPll(pScrn, "chosen", &clock);
++    }
++
++    _debug("disable DPLL first\n");
++
++    if (dpll & DPLL_VCO_ENABLE)
++    {
++	OUTREG(pch_fp_reg, fp);
++	OUTREG(pch_dpll_reg, dpll & ~DPLL_VCO_ENABLE);
++	POSTING_READ(pch_dpll_reg);
++	usleep(150);
++    }
++
++    sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
++    dpll |= ((sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT);
++
++    _debug("enable PCH DPLL 0x%x", dpll);
++    OUTREG(pch_fp_reg, fp);
++    OUTREG(pch_dpll_reg, dpll);
++    POSTING_READ(pch_dpll_reg);
++    /* Wait for the clocks to stabilize. */
++    usleep(150);
++    OUTREG(pch_dpll_reg, dpll);
++    i830WaitForVblank(pScrn);
++
++    _debug("set timing");
++    /* Timing */
++    OUTREG(cpu_htot_reg, (adjusted_mode->CrtcHDisplay - 1) |
++	((adjusted_mode->CrtcHTotal - 1) << 16));
++    OUTREG(cpu_hblank_reg, (adjusted_mode->CrtcHBlankStart - 1) |
++	((adjusted_mode->CrtcHBlankEnd - 1) << 16));
++    OUTREG(cpu_hsync_reg, (adjusted_mode->CrtcHSyncStart - 1) |
++	((adjusted_mode->CrtcHSyncEnd - 1) << 16));
++    OUTREG(cpu_vtot_reg, (adjusted_mode->CrtcVDisplay - 1) |
++	((adjusted_mode->CrtcVTotal - 1) << 16));
++    OUTREG(cpu_vblank_reg, (adjusted_mode->CrtcVBlankStart - 1) |
++	((adjusted_mode->CrtcVBlankEnd - 1) << 16));
++    OUTREG(cpu_vsync_reg, (adjusted_mode->CrtcVSyncStart - 1) |
++	((adjusted_mode->CrtcVSyncEnd - 1) << 16));
++    OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
++
++    OUTREG(data_m1_reg, TU_SIZE(m_n.tu) | m_n.gmch_m);
++    OUTREG(data_n1_reg, TU_SIZE(m_n.tu) | m_n.gmch_n);
++    OUTREG(link_m1_reg, m_n.link_m);
++    OUTREG(link_n1_reg, m_n.link_n);
++
++    /* enable FDI RX PLL too */
++    _debug("enable FDI RX PLL");
++    temp = INREG(fdi_rx_reg);
++    OUTREG(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE);
++    intel_wait_warmup(WARMUP_PCH_FDI_RECEIVER_PLL);
++    intel_wait_warmup(WARMUP_DMI_LATENCY);
++
++    /* enable pipe before any plane enable, and after timing set */
++    _debug("enable pipe 0x%x", pipeconf);
++    OUTREG(pipeconf_reg, pipeconf);
++    i830WaitForVblank(pScrn);
++
++    _debug("set plane");
++    /* Flush the plane changes */
++    OUTREG(dspcntr_reg, dspcntr);
++    IlkPipeSetBase(crtc, x, y);
++    i830WaitForVblank(pScrn);
++
++    temp = INREG(fdi_rx_reg);
++    OUTREG(fdi_rx_reg, temp | FDI_SEL_PCDCLK);
++
++    /* pipesrc and dspsize control the size that is scaled from, which should
++     * always be the user's requested size.
++     */
++
++#ifdef XF86DRI
++   I830DRISetVBlankInterrupt (pScrn, TRUE);
++#endif
++
++   i830WaitForVblank(pScrn);
++}
++
++
++/** Loads the palette/gamma unit for the CRTC with the prepared values */
++static void
++ilk_crtc_load_lut(xf86CrtcPtr crtc)
++{
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830Ptr pI830 = I830PTR(pScrn);
++    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
++    int palreg = (intel_crtc->pipe == 0) ? LGC_PALETTE_A : LGC_PALETTE_B;
++    int i;
++
++    /* The clocks have to be on to load the palette. */
++    if (!crtc->enabled)
++	return;
++
++    for (i = 0; i < 256; i++) {
++	OUTREG(palreg + 4 * i,
++	       (intel_crtc->lut_r[i] << 16) |
++	       (intel_crtc->lut_g[i] << 8) |
++	       intel_crtc->lut_b[i]);
++    }
++}
++
++/** Sets the color ramps on behalf of RandR */
++static void
++ilk_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
++		    int size)
++{
++    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
++    int i;
++
++    assert(size == 256);
++
++    for (i = 0; i < 256; i++) {
++	intel_crtc->lut_r[i] = red[i] >> 8;
++	intel_crtc->lut_g[i] = green[i] >> 8;
++	intel_crtc->lut_b[i] = blue[i] >> 8;
++    }
++
++    ilk_crtc_load_lut(crtc);
++}
++
++/**
++ * Allocates memory for a locked-in-framebuffer shadow of the given
++ * width and height for this CRTC's rotated shadow framebuffer.
++ */
++ 
++static void *
++i830_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
++{
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830Ptr pI830 = I830PTR(pScrn);
++    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
++    unsigned long rotate_pitch;
++    int align = KB(4), size;
++
++    width = i830_pad_drawable_width(width, pI830->cpp);
++    rotate_pitch = width * pI830->cpp;
++    size = rotate_pitch * height;
++
++    assert(intel_crtc->rotate_mem == NULL);
++    intel_crtc->rotate_mem = i830_allocate_memory(pScrn, "rotated crtc",
++						  size, rotate_pitch, align,
++						  0, TILE_NONE);
++    if (intel_crtc->rotate_mem == NULL) {
++	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
++		   "Couldn't allocate shadow memory for rotated CRTC\n");
++	return NULL;
++    }
++    memset(pI830->FbBase + intel_crtc->rotate_mem->offset, 0, size);
++
++    return pI830->FbBase + intel_crtc->rotate_mem->offset;
++}
++    
++/**
++ * Creates a pixmap for this CRTC's rotated shadow framebuffer.
++ */
++static PixmapPtr
++i830_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
++{
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
++    I830Ptr pI830 = I830PTR(pScrn);
++    int rotate_pitch;
++    PixmapPtr rotate_pixmap;
++
++    if (!data)
++	data = i830_crtc_shadow_allocate (crtc, width, height);
++    
++    rotate_pitch = i830_pad_drawable_width(width, pI830->cpp) * pI830->cpp;
++
++    rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
++					   width, height,
++					   pScrn->depth,
++					   pScrn->bitsPerPixel,
++					   rotate_pitch,
++					   data);
++
++    if (rotate_pixmap == NULL) {
++	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
++		   "Couldn't allocate shadow pixmap for rotated CRTC\n");
++    }
++    //if (intel_crtc->rotate_mem && intel_crtc->rotate_mem->bo)
++	//i830_set_pixmap_bo(rotate_pixmap, intel_crtc->rotate_mem->bo);
++    return rotate_pixmap;
++}
++
++static void
++i830_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
++{
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
++
++    if (rotate_pixmap)
++	FreeScratchPixmapHeader(rotate_pixmap);
++
++    if (data) {
++	/* Be sure to sync acceleration before the memory gets unbound. */
++	I830Sync(pScrn);
++	i830_free_memory(pScrn, intel_crtc->rotate_mem);
++	intel_crtc->rotate_mem = NULL;
++    }
++}
++
++#if RANDR_13_INTERFACE
++static void
++ilk_crtc_set_origin(xf86CrtcPtr crtc, int x, int y)
++{
++    if (crtc->enabled)
++	IlkPipeSetBase(crtc, x, y);
++}
++#endif
++
++#if 0
++/* Returns the clock of the currently programmed mode of the given pipe. */
++static int
++i830_crtc_clock_get(ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
++{
++    I830Ptr pI830 = I830PTR(pScrn);
++    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
++    int pipe = intel_crtc->pipe;
++    uint32_t dpll = INREG((pipe == 0) ? DPLL_A : DPLL_B);
++    uint32_t fp;
++    intel_clock_t clock;
++
++    if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
++	fp = INREG((pipe == 0) ? FPA0 : FPB0);
++    else
++	fp = INREG((pipe == 0) ? FPA1 : FPB1);
++
++    clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
++    if (IS_IGD(pI830)) {
++	clock.n = ffs((fp & FP_N_IGD_DIV_MASK) >> FP_N_DIV_SHIFT) - 1;
++	clock.m2 = (fp & FP_M2_IGD_DIV_MASK) >> FP_M2_DIV_SHIFT;
++    } else {
++	clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
++	clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
++    }
++    if (IS_I9XX(pI830)) {
++	if (IS_IGD(pI830))
++	    clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_IGD) >>
++			   DPLL_FPA01_P1_POST_DIV_SHIFT_IGD);
++	else
++	    clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >>
++			   DPLL_FPA01_P1_POST_DIV_SHIFT);
++
++	switch (dpll & DPLL_MODE_MASK) {
++	case DPLLB_MODE_DAC_SERIAL:
++	    clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10;
++	    break;
++	case DPLLB_MODE_LVDS:
++	    clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14;
++	    break;
++	default:
++	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++		       "Unknown DPLL mode %08x in programmed mode\n",
++		       (int)(dpll & DPLL_MODE_MASK));
++	    return 0;
++	}
++
++	if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
++	    intel_clock(pI830, 100000, &clock);
++	else
++	    intel_clock(pI830, 96000, &clock);
++    } else {
++	Bool is_lvds = (pipe == 1) && (INREG(LVDS) & LVDS_PORT_EN);
++
++	if (is_lvds) {
++	    clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
++			   DPLL_FPA01_P1_POST_DIV_SHIFT);
++
++	    /* if LVDS is dual-channel, p2 = 7 */
++	    if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
++		clock.p2 = 7;
++	    else
++		clock.p2 = 14;
++
++	    if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
++		intel_clock(pI830, 66000, &clock); /* XXX: might not be 66MHz */
++	    else
++		intel_clock(pI830, 48000, &clock);
++	} else {
++	    if (dpll & PLL_P1_DIVIDE_BY_TWO) {
++		clock.p1 = 2;
++	    } else {
++		clock.p1 = ((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
++		    DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
++	    }
++	    if (dpll & PLL_P2_DIVIDE_BY_4)
++		clock.p2 = 4;
++	    else
++		clock.p2 = 2;
++
++	    intel_clock(pI830, 48000, &clock);
++	}
++    }
++
++    /* XXX: It would be nice to validate the clocks, but we can't reuse
++     * i830PllIsValid() because it relies on the xf86_config output
++     * configuration being accurate, which it isn't necessarily.
++     */
++    if (0)
++	i830PrintPll(pScrn, "probed", &clock);
++
++    return clock.dot;
++}
++
++/** Returns the currently programmed mode of the given pipe. */
++DisplayModePtr
++i830_crtc_mode_get(ScrnInfoPtr pScrn, xf86CrtcPtr crtc)
++{
++    I830Ptr pI830 = I830PTR(pScrn);
++    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
++    int pipe = intel_crtc->pipe;
++    DisplayModePtr mode;
++    int htot = INREG((pipe == 0) ? HTOTAL_A : HTOTAL_B);
++    int hsync = INREG((pipe == 0) ? HSYNC_A : HSYNC_B);
++    int vtot = INREG((pipe == 0) ? VTOTAL_A : VTOTAL_B);
++    int vsync = INREG((pipe == 0) ? VSYNC_A : VSYNC_B);
++
++    mode = xcalloc(1, sizeof(DisplayModeRec));
++    if (mode == NULL)
++	return NULL;
++
++    mode->Clock = i830_crtc_clock_get(pScrn, crtc);
++    mode->HDisplay = (htot & 0xffff) + 1;
++    mode->HTotal = ((htot & 0xffff0000) >> 16) + 1;
++    mode->HSyncStart = (hsync & 0xffff) + 1;
++    mode->HSyncEnd = ((hsync & 0xffff0000) >> 16) + 1;
++    mode->VDisplay = (vtot & 0xffff) + 1;
++    mode->VTotal = ((vtot & 0xffff0000) >> 16) + 1;
++    mode->VSyncStart = (vsync & 0xffff) + 1;
++    mode->VSyncEnd = ((vsync & 0xffff0000) >> 16) + 1;
++    xf86SetModeDefaultName(mode);
++    xf86SetModeCrtc(mode, 0);
++
++    return mode;
++}
++#endif
++
++static const xf86CrtcFuncsRec cpu_crtc_funcs = {
++    .dpms = cpu_crtc_dpms,
++    .save = NULL, /* XXX */
++    .restore = NULL, /* XXX */
++    .lock = ilk_crtc_lock,
++    .unlock = ilk_crtc_unlock,
++    .mode_fixup = cpu_crtc_mode_fixup,
++    .prepare = ilk_crtc_prepare,
++    .mode_set = cpu_crtc_mode_set,
++    .commit = ilk_crtc_commit,
++    .gamma_set = ilk_crtc_gamma_set,
++    .shadow_create = i830_crtc_shadow_create,
++    .shadow_allocate = i830_crtc_shadow_allocate,
++    .shadow_destroy = i830_crtc_shadow_destroy,
++    .set_cursor_colors = i830_crtc_set_cursor_colors,
++    .set_cursor_position = i830_crtc_set_cursor_position,
++    .show_cursor = i830_crtc_show_cursor,
++    .hide_cursor = i830_crtc_hide_cursor,
++/*    .load_cursor_image = i830_crtc_load_cursor_image, */
++    .load_cursor_argb = i830_crtc_load_cursor_argb,
++    .destroy = NULL, /* XXX */
++#if RANDR_13_INTERFACE
++    .set_origin = ilk_crtc_set_origin,
++#endif
++};
++
++void
++cpu_crtc_init(ScrnInfoPtr pScrn, int pipe)
++{
++    xf86CrtcPtr crtc;
++    I830CrtcPrivatePtr intel_crtc;
++    int i;
++
++    crtc = xf86CrtcCreate (pScrn, &cpu_crtc_funcs);
++    if (crtc == NULL)
++	return;
++
++    intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1);
++    intel_crtc->pipe = pipe;
++    intel_crtc->dpms_mode = DPMSModeOff;
++    intel_crtc->plane = pipe;
++
++    /* Initialize the LUTs for when we turn on the CRTC. */
++    for (i = 0; i < 256; i++) {
++	intel_crtc->lut_r[i] = i;
++	intel_crtc->lut_g[i] = i;
++	intel_crtc->lut_b[i] = i;
++    }
++    crtc->driver_private = intel_crtc;
++}
+--- src/i830.h	2009-08-27 16:23:54.683656693 +0800
++++ src/i830.h	2009-08-27 17:36:49.267915536 +0800
+@@ -731,6 +731,65 @@ typedef struct _I830Rec {
+    uint32_t saveRAMCLK_GATE_D;
+    uint32_t savePWRCTXA;
+ 
++   /* new for Ilk */
++   uint32_t savePCH_DREF_CONTROL;
++   uint32_t saveFDI_RXA_CTL;
++   uint32_t saveFDI_TXA_CTL;
++   uint32_t saveTRANSACONF;
++   uint32_t savePIPEA_DATA_M1;
++   uint32_t savePIPEA_DATA_N1;
++   uint32_t savePIPEA_DATA_M2;
++   uint32_t savePIPEA_DATA_N2;
++   uint32_t savePIPEA_LINK_M1;
++   uint32_t savePIPEA_LINK_N1;
++   uint32_t savePIPEA_LINK_M2;
++   uint32_t savePIPEA_LINK_N2;
++   uint32_t saveTRANS_HTOTAL_A;
++   uint32_t saveTRANS_HBLANK_A;
++   uint32_t saveTRANS_HSYNC_A;
++   uint32_t saveTRANS_VTOTAL_A;
++   uint32_t saveTRANS_VBLANK_A;
++   uint32_t saveTRANS_VSYNC_A;
++   uint32_t saveTRANSA_DATA_M1;
++   uint32_t saveTRANSA_DATA_N1;
++   uint32_t saveTRANSA_DATA_M2;
++   uint32_t saveTRANSA_DATA_N2;
++   uint32_t saveTRANSA_LINK_M1;
++   uint32_t saveTRANSA_LINK_N1;
++   uint32_t saveTRANSA_LINK_M2;
++   uint32_t saveTRANSA_LINK_N2;
++   uint32_t savePFA_CTL_1;
++   uint32_t saveFDI_RXA_TUSIZE1;
++   uint32_t saveFDI_RXA_TUSIZE2;
++
++   uint32_t saveFDI_RXB_CTL;
++   uint32_t saveFDI_TXB_CTL;
++   uint32_t saveTRANSBCONF;
++   uint32_t savePIPEB_DATA_M1;
++   uint32_t savePIPEB_DATA_N1;
++   uint32_t savePIPEB_DATA_M2;
++   uint32_t savePIPEB_DATA_N2;
++   uint32_t savePIPEB_LINK_M1;
++   uint32_t savePIPEB_LINK_N1;
++   uint32_t savePIPEB_LINK_M2;
++   uint32_t savePIPEB_LINK_N2;
++   uint32_t saveTRANS_HTOTAL_B;
++   uint32_t saveTRANS_HBLANK_B;
++   uint32_t saveTRANS_HSYNC_B;
++   uint32_t saveTRANS_VTOTAL_B;
++   uint32_t saveTRANS_VBLANK_B;
++   uint32_t saveTRANS_VSYNC_B;
++   uint32_t saveTRANSB_DATA_M1;
++   uint32_t saveTRANSB_DATA_N1;
++   uint32_t saveTRANSB_DATA_M2;
++   uint32_t saveTRANSB_DATA_N2;
++   uint32_t saveTRANSB_LINK_M1;
++   uint32_t saveTRANSB_LINK_N1;
++   uint32_t saveTRANSB_LINK_M2;
++   uint32_t saveTRANSB_LINK_N2;
++   uint32_t savePFB_CTL_1;
++   uint32_t saveFDI_RXB_TUSIZE1;
++   uint32_t saveFDI_RXB_TUSIZE2;
+    enum last_3d *last_3d;
+ 
+    Bool use_drm_mode;
+@@ -917,6 +976,9 @@ void i830_hdmi_init(ScrnInfoPtr pScrn, i
+ /* i830_lvds.c */
+ void i830_lvds_init(ScrnInfoPtr pScrn);
+ 
++/* pch_crt.c */
++void pch_crt_init(ScrnInfoPtr pScrn);
++
+ extern void i830MarkSync(ScrnInfoPtr pScrn);
+ extern void i830WaitSync(ScrnInfoPtr pScrn);
+ 
+@@ -1094,8 +1156,33 @@ extern const int I830CopyROP[16];
+ #define QUIRK_RESET_MODES		0x00000020
+ #define QUIRK_PFIT_SAFE			0x00000040
+ #define QUIRK_IGNORE_CRT		0x00000080
++#define QUIRK_BROKEN_ACPI_LID           0x00000100
+ extern void i830_fixup_devices(ScrnInfoPtr);
+ 
++/* For debugging ...*/
++#define _debug(s, arg...)				\
++do {							\
++    if (0)						\
++       ErrorF("[%s]: " s "\n", __func__, ##arg);	\
++} while(0)
++
++/* return TRUE if ilk A* stepping (A0/A1) */
++static inline Bool ilk_a_stepping(void)
++{
++    struct pci_device *lpc_bridge;
++    uint8_t rev;
++
++    lpc_bridge = pci_device_find_by_slot(0, 0, 31, 0);
++    if (lpc_bridge == NULL)
++	return FALSE;
++    pci_device_cfg_read_u8(lpc_bridge, &rev, 0x8);
++    _debug("ilk a* stepping check %d\n", rev);
++    if (rev <= 2)
++	return TRUE;
++    else
++	return FALSE;
++}
++
+ /**
+  * Hints to CreatePixmap to tell the driver how the pixmap is going to be
+  * used.
+--- src/i830_debug.c	2009-08-18 11:31:33.499752703 +0800
++++ src/i830_debug.c	2009-08-28 10:07:02.192756355 +0800
+@@ -101,18 +101,42 @@ DEBUGSTRING(i830_debug_dspcntr)
+ {
+     char *enabled = val & DISPLAY_PLANE_ENABLE ? "enabled" : "disabled";
+     char plane = val & DISPPLANE_SEL_PIPE_B ? 'B' : 'A';
+-    return XNFprintf("%s, pipe %c", enabled, plane);
++    if (IS_IGDNG(pI830))
++	return XNFprintf("%s", enabled);
++    else
++	return XNFprintf("%s, pipe %c", enabled, plane);
++
+ }
+ 
+ DEBUGSTRING(i830_debug_pipeconf)
+ {
+     char *enabled = val & PIPEACONF_ENABLE ? "enabled" : "disabled";
+     char *bit30;
++    char *bpc = NULL;
+     if (IS_I965G(pI830))
+ 	bit30 = val & I965_PIPECONF_ACTIVE ? "active" : "inactive";
+     else
+ 	bit30 = val & PIPEACONF_DOUBLE_WIDE ? "double-wide" : "single-wide";
+-    return XNFprintf("%s, %s", enabled, bit30);
++    if (IS_IGDNG(pI830)) {
++	switch (val & (7<<5)) {
++	    case PIPECONF_8BPP:
++		bpc = "8bpc";
++		break;
++	    case PIPECONF_10BPP:
++		bpc = "10bpc";
++		break;
++	    case PIPECONF_6BPP:
++		bpc = "6bpc";
++		break;
++	    case PIPECONF_12BPP:
++		bpc = "12bpc";
++		break;
++	}
++    }
++    if (IS_IGDNG(pI830))
++	return XNFprintf("%s, %s, %s", enabled, bit30, bpc);
++    else
++	return XNFprintf("%s, %s", enabled, bit30);
+ }
+ 
+ DEBUGSTRING(i830_debug_pipestat)
+@@ -349,8 +373,13 @@ DEBUGSTRING(i830_debug_adpa)
+     char hsync = (val & ADPA_HSYNC_ACTIVE_HIGH) ? '+' : '-';
+     char vsync = (val & ADPA_VSYNC_ACTIVE_HIGH) ? '+' : '-';
+ 
+-    return XNFprintf("%s, pipe %c, %chsync, %cvsync",
+-		     enable, pipe, hsync, vsync);
++    if (IS_IGDNG(pI830))
++	return XNFprintf("%s, transcoder %c, %chsync, %cvsync",
++		enable, pipe, hsync, vsync);
++    else
++	return XNFprintf("%s, pipe %c, %chsync, %cvsync",
++		enable, pipe, hsync, vsync);
++
+ }
+ 
+ DEBUGSTRING(i830_debug_lvds)
+@@ -717,18 +746,512 @@ static struct i830SnapshotRec {
+     DEFINEREG2(FENCE_NEW + 120, i810_debug_fence_new),
+ #endif
+ };
+-#undef DEFINEREG
+ #define NUM_I830_SNAPSHOTREGS (sizeof(i830_snapshot) / sizeof(i830_snapshot[0]))
+ 
++/* pI830, reg, val */
++DEBUGSTRING(ilk_debug_rr_hw_ctl)
++{
++    return XNFprintf("low %d, high %d", val & RR_HW_LOW_POWER_FRAMES_MASK,
++	    (val & RR_HW_HIGH_POWER_FRAMES_MASK) >> 8 );
++}
++
++DEBUGSTRING(ilk_debug_m_tu)
++{
++    return XNFprintf("TU %d, val 0x%x %d", (val >> 25) + 1, val & 0xffffff, val & 0xffffff);
++}
++
++DEBUGSTRING(ilk_debug_n)
++{
++    return XNFprintf("val 0x%x %d", val & 0xffffff, val & 0xffffff);
++}
++
++DEBUGSTRING(ilk_debug_fdi_tx_ctl)
++{
++    char *train = NULL, *voltage = NULL, *pre_emphasis = NULL, *portw = NULL;
++
++    switch (val & FDI_LINK_TRAIN_NONE) {
++	case FDI_LINK_TRAIN_PATTERN_1:
++	    train = "pattern_1";
++	    break;
++	case FDI_LINK_TRAIN_PATTERN_2:
++	    train = "pattern_2";
++	    break;
++	case FDI_LINK_TRAIN_PATTERN_IDLE:
++	    train = "pattern_idle";
++	    break;
++	case FDI_LINK_TRAIN_NONE:
++	    train = "not train";
++	    break;
++    }
++
++    switch (val & (7<<25)) {
++	case FDI_LINK_TRAIN_VOLTAGE_0_4V:
++	    voltage = "0.4V";
++	    break;
++	case FDI_LINK_TRAIN_VOLTAGE_0_6V:
++	    voltage = "0.6V";
++	    break;
++	case FDI_LINK_TRAIN_VOLTAGE_0_8V:
++	    voltage = "0.8V";
++	    break;
++	case FDI_LINK_TRAIN_VOLTAGE_1_2V:
++	    voltage = "1.2V";
++	    break;
++	default:
++	    voltage = "reserved";
++    }
++
++    switch (val & (7<<22)) {
++	case FDI_LINK_TRAIN_PRE_EMPHASIS_NONE:
++	    pre_emphasis = "none";
++	    break;
++	case FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X:
++	    pre_emphasis = "1.5x";
++	    break;
++	case FDI_LINK_TRAIN_PRE_EMPHASIS_2X:
++	    pre_emphasis = "2x";
++	    break;
++	case FDI_LINK_TRAIN_PRE_EMPHASIS_3X:
++	    pre_emphasis = "3x";
++	    break;
++	default:
++	    pre_emphasis = "reserved";
++    }
++
++    switch (val & (7<<19)) {
++	case FDI_DP_PORT_WIDTH_X1:
++	    portw = "X1";
++	    break;
++	case FDI_DP_PORT_WIDTH_X2:
++	    portw = "X2";
++	    break;
++	case FDI_DP_PORT_WIDTH_X3:
++	    portw = "X3";
++	    break;
++	case FDI_DP_PORT_WIDTH_X4:
++	    portw = "X4";
++	    break;
++    }
++
++    return XNFprintf("%s, train pattern %s, voltage swing %s,"
++	    "pre-emphasis %s, port width %s, enhanced framing %s, FDI PLL %s, scrambing %s, master mode %s",
++	    val & FDI_TX_ENABLE ? "enable" : "disable",
++	    train, voltage, pre_emphasis, portw,
++	    val & FDI_TX_ENHANCE_FRAME_ENABLE ? "enable" : "disable",
++	    val & FDI_TX_PLL_ENABLE ? "enable" : "disable",
++	    val & (1 << 7) ? "disable" : "enable",
++	    val & (1 << 0) ? "enable" : "disable");
++}
++
++DEBUGSTRING(ilk_debug_fdi_rx_ctl)
++{
++    char *train = NULL, *portw = NULL, *bpc = NULL;
++
++    switch (val & FDI_LINK_TRAIN_NONE) {
++	case FDI_LINK_TRAIN_PATTERN_1:
++	    train = "pattern_1";
++	    break;
++	case FDI_LINK_TRAIN_PATTERN_2:
++	    train = "pattern_2";
++	    break;
++	case FDI_LINK_TRAIN_PATTERN_IDLE:
++	    train = "pattern_idle";
++	    break;
++	case FDI_LINK_TRAIN_NONE:
++	    train = "not train";
++	    break;
++    }
++
++    switch (val & (7<<19)) {
++	case FDI_DP_PORT_WIDTH_X1:
++	    portw = "X1";
++	    break;
++	case FDI_DP_PORT_WIDTH_X2:
++	    portw = "X2";
++	    break;
++	case FDI_DP_PORT_WIDTH_X3:
++	    portw = "X3";
++	    break;
++	case FDI_DP_PORT_WIDTH_X4:
++	    portw = "X4";
++	    break;
++    }
++
++    switch (val & (7<<16)) {
++	case FDI_8BPC:
++	    bpc = "8bpc";
++	    break;
++	case FDI_10BPC:
++	    bpc = "10bpc";
++	    break;
++	case FDI_6BPC:
++	    bpc = "6bpc";
++	    break;
++	case FDI_12BPC:
++	    bpc = "12bpc";
++	    break;
++    }
++
++    return XNFprintf("%s, train pattern %s, port width %s, %s,"
++	    "link_reverse_strap_overwrite %s, dmi_link_reverse %s, FDI PLL %s,"
++	    "FS ecc %s, FE ecc %s, FS err report %s, FE err report %s,"
++	    "scrambing %s, enhanced framing %s, %s",
++	    val & FDI_RX_ENABLE ? "enable" : "disable",
++	    train, portw, bpc,
++	    val & FDI_LINK_REVERSE_OVERWRITE ? "yes" : "no",
++	    val & FDI_DMI_LINK_REVERSE_MASK ? "yes" : "no",
++	    val & FDI_RX_PLL_ENABLE ? "enable" : "disable",
++	    val & FDI_FS_ERR_CORRECT_ENABLE ? "enable" : "disable",
++	    val & FDI_FE_ERR_CORRECT_ENABLE ? "enable" : "disable",
++	    val & FDI_FS_ERR_REPORT_ENABLE ? "enable" : "disable",
++	    val & FDI_FE_ERR_REPORT_ENABLE ? "enable" : "disable",
++	    val & (1 << 7) ? "disable" : "enable",
++	    val & FDI_RX_ENHANCE_FRAME_ENABLE ? "enable" : "disable",
++	    val & FDI_SEL_PCDCLK ? "PCDClk" : "RawClk");
++}
++DEBUGSTRING(ilk_debug_dspstride)
++{
++    return XNFprintf("%d", val >> 6);
++}
++
++DEBUGSTRING(ilk_debug_pch_dpll)
++{
++    char *enable = val & DPLL_VCO_ENABLE ? "enable" : "disable";
++    char *highspeed = val & DPLL_DVO_HIGH_SPEED ? "yes" : "no";
++    char *mode = NULL;
++    char *p2 = NULL;
++    int fpa0_p1, fpa1_p1;
++    char *refclk = NULL;
++    int sdvo_mul;
++
++    if ((val & DPLL_MODE_MASK) == DPLLB_MODE_LVDS) {
++	mode = "LVDS";
++	if (val & DPLLB_LVDS_P2_CLOCK_DIV_7)
++	    p2 = "Div 7";
++	else
++	    p2 = "Div 14";
++    } else if ((val & DPLL_MODE_MASK) == DPLLB_MODE_DAC_SERIAL) {
++	mode = "Non-LVDS";
++	if (val & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5)
++	    p2 = "Div 5";
++	else
++	    p2 = "Div 10";
++    }
++    fpa0_p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK) >> 16);
++    fpa1_p1 = ffs((val & DPLL_FPA1_P1_POST_DIV_MASK));
++
++    switch (val & (7<<13)) {
++	case PLL_REF_INPUT_DREFCLK:
++	    refclk = "default 120Mhz";
++	    break;
++	case PLL_REF_INPUT_SUPER_SSC:
++	    refclk = "SuperSSC 120Mhz";
++	    break;
++	case PLL_REF_INPUT_TVCLKINBC:
++	    refclk = "SDVO TVClkIn";
++	    break;
++	case PLLB_REF_INPUT_SPREADSPECTRUMIN:
++	    refclk = "SSC";
++	    break;
++	case PLL_REF_INPUT_DMICLK:
++	    refclk = "DMI RefCLK";
++	    break;
++    }
++
++    sdvo_mul = ((val & PLL_REF_SDVO_HDMI_MULTIPLIER_MASK) >> 9) + 1;
++
++    return XNFprintf("%s, sdvo high speed %s, mode %s, p2 %s, "
++	    "FPA0 P1 %d, FPA1 P1 %d, refclk %s, sdvo/hdmi mul %d",
++	    enable, highspeed, mode, p2, fpa0_p1, fpa1_p1, refclk, sdvo_mul);
++}
++
++DEBUGSTRING(ilk_debug_dref_ctl)
++{
++    char *cpu_source;
++    char *ssc_source = val & DREF_SSC_SOURCE_ENABLE ? "enable" : "disable";
++    char *nonspread_source = val & DREF_NONSPREAD_SOURCE_ENABLE ? "enable":"disable";
++    char *superspread_source = val & DREF_SUPERSPREAD_SOURCE_ENABLE ? "enable":"disable";
++    char *ssc4_mode = val & DREF_SSC4_CENTERSPREAD ? "centerspread" : "downspread";
++    char *ssc1 = val & DREF_SSC1_ENABLE ? "enable" : "disable";
++    char *ssc4 = val & DREF_SSC4_ENABLE ? "enable" : "disable";
++
++    switch (val & DREF_CPU_SOURCE_OUTPUT_NONSPREAD) {
++	case DREF_CPU_SOURCE_OUTPUT_DISABLE:
++	    cpu_source = "disable";
++	    break;
++	case DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD:
++	    cpu_source = "downspread";
++	    break;
++	case DREF_CPU_SOURCE_OUTPUT_NONSPREAD:
++	    cpu_source = "nonspread";
++	    break;
++	default:
++	    cpu_source = "reserved";
++    }
++    return XNFprintf("cpu source %s, ssc_source %s, nonspread_source %s, "
++	    "superspread_source %s, ssc4_mode %s, ssc1 %s, ssc4 %s",
++	    cpu_source, ssc_source, nonspread_source, superspread_source,
++	    ssc4_mode, ssc1, ssc4);
++}
++
++DEBUGSTRING(ilk_debug_rawclk_freq)
++{
++    char *tp1 = NULL, *tp2 = NULL;
++
++    switch (val & FDL_TP1_TIMER_MASK) {
++	case 0:
++	    tp1 = "0.5us";
++	    break;
++	case (1 << 12):
++	    tp1 = "1.0us";
++	    break;
++	case (2 << 12):
++	    tp1 = "2.0us";
++	    break;
++	case (3 << 12):
++	    tp1 = "4.0us";
++	    break;
++    }
++    switch (val & FDL_TP2_TIMER_MASK) {
++	case 0:
++	    tp2 = "1.5us";
++	    break;
++	case (1 << 10):
++	    tp2 = "3.0us";
++	    break;
++	case (2 << 10):
++	    tp2 = "6.0us";
++	    break;
++	case (3 << 10):
++	    tp2 = "12.0us";
++	    break;
++    }
++    return XNFprintf("FDL_TP1 timer %s, FDL_TP2 timer %s, freq %d",
++	    tp1, tp2, val & RAWCLK_FREQ_MASK);
++
++}
++
++DEBUGSTRING(ilk_debug_fdi_rx_misc)
++{
++    return XNFprintf("FDI Delay %d", val & ((1 << 13) - 1));
++}
++
++DEBUGSTRING(ilk_debug_transconf)
++{
++    return XNFprintf("%s, %s",
++	    val & TRANS_ENABLE ? "enable" : "disable",
++	    val & TRANS_STATE_ENABLE ? "active" : "inactive");
++}
++
++DEBUGSTRING(ilk_debug_panel_fitting)
++{
++    char *vadapt = NULL, *filter_sel = NULL;
++
++    switch (val & (3 << 25)) {
++	case 0:
++	    vadapt = "least";
++	    break;
++	case (1<<25):
++	    vadapt = "moderate";
++	    break;
++	case (2<<25):
++	    vadapt = "reserved";
++	    break;
++	case (3<<25):
++	    vadapt = "most";
++	    break;
++    }
++
++    switch (val & (3 << 23)) {
++	case 0:
++	    filter_sel = "programmed";
++	    break;
++	case (1<<25):
++	    filter_sel = "hardcoded";
++	    break;
++	case (2<<25):
++	    filter_sel = "edge_enhance";
++	    break;
++	case (3<<25):
++	    filter_sel = "edge_soften";
++	    break;
++    }
++
++    return XNFprintf("%s, auto_scale %s, auto_scale_cal %s, v_filter %s, vadapt %s, mode %s, filter_sel %s,"
++	   "chroma pre-filter %s, vert3tap %s, v_inter_invert %s",
++	   val & PF_ENABLE ? "enable" : "disable",
++	   val & (1 << 30) ? "no" : "yes",
++	   val & (1 << 29) ? "yes" : "no",
++	   val & (1 << 28) ? "bypass" : "enable",
++	   val & (1 << 27) ? "enable" : "disable",
++	   vadapt, filter_sel,
++	   val & (1 << 22) ? "enable" : "disable",
++	   val & (1 << 21) ? "force" : "auto",
++	   val & (1 << 20) ? "field 0" : "field 1");
++}
++
++/* new register dumps for ironlake */
++static struct i830SnapshotRec cpu_pch_snapshot[] = {
++    DEFINEREG2(CPU_VGACNTRL, i830_debug_vgacntrl),
++    DEFINEREG(DIGITAL_PORT_HOTPLUG_CNTRL),
++
++    DEFINEREG2(RR_HW_CTL, ilk_debug_rr_hw_ctl),
++
++    DEFINEREG(FDI_PLL_BIOS_0),
++    DEFINEREG(FDI_PLL_BIOS_1),
++    DEFINEREG(FDI_PLL_BIOS_2),
++
++    DEFINEREG(DISPLAY_PORT_PLL_BIOS_0),
++    DEFINEREG(DISPLAY_PORT_PLL_BIOS_1),
++    DEFINEREG(DISPLAY_PORT_PLL_BIOS_2),
++
++    DEFINEREG(FDI_PLL_FREQ_CTL),
++
++    DEFINEREG2(PIPEACONF, i830_debug_pipeconf),
++
++    DEFINEREG2(HTOTAL_A, i830_debug_hvtotal),
++    DEFINEREG2(HBLANK_A, i830_debug_hvsyncblank),
++    DEFINEREG2(HSYNC_A, i830_debug_hvsyncblank),
++    DEFINEREG2(VTOTAL_A, i830_debug_hvtotal),
++    DEFINEREG2(VBLANK_A, i830_debug_hvsyncblank),
++    DEFINEREG2(VSYNC_A, i830_debug_hvsyncblank),
++    DEFINEREG(VSYNCSHIFT_A),
++    DEFINEREG2(PIPEASRC, i830_debug_yxminus1),
++
++    DEFINEREG2(PIPEA_DATA_M1, ilk_debug_m_tu),
++    DEFINEREG2(PIPEA_DATA_N1, ilk_debug_n),
++    DEFINEREG2(PIPEA_DATA_M2, ilk_debug_m_tu),
++    DEFINEREG2(PIPEA_DATA_N2, ilk_debug_n),
++
++    DEFINEREG2(PIPEA_LINK_M1, ilk_debug_n),
++    DEFINEREG2(PIPEA_LINK_N1, ilk_debug_n),
++    DEFINEREG2(PIPEA_LINK_M2, ilk_debug_n),
++    DEFINEREG2(PIPEA_LINK_N2, ilk_debug_n),
++
++    DEFINEREG2(DSPACNTR, i830_debug_dspcntr),
++    DEFINEREG(DSPABASE),
++    DEFINEREG2(DSPASTRIDE, ilk_debug_dspstride),
++    DEFINEREG(DSPASURF),
++    DEFINEREG2(DSPATILEOFF, i830_debug_xy),
++
++    DEFINEREG2(PIPEBCONF, i830_debug_pipeconf),
++
++    DEFINEREG2(HTOTAL_B, i830_debug_hvtotal),
++    DEFINEREG2(HBLANK_B, i830_debug_hvsyncblank),
++    DEFINEREG2(HSYNC_B, i830_debug_hvsyncblank),
++    DEFINEREG2(VTOTAL_B, i830_debug_hvtotal),
++    DEFINEREG2(VBLANK_B, i830_debug_hvsyncblank),
++    DEFINEREG2(VSYNC_B, i830_debug_hvsyncblank),
++    DEFINEREG(VSYNCSHIFT_B),
++
++    DEFINEREG2(DSPBCNTR, i830_debug_dspcntr),
++    DEFINEREG(DSPBBASE),
++    DEFINEREG2(DSPBSTRIDE, ilk_debug_dspstride),
++    DEFINEREG(DSPBSURF),
++    DEFINEREG2(DSPBTILEOFF, i830_debug_xy),
++
++    DEFINEREG2(PIPEBSRC, i830_debug_yxminus1),
++
++    DEFINEREG2(PIPEB_DATA_M1, ilk_debug_m_tu),
++    DEFINEREG2(PIPEB_DATA_N1, ilk_debug_n),
++    DEFINEREG2(PIPEB_DATA_M2, ilk_debug_m_tu),
++    DEFINEREG2(PIPEB_DATA_N2, ilk_debug_n),
++
++    DEFINEREG2(PIPEB_LINK_M1, ilk_debug_n),
++    DEFINEREG2(PIPEB_LINK_N1, ilk_debug_n),
++    DEFINEREG2(PIPEB_LINK_M2, ilk_debug_n),
++    DEFINEREG2(PIPEB_LINK_N2, ilk_debug_n),
++
++    DEFINEREG2(PFA_CTRL_1, ilk_debug_panel_fitting),
++    DEFINEREG2(PFB_CTRL_1, ilk_debug_panel_fitting),
++
++    /* PCH */
++
++    DEFINEREG2(PCH_DREF_CONTROL, ilk_debug_dref_ctl),
++    DEFINEREG2(PCH_RAWCLK_FREQ, ilk_debug_rawclk_freq),
++    DEFINEREG(PCH_DPLL_TMR_CFG),
++    DEFINEREG(PCH_SSC4_PARMS),
++    DEFINEREG(PCH_SSC4_AUX_PARMS),
++
++    DEFINEREG2(PCH_DPLL_A, ilk_debug_pch_dpll),
++    DEFINEREG2(PCH_DPLL_B, ilk_debug_pch_dpll),
++    DEFINEREG2(PCH_FPA0, i830_debug_fp),
++    DEFINEREG2(PCH_FPA1, i830_debug_fp),
++    DEFINEREG2(PCH_FPB0, i830_debug_fp),
++    DEFINEREG2(PCH_FPB1, i830_debug_fp),
++
++    DEFINEREG2(TRANS_HTOTAL_A, i830_debug_hvtotal),
++    DEFINEREG2(TRANS_HBLANK_A, i830_debug_hvsyncblank),
++    DEFINEREG2(TRANS_HSYNC_A, i830_debug_hvsyncblank),
++    DEFINEREG2(TRANS_VTOTAL_A, i830_debug_hvtotal),
++    DEFINEREG2(TRANS_VBLANK_A, i830_debug_hvsyncblank),
++    DEFINEREG2(TRANS_VSYNC_A, i830_debug_hvsyncblank),
++
++    DEFINEREG2(TRANSA_DATA_M1, ilk_debug_m_tu),
++    DEFINEREG2(TRANSA_DATA_N1, ilk_debug_n),
++    DEFINEREG2(TRANSA_DATA_M2, ilk_debug_m_tu),
++    DEFINEREG2(TRANSA_DATA_N2, ilk_debug_n),
++    DEFINEREG2(TRANSA_DP_LINK_M1, ilk_debug_n),
++    DEFINEREG2(TRANSA_DP_LINK_N1, ilk_debug_n),
++    DEFINEREG2(TRANSA_DP_LINK_M2, ilk_debug_n),
++    DEFINEREG2(TRANSA_DP_LINK_N2, ilk_debug_n),
++
++    DEFINEREG2(TRANS_HTOTAL_B, i830_debug_hvtotal),
++    DEFINEREG2(TRANS_HBLANK_B, i830_debug_hvsyncblank),
++    DEFINEREG2(TRANS_HSYNC_B, i830_debug_hvsyncblank),
++    DEFINEREG2(TRANS_VTOTAL_B, i830_debug_hvtotal),
++    DEFINEREG2(TRANS_VBLANK_B, i830_debug_hvsyncblank),
++    DEFINEREG2(TRANS_VSYNC_B, i830_debug_hvsyncblank),
++
++    DEFINEREG2(TRANSB_DATA_M1, ilk_debug_m_tu),
++    DEFINEREG2(TRANSB_DATA_N1, ilk_debug_n),
++    DEFINEREG2(TRANSB_DATA_M2, ilk_debug_m_tu),
++    DEFINEREG2(TRANSB_DATA_N2, ilk_debug_n),
++    DEFINEREG2(TRANSB_DP_LINK_M1, ilk_debug_n),
++    DEFINEREG2(TRANSB_DP_LINK_N1, ilk_debug_n),
++    DEFINEREG2(TRANSB_DP_LINK_M2, ilk_debug_n),
++    DEFINEREG2(TRANSB_DP_LINK_N2, ilk_debug_n),
++
++    DEFINEREG2(TRANSACONF, ilk_debug_transconf),
++    DEFINEREG2(TRANSBCONF, ilk_debug_transconf),
++
++    DEFINEREG2(FDI_TXA_CTL, ilk_debug_fdi_tx_ctl),
++    DEFINEREG2(FDI_TXB_CTL, ilk_debug_fdi_tx_ctl),
++    DEFINEREG2(FDI_RXA_CTL, ilk_debug_fdi_rx_ctl),
++    DEFINEREG2(FDI_RXB_CTL, ilk_debug_fdi_rx_ctl),
++
++    DEFINEREG2(FDI_RXA_MISC, ilk_debug_fdi_rx_misc),
++    DEFINEREG2(FDI_RXB_MISC, ilk_debug_fdi_rx_misc),
++    DEFINEREG(FDI_RXA_TUSIZE1),
++    DEFINEREG(FDI_RXA_TUSIZE2),
++    DEFINEREG(FDI_RXB_TUSIZE1),
++    DEFINEREG(FDI_RXB_TUSIZE2),
++
++    DEFINEREG(FDI_PLL_CTL_1),
++    DEFINEREG(FDI_PLL_CTL_2),
++
++    DEFINEREG2(PCH_ADPA, i830_debug_adpa),
++};
++#define NUM_ILK_SNAPSHOTREGS (sizeof(cpu_pch_snapshot) / sizeof(cpu_pch_snapshot[0]))
++
++#undef DEFINEREG
++
+ #ifndef REG_DUMPER
+ void i830TakeRegSnapshot(ScrnInfoPtr pScrn)
+ {
+     I830Ptr pI830 = I830PTR(pScrn);
+     int i;
+ 
+-    for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
+-	i830_snapshot[i].val = INREG(i830_snapshot[i].reg);
++    if (IS_IGDNG(pI830)) {
++	for (i = 0; i < NUM_ILK_SNAPSHOTREGS; i++) {
++	    cpu_pch_snapshot[i].val = INREG(cpu_pch_snapshot[i].reg);
++	}
++    } else {
++	for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
++	    i830_snapshot[i].val = INREG(i830_snapshot[i].reg);
++	}
+     }
++
+ }
+ 
+ void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn, char *where)
+@@ -765,6 +1288,41 @@ void i830CompareRegsToSnapshot(ScrnInfoP
+ 	}
+     }
+ }
++
++void IlkCompareRegsToSnapshot(ScrnInfoPtr pScrn, char *where)
++{
++    I830Ptr pI830 = I830PTR(pScrn);
++    int i;
++
++    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
++	       "Comparing regs from server start up to %s\n", where);
++    for (i = 0; i < NUM_ILK_SNAPSHOTREGS; i++) {
++	uint32_t val = INREG(cpu_pch_snapshot[i].reg);
++	if (cpu_pch_snapshot[i].val == val)
++	    continue;
++
++	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++		   "Register 0x%x (%s) changed from 0x%08x to 0x%08x\n",
++		   cpu_pch_snapshot[i].reg, cpu_pch_snapshot[i].name,
++		   (int)cpu_pch_snapshot[i].val, (int)val);
++
++	if (cpu_pch_snapshot[i].debug_output != NULL) {
++	    char *before, *after;
++
++	    before = cpu_pch_snapshot[i].debug_output(pI830,
++						   cpu_pch_snapshot[i].reg,
++						   cpu_pch_snapshot[i].val);
++	    after = cpu_pch_snapshot[i].debug_output(pI830,
++						  cpu_pch_snapshot[i].reg,
++						  val);
++	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++		       "%s before: %s\n", cpu_pch_snapshot[i].name, before);
++	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++		       "%s after: %s\n", cpu_pch_snapshot[i].name, after);
++
++	}
++    }
++}
+ #endif /* !REG_DUMPER */
+ 
+ #if 0
+@@ -810,6 +1368,31 @@ static void i830DumpAR(ScrnInfoPtr pScrn
+ }
+ #endif
+ 
++void IlkDumpRegs (ScrnInfoPtr pScrn)
++{
++    I830Ptr pI830 = I830PTR(pScrn);
++    int i;
++
++    xf86DrvMsg (pScrn->scrnIndex, X_INFO, "DumpRegsBegin\n");
++    for (i = 0; i < NUM_ILK_SNAPSHOTREGS; i++) {
++	uint32_t val = INREG(cpu_pch_snapshot[i].reg);
++
++	if (cpu_pch_snapshot[i].debug_output != NULL) {
++	    char *debug = cpu_pch_snapshot[i].debug_output(pI830,
++							cpu_pch_snapshot[i].reg,
++							val);
++	    if (debug != NULL) {
++		xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%08x (%s)\n",
++			    cpu_pch_snapshot[i].name, (unsigned int)val, debug);
++		xfree(debug);
++	    }
++	} else {
++	    xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%08x\n",
++			cpu_pch_snapshot[i].name, (unsigned int)val);
++	}
++    }
++}
++
+ void i830DumpRegs (ScrnInfoPtr pScrn)
+ {
+     I830Ptr pI830 = I830PTR(pScrn);
+--- src/i830_debug.h	2009-08-18 11:31:33.555544787 +0800
++++ src/i830_debug.h	2009-08-27 17:14:09.206663123 +0800
+@@ -31,4 +31,6 @@ void i830DumpRegs (ScrnInfoPtr pScrn);
+ void i830_dump_error_state(ScrnInfoPtr pScrn);
+ void i965_dump_error_state(ScrnInfoPtr pScrn);
+ Bool i830_check_error_state(ScrnInfoPtr pScrn);
++void IlkDumpRegs (ScrnInfoPtr pScrn);
++void IlkCompareRegsToSnapshot(ScrnInfoPtr pScrn, char *where);
+ 
+--- src/i830_display.h	2009-08-27 16:23:54.686604627 +0800
++++ src/i830_display.h	2009-08-27 16:30:40.024207470 +0800
+@@ -41,3 +41,8 @@ DisplayModePtr i830_crtc_mode_get(ScrnIn
+ void i830_output_prepare (xf86OutputPtr output);
+ void i830_output_commit (xf86OutputPtr output);
+ 
++/* Ilk */
++void cpu_crtc_init(ScrnInfoPtr pScrn, int pipe);
++void cpu_crtc_disable(xf86CrtcPtr crtc, Bool disable_pipe);
++void cpu_crtc_enable(xf86CrtcPtr crtc);
++void ilk_disable_vga_plane(xf86CrtcPtr crtc);
+--- src/i830_driver.c	2009-08-27 16:23:54.688885732 +0800
++++ src/i830_driver.c	2009-08-27 17:32:31.511401369 +0800
+@@ -965,6 +965,39 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
+ }
+ 
+ static void
++IntelMCPSetupOutputs(ScrnInfoPtr pScrn)
++{
++   xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR (pScrn);
++   int     o, c;
++   Bool            lvds_detected = FALSE;
++
++   /* IGDNG alpha: single analog output now */
++   pch_crt_init(pScrn);
++
++   for (o = 0; o < config->num_output; o++)
++   {
++      xf86OutputPtr       output = config->output[o];
++      I830OutputPrivatePtr intel_output = output->driver_private;
++      int                 crtc_mask;
++
++      if (intel_output->type == I830_OUTPUT_LVDS)
++         lvds_detected = TRUE;
++      
++      crtc_mask = 0;
++      for (c = 0; c < config->num_crtc; c++)
++      {
++        xf86CrtcPtr          crtc = config->crtc[c];
++        I830CrtcPrivatePtr   intel_crtc = crtc->driver_private;
++
++        if (intel_output->pipe_mask & (1 << intel_crtc->pipe))
++           crtc_mask |= (1 << c);
++      }
++      output->possible_crtcs = crtc_mask;
++      output->possible_clones = i830_output_clones (pScrn, intel_output->clone_mask);
++   }
++}
++
++static void
+ i830_init_clock_gating(ScrnInfoPtr pScrn)
+ {
+     I830Ptr pI830 = I830PTR(pScrn);
+@@ -1686,7 +1719,10 @@ I830AccelMethodInit(ScrnInfoPtr pScrn)
+     if (pI830->debug_modes) {
+ 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ 		   "Hardware state on X startup:\n");
+-	i830DumpRegs (pScrn);
++       if (IS_IGDNG(pI830))
++           IlkDumpRegs(pScrn);
++       else
++   	   i830DumpRegs (pScrn);
+     }
+ 
+     i830TakeRegSnapshot(pScrn);
+@@ -1703,9 +1739,15 @@ I830AccelMethodInit(ScrnInfoPtr pScrn)
+ 
+     I830PreInitDDC(pScrn);
+     for (i = 0; i < num_pipe; i++) {
+-	i830_crtc_init(pScrn, i);
++       if (IS_IGDNG(pI830))
++           cpu_crtc_init(pScrn, i);
++       else
++	   i830_crtc_init(pScrn, i);
+     }
+-    I830SetupOutputs(pScrn);
++    if (IS_IGDNG(pI830))
++       IntelMCPSetupOutputs(pScrn);
++    else
++       I830SetupOutputs(pScrn);
+ 
+     SaveHWState(pScrn);
+     pI830->can_resize = FALSE;
+@@ -1887,7 +1929,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
+       return FALSE;
+ 
+    pI830 = I830PTR(pScrn);
+-   pI830->SaveGeneration = -1;
++   pI830->SaveGeneration = serverGeneration; 
+    pI830->pEnt = pEnt;
+    pI830->use_drm_mode = drm_mode_setting;
+    pI830->kernel_exec_fencing = pI830->use_drm_mode;
+@@ -2100,7 +2142,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
+    }
+ 
+    if (!pI830->use_drm_mode) {
+-       i830CompareRegsToSnapshot(pScrn, "After PreInit");
++       if (IS_IGDNG(pI830))
++          IlkCompareRegsToSnapshot(pScrn, "After PreInit");
++       else
++          i830CompareRegsToSnapshot(pScrn, "After PreInit");
+ 
+        I830UnmapMMIO(pScrn);
+ 
+@@ -2245,15 +2290,21 @@ static void
+ i830_save_palette(I830Ptr pI830, enum pipe pipe)
+ {
+     int i;
++    uint32_t pal_reg;
+ 
+     if (!i830_pipe_enabled(pI830, pipe))
+ 	return;
+ 
++    if (IS_IGDNG(pI830))
++       pal_reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
++    else
++       pal_reg = (pipe == PIPE_A) ? PALETTE_A : PALETTE_B;
++
+     for(i= 0; i < 256; i++) {
+ 	if (pipe == PIPE_A)
+-	    pI830->savePaletteA[i] = INREG(PALETTE_A + (i << 2));
++	    pI830->savePaletteA[i] = INREG(pal_reg + (i << 2));
+ 	else
+-	    pI830->savePaletteB[i] = INREG(PALETTE_B + (i << 2));
++	    pI830->savePaletteB[i] = INREG(pal_reg + (i << 2));
+     }
+ }
+ 
+@@ -2261,20 +2312,26 @@ static void
+ i830_restore_palette(I830Ptr pI830, enum pipe pipe)
+ {
+     int i;
++    uint32_t pal_reg;
+ 
+     if (!i830_pipe_enabled(pI830, pipe))
+ 	return;
+ 
++    if (IS_IGDNG(pI830))
++       pal_reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
++    else
++       pal_reg = (pipe == PIPE_A) ? PALETTE_A : PALETTE_B;
++
+     for(i= 0; i < 256; i++) {
+ 	if (pipe == PIPE_A)
+-	    OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]);
++	    OUTREG(pal_reg + (i << 2), pI830->savePaletteA[i]);
+ 	else
+-	    OUTREG(PALETTE_B + (i << 2), pI830->savePaletteB[i]);
++	    OUTREG(pal_reg + (i << 2), pI830->savePaletteB[i]);
+     }
+ }
+ 
+ static Bool
+-SaveHWState(ScrnInfoPtr pScrn)
++i830_save_hw_state(ScrnInfoPtr pScrn)
+ {
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    I830Ptr pI830 = I830PTR(pScrn);
+@@ -2394,6 +2451,169 @@ SaveHWState(ScrnInfoPtr pScrn)
+    return TRUE;
+ }
+ 
++static Bool
++ilk_save_hw_state(ScrnInfoPtr pScrn)
++{
++   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
++   I830Ptr pI830 = I830PTR(pScrn);
++   vgaHWPtr hwp = VGAHWPTR(pScrn);
++   vgaRegPtr vgaReg = &hwp->SavedReg;
++   int i;
++
++   _debug("ilk save hw state");
++   /* XXX */
++   pI830->saveDSPACNTR = INREG(DSPACNTR);
++   pI830->savePIPEACONF = INREG(PIPEACONF);
++   pI830->savePIPEASRC = INREG(PIPEASRC);
++   pI830->saveHTOTAL_A = INREG(HTOTAL_A);
++   pI830->saveHBLANK_A = INREG(HBLANK_A);
++   pI830->saveHSYNC_A = INREG(HSYNC_A);
++   pI830->saveVTOTAL_A = INREG(VTOTAL_A);
++   pI830->saveVBLANK_A = INREG(VBLANK_A);
++   pI830->saveVSYNC_A = INREG(VSYNC_A);
++   pI830->saveBCLRPAT_A = INREG(BCLRPAT_A);
++   pI830->saveDSPASTRIDE = INREG(DSPASTRIDE);
++   pI830->saveDSPASIZE = INREG(DSPASIZE);
++   pI830->saveDSPAPOS = INREG(DSPAPOS);
++   pI830->saveDSPABASE = INREG(DSPABASE);
++   pI830->saveDSPATILEOFF = INREG(DSPATILEOFF);
++
++   i830_save_palette(pI830, PIPE_A);
++
++   /* FDI/PCH state */
++   pI830->saveFPA0 = INREG(PCH_FPA0);
++   pI830->saveFPA1 = INREG(PCH_FPA1);
++   pI830->saveDPLL_A = INREG(PCH_DPLL_A);
++   pI830->saveFDI_RXA_CTL = INREG(FDI_RXA_CTL);
++   pI830->saveFDI_TXA_CTL = INREG(FDI_TXA_CTL);
++   pI830->saveTRANSACONF = INREG(TRANSACONF);
++   pI830->savePIPEA_DATA_M1 = INREG(PIPEA_DATA_M1);
++   pI830->savePIPEA_DATA_N1 = INREG(PIPEA_DATA_N1);
++   pI830->savePIPEA_DATA_M2 = INREG(PIPEA_DATA_M2);
++   pI830->savePIPEA_DATA_N2 = INREG(PIPEA_DATA_N2);
++   pI830->savePIPEA_LINK_M1 = INREG(PIPEA_LINK_M1);
++   pI830->savePIPEA_LINK_N1 = INREG(PIPEA_LINK_N1);
++   pI830->savePIPEA_LINK_M2 = INREG(PIPEA_LINK_M2);
++   pI830->savePIPEA_LINK_N2 = INREG(PIPEA_LINK_N2);
++   pI830->saveTRANS_HTOTAL_A = INREG(TRANS_HTOTAL_A);
++   pI830->saveTRANS_HBLANK_A = INREG(TRANS_HBLANK_A);
++   pI830->saveTRANS_HSYNC_A = INREG(TRANS_HSYNC_A);
++   pI830->saveTRANS_VTOTAL_A = INREG(TRANS_VTOTAL_A);
++   pI830->saveTRANS_VBLANK_A = INREG(TRANS_VBLANK_A);
++   pI830->saveTRANS_VSYNC_A = INREG(TRANS_VSYNC_A);
++   pI830->saveTRANSA_DATA_M1 = INREG(TRANSA_DATA_M1);
++   pI830->saveTRANSA_DATA_N1 = INREG(TRANSA_DATA_N1);
++   pI830->saveTRANSA_DATA_M2 = INREG(TRANSA_DATA_M2);
++   pI830->saveTRANSA_DATA_N2 = INREG(TRANSA_DATA_N2);
++   /*
++   pI830->saveTRANSA_DP_LINK_M1 = INREG(TRANSA_DP_LINK_M1);
++   pI830->saveTRANSA_DP_LINK_N1 = INREG(TRANSA_DP_LINK_N1);
++   pI830->saveTRANSA_DP_LINK_M2 = INREG(TRANSA_DP_LINK_M2);
++   pI830->saveTRANSA_DP_LINK_N2 = INREG(TRANSA_DP_LINK_N2);
++   */
++
++   pI830->savePFA_CTL_1 = INREG(PFA_CTL_1);
++   pI830->saveFDI_RXA_TUSIZE1 = INREG(FDI_RXA_TUSIZE1);
++   pI830->saveFDI_RXA_TUSIZE2 = INREG(FDI_RXA_TUSIZE2);
++
++   if(xf86_config->num_crtc == 2) {
++      pI830->saveDSPBCNTR = INREG(DSPBCNTR);
++      pI830->savePIPEBCONF = INREG(PIPEBCONF);
++      pI830->savePIPEBSRC = INREG(PIPEBSRC);
++      pI830->saveHTOTAL_B = INREG(HTOTAL_B);
++      pI830->saveHBLANK_B = INREG(HBLANK_B);
++      pI830->saveHSYNC_B = INREG(HSYNC_B);
++      pI830->saveVTOTAL_B = INREG(VTOTAL_B);
++      pI830->saveVBLANK_B = INREG(VBLANK_B);
++      pI830->saveVSYNC_B = INREG(VSYNC_B);
++      pI830->saveBCLRPAT_B = INREG(BCLRPAT_B);
++      pI830->saveDSPBSTRIDE = INREG(DSPBSTRIDE);
++      pI830->saveDSPBSIZE = INREG(DSPBSIZE);
++      pI830->saveDSPBPOS = INREG(DSPBPOS);
++      pI830->saveDSPBBASE = INREG(DSPBBASE);
++      pI830->saveDSPBSURF = INREG(DSPBSURF);
++      pI830->saveDSPBTILEOFF = INREG(DSPBTILEOFF);
++
++      i830_save_palette(pI830, PIPE_B);
++
++      /* FDI/PCH state */
++      pI830->saveFPB0 = INREG(PCH_FPB0);
++      pI830->saveFPB1 = INREG(PCH_FPB1);
++      pI830->saveDPLL_B = INREG(PCH_DPLL_B);
++      pI830->saveFDI_RXB_CTL = INREG(FDI_RXB_CTL);
++      pI830->saveFDI_TXB_CTL = INREG(FDI_TXB_CTL);
++      pI830->saveTRANSBCONF = INREG(TRANSBCONF);
++      pI830->savePIPEB_DATA_M1 = INREG(PIPEB_DATA_M1);
++      pI830->savePIPEB_DATA_N1 = INREG(PIPEB_DATA_N1);
++      pI830->savePIPEB_DATA_M2 = INREG(PIPEB_DATA_M2);
++      pI830->savePIPEB_DATA_N2 = INREG(PIPEB_DATA_N2);
++      pI830->savePIPEB_LINK_M1 = INREG(PIPEB_LINK_M1);
++      pI830->savePIPEB_LINK_N1 = INREG(PIPEB_LINK_N1);
++      pI830->savePIPEB_LINK_M2 = INREG(PIPEB_LINK_M2);
++      pI830->savePIPEB_LINK_N2 = INREG(PIPEB_LINK_N2);
++      pI830->saveTRANS_HTOTAL_B = INREG(TRANS_HTOTAL_B);
++      pI830->saveTRANS_HBLANK_B = INREG(TRANS_HBLANK_B);
++      pI830->saveTRANS_HSYNC_B = INREG(TRANS_HSYNC_B);
++      pI830->saveTRANS_VTOTAL_B = INREG(TRANS_VTOTAL_B);
++      pI830->saveTRANS_VBLANK_B = INREG(TRANS_VBLANK_B);
++      pI830->saveTRANS_VSYNC_B = INREG(TRANS_VSYNC_B);
++      pI830->saveTRANSB_DATA_M1 = INREG(TRANSB_DATA_M1);
++      pI830->saveTRANSB_DATA_N1 = INREG(TRANSB_DATA_N1);
++      pI830->saveTRANSB_DATA_M2 = INREG(TRANSB_DATA_M2);
++      pI830->saveTRANSB_DATA_N2 = INREG(TRANSB_DATA_N2);
++      /*
++      pI830->saveTRANSB_DP_LINK_M1 = INREG(TRANSB_DP_LINK_M1);
++      pI830->saveTRANSB_DP_LINK_N1 = INREG(TRANSB_DP_LINK_N1);
++      pI830->saveTRANSB_DP_LINK_M2 = INREG(TRANSB_DP_LINK_M2);
++      pI830->saveTRANSB_DP_LINK_N2 = INREG(TRANSB_DP_LINK_N2);
++      */
++
++      pI830->savePFB_CTL_1 = INREG(PFB_CTL_1);
++      pI830->saveFDI_RXB_TUSIZE1 = INREG(FDI_RXB_TUSIZE1);
++      pI830->saveFDI_RXB_TUSIZE2 = INREG(FDI_RXB_TUSIZE2);
++
++   }
++
++   pI830->saveVGACNTRL = INREG(CPU_VGACNTRL);
++   pI830->savePCH_DREF_CONTROL = INREG(PCH_DREF_CONTROL);
++
++   pI830->saveCURSOR_A_CONTROL = INREG(CURSOR_A_CONTROL);
++   pI830->saveCURSOR_A_POSITION = INREG(CURSOR_A_POSITION);
++   pI830->saveCURSOR_A_BASE = INREG(CURSOR_A_BASE);
++   pI830->saveCURSOR_B_CONTROL = INREG(CURSOR_B_CONTROL);
++   pI830->saveCURSOR_B_POSITION = INREG(CURSOR_B_POSITION);
++   pI830->saveCURSOR_B_BASE = INREG(CURSOR_B_BASE);
++
++   for(i = 0; i < 7; i++) {
++     pI830->saveSWF[i] = INREG(SWF0 + (i << 2));
++     pI830->saveSWF[i+7] = INREG(SWF00 + (i << 2));
++   }
++   pI830->saveSWF[14] = INREG(SWF30);
++   pI830->saveSWF[15] = INREG(SWF31);
++   pI830->saveSWF[16] = INREG(SWF32);
++   for (i = 0; i < xf86_config->num_output; i++) {
++     xf86OutputPtr   output = xf86_config->output[i];
++      if (output->funcs->save)
++       (*output->funcs->save) (output);
++   }
++
++  vgaHWUnlock(hwp);
++  vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS);
++
++   return TRUE;
++}
++
++static Bool
++SaveHWState(ScrnInfoPtr pScrn)
++{
++   I830Ptr pI830 = I830PTR(pScrn);
++
++   if (IS_IGDNG(pI830))
++       return ilk_save_hw_state(pScrn);
++   else
++       return i830_save_hw_state(pScrn);
++}
++
+ /* Wait for the PLL to settle down after programming */
+ static void
+ i830_dpll_settle(void)
+@@ -2402,7 +2622,7 @@ i830_dpll_settle(void)
+ }
+ 
+ static Bool
+-RestoreHWState(ScrnInfoPtr pScrn)
++i830_restore_hw_state(ScrnInfoPtr pScrn)
+ {
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    I830Ptr pI830 = I830PTR(pScrn);
+@@ -2642,6 +2862,312 @@ RestoreHWState(ScrnInfoPtr pScrn)
+    vgaHWLock(hwp);
+ 
+    return TRUE;
++
++}
++
++static Bool
++ilk_restore_hw_state(ScrnInfoPtr pScrn)
++{
++   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
++   I830Ptr pI830 = I830PTR(pScrn);
++   vgaHWPtr hwp = VGAHWPTR(pScrn);
++   vgaRegPtr vgaReg = &hwp->SavedReg;
++   int i;
++
++   _debug("ilk restore hw state");
++
++#ifdef XF86DRI
++   I830DRISetVBlankInterrupt (pScrn, FALSE);
++#endif
++   /* Disable outputs */
++   _debug("disable outputs");
++   for (i = 0; i < xf86_config->num_output; i++) {
++      xf86OutputPtr   output = xf86_config->output[i];
++      output->funcs->dpms(output, DPMSModeOff);
++   }
++   i830WaitForVblank(pScrn);
++
++#if 0
++   /* Disable pipes */
++   _debug("disable pipes");
++   for (i = 0; i < xf86_config->num_crtc; i++) {
++      xf86CrtcPtr crtc = xf86_config->crtc[i];
++      cpu_crtc_disable(crtc, TRUE);
++   }
++   i830WaitForVblank(pScrn);
++#endif
++
++   _debug("restore state");
++   OUTREG(PCH_DREF_CONTROL, pI830->savePCH_DREF_CONTROL);
++   usleep(150);
++
++   /*
++   OUTREG(FDI_RXA_CTL, pI830->saveFDI_RXA_CTL);
++   usleep(150);
++   OUTREG(FDI_TXA_CTL, pI830->saveFDI_TXA_CTL);
++   usleep(150);
++   OUTREG(PFA_CTL_1, pI830->savePFA_CTL_1);
++   */
++
++   /* If the pipe A PLL is active, we can restore the pipe & plane config */
++   if (pI830->saveDPLL_A & DPLL_VCO_ENABLE)
++   {
++      OUTREG(PCH_FPA0, pI830->saveFPA0);
++      OUTREG(PCH_DPLL_A, pI830->saveDPLL_A & ~DPLL_VCO_ENABLE);
++      POSTING_READ(PCH_DPLL_A);
++      usleep(150);
++   }
++   OUTREG(PCH_FPA0, pI830->saveFPA0);
++   OUTREG(PCH_FPA1, pI830->saveFPA1);
++   OUTREG(PCH_DPLL_A, pI830->saveDPLL_A);
++   POSTING_READ(PCH_DPLL_A);
++   i830_dpll_settle();
++   OUTREG(PCH_DPLL_A, pI830->saveDPLL_A);
++   POSTING_READ(PCH_DPLL_A);
++   i830_dpll_settle();
++
++   /* Restore mode config */
++   OUTREG(HTOTAL_A, pI830->saveHTOTAL_A);
++   OUTREG(HBLANK_A, pI830->saveHBLANK_A);
++   OUTREG(HSYNC_A, pI830->saveHSYNC_A);
++   OUTREG(VTOTAL_A, pI830->saveVTOTAL_A);
++   OUTREG(VBLANK_A, pI830->saveVBLANK_A);
++   OUTREG(VSYNC_A, pI830->saveVSYNC_A);
++   OUTREG(BCLRPAT_A, pI830->saveBCLRPAT_A);
++
++   OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE);
++   OUTREG(DSPASIZE, pI830->saveDSPASIZE);
++   OUTREG(DSPAPOS, pI830->saveDSPAPOS);
++   OUTREG(PIPEASRC, pI830->savePIPEASRC);
++   OUTREG(DSPABASE, pI830->saveDSPABASE);
++   OUTREG(DSPASURF, pI830->saveDSPASURF);
++   OUTREG(DSPATILEOFF, pI830->saveDSPATILEOFF);
++
++   OUTREG(PIPEACONF, pI830->savePIPEACONF);
++   POSTING_READ(PIPEACONF);
++   i830WaitForVblank(pScrn);
++
++   /*
++    * Program Pipe A's plane
++    * The corresponding display plane may be disabled, and should only be
++    * enabled if pipe A is actually on (otherwise we have a bug in the initial
++    * state).
++    */
++   if ((pI830->saveDSPACNTR & DISPPLANE_SEL_PIPE_MASK) ==
++       DISPPLANE_SEL_PIPE_A) {
++       OUTREG(DSPACNTR, pI830->saveDSPACNTR);
++       OUTREG(DSPABASE, INREG(DSPABASE));
++       POSTING_READ(DSPABASE);
++       i830WaitForVblank(pScrn);
++   }
++   if ((pI830->saveDSPBCNTR & DISPPLANE_SEL_PIPE_MASK) ==
++       DISPPLANE_SEL_PIPE_A) {
++       OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
++       OUTREG(DSPBBASE, INREG(DSPBBASE));
++       POSTING_READ(DSPBBASE);
++       i830WaitForVblank(pScrn);
++   }
++
++   OUTREG(FDI_RXA_CTL, pI830->saveFDI_RXA_CTL);
++   usleep(150);
++   OUTREG(FDI_TXA_CTL, pI830->saveFDI_TXA_CTL);
++   usleep(150);
++
++   OUTREG(FDI_RXA_TUSIZE1, pI830->saveFDI_RXA_TUSIZE1);
++   OUTREG(FDI_RXA_TUSIZE2, pI830->saveFDI_RXA_TUSIZE2);
++
++   OUTREG(TRANS_HTOTAL_A, pI830->saveTRANS_HTOTAL_A);
++   OUTREG(TRANS_HBLANK_A, pI830->saveTRANS_HBLANK_A);
++   OUTREG(TRANS_HSYNC_A, pI830->saveTRANS_HSYNC_A);
++   OUTREG(TRANS_VTOTAL_A, pI830->saveTRANS_VTOTAL_A);
++   OUTREG(TRANS_VBLANK_A, pI830->saveTRANS_VBLANK_A);
++   OUTREG(TRANS_VSYNC_A, pI830->saveTRANS_VSYNC_A);
++
++   OUTREG(PIPEA_DATA_M1, pI830->savePIPEA_DATA_M1);
++   OUTREG(PIPEA_DATA_N1, pI830->savePIPEA_DATA_N1);
++   OUTREG(PIPEA_DATA_M2, pI830->savePIPEA_DATA_M2);
++   OUTREG(PIPEA_DATA_N2, pI830->savePIPEA_DATA_N2);
++   OUTREG(PIPEA_LINK_M1, pI830->savePIPEA_LINK_M1);
++   OUTREG(PIPEA_LINK_N1, pI830->savePIPEA_LINK_N1);
++   OUTREG(PIPEA_LINK_M2, pI830->savePIPEA_LINK_M2);
++   OUTREG(PIPEA_LINK_N2, pI830->savePIPEA_LINK_N2);
++   usleep(150);
++
++   OUTREG(TRANSA_DATA_M1, pI830->saveTRANSA_DATA_M1);
++   OUTREG(TRANSA_DATA_N1, pI830->saveTRANSA_DATA_N1);
++   OUTREG(TRANSA_DATA_M2, pI830->saveTRANSA_DATA_M2);
++   OUTREG(TRANSA_DATA_N2, pI830->saveTRANSA_DATA_N2);
++   /*
++   OUTREG(TRANSA_DP_LINK_M1, pI830->saveTRANSA_DP_LINK_M1);
++   OUTREG(TRANSA_DP_LINK_N1, pI830->saveTRANSA_DP_LINK_N1);
++   OUTREG(TRANSA_DP_LINK_M2, pI830->saveTRANSA_DP_LINK_M2);
++   OUTREG(TRANSA_DP_LINK_N2, pI830->saveTRANSA_DP_LINK_N2);
++   */
++
++   OUTREG(TRANSACONF, pI830->saveTRANSACONF);
++   POSTING_READ(TRANSACONF);
++
++   OUTREG(PFA_CTL_1, pI830->savePFA_CTL_1);
++
++   /* See note about pipe programming above */
++   if(xf86_config->num_crtc == 2)
++   {
++       /*
++       OUTREG(FDI_RXB_CTL, pI830->saveFDI_RXB_CTL);
++       usleep(150);
++       OUTREG(FDI_TXB_CTL, pI830->saveFDI_TXB_CTL);
++       usleep(150);
++       OUTREG(PFB_CTL_1, pI830->savePFB_CTL_1);
++       usleep(150);
++       */
++      /* If the pipe B PLL is active, we can restore the pipe & plane config */
++      if (pI830->saveDPLL_B & DPLL_VCO_ENABLE)
++      {
++	 OUTREG(PCH_FPB0, pI830->saveFPB0);
++	 OUTREG(PCH_DPLL_B, pI830->saveDPLL_B & ~DPLL_VCO_ENABLE);
++	 POSTING_READ(PCH_DPLL_B);
++	 usleep(150);
++      }
++      OUTREG(PCH_FPB0, pI830->saveFPB0);
++      OUTREG(PCH_FPB1, pI830->saveFPB1);
++      OUTREG(PCH_DPLL_B, pI830->saveDPLL_B);
++      POSTING_READ(PCH_DPLL_B);
++      i830_dpll_settle();
++      OUTREG(PCH_DPLL_B, pI830->saveDPLL_B);
++      POSTING_READ(PCH_DPLL_B);
++      i830_dpll_settle();
++
++      /* Restore mode config */
++      OUTREG(HTOTAL_B, pI830->saveHTOTAL_B);
++      OUTREG(HBLANK_B, pI830->saveHBLANK_B);
++      OUTREG(HSYNC_B, pI830->saveHSYNC_B);
++      OUTREG(VTOTAL_B, pI830->saveVTOTAL_B);
++      OUTREG(VBLANK_B, pI830->saveVBLANK_B);
++      OUTREG(VSYNC_B, pI830->saveVSYNC_B);
++      OUTREG(BCLRPAT_B, pI830->saveBCLRPAT_B);
++      OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE);
++      OUTREG(DSPBSIZE, pI830->saveDSPBSIZE);
++      OUTREG(DSPBPOS, pI830->saveDSPBPOS);
++      OUTREG(PIPEBSRC, pI830->savePIPEBSRC);
++      OUTREG(DSPBBASE, pI830->saveDSPBBASE);
++      OUTREG(DSPBSURF, pI830->saveDSPBSURF);
++      OUTREG(DSPBTILEOFF, pI830->saveDSPBTILEOFF);
++
++      OUTREG(PIPEBCONF, pI830->savePIPEBCONF);
++      POSTING_READ(PIPEBCONF);
++      i830WaitForVblank(pScrn);
++
++      /*
++       * Program Pipe B's plane
++       * Note that pipe B may be disabled, and in that case, the plane
++       * should also be disabled or we must have had a bad initial state.
++       */
++      if ((pI830->saveDSPACNTR & DISPPLANE_SEL_PIPE_MASK) ==
++	  DISPPLANE_SEL_PIPE_B) {
++	  OUTREG(DSPACNTR, pI830->saveDSPACNTR);
++	  OUTREG(DSPABASE, INREG(DSPABASE));
++	  i830WaitForVblank(pScrn);
++      }
++      if ((pI830->saveDSPBCNTR & DISPPLANE_SEL_PIPE_MASK) ==
++	  DISPPLANE_SEL_PIPE_B) {
++	  OUTREG(DSPBCNTR, pI830->saveDSPBCNTR);
++	  OUTREG(DSPBBASE, INREG(DSPBBASE));
++	  i830WaitForVblank(pScrn);
++      }
++
++      OUTREG(FDI_RXB_CTL, pI830->saveFDI_RXB_CTL);
++      usleep(150);
++      OUTREG(FDI_TXB_CTL, pI830->saveFDI_TXB_CTL);
++      usleep(150);
++
++      OUTREG(FDI_RXB_TUSIZE1, pI830->saveFDI_RXB_TUSIZE1);
++      OUTREG(FDI_RXB_TUSIZE2, pI830->saveFDI_RXB_TUSIZE2);
++
++      OUTREG(TRANS_HTOTAL_B, pI830->saveTRANS_HTOTAL_B);
++      OUTREG(TRANS_HBLANK_B, pI830->saveTRANS_HBLANK_B);
++      OUTREG(TRANS_HSYNC_B, pI830->saveTRANS_HSYNC_B);
++      OUTREG(TRANS_VTOTAL_B, pI830->saveTRANS_VTOTAL_B);
++      OUTREG(TRANS_VBLANK_B, pI830->saveTRANS_VBLANK_B);
++      OUTREG(TRANS_VSYNC_B, pI830->saveTRANS_VSYNC_B);
++
++      OUTREG(PIPEB_DATA_M1, pI830->savePIPEB_DATA_M1);
++      OUTREG(PIPEB_DATA_N1, pI830->savePIPEB_DATA_N1);
++      OUTREG(PIPEB_DATA_M2, pI830->savePIPEB_DATA_M2);
++      OUTREG(PIPEB_DATA_N2, pI830->savePIPEB_DATA_N2);
++      OUTREG(PIPEB_LINK_M1, pI830->savePIPEB_LINK_M1);
++      OUTREG(PIPEB_LINK_N1, pI830->savePIPEB_LINK_N1);
++      OUTREG(PIPEB_LINK_M2, pI830->savePIPEB_LINK_M2);
++      OUTREG(PIPEB_LINK_N2, pI830->savePIPEB_LINK_N2);
++      usleep(150);
++
++      OUTREG(TRANSB_DATA_M1, pI830->saveTRANSB_DATA_M1);
++      OUTREG(TRANSB_DATA_N1, pI830->saveTRANSB_DATA_N1);
++      OUTREG(TRANSB_DATA_M2, pI830->saveTRANSB_DATA_M2);
++      OUTREG(TRANSB_DATA_N2, pI830->saveTRANSB_DATA_N2);
++      /*
++      OUTREG(TRANSB_DP_LINK_M1, pI830->saveTRANSB_DP_LINK_M1);
++      OUTREG(TRANSB_DP_LINK_N1, pI830->saveTRANSB_DP_LINK_N1);
++      OUTREG(TRANSB_DP_LINK_M2, pI830->saveTRANSB_DP_LINK_M2);
++      OUTREG(TRANSB_DP_LINK_N2, pI830->saveTRANSB_DP_LINK_N2);
++      */
++
++      OUTREG(TRANSBCONF, pI830->saveTRANSBCONF);
++      POSTING_READ(TRANSBCONF);
++
++      OUTREG(PFB_CTL_1, pI830->savePFB_CTL_1);
++      usleep(150);
++   }
++
++   OUTREG(CPU_VGACNTRL, pI830->saveVGACNTRL);
++   /*
++    * Restore cursors
++    * Even though the X cursor is hidden before we restore the hw state,
++    * we probably only disabled one cursor plane.  If we're going from
++    * e.g. plane b to plane a here in RestoreHWState, we need to restore
++    * both cursor plane settings.
++    */
++   OUTREG(CURSOR_A_POSITION, pI830->saveCURSOR_A_POSITION);
++   OUTREG(CURSOR_A_BASE, pI830->saveCURSOR_A_BASE);
++   OUTREG(CURSOR_A_CONTROL, pI830->saveCURSOR_A_CONTROL);
++   OUTREG(CURSOR_B_POSITION, pI830->saveCURSOR_B_POSITION);
++   OUTREG(CURSOR_B_BASE, pI830->saveCURSOR_B_BASE);
++   OUTREG(CURSOR_B_CONTROL, pI830->saveCURSOR_B_CONTROL);
++
++   /* Restore outputs */
++   for (i = 0; i < xf86_config->num_output; i++) {
++      xf86OutputPtr   output = xf86_config->output[i];
++      if (output->funcs->restore)
++	 output->funcs->restore(output);
++   }
++
++   i830_restore_palette(pI830, PIPE_A);
++   i830_restore_palette(pI830, PIPE_B);
++
++   for(i = 0; i < 7; i++) {
++      OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]);
++      OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]);
++   }
++
++   OUTREG(SWF30, pI830->saveSWF[14]);
++   OUTREG(SWF31, pI830->saveSWF[15]);
++   OUTREG(SWF32, pI830->saveSWF[16]);
++
++   vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
++   vgaHWLock(hwp);
++
++   return TRUE;
++}
++
++static Bool
++RestoreHWState(ScrnInfoPtr pScrn)
++{
++   I830Ptr pI830 = I830PTR(pScrn);
++
++   if (IS_IGDNG(pI830))
++       return ilk_restore_hw_state(pScrn);
++   else
++       return i830_restore_hw_state(pScrn);
++
+ }
+ 
+ static void
+@@ -3059,7 +3585,7 @@ I830SwapPipes(ScrnInfoPtr pScrn)
+     *       alone in that case.
+     * Also make sure the DRM can handle the swap.
+     */
+-   if (I830LVDSPresent(pScrn) && !IS_I965GM(pI830) && !IS_GM45(pI830) &&
++   if (I830LVDSPresent(pScrn) && !IS_I965GM(pI830) && !IS_GM45(pI830) && !IS_IGDNG(pI830) && 
+        (pI830->directRenderingType != DRI_XF86DRI ||
+ 	(pI830->directRenderingType == DRI_XF86DRI && pI830->drmMinor >= 10))) {
+        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "adjusting plane->pipe mappings "
+@@ -3653,8 +4179,13 @@ I830LeaveVT(int scrnIndex, int flags)
+ 	   i830_stop_ring(pScrn, TRUE);
+ 
+        if (pI830->debug_modes) {
+-	   i830CompareRegsToSnapshot(pScrn, "After LeaveVT");
+-	   i830DumpRegs (pScrn);
++          if (IS_IGDNG(pI830)) {
++              IlkCompareRegsToSnapshot(pScrn, "After LeaveVT");
++              IlkDumpRegs (pScrn);
++          } else {
++	      i830CompareRegsToSnapshot(pScrn, "After LeaveVT");
++	      i830DumpRegs (pScrn);
++          }
+        }
+    }
+ 
+@@ -3691,6 +4222,8 @@ I830EnterVT(int scrnIndex, int flags)
+ {
+    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+    I830Ptr  pI830 = I830PTR(pScrn);
++   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
++   int i = 0;
+ 
+    DPRINTF(PFX, "Enter VT\n");
+ 
+@@ -3704,6 +4237,31 @@ I830EnterVT(int scrnIndex, int flags)
+ 	  SaveHWState(pScrn);
+    }
+ 
++//////////////////////// needed?
++   /* Get the hardware into a known state if needed */
++   if (!pI830->use_drm_mode) {
++       /* disable vga plane first */
++       if (IS_IGDNG(pI830))
++           ilk_disable_vga_plane (xf86_config->crtc[0]);
++
++       /* Disable outputs */
++       for (i = 0; i < xf86_config->num_output; i++) {
++           xf86OutputPtr   output = xf86_config->output[i];
++           output->funcs->dpms(output, DPMSModeOff);
++       }
++       i830WaitForVblank(pScrn);
++
++       /* Disable pipes */
++       for (i = 0; i < xf86_config->num_crtc; i++)
++       {
++           xf86CrtcPtr crtc = xf86_config->crtc[i];
++           cpu_crtc_disable(crtc, TRUE);
++       }
++       i830WaitForVblank(pScrn);
++   }
++
++///////////////////////
++
+    pI830->leaving = FALSE;
+ 
+    if (!pI830->use_drm_mode)
+@@ -3752,9 +4310,10 @@ I830EnterVT(int scrnIndex, int flags)
+ 	   I830InitHWCursor(pScrn);
+ 
+        /* Tell the BIOS that we're in control of mode setting now. */
+-       i830_init_bios_control(pScrn);
+-
+-       i830_init_clock_gating(pScrn);
++       if (!IS_IGDNG(pI830)) {
++           i830_init_bios_control(pScrn);
++           i830_init_clock_gating(pScrn);
++	}
+ 
+        if (pI830->power_context)
+ 	   OUTREG(PWRCTXA, pI830->power_context->offset | PWRCTX_EN);
+@@ -3769,7 +4328,10 @@ I830EnterVT(int scrnIndex, int flags)
+    if (!pI830->use_drm_mode) {
+        if (pI830->debug_modes) {
+ 	   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Hardware state at EnterVT:\n");
+-	   i830DumpRegs (pScrn);
++          if (IS_IGDNG(pI830))
++              IlkDumpRegs (pScrn);
++          else
++    	      i830DumpRegs (pScrn);
+        }
+        i830DescribeOutputConfiguration(pScrn);
+    }
+--- src/pch_crt.c	1970-01-01 08:00:00.000000000 +0800
++++ src/pch_crt.c	2009-08-27 16:34:50.091594434 +0800
+@@ -0,0 +1,332 @@
++/*
++ * Copyright ?? 2009 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Authors:
++ *    Zhenyu Wang <[email protected]>
++ *
++ */
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include <unistd.h>
++#include "xf86.h"
++#include "i830.h"
++#include "xf86Modes.h"
++#include "i830_display.h"
++
++static void
++pch_crt_dpms(xf86OutputPtr output, int mode)
++{
++    ScrnInfoPtr	    pScrn = output->scrn;
++    I830Ptr	    pI830 = I830PTR(pScrn);
++    uint32_t	    temp;
++
++
++    temp = INREG(PCH_ADPA);
++    temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
++    temp &= ~ADPA_DAC_ENABLE;
++
++    switch(mode) {
++    case DPMSModeOn:
++	_debug("crt dpms on");
++	temp |= ADPA_DAC_ENABLE;
++	break;
++    case DPMSModeStandby:
++	_debug("crt dpms standby");
++	temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
++	break;
++    case DPMSModeSuspend:
++	_debug("crt dpms suspend");
++	temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
++	break;
++    case DPMSModeOff:
++	_debug("crt dpms off");
++	temp = 0;
++	break;
++    }
++
++    _debug("crt dpms 0x%x", temp);
++    OUTREG(PCH_ADPA, temp);
++}
++
++static void
++pch_crt_save (xf86OutputPtr output)
++{
++    ScrnInfoPtr	pScrn = output->scrn;
++    I830Ptr	pI830 = I830PTR(pScrn);
++
++    _debug("crt save");
++    pI830->saveADPA = INREG(PCH_ADPA);
++}
++
++static void
++pch_crt_restore (xf86OutputPtr output)
++{
++    ScrnInfoPtr	pScrn = output->scrn;
++    I830Ptr	pI830 = I830PTR(pScrn);
++
++    _debug("crt restore");
++    OUTREG(PCH_ADPA, pI830->saveADPA);
++}
++
++static int
++pch_crt_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
++{
++    ScrnInfoPtr pScrn = output->scrn;
++    I830Ptr	pI830 = I830PTR(pScrn);
++    int		maxclock;
++
++    if (pMode->Flags & V_DBLSCAN)
++	return MODE_NO_DBLESCAN;
++
++    if (pMode->Clock < 25000)
++	return MODE_CLOCK_LOW;
++
++    if (!IS_I9XX(pI830))
++	maxclock = 350000;
++    else
++	maxclock = 400000;
++
++    if (pMode->Clock > maxclock)
++	return MODE_CLOCK_HIGH;
++
++    return MODE_OK;
++}
++
++static Bool
++pch_crt_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
++		    DisplayModePtr adjusted_mode)
++{
++    return TRUE;
++}
++
++static void
++pch_crt_mode_set(xf86OutputPtr output, DisplayModePtr mode,
++		  DisplayModePtr adjusted_mode)
++{
++    ScrnInfoPtr		    pScrn = output->scrn;
++    I830Ptr		    pI830 = I830PTR(pScrn);
++    xf86CrtcPtr		    crtc = output->crtc;
++    I830CrtcPrivatePtr	    i830_crtc = crtc->driver_private;
++    uint32_t		    adpa = 0;
++
++    /*
++    adpa = INREG(PCH_ADPA);
++    if (adjusted_mode->Flags & V_PHSYNC)
++	adpa |= ADPA_HSYNC_ACTIVE_HIGH;
++    if (adjusted_mode->Flags & V_PVSYNC)
++	adpa |= ADPA_VSYNC_ACTIVE_HIGH;
++	*/
++
++    /* This is trancoder_A/B actually, although keep to use
++       origin bit definition here */
++    if (i830_crtc->pipe == 0)
++	adpa |= ADPA_PIPE_A_SELECT;
++    else
++	adpa |= ADPA_PIPE_B_SELECT;
++
++    _debug("crt mode_set 0x%x", adpa);
++
++    OUTREG(PCH_ADPA, adpa);
++}
++
++/**
++ * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
++ *
++ * \return TRUE if CRT is connected.
++ * \return FALSE if CRT is disconnected.
++ */
++static Bool
++pch_crt_detect_hotplug(xf86OutputPtr output)
++{
++    ScrnInfoPtr	pScrn = output->scrn;
++    I830Ptr	pI830 = I830PTR(pScrn);
++    uint32_t	adpa, temp;
++    Bool	ret;
++
++    /* PCH CRT hotplug is within PCH_ADPA itself */
++
++    temp = adpa = INREG(PCH_ADPA);
++
++    adpa &= ~ADPA_CRT_HOTPLUG_MASK;
++
++    adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 |
++	    ADPA_CRT_HOTPLUG_WARMUP_10MS |
++	    ADPA_CRT_HOTPLUG_SAMPLE_4S |
++	    ADPA_CRT_HOTPLUG_VOLTAGE_50 | /* default */
++	    ADPA_CRT_HOTPLUG_VOLREF_325MV |
++	    ADPA_CRT_HOTPLUG_ENABLE);
++
++    _debug("pch crt adpa 0x%x", adpa);
++    OUTREG(PCH_ADPA, adpa);
++
++    /* This might not be needed as not specified in spec...*/
++    usleep(1000);
++
++    /* Check the status to see if both blue and green are on now */
++    adpa = INREG(PCH_ADPA);
++    if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) ==
++	    ADPA_CRT_HOTPLUG_MONITOR_COLOR)
++	ret = TRUE;
++    else
++	ret = FALSE;
++
++    /* restore origin register */
++    OUTREG(PCH_ADPA, temp);
++    return ret;
++}
++
++/**
++ * Attempts to detect CRT presence through any method available.
++ *
++ * @param allow_disturb enables detection methods that may cause flickering
++ *        on active displays.
++ */
++static xf86OutputStatus
++pch_crt_detect(xf86OutputPtr output)
++{
++    xf86OutputStatus	    status;
++
++    if (pch_crt_detect_hotplug(output)) {
++	_debug("VGA detect connected!");
++	status = XF86OutputStatusConnected;
++    } else {
++	_debug("VGA detect connected!");
++	status = XF86OutputStatusDisconnected;
++    }
++
++    return status;
++}
++
++static void
++pch_crt_destroy (xf86OutputPtr output)
++{
++    if (output->driver_private)
++	xfree (output->driver_private);
++}
++
++#ifdef RANDR_GET_CRTC_INTERFACE
++static xf86CrtcPtr
++pch_crt_get_crtc(xf86OutputPtr output)
++{
++    ScrnInfoPtr	pScrn = output->scrn;
++    I830Ptr pI830 = I830PTR(pScrn);
++    /* Transcoder actually */
++    int pipe = !!(INREG(PCH_ADPA) & ADPA_PIPE_SELECT_MASK);
++
++    return i830_pipe_to_crtc(pScrn, pipe);
++}
++#endif
++
++static xf86MonPtr
++pch_get_edid(xf86OutputPtr output, int gpio_reg, char *gpio_str)
++{
++    I830OutputPrivatePtr    intel_output = output->driver_private;
++    xf86MonPtr		    edid_mon = NULL;
++
++    /* Set up the DDC bus. */
++    I830I2CInit(output->scrn, &intel_output->pDDCBus, gpio_reg, gpio_str);
++
++    edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
++
++    if (!edid_mon || DIGITAL(edid_mon->features.input_type)) {
++	xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE);
++	intel_output->pDDCBus = NULL;
++	if (edid_mon) {
++	    xfree(edid_mon);
++	    edid_mon = NULL;
++	}
++    }
++
++    return edid_mon;
++}
++
++static DisplayModePtr
++pch_crt_get_modes (xf86OutputPtr output)
++{
++    DisplayModePtr	    modes;
++    xf86MonPtr		    edid_mon = NULL;
++    I830OutputPrivatePtr    intel_output = output->driver_private;
++
++    _debug("crt get_modes");
++
++    if ((edid_mon = pch_get_edid(output, PCH_GPIOA, "CRTDDC_A")))
++	goto found;
++found:
++    /* Destroy DDC bus after probe, so every other new probe will
++       scan all ports again */
++    if (intel_output->pDDCBus)
++	xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE);
++
++    xf86OutputSetEDID (output, edid_mon);
++
++    modes = xf86OutputGetEDIDModes (output);
++    return modes;
++}
++
++static const xf86OutputFuncsRec pch_crt_output_funcs = {
++    .dpms = pch_crt_dpms,
++    .save = pch_crt_save,
++    .restore = pch_crt_restore,
++    .mode_valid = pch_crt_mode_valid,
++    .mode_fixup = pch_crt_mode_fixup,
++    .prepare = i830_output_prepare,
++    .mode_set = pch_crt_mode_set,
++    .commit = i830_output_commit,
++    .detect = pch_crt_detect,
++    .get_modes = pch_crt_get_modes,
++    .destroy = pch_crt_destroy,
++#ifdef RANDR_GET_CRTC_INTERFACE
++    .get_crtc = pch_crt_get_crtc,
++#endif
++};
++
++void
++pch_crt_init(ScrnInfoPtr pScrn)
++{
++    xf86OutputPtr	    output;
++    I830OutputPrivatePtr    i830_output;
++    I830Ptr		    pI830 = I830PTR(pScrn);
++
++    if (pI830->quirk_flag & QUIRK_IGNORE_CRT)
++	return;
++
++    output = xf86OutputCreate (pScrn, &pch_crt_output_funcs, "VGA");
++    if (!output)
++	return;
++    i830_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
++    if (!i830_output)
++    {
++	xf86OutputDestroy (output);
++	return;
++    }
++    i830_output->type = I830_OUTPUT_ANALOG;
++    i830_output->pipe_mask = ((1 << 0) | (1 << 1));
++    i830_output->clone_mask = ((1 << I830_OUTPUT_ANALOG) |
++			       (1 << I830_OUTPUT_DVO_TMDS));
++
++    output->driver_private = i830_output;
++    output->interlaceAllowed = FALSE;
++    output->doubleScanAllowed = FALSE;
++}
+--- src/reg_dumper/gtt.c	2009-08-18 11:31:33.529207970 +0800
++++ src/reg_dumper/gtt.c	2009-08-27 17:12:09.345781654 +0800
+@@ -52,7 +52,7 @@ int main(int argc, char **argv)
+ 		exit(1);
+ 	}
+ 
+-	if (IS_G4X(pI830))
++	if (IS_G4X(pI830) || IS_IGDNG(pI830))
+ 		gtt = (unsigned char *)(pI830->mmio + MB(2));
+ 	else if (IS_I965G(pI830))
+ 		gtt = (unsigned char *)(pI830->mmio + KB(512));
+--- src/reg_dumper/reg_dumper.h	2009-08-18 11:31:33.533849863 +0800
++++ src/reg_dumper/reg_dumper.h	2009-08-27 17:13:32.560903804 +0800
+@@ -90,3 +90,4 @@ char *XNFprintf(const char *format, ...)
+ void xf86DrvMsg(int scrnIndex, int severity, const char *format, ...);
+ void i830DumpRegs(ScrnInfoPtr pScrn);
+ void intel_i830rec_init(I830Ptr pI830);
++void IlkDumpRegs(ScrnInfoPtr pScrn);
+
+--- src/cpu_display.c	2009-08-28 13:21:29.203502631 +0800
++++ src/cpu_display.c	2009-08-28 15:23:56.125153078 +0800
+@@ -788,7 +788,7 @@ ilk_crtc_commit (xf86CrtcPtr crtc)
+ 
+ #ifdef XF86DRI
+     /* Tell DRI1 the news about new output config */
+-    i830_update_dri_buffers(crtc->scrn);
++    //i830_update_dri_buffers(crtc->scrn);
+ #endif
+ }
+ 
+--- src/i830_display.c	2009-08-27 16:23:54.686338474 +0800
++++ src/i830_display.c	2009-08-28 15:31:04.866331719 +0800
+@@ -100,6 +100,8 @@ typedef struct {
+ #define I9XX_DOT_MAX		 400000
+ #define I9XX_VCO_MIN		1400000
+ #define I9XX_VCO_MAX		2800000
++#define IGD_VCO_MIN            1700000
++#define IGD_VCO_MAX            3500000
+ 
+ /* Haven't found any reason to go this fast, but newer chips support it */
+ #define I96X_VCO_MAX		3200000
+@@ -111,19 +113,31 @@ typedef struct {
+  */
+ #define I9XX_N_MIN		      1
+ #define I9XX_N_MAX		      6
+-#define I9XX_M_MIN		     70
+-#define I9XX_M_MAX		    120
++/* IGD's Ncounter is a ring counter */
++#define IGD_N_MIN                    3
++#define IGD_N_MAX                    6
++#define I9XX_M_MIN                  70
++#define I9XX_M_MAX                 120
++#define IGD_M_MIN                    2
++#define IGD_M_MAX                  256
+ 
+ /* these two come from the calm1 macro */
+ #define I9XX_M1_MIN		     10
+ #define I9XX_M1_MAX		     22
+ #define I9XX_M2_MIN		      5
+ #define I9XX_M2_MAX		      9
++/* IGD M1 is reserved, and must be 0 */
++#define IGD_M1_MIN                   0
++#define IGD_M1_MAX                   0
++#define IGD_M2_MIN                   0
++#define IGD_M2_MAX                   254
+ 
+ #define I9XX_P_SDVO_DAC_MIN	      5
+ #define I9XX_P_SDVO_DAC_MAX	     80
+ #define I9XX_P_LVDS_MIN		      7
+ #define I9XX_P_LVDS_MAX		     98
++#define IGD_P_LVDS_MIN               7
++#define IGD_P_LVDS_MAX              112
+ #define I9XX_P1_MIN		      1
+ #define I9XX_P1_MAX		      8
+ #define I9XX_P2_SDVO_DAC_SLOW		     10
+@@ -137,6 +151,92 @@ typedef struct {
+ #define INTEL_LIMIT_I8XX_LVDS	    1
+ #define INTEL_LIMIT_I9XX_SDVO_DAC   2
+ #define INTEL_LIMIT_I9XX_LVDS	    3
++#define INTEL_LIMIT_IGD_SDVO_DAC    4
++#define INTEL_LIMIT_IGD_LVDS       5
++#define INTEL_LIMIT_G4X_SDVO	    6
++#define INTEL_LIMIT_G4X_HDMI_DAC    7
++#define INTEL_LIMIT_G4X_SINGLE_LVDS 8
++#define INTEL_LIMIT_G4X_DUAL_LVDS   9
++#define INTEL_LIMIT_ILK_SDVO_DAC   10
++#define INTEL_LIMIT_ILK_LVDS       11
++
++/*The parameter is for SDVO on G4x platform*/
++#define G4X_VCO_MIN                1750000
++#define G4X_VCO_MAX                3500000
++#define G4X_DOT_SDVO_MIN           25000
++#define G4X_DOT_SDVO_MAX           270000
++#define G4X_N_SDVO_MIN             1
++#define G4X_N_SDVO_MAX             4
++#define G4X_M_SDVO_MIN             104
++#define G4X_M_SDVO_MAX             138
++#define G4X_M1_SDVO_MIN            17
++#define G4X_M1_SDVO_MAX            23
++#define G4X_M2_SDVO_MIN            5
++#define G4X_M2_SDVO_MAX            11
++#define G4X_P_SDVO_MIN             10
++#define G4X_P_SDVO_MAX             30
++#define G4X_P1_SDVO_MIN            1
++#define G4X_P1_SDVO_MAX            3
++#define G4X_P2_SDVO_SLOW           10
++#define G4X_P2_SDVO_FAST           10
++#define G4X_P2_SDVO_LIMIT          270000
++
++/*The parameter is for HDMI_DAC on G4x platform*/
++#define G4X_DOT_HDMI_DAC_MIN           22000
++#define G4X_DOT_HDMI_DAC_MAX           400000
++#define G4X_N_HDMI_DAC_MIN             1
++#define G4X_N_HDMI_DAC_MAX             4
++#define G4X_M_HDMI_DAC_MIN             104
++#define G4X_M_HDMI_DAC_MAX             138
++#define G4X_M1_HDMI_DAC_MIN            16
++#define G4X_M1_HDMI_DAC_MAX            23
++#define G4X_M2_HDMI_DAC_MIN            5
++#define G4X_M2_HDMI_DAC_MAX            11
++#define G4X_P_HDMI_DAC_MIN             5
++#define G4X_P_HDMI_DAC_MAX             80
++#define G4X_P1_HDMI_DAC_MIN            1
++#define G4X_P1_HDMI_DAC_MAX            8
++#define G4X_P2_HDMI_DAC_SLOW           10
++#define G4X_P2_HDMI_DAC_FAST           5
++#define G4X_P2_HDMI_DAC_LIMIT          165000
++
++/*The parameter is for SINGLE_LVDS on G4x platform*/
++#define G4X_DOT_SINGLE_LVDS_MIN           20000
++#define G4X_DOT_SINGLE_LVDS_MAX           115000
++#define G4X_N_SINGLE_LVDS_MIN             1
++#define G4X_N_SINGLE_LVDS_MAX             3
++#define G4X_M_SINGLE_LVDS_MIN             104
++#define G4X_M_SINGLE_LVDS_MAX             138
++#define G4X_M1_SINGLE_LVDS_MIN            17
++#define G4X_M1_SINGLE_LVDS_MAX            23
++#define G4X_M2_SINGLE_LVDS_MIN            5
++#define G4X_M2_SINGLE_LVDS_MAX            11
++#define G4X_P_SINGLE_LVDS_MIN             28
++#define G4X_P_SINGLE_LVDS_MAX             112
++#define G4X_P1_SINGLE_LVDS_MIN            2
++#define G4X_P1_SINGLE_LVDS_MAX            8
++#define G4X_P2_SINGLE_LVDS_SLOW           14
++#define G4X_P2_SINGLE_LVDS_FAST           14
++#define G4X_P2_SINGLE_LVDS_LIMIT          0
++
++/*The parameter is for DUAL_LVDS on G4x platform*/
++#define G4X_DOT_DUAL_LVDS_MIN           80000
++#define G4X_DOT_DUAL_LVDS_MAX           224000
++#define G4X_N_DUAL_LVDS_MIN             1
++#define G4X_N_DUAL_LVDS_MAX             3
++#define G4X_M_DUAL_LVDS_MIN             104
++#define G4X_M_DUAL_LVDS_MAX             138
++#define G4X_M1_DUAL_LVDS_MIN            17
++#define G4X_M1_DUAL_LVDS_MAX            23
++#define G4X_M2_DUAL_LVDS_MIN            5
++#define G4X_M2_DUAL_LVDS_MAX            11
++#define G4X_P_DUAL_LVDS_MIN             14
++#define G4X_P_DUAL_LVDS_MAX             42
++#define G4X_P1_DUAL_LVDS_MIN            2
++#define G4X_P1_DUAL_LVDS_MAX            6
++#define G4X_P2_DUAL_LVDS_SLOW           7
++#define G4X_P2_DUAL_LVDS_FAST           7
++#define G4X_P2_DUAL_LVDS_LIMIT          0
+ 
+ static const intel_limit_t intel_limits[] = {
+     { /* INTEL_LIMIT_I8XX_DVO_DAC */
+@@ -190,24 +290,156 @@ static const intel_limit_t intel_limits[
+ 	.p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
+ 		 .p2_slow = I9XX_P2_LVDS_SLOW,	.p2_fast = I9XX_P2_LVDS_FAST },
+     },
++    { /* INTEL_LIMIT_IGD_SDVO */
++        .dot = { .min = I9XX_DOT_MIN,          .max = I9XX_DOT_MAX},
++        .vco = { .min = IGD_VCO_MIN,           .max = IGD_VCO_MAX },
++        .n   = { .min = IGD_N_MIN,             .max = IGD_N_MAX },
++        .m   = { .min = IGD_M_MIN,             .max = IGD_M_MAX },
++        .m1  = { .min = IGD_M1_MIN,            .max = IGD_M1_MAX },
++        .m2  = { .min = IGD_M2_MIN,            .max = IGD_M2_MAX },
++        .p   = { .min = I9XX_P_SDVO_DAC_MIN,    .max = I9XX_P_SDVO_DAC_MAX },
++        .p1  = { .min = I9XX_P1_MIN,           .max = I9XX_P1_MAX },
++       .p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
++                .p2_slow = I9XX_P2_SDVO_DAC_SLOW,      .p2_fast = I9XX_P2_SDVO_DAC_FAST },
++    },
++    { /* INTEL_LIMIT_IGD_LVDS */
++        .dot = { .min = I9XX_DOT_MIN,          .max = I9XX_DOT_MAX },
++        .vco = { .min = IGD_VCO_MIN,           .max = IGD_VCO_MAX },
++        .n   = { .min = IGD_N_MIN,             .max = IGD_N_MAX },
++        .m   = { .min = IGD_M_MIN,             .max = IGD_M_MAX },
++        .m1  = { .min = IGD_M1_MIN,            .max = IGD_M1_MAX },
++        .m2  = { .min = IGD_M2_MIN,            .max = IGD_M2_MAX },
++        .p   = { .min = IGD_P_LVDS_MIN,        .max = IGD_P_LVDS_MAX },
++        .p1  = { .min = I9XX_P1_MIN,           .max = I9XX_P1_MAX },
++       /* IGD only supports single-channel mode. */
++       .p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
++                .p2_slow = I9XX_P2_LVDS_SLOW,  .p2_fast = I9XX_P2_LVDS_SLOW },
++    },
++    /* below parameter and function is for G4X Chipset Family*/
++    {   /* INTEL_LIMIT_G4X_SDVO */
++        .dot = { .min = G4X_DOT_SDVO_MIN,       .max = G4X_DOT_SDVO_MAX },
++        .vco = { .min = G4X_VCO_MIN,            .max = G4X_VCO_MAX},
++        .n   = { .min = G4X_N_SDVO_MIN,         .max = G4X_N_SDVO_MAX },
++        .m   = { .min = G4X_M_SDVO_MIN,         .max = G4X_M_SDVO_MAX },
++        .m1  = { .min = G4X_M1_SDVO_MIN,        .max = G4X_M1_SDVO_MAX },
++        .m2  = { .min = G4X_M2_SDVO_MIN,        .max = G4X_M2_SDVO_MAX },
++        .p   = { .min = G4X_P_SDVO_MIN,         .max = G4X_P_SDVO_MAX },
++        .p1  = { .min = G4X_P1_SDVO_MIN,        .max = G4X_P1_SDVO_MAX},
++        .p2  = { .dot_limit = G4X_P2_SDVO_LIMIT,
++                 .p2_slow = G4X_P2_SDVO_SLOW,
++                 .p2_fast = G4X_P2_SDVO_FAST },
++    },
++    {   /* INTEL_LIMIT_G4X_HDMI_DAC */
++        .dot = { .min = G4X_DOT_HDMI_DAC_MIN,	.max = G4X_DOT_HDMI_DAC_MAX },
++        .vco = { .min = G4X_VCO_MIN,	        .max = G4X_VCO_MAX},
++        .n   = { .min = G4X_N_HDMI_DAC_MIN,	.max = G4X_N_HDMI_DAC_MAX },
++        .m   = { .min = G4X_M_HDMI_DAC_MIN,	.max = G4X_M_HDMI_DAC_MAX },
++        .m1  = { .min = G4X_M1_HDMI_DAC_MIN,	.max = G4X_M1_HDMI_DAC_MAX },
++        .m2  = { .min = G4X_M2_HDMI_DAC_MIN,	.max = G4X_M2_HDMI_DAC_MAX },
++        .p   = { .min = G4X_P_HDMI_DAC_MIN,	.max = G4X_P_HDMI_DAC_MAX },
++        .p1  = { .min = G4X_P1_HDMI_DAC_MIN,	.max = G4X_P1_HDMI_DAC_MAX},
++        .p2  = { .dot_limit = G4X_P2_HDMI_DAC_LIMIT,
++                 .p2_slow = G4X_P2_HDMI_DAC_SLOW,
++                 .p2_fast = G4X_P2_HDMI_DAC_FAST },
++    },
++    {   /* INTEL_LIMIT_G4X_SINGLE_LVDS */
++        .dot = { .min = G4X_DOT_SINGLE_LVDS_MIN,
++                 .max = G4X_DOT_SINGLE_LVDS_MAX },
++        .vco = { .min = G4X_VCO_MIN,
++                 .max = G4X_VCO_MAX },
++        .n   = { .min = G4X_N_SINGLE_LVDS_MIN,
++                 .max = G4X_N_SINGLE_LVDS_MAX },
++        .m   = { .min = G4X_M_SINGLE_LVDS_MIN,
++                 .max = G4X_M_SINGLE_LVDS_MAX },
++        .m1  = { .min = G4X_M1_SINGLE_LVDS_MIN,
++                 .max = G4X_M1_SINGLE_LVDS_MAX },
++        .m2  = { .min = G4X_M2_SINGLE_LVDS_MIN,
++                 .max = G4X_M2_SINGLE_LVDS_MAX },
++        .p   = { .min = G4X_P_SINGLE_LVDS_MIN,
++                 .max = G4X_P_SINGLE_LVDS_MAX },
++        .p1  = { .min = G4X_P1_SINGLE_LVDS_MIN,
++                 .max = G4X_P1_SINGLE_LVDS_MAX },
++        .p2  = { .dot_limit = G4X_P2_SINGLE_LVDS_LIMIT,
++                 .p2_slow = G4X_P2_SINGLE_LVDS_SLOW,
++                 .p2_fast = G4X_P2_SINGLE_LVDS_FAST },
++    },
++    {   /* INTEL_LIMIT_G4X_DUAL_LVDS */
++        .dot = { .min = G4X_DOT_DUAL_LVDS_MIN,
++                 .max = G4X_DOT_DUAL_LVDS_MAX },
++        .vco = { .min = G4X_VCO_MIN,
++                 .max = G4X_VCO_MAX},
++        .n   = { .min = G4X_N_DUAL_LVDS_MIN,
++                 .max = G4X_N_DUAL_LVDS_MAX },
++        .m   = { .min = G4X_M_DUAL_LVDS_MIN,
++                 .max = G4X_M_DUAL_LVDS_MAX },
++        .m1  = { .min = G4X_M1_DUAL_LVDS_MIN,
++                 .max = G4X_M1_DUAL_LVDS_MAX },
++        .m2  = { .min = G4X_M2_DUAL_LVDS_MIN,
++                 .max = G4X_M2_DUAL_LVDS_MAX },
++        .p   = { .min = G4X_P_DUAL_LVDS_MIN,
++                 .max = G4X_P_DUAL_LVDS_MAX },
++        .p1  = { .min = G4X_P1_DUAL_LVDS_MIN,
++                 .max = G4X_P1_DUAL_LVDS_MAX},
++        .p2  = { .dot_limit = G4X_P2_DUAL_LVDS_LIMIT,
++                 .p2_slow = G4X_P2_DUAL_LVDS_SLOW,
++                 .p2_fast = G4X_P2_DUAL_LVDS_FAST },
++    },
+ };
+ 
+-static const intel_limit_t *intel_limit (xf86CrtcPtr crtc)
++static const intel_limit_t *intel_limit_ilk (xf86CrtcPtr crtc)
++{
++    const intel_limit_t *limit;
++
++    if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
++       limit = &intel_limits[INTEL_LIMIT_ILK_LVDS];
++    else
++        limit = &intel_limits[INTEL_LIMIT_ILK_SDVO_DAC];
++
++    return limit;
++}
++
++static const intel_limit_t *intel_limit_g4x (xf86CrtcPtr crtc)
+ {
+     ScrnInfoPtr	pScrn = crtc->scrn;
+     I830Ptr	pI830 = I830PTR(pScrn);
+     const intel_limit_t *limit;
+ 
+-    if (IS_I9XX(pI830)) {
+-	if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
+-	    limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS];
+-	else
+-	    limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
++    if (i830PipeHasType (crtc, I830_OUTPUT_LVDS)) {
++        if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) {
++            /* LVDS with dual channel */
++            limit = &intel_limits[INTEL_LIMIT_G4X_DUAL_LVDS];
++        } else /* LVDS with single channel */
++            limit = &intel_limits[INTEL_LIMIT_G4X_SINGLE_LVDS];
++    } else if (i830PipeHasType (crtc, I830_OUTPUT_HDMI) ||
++               i830PipeHasType (crtc, I830_OUTPUT_ANALOG)) {
++        limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC];
++    } else if (i830PipeHasType (crtc, I830_OUTPUT_SDVO)) {
++        limit = &intel_limits[INTEL_LIMIT_G4X_SDVO];
++    } else /* The option is for other outputs */
++        limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
++    return limit;
++}
++
++static const intel_limit_t *intel_limit (xf86CrtcPtr crtc)
++{
++    ScrnInfoPtr        pScrn = crtc->scrn;
++    I830Ptr    pI830 = I830PTR(pScrn);
++    const intel_limit_t *limit;
++
++    if (IS_IGDNG(pI830))
++       limit = intel_limit_ilk(crtc);
++    else if (IS_G4X(pI830)) 
++         limit = intel_limit_g4x(crtc);
++    else if (IS_I9XX(pI830)) {
++       if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
++           limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS];
++       else
++           limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
+     } else {
+-	if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
+-	    limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS];
+-	else
+-	    limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC];
++       if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
++           limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS];
++       else
++           limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC];
+     }
+ 
+     return limit;
+@@ -486,6 +718,8 @@ Bool
+ i830_pipe_a_require_activate (ScrnInfoPtr scrn)
+ {
+     xf86CrtcPtr	crtc = i830_crtc_for_pipe (scrn, 0);
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830Ptr pI830 = I830PTR(pScrn);
+     /* VESA 640x480x72Hz mode to set on the pipe */
+     static DisplayModeRec   mode = {
+ 	NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
+@@ -503,6 +737,8 @@ i830_pipe_a_require_activate (ScrnInfoPt
+ 	return FALSE;
+     if (crtc->enabled)
+ 	return FALSE;
++    if (IS_IGDNG(pI830))
++       return FALSE;
+     xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+     crtc->funcs->mode_set (crtc, &mode, &mode, 0, 0);
+     crtc->funcs->dpms (crtc, DPMSModeOn);
+@@ -791,9 +1027,16 @@ i830_disable_vga_plane (xf86CrtcPtr crtc
+ {
+     ScrnInfoPtr pScrn = crtc->scrn;
+     I830Ptr pI830 = I830PTR(pScrn);
+-    uint32_t vgacntrl = INREG(VGACNTRL);
++    uint32_t vgacntrl, reg;
+     uint8_t sr01;
+ 
++    if (IS_IGDNG(pI830))
++       reg = CPU_VGACNTRL;
++    else
++       reg = VGACNTRL;
++
++    vgacntrl = INREG(reg);
++
+     if (vgacntrl & VGA_DISP_DISABLE)
+ 	return;
+ 
+@@ -805,6 +1048,9 @@ i830_disable_vga_plane (xf86CrtcPtr crtc
+     sr01 = INREG8(SRX + 1);
+     OUTREG8(SRX + 1, sr01 | (1 << 5));
+     usleep(30);
++    /* disable center mode on 965GM and G4X platform */
++    if (IS_I965GM(pI830) || IS_G4X(pI830) || IS_IGDNG(pI830))
++        vgacntrl &= ~(3 << 24);
+ 
+     vgacntrl |= VGA_DISP_DISABLE;
+ 
+@@ -813,14 +1059,8 @@ i830_disable_vga_plane (xf86CrtcPtr crtc
+ 
+ }
+ 
+-/**
+- * Sets the power management mode of the pipe and plane.
+- *
+- * This code should probably grow support for turning the cursor off and back
+- * on appropriately at the same time as we're turning the pipe off/on.
+- */
+ static void
+-i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
++i830_crtc_enable(xf86CrtcPtr crtc)
+ {
+     ScrnInfoPtr pScrn = crtc->scrn;
+     I830Ptr pI830 = I830PTR(pScrn);
+@@ -833,112 +1073,528 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
+     int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
+     uint32_t temp;
+ 
+-    /* XXX: When our outputs are all unaware of DPMS modes other than off and
+-     * on, we should map those modes to DPMSModeOff in the CRTC.
++    /* Enable the DPLL */
++    temp = INREG(dpll_reg);
++    if ((temp & DPLL_VCO_ENABLE) == 0)
++    {
++	OUTREG(dpll_reg, temp);
++	POSTING_READ(dpll_reg);
++	/* Wait for the clocks to stabilize. */
++	usleep(150);
++	OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
++	POSTING_READ(dpll_reg);
++	/* Wait for the clocks to stabilize. */
++	usleep(150);
++	OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
++	POSTING_READ(dpll_reg);
++	/* Wait for the clocks to stabilize. */
++	usleep(150);
++    }
++
++    /* Enable the pipe */
++    temp = INREG(pipeconf_reg);
++    if ((temp & PIPEACONF_ENABLE) == 0)
++	OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
++
++    /* Enable the plane */
++    temp = INREG(dspcntr_reg);
++    if ((temp & DISPLAY_PLANE_ENABLE) == 0)
++    {
++	OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
++	/* Flush the plane changes */
++	OUTREG(dspbase_reg, INREG(dspbase_reg));
++    }
++
++    i830_crtc_load_lut(crtc);
++
++    /* Give the overlay scaler a chance to enable if it's on this pipe */
++    i830_crtc_dpms_video(crtc, TRUE);
++
++    /* Reenable compression if needed */
++    if (i830_use_fb_compression(crtc))
++	i830_enable_fb_compression(crtc);
++    i830_modeset_ctl(crtc, 0);
++}
++
++void
++i830_crtc_disable(xf86CrtcPtr crtc, Bool disable_pipe)
++{
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830Ptr pI830 = I830PTR(pScrn);
++    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
++    int pipe = intel_crtc->pipe;
++    int plane = intel_crtc->plane;
++    int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
++    int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
++    int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
++    int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
++    uint32_t temp;
++
++    i830_modeset_ctl(crtc, 1);
++    /* Shut off compression if in use */
++    if (i830_use_fb_compression(crtc))
++	i830_disable_fb_compression(crtc);
++
++    /* Give the overlay scaler a chance to disable if it's on this pipe */
++    i830_crtc_dpms_video(crtc, FALSE);
++
++    /* 
++     * The documentation says :
++     * - Disable planes (VGA or hires)
++     * - Disable pipe
++     * - Disable VGA display
+      */
+-    switch (mode) {
+-    case DPMSModeOn:
+-    case DPMSModeStandby:
+-    case DPMSModeSuspend:
+-	/* Enable the DPLL */
++
++    /* Disable display plane */
++    temp = INREG(dspcntr_reg);
++    if ((temp & DISPLAY_PLANE_ENABLE) != 0)
++    {
++	OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
++	/* Flush the plane changes */
++	OUTREG(dspbase_reg, INREG(dspbase_reg));
++	POSTING_READ(dspbase_reg);
++    }
++
++    if (!IS_I9XX(pI830)) {
++	/* Wait for vblank for the disable to take effect */
++	i830WaitForVblank(pScrn);
++    }
++
++    /* May need to leave pipe A on */
++    if (disable_pipe)
++    {
++	/* Next, disable display pipes */
++	temp = INREG(pipeconf_reg);
++	if ((temp & PIPEACONF_ENABLE) != 0) {
++	    OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
++	    POSTING_READ(pipeconf_reg);
++	}
++
++	/* Wait for vblank for the disable to take effect. */
++	i830WaitForVblank(pScrn);
++
+ 	temp = INREG(dpll_reg);
+-	if ((temp & DPLL_VCO_ENABLE) == 0)
+-	{
+-	    OUTREG(dpll_reg, temp);
+-	    POSTING_READ(dpll_reg);
+-	    /* Wait for the clocks to stabilize. */
+-	    usleep(150);
+-	    OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
++	if ((temp & DPLL_VCO_ENABLE) != 0) {
++	    OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
+ 	    POSTING_READ(dpll_reg);
+-	    /* Wait for the clocks to stabilize. */
+-	    usleep(150);
+-	    OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
+-	    POSTING_READ(dpll_reg);
+-	    /* Wait for the clocks to stabilize. */
+-	    usleep(150);
+ 	}
+ 
+-	/* Enable the pipe */
+-	temp = INREG(pipeconf_reg);
+-	if ((temp & PIPEACONF_ENABLE) == 0)
+-	    OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
++	/* Wait for the clocks to turn off. */
++	usleep(150);
++    }
+ 
+-	/* Enable the plane */
+-	temp = INREG(dspcntr_reg);
+-	if ((temp & DISPLAY_PLANE_ENABLE) == 0)
+-	{
+-	    OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
+-	    /* Flush the plane changes */
+-	    OUTREG(dspbase_reg, INREG(dspbase_reg));
+-	}
++    /* Disable the VGA plane that we never use. */
++    i830_disable_vga_plane (crtc);
++}
+ 
+-	i830_crtc_load_lut(crtc);
++static void
++intel_wait_warmup(int w)
++{
++    usleep(w);
++}
+ 
+-	/* Give the overlay scaler a chance to enable if it's on this pipe */
+-	i830_crtc_dpms_video(crtc, TRUE);
++static void
++ilk_crtc_enable(xf86CrtcPtr crtc)
++{
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830Ptr pI830 = I830PTR(pScrn);
++    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
++    int pipe = intel_crtc->pipe;
++    int plane = intel_crtc->plane;
++    int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
++    int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
++    int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
++    int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
++    int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
++    int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
++    int fdi_rx_chicken_reg = (pipe == 0) ? FDI_RXA_CHICKEN : FDI_RXB_CHICKEN;
++    int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR;
++    int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR;
++    int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
++    /* int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1; */
++    uint32_t temp;
++    int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
++    int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
++    int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
++    int cpu_vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
++    int cpu_vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
++    int cpu_vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
++    int trans_htot_reg = (pipe == 0) ? TRANS_HTOTAL_A : TRANS_HTOTAL_B;
++    int trans_hblank_reg = (pipe == 0) ? TRANS_HBLANK_A : TRANS_HBLANK_B;
++    int trans_hsync_reg = (pipe == 0) ? TRANS_HSYNC_A : TRANS_HSYNC_B;
++    int trans_vtot_reg = (pipe == 0) ? TRANS_VTOTAL_A : TRANS_VTOTAL_B;
++    int trans_vblank_reg = (pipe == 0) ? TRANS_VBLANK_A : TRANS_VBLANK_B;
++    int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B;
++
++    ErrorF("cpu crtc %d enable\n", pipe);
++
++    /* enable PCH clock reference source */
++    temp = INREG(PCH_DREF_CONTROL);
++    temp &= ~DREF_CONTROL_MASK;
++    /* XXX match bios dump, need to change for more outputs */
++    temp |= DREF_NONSPREAD_SOURCE_ENABLE;
++    OUTREG(PCH_DREF_CONTROL, temp);
++
++    /* enable PCH SSC modulator, looks not needed for CRT */
++
++    /* ignore eDP now */
++
++    /* enable PCH DPLL */
++    temp = INREG(pch_dpll_reg);
++    if ((temp & DPLL_VCO_ENABLE) == 0) {
++	OUTREG(pch_dpll_reg, temp | DPLL_VCO_ENABLE);
++	POSTING_READ(pch_dpll_reg);
++    }
++
++    /* enable PCH FDI RX PLL, wait warmup plus DMI latency */
++    temp = INREG(fdi_rx_reg);
++    OUTREG(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE | FDI_SEL_PCDCLK | FDI_DP_PORT_WIDTH_X4);
++    POSTING_READ(fdi_rx_reg);
++    intel_wait_warmup(WARMUP_PCH_FDI_RECEIVER_PLL);
++    intel_wait_warmup(WARMUP_DMI_LATENCY);
++
++    /* Enable CPU FDI TX PLL, always on for ILK */
++    temp = INREG(fdi_tx_reg);
++    if ((temp & FDI_TX_PLL_ENABLE) == 0) {
++	OUTREG(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE);
++	POSTING_READ(fdi_tx_reg);
++	intel_wait_warmup(WARMUP_CPU_FDI_TRANSMITTER_PLL);
++    }
++
++    /* FIXME when to enable CPU panel fitter? */
++#if 0
++    temp = INREG(pf_ctl_reg);
++    if ((temp & PF_ENABLE) == 0) {
++	OUTREG(pf_ctl_reg, temp | PF_ENABLE);
++	POSTING_READ(pf_ctl_reg);
++    }
++#endif
+ 
+-	/* Reenable compression if needed */
+-	if (i830_use_fb_compression(crtc))
+-	    i830_enable_fb_compression(crtc);
+-	i830_modeset_ctl(crtc, 0);
+-	break;
+-    case DPMSModeOff:
+-	i830_modeset_ctl(crtc, 1);
+-	/* Shut off compression if in use */
+-	if (i830_use_fb_compression(crtc))
+-	    i830_disable_fb_compression(crtc);
++    /* Enable CPU pipe */
++    temp = INREG(pipeconf_reg);
++    if ((temp & PIPEACONF_ENABLE) == 0) {
++	OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
++	POSTING_READ(pipeconf_reg);
++    }
++    /*
++    while ((INREG(pipeconf_reg) & I965_PIPECONF_ACTIVE) == 0) ;
++     */
+ 
+-	/* Give the overlay scaler a chance to disable if it's on this pipe */
+-	i830_crtc_dpms_video(crtc, FALSE);
++    /* configure and enable CPU plane */
++    temp = INREG(dspcntr_reg);
++    if ((temp & DISPLAY_PLANE_ENABLE) == 0)
++    {
++	OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
++	/* Flush the plane changes */
++	OUTREG(dspbase_reg, INREG(dspbase_reg));
++    }
+ 
+-	/* 
+-	 * The documentation says :
+-	 * - Disable planes (VGA or hires)
+-	 * - Disable pipe
+-	 * - Disable VGA display
+-	 */
++    /* enable CPU FDI TX and PCH FDI RX */
+ 
+-	/* Disable display plane */
+-	temp = INREG(dspcntr_reg);
+-	if ((temp & DISPLAY_PLANE_ENABLE) != 0)
+-	{
+-	    OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
+-	    /* Flush the plane changes */
+-	    OUTREG(dspbase_reg, INREG(dspbase_reg));
+-	    POSTING_READ(dspbase_reg);
+-	}
++    temp = INREG(fdi_tx_reg);
++    temp |= FDI_TX_ENABLE;
++    temp |= FDI_DP_PORT_WIDTH_X4;
++    OUTREG(fdi_tx_reg, temp);
++    POSTING_READ(fdi_tx_reg);
+ 
+-	if (!IS_I9XX(pI830)) {
+-	    /* Wait for vblank for the disable to take effect */
+-	    i830WaitForVblank(pScrn);
+-	}
++    temp = INREG(fdi_rx_reg);
++    OUTREG(fdi_rx_reg, temp | FDI_RX_ENABLE);
++    POSTING_READ(fdi_rx_reg);
+ 
+-	/* May need to leave pipe A on */
+-	if ((pipe != 0) || !(pI830->quirk_flag & QUIRK_PIPEA_FORCE))
+-	{
+-		/* Next, disable display pipes */
+-		temp = INREG(pipeconf_reg);
+-		if ((temp & PIPEACONF_ENABLE) != 0) {
+-		    OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
+-		    POSTING_READ(pipeconf_reg);
+-		}
++    if (ilk_a_stepping()) {
++	temp = INREG(fdi_rx_chicken_reg);
++	OUTREG(fdi_rx_chicken_reg, temp | FDI_RX_PHASE_SYNC_POINTER_ENABLE);
++    }
+ 
+-		/* Wait for vblank for the disable to take effect. */
+-		i830WaitForVblank(pScrn);
++    intel_wait_warmup(FDI_TRAIN_PATTERN_1_TIME);
++    usleep(150);
+ 
+-		temp = INREG(dpll_reg);
+-		if ((temp & DPLL_VCO_ENABLE) != 0) {
+-		    OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
+-		    POSTING_READ(dpll_reg);
+-		}
++    /* Train FDI */
+ 
+-		/* Wait for the clocks to turn off. */
+-		usleep(150);
+-	}
++#if 0
++    temp = INREG(fdi_rx_iir_reg);
++    temp |= (FDI_RX_BIT_LOCK | FDI_RX_SYMBOL_LOCK | FDI_RX_INTER_LANE_ALIGN);
++    OUTREG(fdi_rx_iir_reg, temp);
++#endif
++
++    /* umask FDI RX Interrupt symbol_lock and bit_lock bit for train result */
++    temp = INREG(fdi_rx_imr_reg);
++    temp &= ~FDI_RX_SYMBOL_LOCK;
++    temp &= ~FDI_RX_BIT_LOCK;
++    OUTREG(fdi_rx_imr_reg, 0);
++    POSTING_READ(fdi_rx_imr_reg);
++    usleep(150);
++
++    ErrorF("train start\n");
++
++    temp = INREG(fdi_rx_iir_reg);
++    ErrorF("FDI_RX_IIR 0x%x\n", temp);
++
++    if ((temp & FDI_RX_BIT_LOCK) == 0) {
++	/* try more times for luck */
++	int tries = 10, j;
++	for (j = 0; j < tries; j++) {
++	    temp = INREG(fdi_rx_iir_reg);
++	    ErrorF("FDI_RX_IIR 0x%x\n", temp);
++	    if (temp & FDI_RX_BIT_LOCK)
++		break;
++	    intel_wait_warmup(FDI_TRAIN_PATTERN_1_TIME);
++	}
++	if (j != tries) {
++	    ErrorF("train 1 ok 1!\n");
++	    /* clear it */
++	    OUTREG(fdi_rx_iir_reg, temp | FDI_RX_BIT_LOCK);
++	} else
++	    ErrorF("train 1 fail\n");
++    } else {
++	/* clear it */
++	OUTREG(fdi_rx_iir_reg, temp | FDI_RX_BIT_LOCK);
++	ErrorF("train 1 ok 2!\n");
++    }
++
++    temp = INREG(fdi_tx_reg);
++    temp &= ~FDI_LINK_TRAIN_NONE;
++    temp |= FDI_LINK_TRAIN_PATTERN_2;
++    OUTREG(fdi_tx_reg, temp);
++
++    temp = INREG(fdi_rx_reg);
++    temp &= ~FDI_LINK_TRAIN_NONE;
++    temp |= FDI_LINK_TRAIN_PATTERN_2;
++    OUTREG(fdi_rx_reg, temp);
++
++    intel_wait_warmup(FDI_TRAIN_PATTERN_2_TIME);
++    usleep(150);
++
++    ErrorF("train 2 start\n");
++
++    temp = INREG(fdi_rx_iir_reg);
++    ErrorF("FDI_RX_IIR 0x%x\n", temp);
++
++    if ((temp & FDI_RX_SYMBOL_LOCK) == 0) {
++	/* try more times for luck */
++	int tries = 10, j;
++	for (j = 0; j < tries; j++) {
++	    temp = INREG(fdi_rx_iir_reg);
++	    ErrorF("FDI_RX_IIR 0x%x\n", temp);
++	    if (temp & FDI_RX_SYMBOL_LOCK)
++		break;
++	    intel_wait_warmup(FDI_TRAIN_PATTERN_2_TIME);
++	}
++	if (j != tries) {
++	    /* clear it */
++	    OUTREG(fdi_rx_iir_reg, temp | FDI_RX_SYMBOL_LOCK);
++	    ErrorF("train 2 ok 1!\n");
++	} else
++	    ErrorF("train 2 fail\n");
++    } else {
++	/* clear it */
++	OUTREG(fdi_rx_iir_reg, temp | FDI_RX_SYMBOL_LOCK);
++	ErrorF("train 2 ok 2!\n");
++    }
++    ErrorF("FDI train done\n");
++
++    /* set transcoder timing */
++    OUTREG(trans_htot_reg, INREG(cpu_htot_reg));
++    OUTREG(trans_hblank_reg, INREG(cpu_hblank_reg));
++    OUTREG(trans_hsync_reg, INREG(cpu_hsync_reg));
++
++    OUTREG(trans_vtot_reg, INREG(cpu_vtot_reg));
++    OUTREG(trans_vblank_reg, INREG(cpu_vblank_reg));
++    OUTREG(trans_vsync_reg, INREG(cpu_vsync_reg));
++
++    /* enable PCH transcoder */
++    temp = INREG(transconf_reg);
++    OUTREG(transconf_reg, temp | TRANS_ENABLE);
++    POSTING_READ(transconf_reg);
++
++    while ((INREG(transconf_reg) & TRANS_STATE_ENABLE) == 0) ;
++
++    /* enable normal */
++
++    temp = INREG(fdi_tx_reg);
++    temp &= ~FDI_LINK_TRAIN_NONE;
++    OUTREG(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE);
++    POSTING_READ(fdi_tx_reg);
++
++    temp = INREG(fdi_rx_reg);
++    temp &= ~FDI_LINK_TRAIN_NONE;
++    OUTREG(fdi_rx_reg, temp | FDI_LINK_TRAIN_NONE | FDI_RX_ENHANCE_FRAME_ENABLE);
++    POSTING_READ(fdi_rx_reg);
++
++    /* wait one idle pattern time */
++    intel_wait_warmup(FDI_ONE_IDLE_PATTERN_TIME);
++
++     i830WaitForVblank(pScrn);
++ 
++    i830_crtc_load_lut(crtc);
++
++    /* Give the overlay scaler a chance to enable if it's on this pipe */
++    i830_crtc_dpms_video(crtc, TRUE);
++
++    i830_modeset_ctl(crtc, 0);
++    ErrorF("crtc enable done.\n");
++}
++
++void
++ilk_crtc_disable(xf86CrtcPtr crtc)
++{
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830Ptr pI830 = I830PTR(pScrn);
++    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
++    int pipe = intel_crtc->pipe;
++    int plane = intel_crtc->plane;
++    int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
++    int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
++    int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
++    int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
++    int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
++    int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
++    int fdi_rx_chicken_reg = (pipe == 0) ? FDI_RXA_CHICKEN : FDI_RXB_CHICKEN;
++    int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
++    int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1;
++    uint32_t temp;
++
++    ErrorF("ilk crtc %d disable\n", pipe);
++
++    i830_modeset_ctl(crtc, 1);
++
++    /* Give the overlay scaler a chance to disable if it's on this pipe */
++    i830_crtc_dpms_video(crtc, FALSE);
++
++    /** disable sequence **/
++
++    /* Disable the VGA plane that we never use. */
++    i830_disable_vga_plane (crtc);
+ 
+-	/* Disable the VGA plane that we never use. */
+-	i830_disable_vga_plane (crtc);
++    /* disable cpu planes */
++    temp = INREG(dspcntr_reg);
++    if ((temp & DISPLAY_PLANE_ENABLE) != 0)
++    {
++	OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
++	/* Flush the plane changes */
++	OUTREG(dspbase_reg, INREG(dspbase_reg));
++	POSTING_READ(dspbase_reg);
++    }
++
++    /* disable cpu pipe, disable after all planes disabled */
++    temp = INREG(pipeconf_reg);
++    if ((temp & PIPEACONF_ENABLE) != 0) {
++	OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
++	POSTING_READ(pipeconf_reg);
++	/* wait for cpu pipe off, pipe state */
++	while ((INREG(pipeconf_reg) & I965_PIPECONF_ACTIVE) != 0)
++		;
++    }
++
++    /* disable panel power -> output power down */
++
++    /* ILK-B : disable cpu panel fitter ? */
++    temp = INREG(pf_ctl_reg);
++    if ((temp & PF_ENABLE) != 0) {
++	OUTREG(pf_ctl_reg, temp & ~PF_ENABLE);
++	POSTING_READ(pf_ctl_reg);
++    }
++
++    /* ignore eDP now */
++
++    /* disable CPU FDI tx and PCH FDI rx */
++    temp = INREG(fdi_tx_reg);
++    OUTREG(fdi_tx_reg, temp & ~FDI_TX_ENABLE);
++    POSTING_READ(fdi_tx_reg);
++
++    temp = INREG(fdi_rx_reg);
++    OUTREG(fdi_rx_reg, temp & ~FDI_RX_ENABLE);
++    POSTING_READ(fdi_rx_reg);
++
++    if (ilk_a_stepping()) {
++	temp = INREG(fdi_rx_chicken_reg);
++	OUTREG(fdi_rx_chicken_reg, temp & ~FDI_RX_PHASE_SYNC_POINTER_ENABLE);
++    }
++
++    /* still set train pattern 1 */
++    temp = INREG(fdi_tx_reg);
++    temp &= ~FDI_LINK_TRAIN_NONE;
++    temp |= FDI_LINK_TRAIN_PATTERN_1;
++    OUTREG(fdi_tx_reg, temp);
++
++    temp = INREG(fdi_rx_reg);
++    temp &= ~FDI_LINK_TRAIN_NONE;
++    temp |= FDI_LINK_TRAIN_PATTERN_1;
++    OUTREG(fdi_rx_reg, temp);
++
++    /* disable PCH transcoder */
++    temp = INREG(transconf_reg);
++    if ((temp & TRANS_ENABLE) != 0) {
++	    OUTREG(transconf_reg, temp & ~TRANS_ENABLE);
++	    POSTING_READ(transconf_reg);
++	    /* wait for PCH transcoder off, transcoder state */
++	    while ((INREG(transconf_reg) & TRANS_STATE_ENABLE) != 0)
++		;
++    }
++
++    /* disable PCH DPLL */
++    temp = INREG(pch_dpll_reg);
++    if ((temp & DPLL_VCO_ENABLE) != 0) {
++	OUTREG(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE);
++	POSTING_READ(pch_dpll_reg);
++    }
++
++    /* XXX never disable FDI TX pll ? */
++#if 0
++    temp = INREG(fdi_tx_reg);
++    if ((temp & FDI_TX_PLL_ENABLE) != 0) {
++	OUTREG(fdi_tx_reg, temp & ~FDI_TX_PLL_ENABLE);
++	POSTING_READ(fdi_tx_reg);
++    }
++#endif
++
++    temp = INREG(fdi_rx_reg);
++    if ((temp & FDI_RX_PLL_ENABLE) != 0) {
++	temp &= ~FDI_RX_PLL_ENABLE;
++	temp &= ~FDI_SEL_PCDCLK;
++	OUTREG(fdi_rx_reg, temp & ~FDI_RX_PLL_ENABLE);
++	POSTING_READ(fdi_rx_reg);
++    }
++
++    i830WaitForVblank(pScrn);
++ }
++
++/**
++ * Sets the power management mode of the pipe and plane.
++ *
++ * This code should probably grow support for turning the cursor off and back
++ * on appropriately at the same time as we're turning the pipe off/on.
++ */
++static void
++i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
++{
++    ScrnInfoPtr pScrn = crtc->scrn;
++    I830Ptr pI830 = I830PTR(pScrn);
++    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
++    int pipe = intel_crtc->pipe;
++    Bool disable_pipe = TRUE;
+ 
++    /* XXX: When our outputs are all unaware of DPMS modes other than off and
++     * on, we should map those modes to DPMSModeOff in the CRTC.
++     */
++    switch (mode) {
++    case DPMSModeOn:
++    case DPMSModeStandby:
++    case DPMSModeSuspend:
++	/* Enable the DPLL */
++	if (IS_IGDNG(pI830))
++	    ilk_crtc_enable(crtc);
++	else
++	    i830_crtc_enable(crtc);
++	break;
++    case DPMSModeOff:
++	if (IS_IGDNG(pI830))
++	    ilk_crtc_disable(crtc);
++	else {
++	    if ((pipe == 0) && (pI830->quirk_flag & QUIRK_PIPEA_FORCE))
++		disable_pipe = FALSE;
++	    i830_crtc_disable(crtc, disable_pipe);
++	}
+ 	break;
+     }
+ 
+@@ -1043,6 +1699,12 @@ static Bool
+ i830_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
+ 		     DisplayModePtr adjusted_mode)
+ {
++    I830Ptr pI830 = I830PTR(crtc->scrn);
++    if (IS_IGDNG(pI830)) {
++       /* FDI link clock is fixed at 2.7G */
++       if (mode->Clock * 3 > 270000 * 4)
++           return MODE_CLOCK_HIGH;
++    }
+     return TRUE;
+ }
+ 
+@@ -1200,6 +1862,50 @@ i830_update_dsparb(ScrnInfoPtr pScrn)
+        OUTREG(DSPARB, planea_entries << DSPARB_AEND_SHIFT);
+ }
+ 
++/* M/N cal, steal from keithp's display-port branch */
++struct ilk_m_n {
++    uint32_t        tu;
++    uint32_t        gmch_m;
++    uint32_t        gmch_n;
++    uint32_t        link_m;
++    uint32_t        link_n;
++};
++
++static void
++ilk_reduce_ratio(uint32_t *num, uint32_t *den)
++{
++    while (*num > 0xffffff || *den > 0xffffff) {
++	*num >>= 1;
++	*den >>= 1;
++    }
++}
++
++#define DATA_N 0x800000
++#define LINK_N 0x80000
++
++static void
++ilk_compute_m_n(int bytes_per_pixel,
++	int nlanes,
++	int pixel_clock,
++	int link_clock,
++	struct ilk_m_n *m_n)
++{
++    uint64_t temp;
++
++    m_n->tu = 64; /* default size */
++
++    temp = (uint64_t) DATA_N * pixel_clock;
++    temp /= link_clock;
++    m_n->gmch_m = temp * bytes_per_pixel / nlanes;
++    m_n->gmch_n = DATA_N;
++    ilk_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
++
++    temp = (uint64_t) LINK_N * pixel_clock;
++    m_n->link_m = temp / link_clock;
++    m_n->link_n = LINK_N;
++    ilk_reduce_ratio(&m_n->link_m, &m_n->link_n);
++}
++
+ /**
+  * Sets up registers for the given mode/adjusted_mode pair.
+  *
+@@ -1234,12 +1940,22 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
+     int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
+     int dsppos_reg = (plane == 0) ? DSPAPOS : DSPBPOS;
+     int dspsize_reg = (plane == 0) ? DSPASIZE : DSPBSIZE;
++    int pipestat_reg = (pipe == 0) ? PIPEASTAT : PIPEBSTAT;
++    int data_m1_reg = (pipe == 0) ? PIPEA_DATA_M1 : PIPEB_DATA_M1;
++    int data_n1_reg = (pipe == 0) ? PIPEA_DATA_N1 : PIPEB_DATA_N1;
++    int link_m1_reg = (pipe == 0) ? PIPEA_LINK_M1 : PIPEB_LINK_M1;
++    int link_n1_reg = (pipe == 0) ? PIPEA_LINK_N1 : PIPEB_LINK_N1;
++    int pch_fp_reg = (pipe == 0) ? PCH_FPA0 : PCH_FPB0;
++    int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
++    int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
+     int i, num_outputs = 0;
+     int refclk;
+     intel_clock_t clock;
+     uint32_t dpll = 0, fp = 0, dspcntr, pipeconf, lvds_bits = 0;
+     Bool ok, is_sdvo = FALSE, is_dvo = FALSE;
+     Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
++    struct ilk_m_n m_n = {0};
++    int sdvo_pixel_multiply;
+ 
+     /* Set up some convenient bools for what outputs are connected to
+      * our pipe, used in DPLL setup.
+@@ -1288,6 +2004,8 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
+ 		   "using SSC reference clock of %d MHz\n", refclk / 1000);
+     } else if (IS_I9XX(pI830)) {
+ 	refclk = 96000;
++        if (IS_IGDNG(pI830))
++           refclk = 120000; /* reference clock at 120Mhz */
+     } else {
+ 	refclk = 48000;
+     }
+@@ -1305,8 +2023,14 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
+     }
+ 
+     fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
++    if (IS_IGDNG(pI830))
++       ilk_compute_m_n(3, 4, /* lane num 4 */
++               adjusted_mode->Clock,
++               270000, /* lane clock */
++               &m_n);
+ 
+-    dpll = DPLL_VGA_MODE_DIS;
++    if (!IS_IGDNG(pI830))
++       dpll = DPLL_VGA_MODE_DIS;
+     if (IS_I9XX(pI830)) {
+ 	if (is_lvds)
+ 	    dpll |= DPLLB_MODE_LVDS;
+@@ -1315,16 +2039,20 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
+ 	if (is_sdvo)
+ 	{
+ 	    dpll |= DPLL_DVO_HIGH_SPEED;
++	    sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
+ 	    if ((IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830)) &&
+ 		!is_tv)
+ 	    {
+-		int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
+ 		dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
+-	    }
++           } else if (IS_IGDNG(pI830))
++               dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
+ 	}
+ 	
+ 	/* compute bitmask from p1 value */
+-	dpll |= (1 << (clock.p1 - 1)) << 16;
++       dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
++       if (IS_IGDNG(pI830))
++               dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
++
+ 	switch (clock.p2) {
+ 	case 5:
+ 	    dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
+@@ -1339,7 +2067,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
+ 	    dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
+ 	    break;
+ 	}
+-	if (IS_I965G(pI830) && !IS_GM45(pI830))
++	if (IS_I965G(pI830) && !IS_GM45(pI830) && !IS_IGDNG(pI830))
+ 	    dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
+     } else {
+ 	if (is_lvds) {
+@@ -1359,7 +2087,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
+     else if (is_tv)
+     {
+ 	/* XXX: just matching BIOS for now */
+-/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
++	/*      dpll |= PLL_REF_INPUT_TVCLKINBC; */
+ 	dpll |= 3;
+     }
+     else if (is_lvds && pI830->lvds_use_ssc && num_outputs < 2)
+@@ -1386,10 +2114,14 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
+ 	FatalError("unknown display bpp\n");
+     }
+ 
+-    if (pipe == 0)
+-	dspcntr |= DISPPLANE_SEL_PIPE_A;
+-    else
+-	dspcntr |= DISPPLANE_SEL_PIPE_B;
++    /* Ironlake's plane is forced to pipe, bit 24 is to
++       enable color space conversion */
++    if (!IS_IGDNG(pI830)) {
++       if (pipe == 0)
++           dspcntr |= DISPPLANE_SEL_PIPE_A;
++       else
++           dspcntr |= DISPPLANE_SEL_PIPE_B;
++    }
+ 
+     if (IS_I965G(pI830) && i830_display_tiled(crtc))
+ 	dspcntr |= DISPLAY_PLANE_TILED;
+@@ -1421,7 +2153,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
+     }
+     
+     /* Disable the panel fitter if it was on our pipe */
+-    if (i830_panel_fitter_pipe (pI830) == pipe)
++    if (!IS_IGDNG(pI830) && i830_panel_fitter_pipe (pI830) == pipe)
+ 	OUTREG(PFIT_CONTROL, 0);
+ 
+     if (pI830->debug_modes) {
+@@ -1436,6 +2168,12 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
+ 	i830PrintPll(pScrn, "chosen", &clock);
+     }
+ 
++    /* assign to Ironlake registers */
++    if (IS_IGDNG(pI830)) {
++       fp_reg = pch_fp_reg;
++       dpll_reg = pch_dpll_reg;
++    }
++
+     if (dpll & DPLL_VCO_ENABLE)
+     {
+ 	OUTREG(fp_reg, fp);
+@@ -1498,8 +2236,8 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
+     /* Wait for the clocks to stabilize. */
+     usleep(150);
+     
+-    if (IS_I965G(pI830)) {
+-	int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
++    if (IS_I965G(pI830) && !IS_IGDNG(pI830)) {
++        sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
+ 	OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
+ 	       ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
+     } else {
+@@ -1529,8 +2267,26 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
+     /* pipesrc and dspsize control the size that is scaled from, which should
+      * always be the user's requested size.
+      */
+-    OUTREG(dspsize_reg, ((mode->VDisplay - 1) << 16) | (mode->HDisplay - 1));
+-    OUTREG(dsppos_reg, 0);
++    if (!IS_IGDNG(pI830)) {
++       OUTREG(dspsize_reg, ((mode->VDisplay - 1) << 16) | (mode->HDisplay - 1));
++       OUTREG(dsppos_reg, 0);
++    }
++    OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
++
++    if (IS_IGDNG(pI830)) {
++       int temp;
++
++       OUTREG(data_m1_reg, TU_SIZE(m_n.tu) | m_n.gmch_m);
++       OUTREG(data_n1_reg, TU_SIZE(m_n.tu) | m_n.gmch_n);
++       OUTREG(link_m1_reg, m_n.link_m);
++       OUTREG(link_n1_reg, m_n.link_n);
++
++       /* enable FDI RX PLL too */
++       temp = INREG(fdi_rx_reg);
++       OUTREG(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE);
++       intel_wait_warmup(WARMUP_PCH_FDI_RECEIVER_PLL);
++       intel_wait_warmup(WARMUP_DMI_LATENCY);
++    }
+     OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
+     OUTREG(pipeconf_reg, pipeconf);
+     POSTING_READ(pipeconf_reg);
+@@ -1561,6 +2317,10 @@ i830_crtc_load_lut(xf86CrtcPtr crtc)
+     if (!crtc->enabled)
+ 	return;
+ 
++    /* use legacy palette for Ironlake */
++    if (IS_IGDNG(pI830))
++       palreg = (intel_crtc->pipe == 0) ? LGC_PALETTE_A : LGC_PALETTE_B;
++
+     for (i = 0; i < 256; i++) {
+ 	OUTREG(palreg + 4 * i,
+ 	       (intel_crtc->lut_r[i] << 16) |
+--- src/i830_display.h	2009-08-28 13:21:29.206122925 +0800
++++ src/i830_display.h	2009-08-28 15:07:56.042727475 +0800
+@@ -46,3 +46,4 @@ void cpu_crtc_init(ScrnInfoPtr pScrn, in
+ void cpu_crtc_disable(xf86CrtcPtr crtc, Bool disable_pipe);
+ void cpu_crtc_enable(xf86CrtcPtr crtc);
+ void ilk_disable_vga_plane(xf86CrtcPtr crtc);
++void ilk_crtc_disable(xf86CrtcPtr crtc);
+--- src/i830_driver.c	2009-08-28 13:21:29.208727305 +0800
++++ src/i830_driver.c	2009-08-28 15:24:52.313672794 +0800
+@@ -915,6 +915,9 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
+    /* everyone has at least a single analog output */
+    i830_crt_init(pScrn);
+ 
++   if (IS_IGDNG(pI830))
++       goto done;
++
+    /* Set up integrated LVDS */
+    if (IS_MOBILE(pI830) && !IS_I830(pI830))
+       i830_lvds_init(pScrn);
+@@ -940,6 +943,8 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
+    }
+    if (IS_I9XX(pI830) && IS_MOBILE(pI830))
+       i830_tv_init(pScrn);
++
++done:
+    
+    for (o = 0; o < config->num_output; o++)
+    {
+@@ -3872,7 +3877,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
+        pI830->back_buffer != NULL)
+        i830_free_3d_memory(pScrn);
+ 
+-   if (!pI830->use_drm_mode)
++   if (!pI830->use_drm_mode && !IS_IGDNG(pI830))
+        I830SwapPipes(pScrn);
+ #endif
+ 
+@@ -4255,7 +4260,10 @@ I830EnterVT(int scrnIndex, int flags)
+        for (i = 0; i < xf86_config->num_crtc; i++)
+        {
+            xf86CrtcPtr crtc = xf86_config->crtc[i];
+-           cpu_crtc_disable(crtc, TRUE);
++          if (IS_IGDNG(pI830))
++	      cpu_crtc_disable(crtc,TRUE);
++          else
++              i830_crtc_disable(crtc, TRUE);
+        }
+        i830WaitForVblank(pScrn);
+    }
+@@ -4310,7 +4318,11 @@ I830EnterVT(int scrnIndex, int flags)
+ 	   I830InitHWCursor(pScrn);
+ 
+        /* Tell the BIOS that we're in control of mode setting now. */
+-       if (!IS_IGDNG(pI830)) {
++       /* XXX check if Ironlake needs */
++       if (!IS_IGDNG(pI830))
++          i830_init_clock_gating(pScrn);
++
++       if (0) {
+            i830_init_bios_control(pScrn);
+            i830_init_clock_gating(pScrn);
+ 	}
+--- src/i830_exa.c	2009-08-18 11:31:33.556347389 +0800
++++ src/i830_exa.c	2009-08-28 15:28:23.143375596 +0800
+@@ -705,10 +705,17 @@ I830EXAInit(ScreenPtr pScreen)
+ 	pI830->EXADriverPtr->Composite = i915_composite;
+     	pI830->EXADriverPtr->DoneComposite = i830_done_composite;
+     } else {
+- 	pI830->EXADriverPtr->CheckComposite = i965_check_composite;
+- 	pI830->EXADriverPtr->PrepareComposite = i965_prepare_composite;
+- 	pI830->EXADriverPtr->Composite = i965_composite;
+- 	pI830->EXADriverPtr->DoneComposite = i830_done_composite;
++        if (IS_IGDNG(pI830)) {
++          pI830->EXADriverPtr->CheckComposite = NULL;
++          pI830->EXADriverPtr->PrepareComposite = NULL;
++          pI830->EXADriverPtr->Composite = NULL;
++          pI830->EXADriverPtr->DoneComposite = NULL;
++	} else {
++ 	   pI830->EXADriverPtr->CheckComposite = i965_check_composite;
++ 	   pI830->EXADriverPtr->PrepareComposite = i965_prepare_composite;
++ 	   pI830->EXADriverPtr->Composite = i965_composite;
++ 	   pI830->EXADriverPtr->DoneComposite = i830_done_composite;
++	}
+     }
+ #if EXA_VERSION_MINOR >= 2
+     if (!pI830->use_drm_mode)
+
+--- src/i810_reg.h	2009-08-27 16:23:54.682894862 +0800
++++ src/i810_reg.h	2009-08-28 16:26:35.023343806 +0800
+@@ -3347,5 +3347,6 @@ typedef enum {
+ 
+ #define HDMIC	0xe1150
+ #define HDMID	0xe1160
++#define PCH_LVDS 0xe1180
+ 
+ #endif /* _I810_REG_H */
+--- src/i830_debug.c	2009-08-28 13:21:29.205566212 +0800
++++ src/i830_debug.c	2009-08-28 16:46:07.816651436 +0800
+@@ -1231,6 +1231,11 @@ static struct i830SnapshotRec cpu_pch_sn
+     DEFINEREG(FDI_PLL_CTL_2),
+ 
+     DEFINEREG2(PCH_ADPA, i830_debug_adpa),
++
++    DEFINEREG(PCH_PORT_HOTPLUG),
++    DEFINEREG(HDMIB),
++    DEFINEREG(HDMIC),
++    DEFINEREG(HDMID),
+ };
+ #define NUM_ILK_SNAPSHOTREGS (sizeof(cpu_pch_snapshot) / sizeof(cpu_pch_snapshot[0]))
+ 
+@@ -1261,10 +1266,38 @@ void i830CompareRegsToSnapshot(ScrnInfoP
+ 
+     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ 	       "Comparing regs from server start up to %s\n", where);
+-    for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
+-	uint32_t val = INREG(i830_snapshot[i].reg);
+-	if (i830_snapshot[i].val == val)
+-	    continue;
++    if (IS_IGDNG(pI830)) {
++        for (i = 0; i < NUM_ILK_SNAPSHOTREGS; i++) {
++           uint32_t val = INREG(cpu_pch_snapshot[i].reg);
++           if (cpu_pch_snapshot[i].val == val)
++               continue;
++
++           xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++                      "Register 0x%x (%s) changed from 0x%08x to 0x%08x\n",
++                      cpu_pch_snapshot[i].reg, cpu_pch_snapshot[i].name,
++                      (int)cpu_pch_snapshot[i].val, (int)val);
++
++           if (cpu_pch_snapshot[i].debug_output != NULL) {
++               char *before, *after;
++    
++               before = cpu_pch_snapshot[i].debug_output(pI830,
++                                                  cpu_pch_snapshot[i].reg,
++                                                  cpu_pch_snapshot[i].val);
++               after = cpu_pch_snapshot[i].debug_output(pI830,
++                                                 cpu_pch_snapshot[i].reg,
++                                                 val);
++               xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++                      "%s before: %s\n", cpu_pch_snapshot[i].name, before);
++               xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++                      "%s after: %s\n", cpu_pch_snapshot[i].name, after);
++
++           }
++        }
++    } else {
++        for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
++           uint32_t val = INREG(i830_snapshot[i].reg);
++           if (i830_snapshot[i].val == val)
++               continue;
+ 
+ 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		   "Register 0x%x (%s) changed from 0x%08x to 0x%08x\n",
+@@ -1284,7 +1317,7 @@ void i830CompareRegsToSnapshot(ScrnInfoP
+ 		       "%s before: %s\n", i830_snapshot[i].name, before);
+ 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		       "%s after: %s\n", i830_snapshot[i].name, after);
+-
++	  }
+ 	}
+     }
+ }
+--- src/i830_display.c	2009-08-28 16:21:01.562322696 +0800
++++ src/i830_display.c	2009-08-28 16:44:18.366589787 +0800
+@@ -1294,10 +1294,14 @@ ilk_crtc_enable(xf86CrtcPtr crtc)
+     temp = INREG(fdi_tx_reg);
+     temp |= FDI_TX_ENABLE;
+     temp |= FDI_DP_PORT_WIDTH_X4;
++    temp &= ~FDI_LINK_TRAIN_NONE;
++    temp |= FDI_LINK_TRAIN_PATTERN_1;
+     OUTREG(fdi_tx_reg, temp);
+     POSTING_READ(fdi_tx_reg);
+ 
+     temp = INREG(fdi_rx_reg);
++    temp &= ~FDI_LINK_TRAIN_NONE;
++    temp |= FDI_LINK_TRAIN_PATTERN_1;
+     OUTREG(fdi_rx_reg, temp | FDI_RX_ENABLE);
+     POSTING_READ(fdi_rx_reg);
+ 
+--- src/i830_driver.c	2009-08-28 16:21:01.564359735 +0800
++++ src/i830_driver.c	2009-08-28 16:52:06.343748484 +0800
+@@ -911,20 +911,31 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
+    I830Ptr  pI830 = I830PTR(pScrn);
+    int	    o, c;
+    Bool	    lvds_detected = FALSE;
++   Bool     found = FALSE;
+ 
+    /* everyone has at least a single analog output */
+    i830_crt_init(pScrn);
+ 
+-   if (IS_IGDNG(pI830))
+-       goto done;
+-
+    /* Set up integrated LVDS */
+-   if (IS_MOBILE(pI830) && !IS_I830(pI830))
++   if (IS_MOBILE(pI830) && !IS_I830(pI830) && !IS_IGDNG(pI830))
+       i830_lvds_init(pScrn);
++   if (IS_IGDNG(pI830)) {
++       if (INREG(HDMIB) & PORT_DETECTED) {
++          /* check SDVOB if possible */
++	  found = i830_sdvo_init(pScrn, HDMIB);
++          if (!found)
++              i830_hdmi_init(pScrn, HDMIB);
++       }
++
++       if (INREG(HDMIC) & PORT_DETECTED)
++          i830_hdmi_init(pScrn, HDMIC);
+ 
+-   if (IS_I9XX(pI830)) {
++       if (INREG(HDMID) & PORT_DETECTED)
++          i830_hdmi_init(pScrn, HDMID);
++   } else if (IS_I9XX(pI830)) {
++      found = FALSE;
+       if ((INREG(SDVOB) & SDVO_DETECTED) || pI830->force_sdvo_detect) {
+-	 Bool found = i830_sdvo_init(pScrn, SDVOB);
++	 found = i830_sdvo_init(pScrn, SDVOB);
+ 
+ 	 if (!found && SUPPORTS_INTEGRATED_HDMI(pI830))
+ 	    i830_hdmi_init(pScrn, SDVOB);
+@@ -941,11 +952,9 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
+    } else {
+       i830_dvo_init(pScrn);
+    }
+-   if (IS_I9XX(pI830) && IS_MOBILE(pI830))
++   if (IS_I9XX(pI830) && IS_MOBILE(pI830) && !IS_IGDNG(pI830))
+       i830_tv_init(pScrn);
+ 
+-done:
+-   
+    for (o = 0; o < config->num_output; o++)
+    {
+       xf86OutputPtr	   output = config->output[o];
+--- src/i830_hdmi.c	2009-08-27 16:06:09.763324775 +0800
++++ src/i830_hdmi.c	2009-08-28 16:46:52.999087947 +0800
+@@ -131,6 +131,47 @@ i830_hdmi_restore(xf86OutputPtr output)
+     OUTREG(dev_priv->output_reg, dev_priv->save_SDVO);
+ }
+ 
++static xf86OutputStatus
++ilk_hdmi_detect(xf86OutputPtr output)
++{
++    /* Check PCH display hotplug bits.
++       XXX hotplug detect not working? */
++    ScrnInfoPtr        pScrn = output->scrn;
++    I830OutputPrivatePtr intel_output = output->driver_private;
++    struct i830_hdmi_priv *dev_priv = intel_output->dev_priv;
++    I830Ptr pI830 = I830PTR(pScrn);
++    xf86OutputStatus status;
++    xf86MonPtr edid_mon;
++
++    edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
++    if (!edid_mon)
++       status = XF86OutputStatusDisconnected;
++    else
++       status = XF86OutputStatusConnected;
++
++    /*
++    if (xf86LoaderCheckSymbol("xf86MonitorIsHDMI") &&
++           xf86MonitorIsHDMI(edid_mon))
++       dev_priv->has_hdmi_sink = TRUE;
++
++    if (pI830->debug_modes) {
++       int num;
++       if (dev_priv->output_reg == HDMIB)
++           num = 1;
++       else if (dev_priv->output_reg == HDMIC)
++           num = 2;
++       else
++           num = 3;
++       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
++               "%s monitor detected on HDMI-%d\n",
++               dev_priv->has_hdmi_sink ? "HDMI" : "DVI",
++               num);
++    }
++    */
++    xfree(edid_mon);
++    return status;
++}
++
+ /**
+  * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect HDMI connection.
+  *
+@@ -150,6 +191,9 @@ i830_hdmi_detect(xf86OutputPtr output)
+ 
+     dev_priv->has_hdmi_sink = FALSE;
+ 
++    if (IS_IGDNG(pI830))
++       return ilk_hdmi_detect(output);
++
+     /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written 0xd.
+      * Failure to do so will result in spurious interrupts being
+      * generated on the port when a cable is not attached.
+@@ -234,9 +278,27 @@ i830_hdmi_init(ScrnInfoPtr pScrn, int ou
+     xf86OutputPtr output;
+     I830OutputPrivatePtr intel_output;
+     struct i830_hdmi_priv *dev_priv;
++    const char *output_name = NULL;
++
++    switch (output_reg) {
++       case SDVOB:
++           output_name = "HDMI-1";
++           break;
++       case SDVOC:
++           output_name = "HDMI-2";
++           break;
++       case HDMIB:
++           output_name = "HDMI-1";
++           break;
++       case HDMIC:
++           output_name = "HDMI-2";
++           break;
++       case HDMID:
++           output_name = "HDMI-3";
++           break;
++    }
++    output = xf86OutputCreate(pScrn, &i830_hdmi_output_funcs, output_name);
+ 
+-    output = xf86OutputCreate(pScrn, &i830_hdmi_output_funcs,
+-			      (output_reg == SDVOB) ? "HDMI-1" : "HDMI-2");
+     if (!output)
+ 	return;
+     intel_output = xnfcalloc(sizeof (I830OutputPrivateRec) +
+@@ -261,10 +323,15 @@ i830_hdmi_init(ScrnInfoPtr pScrn, int ou
+     /* Set up the DDC bus. */
+     if (output_reg == SDVOB)
+ 	I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOE, "HDMIDDC_B");
+-    else
+-	I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOD, "HDMIDDC_C");
++    else if (output_reg == SDVOC)
++       I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOD, "HDMIDDC_C");
++    else if (output_reg == HDMIB)
++       I830I2CInit(pScrn, &intel_output->pDDCBus, PCH_GPIOE, "HDMIDDC_B");
++    else if (output_reg == HDMIC)
++       I830I2CInit(pScrn, &intel_output->pDDCBus, PCH_GPIOD, "HDMIDDC_C");
++    else if (output_reg == HDMID)
++       I830I2CInit(pScrn, &intel_output->pDDCBus, PCH_GPIOF, "HDMIDDC_D");
+ 
+     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+-	       "HDMI output %d detected\n",
+-	       (output_reg == SDVOB) ? 1 : 2);
++		"HDMI output %s detected\n", output_name);
+ }
+--- src/i830_sdvo.c	2009-08-18 11:31:33.545853964 +0800
++++ src/i830_sdvo.c	2009-08-28 16:42:07.657213156 +0800
+@@ -127,6 +127,12 @@ static void i830_sdvo_write_sdvox(xf86Ou
+     uint32_t		    bval = val, cval = val;
+     int			    i;
+ 
++    if (IS_IGDNG(pI830)) {
++       for (i = 0; i < 2; i++)
++           OUTREG(HDMIB, val);
++       return;
++    }
++
+     if (dev_priv->output_device == SDVOB)
+ 	cval = INREG(SDVOC);
+     else
+@@ -263,7 +269,7 @@ const static struct _sdvo_cmd_name {
+ 
+ static I2CSlaveAddr slaveAddr;
+ 
+-#define SDVO_NAME(dev_priv) ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC")
++#define SDVO_NAME(dev_priv) ((((dev_priv)->output_device == SDVOB) || ((dev_priv)->output_device == HDMIB)) ? "SDVOB" : "SDVOC")
+ #define SDVO_PRIV(output)   ((struct i830_sdvo_priv *) (output)->dev_priv)
+ 
+ /**
+@@ -1788,8 +1794,10 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
+      */
+     if (output_device == SDVOB)
+ 	I830I2CInit(pScrn, &i2cbus, GPIOE, "SDVOCTRL_E for SDVOB");
+-    else
+-	I830I2CInit(pScrn, &i2cbus, GPIOE, "SDVOCTRL_E for SDVOC");
++    else if (output_device == SDVOC)
++        I830I2CInit(pScrn, &i2cbus, GPIOE, "SDVOCTRL_E for SDVOC");
++    else if (output_device == HDMIB)
++       I830I2CInit(pScrn, &i2cbus, PCH_GPIOE, "SDVOCTRL_E for SDVOB");
+ 
+     if (i2cbus == NULL)
+     {
+@@ -1797,7 +1805,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
+ 	return FALSE;
+     }
+ 
+-    if (output_device == SDVOB) {
++    if (output_device == SDVOB || output_device == HDMIB) {
+ 	dev_priv->d.DevName = "SDVO Controller B";
+ 	dev_priv->d.SlaveAddr = 0x70;
+ 	name_suffix="-1";
+@@ -1826,7 +1834,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
+ 	if (!i830_sdvo_read_byte_quiet(output, i, &ch[i])) {
+ 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ 		       "No SDVO device found on SDVO%c\n",
+-		       output_device == SDVOB ? 'B' : 'C');
++			(output_device == SDVOB || output_device == HDMIB) ? 'B' : 'C');
+ 	    xf86OutputDestroy (output);
+ 	    return FALSE;
+ 	}
+@@ -1843,7 +1851,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
+ 	xf86OutputDestroy (output);
+ 	return FALSE;
+     }
+-    if (output_device == SDVOB)
++    if (output_device == SDVOB || output_device == HDMIB)
+         ddcbus->BusName = "SDVOB DDC Bus";
+     else
+         ddcbus->BusName = "SDVOC DDC Bus";
+--- src/reg_dumper/main.c	2009-08-18 11:31:33.533384332 +0800
++++ src/reg_dumper/main.c	2009-08-28 16:25:14.954893827 +0800
+@@ -84,7 +84,10 @@ int main(int argc, char **argv)
+     scrn.scrnIndex = 0;
+     scrn.pI830 = &i830;
+ 
+-    i830DumpRegs(&scrn);
++    if (IS_IGDNG((&i830)))
++       IlkDumpRegs(&scrn);
++    else
++       i830DumpRegs(&scrn);
+ 
+     return 0;
+ }
+
+--- configure.ac	2009-08-27 16:05:51.340831448 +0800
++++ configure.ac	2009-08-28 17:09:45.112978233 +0800
+@@ -42,6 +42,15 @@ AC_PROG_CC
+ AM_PROG_CC_C_O
+ 
+ AC_CHECK_PROG(gen4asm, [intel-gen4asm], yes, no)
++
++if test x$gen4asm != xno; then
++ intel-gen4asm -g 5 src/exa_sf.g4a > /dev/null
++
++ if test "$?" != "0"; then
++ echo "Error: Require new intel-gen4asm with -g option!"
++ exit 1
++ fi
++fi
+ AM_CONDITIONAL(HAVE_GEN4ASM, test x$gen4asm = xyes)
+ 
+ AC_CHECK_HEADERS(sys/mman.h)
+--- src/Makefile.am	2009-08-28 13:21:29.201753370 +0800
++++ src/Makefile.am	2009-08-28 17:09:45.113527807 +0800
+@@ -189,11 +189,33 @@ INTEL_G4B = 				\
+ 	exa_wm_yuv_rgb.g4b		\
+ 	exa_wm_xy.g4b
+ 
++INTEL_G4B_GEN5 = \
++	packed_yuv_sf.g4b.gen5 \
++	packed_yuv_wm.g4b.gen5 \
++	exa_sf.g4b.gen5 \
++	exa_sf_mask.g4b.gen5 \
++	exa_wm_src_affine.g4b.gen5 \
++	exa_wm_src_projective.g4b.gen5 \
++	exa_wm_src_sample_argb.g4b.gen5 \
++	exa_wm_src_sample_a.g4b.gen5 \
++	exa_wm_src_sample_planar.g4b.gen5 \
++	exa_wm_mask_affine.g4b.gen5 \
++	exa_wm_mask_projective.g4b.gen5 \
++	exa_wm_mask_sample_argb.g4b.gen5 \
++	exa_wm_mask_sample_a.g4b.gen5 \
++	exa_wm_noca.g4b.gen5 \
++	exa_wm_ca.g4b.gen5 \
++	exa_wm_ca_srcalpha.g4b.gen5 \
++	exa_wm_write.g4b.gen5 \
++	exa_wm_yuv_rgb.g4b.gen5 \
++	exa_wm_xy.g4b.gen5
++
+ EXTRA_DIST = 		\
+ 	$(XMODE_SRCS)	\
+ 	$(INTEL_G4A)	\
+ 	$(INTEL_G4I)	\
+ 	$(INTEL_G4B)	\
++	$(INTEL_G4B_GEN5) \
+ 	$(INTEL_DRI_SRCS) \
+ 	$(INTEL_XVMC_SRCS)
+ 
+@@ -201,14 +223,14 @@ if HAVE_GEN4ASM
+ 
+ SUFFIXES = .g4a .g4b
+ .g4a.g4b:
+-	m4 -I$(srcdir) -s $< > $*.g4m && intel-gen4asm -o $@ $*.g4m && rm $*.g4m
++	m4 -I$(srcdir) -s $< > $*.g4m && intel-gen4asm -o $@ $*.g4m && intel-gen4asm -g 5 -o [email protected] $*.g4m && rm $*.g4m
+ 
+ $(INTEL_G4B): $(INTEL_G4I)
+ 
+ BUILT_SOURCES= $(INTEL_G4B)
+ 
+ clean-local:
+-	-rm -f $(INTEL_G4B)
++	-rm -f $(INTEL_G4B) $(INTEL_G4B_GEN5)
+ endif
+ 
+ if XMODES
+--- src/brw_structs.h	2009-08-27 16:05:47.138925290 +0800
++++ src/brw_structs.h	2009-08-31 10:51:05.155997832 +0800
+@@ -838,6 +838,27 @@ struct brw_wm_unit_state
+    
+    float global_depth_offset_constant;  
+    float global_depth_offset_scale;   
++
++   struct {
++      unsigned int pad0:1;
++      unsigned int grf_reg_count_1:3; 
++      unsigned int pad1:2;
++      unsigned int kernel_start_pointer_1:26;
++   } wm8;       
++
++   struct {
++      unsigned int pad0:1;
++      unsigned int grf_reg_count_2:3; 
++      unsigned int pad1:2;
++      unsigned int kernel_start_pointer_2:26;
++   } wm9;       
++
++   struct {
++      unsigned int pad0:1;
++      unsigned int grf_reg_count_3:3; 
++      unsigned int pad1:2;
++      unsigned int kernel_start_pointer_3:26;
++   } wm10; 
+ };
+ 
+ /* The hardware supports two different modes for border color. The
+--- src/exa_sf.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_sf.g4b.gen5	2009-08-28 17:09:45.113752076 +0800
+@@ -0,0 +1,15 @@
++   { 0x00400031, 0x20c01fbd, 0x1069002c, 0x02100001 },
++   { 0x00400001, 0x206003be, 0x00690060, 0x00000000 },
++   { 0x00400040, 0x20e077bd, 0x00690080, 0x006940a0 },
++   { 0x00400041, 0x202077be, 0x006900e0, 0x000000c0 },
++   { 0x00400040, 0x20e077bd, 0x006900a0, 0x00694060 },
++   { 0x00400041, 0x204077be, 0x006900e0, 0x000000c8 },
++   { 0x00600031, 0x20001fbc, 0x648d0000, 0x8808c800 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+--- src/exa_sf_mask.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_sf_mask.g4b.gen5	2009-08-28 17:09:45.113956431 +0800
+@@ -0,0 +1,15 @@
++   { 0x00400031, 0x20c01fbd, 0x1069002c, 0x02100001 },
++   { 0x00600001, 0x206003be, 0x008d0060, 0x00000000 },
++   { 0x00600040, 0x20e077bd, 0x008d0080, 0x008d40a0 },
++   { 0x00600041, 0x202077be, 0x008d00e0, 0x000000c0 },
++   { 0x00600040, 0x20e077bd, 0x008d00a0, 0x008d4060 },
++   { 0x00600041, 0x204077be, 0x008d00e0, 0x000000c8 },
++   { 0x00600031, 0x20001fbc, 0x648d0000, 0x8808c800 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+--- src/exa_wm_ca.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_wm_ca.g4b.gen5	2009-08-28 17:09:45.114151909 +0800
+@@ -0,0 +1,4 @@
++   { 0x00802041, 0x21c077bd, 0x008d01c0, 0x008d02c0 },
++   { 0x00802041, 0x220077bd, 0x008d0200, 0x008d0300 },
++   { 0x00802041, 0x224077bd, 0x008d0240, 0x008d0340 },
++   { 0x00802041, 0x228077bd, 0x008d0280, 0x008d0380 },
+--- src/exa_wm_ca_srcalpha.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_wm_ca_srcalpha.g4b.gen5	2009-08-28 17:09:45.114346857 +0800
+@@ -0,0 +1,4 @@
++   { 0x00802041, 0x21c077bd, 0x008d02c0, 0x008d0280 },
++   { 0x00802041, 0x220077bd, 0x008d0300, 0x008d0280 },
++   { 0x00802041, 0x224077bd, 0x008d0340, 0x008d0280 },
++   { 0x00802041, 0x228077bd, 0x008d0380, 0x008d0280 },
+--- src/exa_wm_mask_affine.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_wm_mask_affine.g4b.gen5	2009-08-28 17:09:45.114542449 +0800
+@@ -0,0 +1,8 @@
++   { 0x00802041, 0x23c077bd, 0x008d0100, 0x000000a0 },
++   { 0x00802041, 0x238077bd, 0x008d0140, 0x000000a4 },
++   { 0x00802040, 0x23c077bd, 0x008d03c0, 0x008d0380 },
++   { 0x00802040, 0x210077be, 0x008d03c0, 0x000000ac },
++   { 0x00802041, 0x23c077bd, 0x008d0100, 0x000000b0 },
++   { 0x00802041, 0x238077bd, 0x008d0140, 0x000000b4 },
++   { 0x00802040, 0x23c077bd, 0x008d03c0, 0x008d0380 },
++   { 0x00802040, 0x214077be, 0x008d03c0, 0x000000bc },
+--- src/exa_wm_mask_projective.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_wm_mask_projective.g4b.gen5	2009-08-28 17:09:45.114742687 +0800
+@@ -0,0 +1,16 @@
++   { 0x00802041, 0x23c077bd, 0x008d0100, 0x000000c0 },
++   { 0x00802041, 0x238077bd, 0x008d0140, 0x000000c4 },
++   { 0x00802040, 0x23c077bd, 0x008d03c0, 0x008d0380 },
++   { 0x00802040, 0x23c077bd, 0x008d03c0, 0x000000cc },
++   { 0x00600031, 0x21801fbd, 0x108d03c0, 0x02100001 },
++   { 0x00600031, 0x21a01fbd, 0x108d03e0, 0x02100001 },
++   { 0x00802041, 0x23c077bd, 0x008d0100, 0x000000a0 },
++   { 0x00802041, 0x238077bd, 0x008d0140, 0x000000a4 },
++   { 0x00802040, 0x23c077bd, 0x008d03c0, 0x008d0380 },
++   { 0x00802040, 0x23c077bd, 0x008d03c0, 0x000000ac },
++   { 0x00802041, 0x210077be, 0x008d03c0, 0x008d0180 },
++   { 0x00802041, 0x23c077bd, 0x008d0100, 0x000000b0 },
++   { 0x00802041, 0x238077bd, 0x008d0140, 0x000000b4 },
++   { 0x00802040, 0x23c077bd, 0x008d03c0, 0x008d0380 },
++   { 0x00802040, 0x23c077bd, 0x008d03c0, 0x000000bc },
++   { 0x00802041, 0x214077be, 0x008d03c0, 0x008d0180 },
+--- src/exa_wm_mask_sample_a.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_wm_mask_sample_a.g4b.gen5	2009-08-28 17:09:45.114947699 +0800
+@@ -0,0 +1,2 @@
++   { 0x00000201, 0x20080061, 0x00000000, 0x00007000 },
++   { 0x07800031, 0x23801d29, 0x208d0000, 0x0a2a0102 },
+--- src/exa_wm_mask_sample_argb.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_wm_mask_sample_argb.g4b.gen5	2009-08-28 17:09:45.115140772 +0800
+@@ -0,0 +1,2 @@
++   { 0x00000201, 0x20080061, 0x00000000, 0x00000000 },
++   { 0x07800031, 0x22c01d29, 0x208d0000, 0x0a8a0102 },
+--- src/exa_wm_noca.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_wm_noca.g4b.gen5	2009-08-28 17:09:45.115330284 +0800
+@@ -0,0 +1,4 @@
++   { 0x00802041, 0x21c077bd, 0x008d01c0, 0x008d0380 },
++   { 0x00802041, 0x220077bd, 0x008d0200, 0x008d0380 },
++   { 0x00802041, 0x224077bd, 0x008d0240, 0x008d0380 },
++   { 0x00802041, 0x228077bd, 0x008d0280, 0x008d0380 },
+--- src/exa_wm_src_affine.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_wm_src_affine.g4b.gen5	2009-08-28 17:09:45.115524007 +0800
+@@ -0,0 +1,8 @@
++   { 0x00802041, 0x23c077bd, 0x008d0100, 0x00000060 },
++   { 0x00802041, 0x238077bd, 0x008d0140, 0x00000064 },
++   { 0x00802040, 0x23c077bd, 0x008d03c0, 0x008d0380 },
++   { 0x00802040, 0x204077be, 0x008d03c0, 0x0000006c },
++   { 0x00802041, 0x23c077bd, 0x008d0100, 0x00000070 },
++   { 0x00802041, 0x238077bd, 0x008d0140, 0x00000074 },
++   { 0x00802040, 0x23c077bd, 0x008d03c0, 0x008d0380 },
++   { 0x00802040, 0x208077be, 0x008d03c0, 0x0000007c },
+--- src/exa_wm_src_projective.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_wm_src_projective.g4b.gen5	2009-08-28 17:09:45.115718978 +0800
+@@ -0,0 +1,16 @@
++   { 0x00802041, 0x23c077bd, 0x008d0100, 0x00000080 },
++   { 0x00802041, 0x238077bd, 0x008d0140, 0x00000084 },
++   { 0x00802040, 0x23c077bd, 0x008d03c0, 0x008d0380 },
++   { 0x00802040, 0x23c077bd, 0x008d03c0, 0x0000008c },
++   { 0x00600031, 0x21801fbd, 0x108d03c0, 0x02100001 },
++   { 0x00600031, 0x21a01fbd, 0x108d03e0, 0x02100001 },
++   { 0x00802041, 0x23c077bd, 0x008d0100, 0x00000060 },
++   { 0x00802041, 0x238077bd, 0x008d0140, 0x00000064 },
++   { 0x00802040, 0x23c077bd, 0x008d03c0, 0x008d0380 },
++   { 0x00802040, 0x23c077bd, 0x008d03c0, 0x0000006c },
++   { 0x00802041, 0x204077be, 0x008d03c0, 0x008d0180 },
++   { 0x00802041, 0x23c077bd, 0x008d0100, 0x00000070 },
++   { 0x00802041, 0x238077bd, 0x008d0140, 0x00000074 },
++   { 0x00802040, 0x23c077bd, 0x008d03c0, 0x008d0380 },
++   { 0x00802040, 0x23c077bd, 0x008d03c0, 0x0000007c },
++   { 0x00802041, 0x208077be, 0x008d03c0, 0x008d0180 },
+--- src/exa_wm_src_sample_a.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_wm_src_sample_a.g4b.gen5	2009-08-28 17:09:45.115909020 +0800
+@@ -0,0 +1,2 @@
++   { 0x00000201, 0x20080061, 0x00000000, 0x00007000 },
++   { 0x01800031, 0x22801d29, 0x208d0000, 0x0a2a0001 },
+--- src/exa_wm_src_sample_argb.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_wm_src_sample_argb.g4b.gen5	2009-08-28 17:09:45.116097032 +0800
+@@ -0,0 +1,2 @@
++   { 0x00000201, 0x20080061, 0x00000000, 0x00000000 },
++   { 0x01800031, 0x21c01d29, 0x208d0000, 0x0a8a0001 },
+--- src/exa_wm_src_sample_planar.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_wm_src_sample_planar.g4b.gen5	2009-08-28 17:09:45.116285642 +0800
+@@ -0,0 +1,4 @@
++   { 0x00000201, 0x20080061, 0x00000000, 0x0000e000 },
++   { 0x01800031, 0x22001d29, 0x208d0000, 0x0a2a0001 },
++   { 0x01800031, 0x21c01d29, 0x208d0000, 0x0a2a0203 },
++   { 0x01800031, 0x22401d29, 0x208d0000, 0x0a2a0405 },
+--- src/exa_wm_write.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_wm_write.g4b.gen5	2009-08-28 17:09:45.116480771 +0800
+@@ -0,0 +1,18 @@
++   { 0x00600001, 0x204003be, 0x008d01c0, 0x00000000 },
++   { 0x00600001, 0x206003be, 0x008d0200, 0x00000000 },
++   { 0x00600001, 0x208003be, 0x008d0240, 0x00000000 },
++   { 0x00600001, 0x20a003be, 0x008d0280, 0x00000000 },
++   { 0x00601001, 0x20c003be, 0x008d01e0, 0x00000000 },
++   { 0x00601001, 0x20e003be, 0x008d0220, 0x00000000 },
++   { 0x00601001, 0x210003be, 0x008d0260, 0x00000000 },
++   { 0x00601001, 0x212003be, 0x008d02a0, 0x00000000 },
++   { 0x00600201, 0x20200022, 0x008d0020, 0x00000000 },
++   { 0x00800031, 0x24001d28, 0x548d0000, 0x94084800 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
++   { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+--- src/exa_wm_xy.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_wm_xy.g4b.gen5	2009-08-28 17:09:45.116666456 +0800
+@@ -0,0 +1,4 @@
++   { 0x00800040, 0x23c06d29, 0x00480028, 0x10101010 },
++   { 0x00800040, 0x23806d29, 0x0048002a, 0x11001100 },
++   { 0x00802040, 0x2100753d, 0x008d03c0, 0x00004020 },
++   { 0x00802040, 0x2140753d, 0x008d0380, 0x00004024 },
+--- src/exa_wm_yuv_rgb.g4b.gen5	1970-01-01 08:00:00.000000000 +0800
++++ src/exa_wm_yuv_rgb.g4b.gen5	2009-08-28 17:09:45.116859901 +0800
+@@ -0,0 +1,12 @@
++   { 0x00802040, 0x23007fbd, 0x008d0200, 0xbd808081 },
++   { 0x00802041, 0x23007fbd, 0x008d0300, 0x3f94fdf4 },
++   { 0x00802040, 0x22c07fbd, 0x008d01c0, 0xbf008084 },
++   { 0x00802040, 0x23407fbd, 0x008d0240, 0xbf008084 },
++   { 0x00802001, 0x240003bc, 0x008d0300, 0x00000000 },
++   { 0x80802048, 0x21c07fbd, 0x008d02c0, 0x3fcc49ba },
++   { 0x00802001, 0x240003bc, 0x008d0300, 0x00000000 },
++   { 0x00802048, 0x24007fbc, 0x008d02c0, 0xbf5020c5 },
++   { 0x80802048, 0x22007fbd, 0x008d0340, 0xbec8b439 },
++   { 0x00802001, 0x240003bc, 0x008d0300, 0x00000000 },
++   { 0x80802048, 0x22407fbd, 0x008d0340, 0x40011687 },
++   { 0x00802001, 0x228003fd, 0x00000000, 0x3f800000 },
+--- src/i830.h	2009-08-28 13:21:29.204256913 +0800
++++ src/i830.h	2009-08-31 11:13:25.081009052 +0800
+@@ -1075,6 +1075,8 @@ static inline int i830_fb_compression_su
+      */
+     if (IS_I965GM(pI830))
+ 	return FALSE;
++    if (IS_IGDNG(pI830))
++	return FALSE;
+     return TRUE;
+ }
+ 
+--- src/i830_exa.c	2009-08-28 16:21:01.564883804 +0800
++++ src/i830_exa.c	2009-08-31 11:41:57.280365152 +0800
+@@ -705,17 +705,10 @@ I830EXAInit(ScreenPtr pScreen)
+ 	pI830->EXADriverPtr->Composite = i915_composite;
+     	pI830->EXADriverPtr->DoneComposite = i830_done_composite;
+     } else {
+-        if (IS_IGDNG(pI830)) {
+-          pI830->EXADriverPtr->CheckComposite = NULL;
+-          pI830->EXADriverPtr->PrepareComposite = NULL;
+-          pI830->EXADriverPtr->Composite = NULL;
+-          pI830->EXADriverPtr->DoneComposite = NULL;
+-	} else {
+  	   pI830->EXADriverPtr->CheckComposite = i965_check_composite;
+  	   pI830->EXADriverPtr->PrepareComposite = i965_prepare_composite;
+  	   pI830->EXADriverPtr->Composite = i965_composite;
+  	   pI830->EXADriverPtr->DoneComposite = i830_done_composite;
+-	}
+     }
+ #if EXA_VERSION_MINOR >= 2
+     if (!pI830->use_drm_mode)
+--- src/i965_render.c	2009-08-27 16:05:47.148874047 +0800
++++ src/i965_render.c	2009-08-31 11:12:11.663192920 +0800
+@@ -390,6 +390,89 @@ static const uint32_t ps_kernel_masknoca
+ #include "exa_wm_write.g4b"
+ };
+ 
++/* new programs for ILK */
++static const uint32_t sf_kernel_static_gen5[][4] = {
++#include "exa_sf.g4b.gen5"
++};
++
++static const uint32_t sf_kernel_mask_static_gen5[][4] = {
++#include "exa_sf_mask.g4b.gen5"
++};
++
++static const uint32_t ps_kernel_nomask_affine_static_gen5 [][4] = {
++#include "exa_wm_xy.g4b.gen5"
++#include "exa_wm_src_affine.g4b.gen5"
++#include "exa_wm_src_sample_argb.g4b.gen5"
++#include "exa_wm_write.g4b.gen5"
++};
++
++static const uint32_t ps_kernel_nomask_projective_static_gen5 [][4] = {
++#include "exa_wm_xy.g4b.gen5"
++#include "exa_wm_src_projective.g4b.gen5"
++#include "exa_wm_src_sample_argb.g4b.gen5"
++#include "exa_wm_write.g4b.gen5"
++};
++
++static const uint32_t ps_kernel_maskca_affine_static_gen5 [][4] = {
++#include "exa_wm_xy.g4b.gen5"
++#include "exa_wm_src_affine.g4b.gen5"
++#include "exa_wm_src_sample_argb.g4b.gen5"
++#include "exa_wm_mask_affine.g4b.gen5"
++#include "exa_wm_mask_sample_argb.g4b.gen5"
++#include "exa_wm_ca.g4b.gen5"
++#include "exa_wm_write.g4b.gen5"
++};
++
++static const uint32_t ps_kernel_maskca_projective_static_gen5 [][4] = {
++#include "exa_wm_xy.g4b.gen5"
++#include "exa_wm_src_projective.g4b.gen5"
++#include "exa_wm_src_sample_argb.g4b.gen5"
++#include "exa_wm_mask_projective.g4b.gen5"
++#include "exa_wm_mask_sample_argb.g4b.gen5"
++#include "exa_wm_ca.g4b.gen5"
++#include "exa_wm_write.g4b.gen5"
++};
++
++static const uint32_t ps_kernel_maskca_srcalpha_affine_static_gen5 [][4] = {
++#include "exa_wm_xy.g4b.gen5"
++#include "exa_wm_src_affine.g4b.gen5"
++#include "exa_wm_src_sample_a.g4b.gen5"
++#include "exa_wm_mask_affine.g4b.gen5"
++#include "exa_wm_mask_sample_argb.g4b.gen5"
++#include "exa_wm_ca_srcalpha.g4b.gen5"
++#include "exa_wm_write.g4b.gen5"
++};
++
++static const uint32_t ps_kernel_maskca_srcalpha_projective_static_gen5 [][4] = {
++#include "exa_wm_xy.g4b.gen5"
++#include "exa_wm_src_projective.g4b.gen5"
++#include "exa_wm_src_sample_a.g4b.gen5"
++#include "exa_wm_mask_projective.g4b.gen5"
++#include "exa_wm_mask_sample_argb.g4b.gen5"
++#include "exa_wm_ca_srcalpha.g4b.gen5"
++#include "exa_wm_write.g4b.gen5"
++};
++
++static const uint32_t ps_kernel_masknoca_affine_static_gen5 [][4] = {
++#include "exa_wm_xy.g4b.gen5"
++#include "exa_wm_src_affine.g4b.gen5"
++#include "exa_wm_src_sample_argb.g4b.gen5"
++#include "exa_wm_mask_affine.g4b.gen5"
++#include "exa_wm_mask_sample_a.g4b.gen5"
++#include "exa_wm_noca.g4b.gen5"
++#include "exa_wm_write.g4b.gen5"
++};
++
++static const uint32_t ps_kernel_masknoca_projective_static_gen5 [][4] = {
++#include "exa_wm_xy.g4b.gen5"
++#include "exa_wm_src_projective.g4b.gen5"
++#include "exa_wm_src_sample_argb.g4b.gen5"
++#include "exa_wm_mask_projective.g4b.gen5"
++#include "exa_wm_mask_sample_a.g4b.gen5"
++#include "exa_wm_noca.g4b.gen5"
++#include "exa_wm_write.g4b.gen5"
++};
++
+ #define WM_STATE_DECL(kernel) \
+     struct brw_wm_unit_state wm_state_ ## kernel[SAMPLER_STATE_FILTER_COUNT] \
+ 						[SAMPLER_STATE_EXTEND_COUNT] \
+@@ -435,7 +518,9 @@ struct wm_kernel_info {
+     void *data;
+     unsigned int size;
+     Bool has_mask;
+-} wm_kernels[] = {
++};
++
++static struct wm_kernel_info wm_kernels[] = {
+     KERNEL(WM_KERNEL_NOMASK_AFFINE,
+ 	   ps_kernel_nomask_affine_static, FALSE),
+     KERNEL(WM_KERNEL_NOMASK_PROJECTIVE,
+@@ -453,6 +538,26 @@ struct wm_kernel_info {
+     KERNEL(WM_KERNEL_MASKNOCA_PROJECTIVE,
+ 	   ps_kernel_masknoca_projective_static, TRUE),
+ };
++
++static struct wm_kernel_info wm_kernels_gen5[] = {
++    KERNEL(WM_KERNEL_NOMASK_AFFINE,
++	   ps_kernel_nomask_affine_static_gen5, FALSE),
++    KERNEL(WM_KERNEL_NOMASK_PROJECTIVE,
++	   ps_kernel_nomask_projective_static_gen5, FALSE),
++    KERNEL(WM_KERNEL_MASKCA_AFFINE,
++	   ps_kernel_maskca_affine_static_gen5, TRUE),
++    KERNEL(WM_KERNEL_MASKCA_PROJECTIVE,
++	   ps_kernel_maskca_projective_static_gen5, TRUE),
++    KERNEL(WM_KERNEL_MASKCA_SRCALPHA_AFFINE,
++	   ps_kernel_maskca_srcalpha_affine_static_gen5, TRUE),
++    KERNEL(WM_KERNEL_MASKCA_SRCALPHA_PROJECTIVE,
++	   ps_kernel_maskca_srcalpha_projective_static_gen5, TRUE),
++    KERNEL(WM_KERNEL_MASKNOCA_AFFINE,
++	   ps_kernel_masknoca_affine_static_gen5, TRUE),
++    KERNEL(WM_KERNEL_MASKNOCA_PROJECTIVE,
++	   ps_kernel_masknoca_projective_static_gen5, TRUE),
++};
++
+ #undef KERNEL
+ 
+ typedef struct _brw_cc_unit_state_padded {
+@@ -768,7 +873,10 @@ gen4_create_wm_state(ScrnInfoPtr scrn,
+     wm_state->thread3.dispatch_grf_start_reg = 3; /* must match kernel */
+ 
+     wm_state->wm4.stats_enable = 1;  /* statistic */
+-    wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
++    if (IS_IGDNG(pI830))
++        wm_state->wm4.sampler_count = 0; /* hardware requirement */
++    else
++        wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
+     wm_state->wm4.sampler_state_pointer =
+ 	intel_emit_reloc(wm_state_bo, offsetof(struct brw_wm_unit_state, wm4),
+ 			 sampler_bo,
+@@ -794,6 +902,12 @@ gen4_create_wm_state(ScrnInfoPtr scrn,
+ 	wm_state->thread3.urb_entry_read_length = 2;
+     }
+ 
++    /* binding table entry count is only used for prefetching, and it has to 
++     * be set 0 for IGDNG
++     */
++    if (IS_IGDNG(pI830))
++        wm_state->thread1.binding_table_entry_count = 0;
++
+     drm_intel_bo_unmap(wm_state_bo);
+ 
+     return wm_state_bo;
+@@ -819,11 +933,15 @@ gen4_create_cc_viewport(ScrnInfoPtr scrn
+ static drm_intel_bo *
+ gen4_create_vs_unit_state(ScrnInfoPtr scrn)
+ {
++    I830Ptr pI830 = I830PTR(scrn);
+     struct brw_vs_unit_state vs_state;
+     memset(&vs_state, 0, sizeof(vs_state));
+ 
+     /* Set up the vertex shader to be disabled (passthrough) */
+-    vs_state.thread4.nr_urb_entries = URB_VS_ENTRIES;
++    if (IS_IGDNG(pI830))
++        vs_state.thread4.nr_urb_entries = URB_VS_ENTRIES >> 2; /* hardware requirement */
++    else
++        vs_state.thread4.nr_urb_entries = URB_VS_ENTRIES;
+     vs_state.thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
+     vs_state.vs6.vs_enable = 0;
+     vs_state.vs6.vert_cache_disable = 1;
+@@ -1040,10 +1158,13 @@ i965_emit_composite_state(ScrnInfoPtr pS
+ 	ADVANCE_BATCH();
+     }
+     {
+-        BEGIN_BATCH(12);
++        if (IS_IGDNG(pI830))
++            BEGIN_BATCH(14);
++        else
++            BEGIN_BATCH(12);
+ 
+         /* Match Mesa driver setup */
+-	if (IS_G4X(pI830))
++	if (IS_G4X(pI830) || IS_IGDNG(pI830))
+ 	    OUT_BATCH(NEW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
+ 	else
+ 	    OUT_BATCH(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
+@@ -1055,15 +1176,29 @@ i965_emit_composite_state(ScrnInfoPtr pS
+ 	/* Zero out the two base address registers so all offsets are
+ 	 * absolute.
+ 	 */
+-	OUT_BATCH(BRW_STATE_BASE_ADDRESS | 4);
+-	OUT_BATCH(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
+-	OUT_BATCH(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
+-	OUT_BATCH(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
+-	/* general state max addr, disabled */
+-	OUT_BATCH(0x10000000 | BASE_ADDRESS_MODIFY);
+-	/* media object state max addr, disabled */
+-	OUT_BATCH(0x10000000 | BASE_ADDRESS_MODIFY);
+-
++        if (IS_IGDNG(pI830)) {
++            OUT_BATCH(BRW_STATE_BASE_ADDRESS | 6);
++            OUT_BATCH(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
++            OUT_BATCH(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
++            OUT_BATCH(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
++            OUT_BATCH(0 | BASE_ADDRESS_MODIFY);  /* Instruction base address */
++            /* general state max addr, disabled */
++            OUT_BATCH(0x10000000 | BASE_ADDRESS_MODIFY);
++            /* media object state max addr, disabled */
++            OUT_BATCH(0x10000000 | BASE_ADDRESS_MODIFY);
++            /* Instruction max addr, disabled */
++            OUT_BATCH(0x10000000 | BASE_ADDRESS_MODIFY);
++        } else {
++
++   	    OUT_BATCH(BRW_STATE_BASE_ADDRESS | 4);
++	    OUT_BATCH(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
++	    OUT_BATCH(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
++	    OUT_BATCH(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
++	    /* general state max addr, disabled */
++	    OUT_BATCH(0x10000000 | BASE_ADDRESS_MODIFY);
++	    /* media object state max addr, disabled */
++	    OUT_BATCH(0x10000000 | BASE_ADDRESS_MODIFY);
++        }
+ 	/* Set system instruction pointer */
+ 	OUT_BATCH(BRW_STATE_SIP | 0);
+ 	OUT_RELOC(render_state->sip_kernel_bo,
+@@ -1074,10 +1209,14 @@ i965_emit_composite_state(ScrnInfoPtr pS
+     {
+ 	BEGIN_BATCH(26);
+ 	/* Pipe control */
+-	OUT_BATCH(BRW_PIPE_CONTROL |
+-		  BRW_PIPE_CONTROL_NOWRITE |
+-		  BRW_PIPE_CONTROL_IS_FLUSH |
+-		  2);
++	int pipe_ctrl;        
++	if (IS_IGDNG(pI830))
++            pipe_ctrl = BRW_PIPE_CONTROL_NOWRITE;
++	else
++            pipe_ctrl = BRW_PIPE_CONTROL_NOWRITE | BRW_PIPE_CONTROL_IS_FLUSH;
++
++	OUT_BATCH(BRW_PIPE_CONTROL | pipe_ctrl | 2);
++
+ 	OUT_BATCH(0);			       /* Destination address */
+ 	OUT_BATCH(0);			       /* Immediate data low DW */
+ 	OUT_BATCH(0);			       /* Immediate data high DW */
+@@ -1174,32 +1313,75 @@ i965_emit_composite_state(ScrnInfoPtr pS
+ 	    src_format = BRW_SURFACEFORMAT_R32G32B32_FLOAT;
+ 	    w_component = BRW_VFCOMPONENT_STORE_SRC;
+ 	}
+-	BEGIN_BATCH(pMask?7:5);
+-	/* Set up our vertex elements, sourced from the single vertex buffer.
+-	 * that will be set up later.
+-	 */
+-	
+-	OUT_BATCH(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * (1 + nelem)) - 1));
++        if (IS_IGDNG(pI830)) {
++            BEGIN_BATCH(pMask?9:7);
++	    /*
++	     * The reason to add this extra vertex element in the header is that
++	     * IGDNG has different vertex header definition and origin method to
++	     * set destination element offset doesn't exist anymore, which means
++	     * hardware requires a predefined vertex element layout.
++	     *
++	     * haihao proposed this approach to fill the first vertex element, so
++	     * origin layout for Gen4 doesn't need to change, and origin shader
++	     * programs behavior is also kept.
++	     *
++	     * I think this is not bad. - zhenyu
++	     */
++
++	    OUT_BATCH(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * (2 + nelem)) - 1));
++	    OUT_BATCH((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
++                      VE0_VALID |
++                      (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
++                      (0 << VE0_OFFSET_SHIFT));
++
++	    OUT_BATCH((BRW_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_0_SHIFT) |
++                      (BRW_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_1_SHIFT) |
++                      (BRW_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_2_SHIFT) |
++                      (BRW_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_3_SHIFT));
++        } else {
++            BEGIN_BATCH(pMask?7:5);
++            /* Set up our vertex elements, sourced from the single vertex buffer.
++             * that will be set up later.
++             */
++            OUT_BATCH(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * (1 + nelem)) - 1));
++        }
++
+ 	/* x,y */
+ 	OUT_BATCH((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+ 		  VE0_VALID |
+ 		  (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+-		  (0				<< VE0_OFFSET_SHIFT));
+-	OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC	<< VE1_VFCOMPONENT_0_SHIFT) |
+-		  (BRW_VFCOMPONENT_STORE_SRC	<< VE1_VFCOMPONENT_1_SHIFT) |
+-		  (BRW_VFCOMPONENT_STORE_1_FLT	<< VE1_VFCOMPONENT_2_SHIFT) |
+-		  (BRW_VFCOMPONENT_STORE_1_FLT	<< VE1_VFCOMPONENT_3_SHIFT) |
+-		  (4				<< VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
++		  (0                            << VE0_OFFSET_SHIFT));
++
++        if (IS_IGDNG(pI830))
++            OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC	<< VE1_VFCOMPONENT_0_SHIFT) |
++                      (BRW_VFCOMPONENT_STORE_SRC	<< VE1_VFCOMPONENT_1_SHIFT) |
++                      (BRW_VFCOMPONENT_STORE_1_FLT	<< VE1_VFCOMPONENT_2_SHIFT) |
++                      (BRW_VFCOMPONENT_STORE_1_FLT	<< VE1_VFCOMPONENT_3_SHIFT));
++        else
++            OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC	<< VE1_VFCOMPONENT_0_SHIFT) |
++                      (BRW_VFCOMPONENT_STORE_SRC	<< VE1_VFCOMPONENT_1_SHIFT) |
++                      (BRW_VFCOMPONENT_STORE_1_FLT	<< VE1_VFCOMPONENT_2_SHIFT) |
++                      (BRW_VFCOMPONENT_STORE_1_FLT	<< VE1_VFCOMPONENT_3_SHIFT) |
++                      (4				<< VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
++
+ 	/* u0, v0, w0 */
+ 	OUT_BATCH((0				<< VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+ 		  VE0_VALID					     |
+ 		  (src_format			<< VE0_FORMAT_SHIFT) |
+-		  ((2 * 4)			<< VE0_OFFSET_SHIFT)); /* offset vb in bytes */
+-	OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC	<< VE1_VFCOMPONENT_0_SHIFT) |
+-		  (BRW_VFCOMPONENT_STORE_SRC	<< VE1_VFCOMPONENT_1_SHIFT) |
+-		  (w_component			<< VE1_VFCOMPONENT_2_SHIFT) |
+-		  (BRW_VFCOMPONENT_STORE_1_FLT	<< VE1_VFCOMPONENT_3_SHIFT) |
+-		  ((4 + 4)			<< VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); /* VUE offset in dwords */
++		  ((2 * 4)                      << VE0_OFFSET_SHIFT)); /* offset vb in bytes */
++
++        if (IS_IGDNG(pI830))
++            OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC	<< VE1_VFCOMPONENT_0_SHIFT) |
++                      (BRW_VFCOMPONENT_STORE_SRC	<< VE1_VFCOMPONENT_1_SHIFT) |
++                      (w_component			<< VE1_VFCOMPONENT_2_SHIFT) |
++                      (BRW_VFCOMPONENT_STORE_1_FLT	<< VE1_VFCOMPONENT_3_SHIFT));
++        else
++            OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC	<< VE1_VFCOMPONENT_0_SHIFT) |
++                      (BRW_VFCOMPONENT_STORE_SRC	<< VE1_VFCOMPONENT_1_SHIFT) |
++                      (w_component			<< VE1_VFCOMPONENT_2_SHIFT) |
++                      (BRW_VFCOMPONENT_STORE_1_FLT	<< VE1_VFCOMPONENT_3_SHIFT) |
++                      ((4 + 4)			<< VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); /* VUE offset in dwords */
++
+ 	/* u1, v1, w1 */
+    	if (pMask) {
+ 	    OUT_BATCH((0			    << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+@@ -1207,11 +1389,18 @@ i965_emit_composite_state(ScrnInfoPtr pS
+ 		      (src_format		    << VE0_FORMAT_SHIFT) |
+ 		      (((2 + selem) * 4)    	    << VE0_OFFSET_SHIFT));  /* vb offset in bytes */
+ 	    
+-	    OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC    << VE1_VFCOMPONENT_0_SHIFT) |
+-		      (BRW_VFCOMPONENT_STORE_SRC    << VE1_VFCOMPONENT_1_SHIFT) |
+-		      (w_component		    << VE1_VFCOMPONENT_2_SHIFT) |
+-		      (BRW_VFCOMPONENT_STORE_1_FLT  << VE1_VFCOMPONENT_3_SHIFT) |
+-		      ((4 + 4 + 4)		    << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); /* VUE offset in dwords */
++            if (IS_IGDNG(pI830))
++                OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC    << VE1_VFCOMPONENT_0_SHIFT) |
++                          (BRW_VFCOMPONENT_STORE_SRC    << VE1_VFCOMPONENT_1_SHIFT) |
++                          (w_component		    << VE1_VFCOMPONENT_2_SHIFT) |
++                          (BRW_VFCOMPONENT_STORE_1_FLT  << VE1_VFCOMPONENT_3_SHIFT));
++            else
++                OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC    << VE1_VFCOMPONENT_0_SHIFT) |
++                          (BRW_VFCOMPONENT_STORE_SRC    << VE1_VFCOMPONENT_1_SHIFT) |
++                          (w_component		    << VE1_VFCOMPONENT_2_SHIFT) |
++                          (BRW_VFCOMPONENT_STORE_1_FLT  << VE1_VFCOMPONENT_3_SHIFT) |
++                          ((4 + 4 + 4)		    << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); /* VUE offset in dwords */
++
+    	}
+ 
+ 	ADVANCE_BATCH();
+@@ -1585,7 +1774,11 @@ i965_composite(PixmapPtr pDst, int srcX,
+ 	      VB0_VERTEXDATA |
+ 	      (render_state->vertex_size << VB0_BUFFER_PITCH_SHIFT));
+     OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, render_state->vb_offset * 4);
+-    OUT_BATCH(3);
++    if (IS_IGDNG(pI830))
++        OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, render_state->vb_offset * 4 + i * 4);
++    else
++        OUT_BATCH(3);
++
+     OUT_BATCH(0); // ignore for VERTEXDATA, but still there
+ 
+     OUT_BATCH(BRW_3DPRIMITIVE |
+@@ -1649,14 +1842,26 @@ gen4_render_state_init(ScrnInfoPtr pScrn
+     render_state->vs_state_bo = gen4_create_vs_unit_state(pScrn);
+ 
+     /* Set up the two SF states (one for blending with a mask, one without) */
+-    sf_kernel_bo = intel_bo_alloc_for_data(pScrn,
++    if (IS_IGDNG(pI830)) {
++	sf_kernel_bo = intel_bo_alloc_for_data(pScrn,
++					       sf_kernel_static_gen5,
++					       sizeof(sf_kernel_static_gen5),
++					       "sf kernel gen5");
++	sf_kernel_mask_bo = intel_bo_alloc_for_data(pScrn,
++						    sf_kernel_mask_static_gen5,
++						    sizeof(sf_kernel_mask_static_gen5),
++						    "sf mask kernel");
++    } else {
++
++        sf_kernel_bo = intel_bo_alloc_for_data(pScrn,
+ 					   sf_kernel_static,
+ 					   sizeof(sf_kernel_static),
+ 					   "sf kernel");
+-    sf_kernel_mask_bo = intel_bo_alloc_for_data(pScrn,
++        sf_kernel_mask_bo = intel_bo_alloc_for_data(pScrn,
+ 						sf_kernel_mask_static,
+ 						sizeof(sf_kernel_mask_static),
+ 						"sf mask kernel");
++    }
+     render_state->sf_state_bo = gen4_create_sf_state(pScrn, sf_kernel_bo);
+     render_state->sf_mask_state_bo = gen4_create_sf_state(pScrn,
+ 							  sf_kernel_mask_bo);
+@@ -1664,8 +1869,14 @@ gen4_render_state_init(ScrnInfoPtr pScrn
+     drm_intel_bo_unreference(sf_kernel_mask_bo);
+ 
+     for (m = 0; m < WM_KERNEL_COUNT; m++) {
+-	render_state->wm_kernel_bo[m] =
+-	    intel_bo_alloc_for_data(pScrn,
++	if (IS_IGDNG(pI830))
++	    render_state->wm_kernel_bo[m] =
++		intel_bo_alloc_for_data(pScrn,
++				        wm_kernels_gen5[m].data, wm_kernels_gen5[m].size,
++				        "WM kernel gen5");
++	else
++	    render_state->wm_kernel_bo[m] =
++	        intel_bo_alloc_for_data(pScrn,
+ 				    wm_kernels[m].data, wm_kernels[m].size,
+ 				    "WM kernel");
+     }
+@@ -1687,8 +1898,15 @@ gen4_render_state_init(ScrnInfoPtr pScrn
+ 						  border_color_bo);
+ 
+ 		    for (m = 0; m < WM_KERNEL_COUNT; m++) {
+-			render_state->wm_state_bo[m][i][j][k][l] =
+-			    gen4_create_wm_state(pScrn,
++			if (IS_IGDNG(pI830))
++			    render_state->wm_state_bo[m][i][j][k][l] =
++				gen4_create_wm_state(pScrn,
++						     wm_kernels_gen5[m].has_mask,
++						     render_state->wm_kernel_bo[m],
++						     sampler_state_bo);
++			else
++			    render_state->wm_state_bo[m][i][j][k][l] =
++			        gen4_create_wm_state(pScrn,
+ 						 wm_kernels[m].has_mask,
+ 						 render_state->wm_kernel_bo[m],
+ 						 sampler_state_bo);
+--- src/i965_video.c	2009-08-27 16:05:41.607286866 +0800
++++ src/i965_video.c	2009-08-28 17:39:10.881402774 +0800
+@@ -110,6 +110,27 @@ static const uint32_t ps_kernel_planar_s
+ #include "exa_wm_write.g4b"
+ };
+ 
++/* new program for ILK */
++static const uint32_t sf_kernel_static_gen5[][4] = {
++#include "exa_sf.g4b.gen5"
++};
++
++static const uint32_t ps_kernel_packed_static_gen5[][4] = {
++#include "exa_wm_xy.g4b.gen5"
++#include "exa_wm_src_affine.g4b.gen5"
++#include "exa_wm_src_sample_argb.g4b.gen5"
++#include "exa_wm_yuv_rgb.g4b.gen5"
++#include "exa_wm_write.g4b.gen5"
++};
++
++static const uint32_t ps_kernel_planar_static_gen5[][4] = {
++#include "exa_wm_xy.g4b.gen5"
++#include "exa_wm_src_affine.g4b.gen5"
++#include "exa_wm_src_sample_planar.g4b.gen5"
++#include "exa_wm_yuv_rgb.g4b.gen5"
++#include "exa_wm_write.g4b.gen5"
++};
++
+ #define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
+ #define MIN(a,b) ((a) < (b) ? (a) : (b))
+ 
+@@ -497,7 +518,10 @@ i965_create_vs_state(ScrnInfoPtr scrn)
+ 	return NULL;
+ 
+     /* Set up the vertex shader to be disabled (passthrough) */
+-    vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES;
++    if (IS_IGDNG(pI830))
++        vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES >> 2;
++    else
++        vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES;
+     vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
+     vs_state->vs6.vs_enable = 0;
+     vs_state->vs6.vert_cache_disable = 1;
+@@ -530,8 +554,12 @@ i965_create_sf_state(ScrnInfoPtr scrn)
+     drm_intel_bo *sf_bo, *kernel_bo;
+     struct brw_sf_unit_state *sf_state;
+ 
+-    kernel_bo = i965_create_program(scrn, &sf_kernel_static[0][0],
+-				    sizeof(sf_kernel_static));
++    if (IS_IGDNG(pI830))
++        kernel_bo = i965_create_program(scrn, &sf_kernel_static_gen5[0][0],
++                                        sizeof(sf_kernel_static_gen5));
++    else
++        kernel_bo = i965_create_program(scrn, &sf_kernel_static[0][0],
++   				        sizeof(sf_kernel_static));
+ 
+     if (!kernel_bo)
+ 	return NULL;
+@@ -590,10 +618,18 @@ i965_create_wm_state(ScrnInfoPtr scrn, d
+     struct brw_wm_unit_state *wm_state;
+ 
+     if (is_packed) {
+-	kernel_bo = i965_create_program(scrn, &ps_kernel_packed_static[0][0],
++	if (IS_IGDNG(pI830))
++	   kernel_bo = i965_create_program(scrn, &ps_kernel_packed_static_gen5[0][0],
++				sizeof(ps_kernel_packed_static_gen5));
++	else
++	   kernel_bo = i965_create_program(scrn, &ps_kernel_packed_static[0][0],
+ 					sizeof(ps_kernel_packed_static));
+     } else {
+-	kernel_bo = i965_create_program(scrn, &ps_kernel_planar_static[0][0],
++	if (IS_IGDNG(pI830))
++	    kernel_bo = i965_create_program(scrn, &ps_kernel_planar_static_gen5[0][0],
++	    sizeof(ps_kernel_planar_static_gen5));
++	else
++	    kernel_bo = i965_create_program(scrn, &ps_kernel_planar_static[0][0],
+ 					sizeof(ps_kernel_planar_static));
+     }
+     if (!kernel_bo)
+@@ -615,6 +651,12 @@ i965_create_wm_state(ScrnInfoPtr scrn, d
+ 	wm_state->thread1.binding_table_entry_count = 2;
+     else
+ 	wm_state->thread1.binding_table_entry_count = 7;
++    /* binding table entry count is only used for prefetching, and it has to
++     * be set 0 for IGDNG
++     */
++    if (IS_IGDNG(pI830))
++	wm_state->thread1.binding_table_entry_count = 0;
++
+     /* Though we never use the scratch space in our WM kernel, it has to be
+      * set, and the minimum allocation is 1024 bytes.
+      */
+@@ -630,7 +672,10 @@ i965_create_wm_state(ScrnInfoPtr scrn, d
+ 	intel_emit_reloc(wm_bo, offsetof(struct brw_wm_unit_state, wm4),
+ 			 sampler_bo, 0,
+ 			 I915_GEM_DOMAIN_INSTRUCTION, 0) >> 5;
+-    wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
++    if (IS_IGDNG(pI830))
++	wm_state->wm4.sampler_count = 0;
++    else
++	wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */
+     wm_state->wm5.max_threads = PS_MAX_THREADS - 1;
+     wm_state->wm5.thread_dispatch_enable = 1;
+     wm_state->wm5.enable_16_pix = 1;
+@@ -712,6 +757,7 @@ i965_emit_video_setup(ScrnInfoPtr pScrn,
+     int urb_clip_start, urb_clip_size;
+     int urb_sf_start, urb_sf_size;
+     int urb_cs_start, urb_cs_size;
++    int pipe_ctl;
+ 
+     IntelEmitInvarientState(pScrn);
+     *pI830->last_3d = LAST_3D_VIDEO;
+@@ -735,9 +781,12 @@ i965_emit_video_setup(ScrnInfoPtr pScrn,
+     ADVANCE_BATCH();
+ 
+     /* brw_debug (pScrn, "before base address modify"); */
+-    BEGIN_BATCH(12);
++    if (IS_IGDNG(pI830))
++	BEGIN_BATCH(14);
++    else
++	BEGIN_BATCH(12);
+     /* Match Mesa driver setup */
+-    if (IS_G4X(pI830))
++    if (IS_G4X(pI830) || IS_IGDNG(pI830))
+ 	OUT_BATCH(NEW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
+     else
+ 	OUT_BATCH(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
+@@ -750,14 +799,28 @@ i965_emit_video_setup(ScrnInfoPtr pScrn,
+     /* Zero out the two base address registers so all offsets are
+      * absolute
+      */
+-    OUT_BATCH(BRW_STATE_BASE_ADDRESS | 4);
+-    OUT_BATCH(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
+-    OUT_BATCH(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
+-    OUT_BATCH(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
+-    /* general state max addr, disabled */
+-    OUT_BATCH(0x10000000 | BASE_ADDRESS_MODIFY);
+-    /* media object state max addr, disabled */
+-    OUT_BATCH(0x10000000 | BASE_ADDRESS_MODIFY);
++    if (IS_IGDNG(pI830)) {
++	OUT_BATCH(BRW_STATE_BASE_ADDRESS | 6);
++	OUT_BATCH(0 | BASE_ADDRESS_MODIFY); /* Generate state base address */
++	OUT_BATCH(0 | BASE_ADDRESS_MODIFY); /* Surface state base address */
++	OUT_BATCH(0 | BASE_ADDRESS_MODIFY); /* media base addr, don't care */
++	OUT_BATCH(0 | BASE_ADDRESS_MODIFY); /* Instruction base address */
++	/* general state max addr, disabled */
++	OUT_BATCH(0x10000000 | BASE_ADDRESS_MODIFY);
++	/* media object state max addr, disabled */
++	OUT_BATCH(0x10000000 | BASE_ADDRESS_MODIFY);
++	/* Instruction max addr, disabled */
++	OUT_BATCH(0x10000000 | BASE_ADDRESS_MODIFY);
++    } else {
++	OUT_BATCH(BRW_STATE_BASE_ADDRESS | 4);
++	OUT_BATCH(0 | BASE_ADDRESS_MODIFY);  /* Generate state base address */
++	OUT_BATCH(0 | BASE_ADDRESS_MODIFY);  /* Surface state base address */
++	OUT_BATCH(0 | BASE_ADDRESS_MODIFY);  /* media base addr, don't care */
++	/* general state max addr, disabled */
++	OUT_BATCH(0x10000000 | BASE_ADDRESS_MODIFY);
++	/* media object state max addr, disabled */
++	OUT_BATCH(0x10000000 | BASE_ADDRESS_MODIFY);
++    }
+ 
+     /* Set system instruction pointer */
+     OUT_BATCH(BRW_STATE_SIP | 0);
+@@ -770,15 +833,17 @@ i965_emit_video_setup(ScrnInfoPtr pScrn,
+ 
+     /* brw_debug (pScrn, "after base address modify"); */
+ 
++    if (IS_IGDNG(pI830))
++	pipe_ctl = BRW_PIPE_CONTROL_NOWRITE;
++    else
++	pipe_ctl = BRW_PIPE_CONTROL_NOWRITE | BRW_PIPE_CONTROL_IS_FLUSH;
++
+     BEGIN_BATCH(38);
+     /* Enable VF statistics */
+     OUT_BATCH(BRW_3DSTATE_VF_STATISTICS | 1);
+ 
+     /* Pipe control */
+-    OUT_BATCH(BRW_PIPE_CONTROL |
+-	      BRW_PIPE_CONTROL_NOWRITE |
+-	      BRW_PIPE_CONTROL_IS_FLUSH |
+-	      2);
++    OUT_BATCH(BRW_PIPE_CONTROL | pipe_ctl | 2);
+     OUT_BATCH(0);			/* Destination address */
+     OUT_BATCH(0);			/* Immediate data low DW */
+     OUT_BATCH(0);			/* Immediate data high DW */
+@@ -850,27 +915,50 @@ i965_emit_video_setup(ScrnInfoPtr pScrn,
+ 	      (URB_CS_ENTRIES << 0));
+ 
+     /* Set up our vertex elements, sourced from the single vertex buffer. */
+-    OUT_BATCH(BRW_3DSTATE_VERTEX_ELEMENTS | 3);
+-    /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
+-    OUT_BATCH((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+-	      VE0_VALID |
+-	      (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+-	      (0 << VE0_OFFSET_SHIFT));
+-    OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+-	      (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+-	      (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+-	      (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+-	      (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
+-    /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
+-    OUT_BATCH((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+-	      VE0_VALID |
+-	      (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+-	      (8 << VE0_OFFSET_SHIFT));
+-    OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+-	      (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+-	      (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+-	      (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
+-	      (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
++    if (IS_IGDNG(pI830)) {
++	OUT_BATCH(BRW_3DSTATE_VERTEX_ELEMENTS | 3);
++	/* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
++	OUT_BATCH((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
++	          VE0_VALID |
++	          (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
++	          (0 << VE0_OFFSET_SHIFT));
++	OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
++	          (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
++	          (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
++	          (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT));
++	/* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
++	OUT_BATCH((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
++	          VE0_VALID |
++	          (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
++	          (8 << VE0_OFFSET_SHIFT));
++	OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
++	          (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
++	          (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
++	          (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT));
++    } else {
++	OUT_BATCH(BRW_3DSTATE_VERTEX_ELEMENTS | 3);
++	/* offset 0: X,Y -> {X, Y, 1.0, 1.0} */
++	OUT_BATCH((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
++	          VE0_VALID |
++	          (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
++	          (0 << VE0_OFFSET_SHIFT));
++	OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
++	          (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
++	          (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
++	          (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
++	          (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
++	/* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */
++	OUT_BATCH((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) |
++	          VE0_VALID |
++	          (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
++	          (8 << VE0_OFFSET_SHIFT));
++	OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
++	          (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
++	          (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
++	          (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) |
++	          (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
++    }
++
+ 
+     OUT_BATCH(MI_NOOP);			/* pad to quadword */
+     ADVANCE_BATCH();
+@@ -1113,7 +1201,8 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
+ 
+ 	drm_intel_bo_unmap(vb_bo);
+ 
+-	i965_pre_draw_debug(pScrn);
++	if (!IS_IGDNG(pI830))
++	    i965_pre_draw_debug(pScrn);
+ 
+ 	/* If this command won't fit in the current batch, flush.
+ 	 * Assume that it does after being flushed.
+@@ -1135,7 +1224,11 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
+ 		  VB0_VERTEXDATA |
+ 		  ((4 * 4) << VB0_BUFFER_PITCH_SHIFT));
+ 	OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, 0);
+-	OUT_BATCH(3); /* four corners to our rectangle */
++	if (IS_IGDNG(pI830))
++	    OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, (vb_bo->offset + i) * 4);
++	else
++	    OUT_BATCH(3); /* four corners to our rectangle */
++
+ 
+ 	OUT_BATCH(BRW_3DPRIMITIVE |
+ 		  BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL |
+@@ -1153,7 +1246,9 @@ I965DisplayVideoTextured(ScrnInfoPtr pSc
+ 
+ 	drm_intel_bo_unreference(vb_bo);
+ 
+-	i965_post_draw_debug(pScrn);
++	if (!IS_IGDNG(pI830))
++	    i965_post_draw_debug(pScrn);
++
+     }
+ 
+     i830MarkSync(pScrn);
+
+--- src/cpu_display.c	2009-09-17 14:55:10.778428517 +0800
++++ src/cpu_display.c	2009-09-17 14:56:10.206137629 +0800
+@@ -85,7 +85,7 @@ struct intel_limit {
+ #define DOT_MAX		350000
+ #define VCO_MIN		1760000
+ #define VCO_MAX		3510000
+-#define N_MIN		3
++#define N_MIN		1	
+ #define N_MAX		8
+ #define M_MIN		79
+ #define M_MAX		127
+--- src/i830_driver.c	2009-09-17 14:55:10.861326575 +0800
++++ src/i830_driver.c	2009-09-17 14:58:45.686298305 +0800
+@@ -982,11 +982,25 @@ static void
+ IntelMCPSetupOutputs(ScrnInfoPtr pScrn)
+ {
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR (pScrn);
++   I830Ptr  pI830 = I830PTR(pScrn);
+    int     o, c;
+    Bool            lvds_detected = FALSE;
++   Bool     found=0;
+ 
+    /* IGDNG alpha: single analog output now */
+    pch_crt_init(pScrn);
++   if (INREG(HDMIB) & PORT_DETECTED) {
++	/* check SDVOB if possible */
++	found = i830_sdvo_init(pScrn, HDMIB);
++	if (!found)
++	    i830_hdmi_init(pScrn, HDMIB);
++   }
++
++   if (INREG(HDMIC) & PORT_DETECTED)
++	i830_hdmi_init(pScrn, HDMIC);
++
++   if (INREG(HDMID) & PORT_DETECTED)
++	i830_hdmi_init(pScrn, HDMID);
+ 
+    for (o = 0; o < config->num_output; o++)
+    {
+--- src/pch_crt.c	2009-09-17 14:55:10.773944740 +0800
++++ src/pch_crt.c	2009-09-17 14:56:10.210656755 +0800
+@@ -212,7 +212,7 @@ pch_crt_detect(xf86OutputPtr output)
+ 	_debug("VGA detect connected!");
+ 	status = XF86OutputStatusConnected;
+     } else {
+-	_debug("VGA detect connected!");
++	_debug("VGA detect disconnected!");
+ 	status = XF86OutputStatusDisconnected;
+     }
+ 
+
+--- src/i830_accel.c	2009-08-18 11:31:33.480646280 +0800
++++ src/i830_accel.c	2009-08-26 10:46:26.515523329 +0800
+@@ -173,6 +173,7 @@ void
+ I830Sync(ScrnInfoPtr pScrn)
+ {
+    I830Ptr pI830 = I830PTR(pScrn);
++   int busy_count = 0;
+ 
+    if (I810_DEBUG & (DEBUG_VERBOSE_ACCEL | DEBUG_VERBOSE_SYNC))
+       ErrorF("I830Sync\n");
+@@ -213,10 +214,15 @@ I830Sync(ScrnInfoPtr pScrn)
+        do {
+ 	   ret = drmCommandWrite(pI830->drmSubFD, DRM_I830_IRQ_WAIT, &wait,
+ 				 sizeof(wait));
+-       } while (ret == -EINTR);
++           if (ret == -EBUSY) {
++                xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++                   "wait.irq_seq %d busy_count %d .\n", wait.irq_seq, busy_count);
++                busy_count++;
++           }
++        } while ((ret == -EINTR) || (ret == -EBUSY && busy_count < 5));
+ 
+        if (ret != 0)
+-	   FatalError("Failure to wait for IRQ: %s\n", strerror(-ret));
++	   FatalError("Failure to wait for IRQ: %s busy_count %d\n", strerror(-ret), busy_count);
+ 
+        if (!pI830->memory_manager)
+ 	   i830_refresh_ring(pScrn);
+
+--- src/i830_debug.c	2009-09-17 14:55:10.777762639 +0800
++++ src/i830_debug.c	2009-09-17 15:03:18.360869725 +0800
+@@ -1090,7 +1090,7 @@ DEBUGSTRING(ilk_debug_panel_fitting)
+ 	   val & (1 << 20) ? "field 0" : "field 1");
+ }
+ 
+-/* new register dumps for ironlake */
++/* new register dumps for IGDNG */
+ static struct i830SnapshotRec cpu_pch_snapshot[] = {
+     DEFINEREG2(CPU_VGACNTRL, i830_debug_vgacntrl),
+     DEFINEREG(DIGITAL_PORT_HOTPLUG_CNTRL),
+@@ -1237,7 +1237,7 @@ static struct i830SnapshotRec cpu_pch_sn
+     DEFINEREG(HDMIC),
+     DEFINEREG(HDMID),
+ };
+-#define NUM_ILK_SNAPSHOTREGS (sizeof(cpu_pch_snapshot) / sizeof(cpu_pch_snapshot[0]))
++#define NUM_IGDNG_SNAPSHOTREGS (sizeof(cpu_pch_snapshot) / sizeof(cpu_pch_snapshot[0]))
+ 
+ #undef DEFINEREG
+ 
+@@ -1248,7 +1248,7 @@ void i830TakeRegSnapshot(ScrnInfoPtr pSc
+     int i;
+ 
+     if (IS_IGDNG(pI830)) {
+-	for (i = 0; i < NUM_ILK_SNAPSHOTREGS; i++) {
++	for (i = 0; i < NUM_IGDNG_SNAPSHOTREGS; i++) {
+ 	    cpu_pch_snapshot[i].val = INREG(cpu_pch_snapshot[i].reg);
+ 	}
+     } else {
+@@ -1267,7 +1267,7 @@ void i830CompareRegsToSnapshot(ScrnInfoP
+     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ 	       "Comparing regs from server start up to %s\n", where);
+     if (IS_IGDNG(pI830)) {
+-        for (i = 0; i < NUM_ILK_SNAPSHOTREGS; i++) {
++        for (i = 0; i < NUM_IGDNG_SNAPSHOTREGS; i++) {
+            uint32_t val = INREG(cpu_pch_snapshot[i].reg);
+            if (cpu_pch_snapshot[i].val == val)
+                continue;
+@@ -1329,7 +1329,7 @@ void IlkCompareRegsToSnapshot(ScrnInfoPt
+ 
+     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ 	       "Comparing regs from server start up to %s\n", where);
+-    for (i = 0; i < NUM_ILK_SNAPSHOTREGS; i++) {
++    for (i = 0; i < NUM_IGDNG_SNAPSHOTREGS; i++) {
+ 	uint32_t val = INREG(cpu_pch_snapshot[i].reg);
+ 	if (cpu_pch_snapshot[i].val == val)
+ 	    continue;
+@@ -1407,7 +1407,7 @@ void IlkDumpRegs (ScrnInfoPtr pScrn)
+     int i;
+ 
+     xf86DrvMsg (pScrn->scrnIndex, X_INFO, "DumpRegsBegin\n");
+-    for (i = 0; i < NUM_ILK_SNAPSHOTREGS; i++) {
++    for (i = 0; i < NUM_IGDNG_SNAPSHOTREGS; i++) {
+ 	uint32_t val = INREG(cpu_pch_snapshot[i].reg);
+ 
+ 	if (cpu_pch_snapshot[i].debug_output != NULL) {
+--- src/i830_display.c	2009-09-17 14:55:10.806093370 +0800
++++ src/i830_display.c	2009-09-17 15:03:18.362395018 +0800
+@@ -157,8 +157,8 @@ typedef struct {
+ #define INTEL_LIMIT_G4X_HDMI_DAC    7
+ #define INTEL_LIMIT_G4X_SINGLE_LVDS 8
+ #define INTEL_LIMIT_G4X_DUAL_LVDS   9
+-#define INTEL_LIMIT_ILK_SDVO_DAC   10
+-#define INTEL_LIMIT_ILK_LVDS       11
++#define INTEL_LIMIT_IGDNG_SDVO_DAC   10
++#define INTEL_LIMIT_IGDNG_LVDS       11
+ 
+ /*The parameter is for SDVO on G4x platform*/
+ #define G4X_VCO_MIN                1750000
+@@ -391,9 +391,9 @@ static const intel_limit_t *intel_limit_
+     const intel_limit_t *limit;
+ 
+     if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
+-       limit = &intel_limits[INTEL_LIMIT_ILK_LVDS];
++       limit = &intel_limits[INTEL_LIMIT_IGDNG_LVDS];
+     else
+-        limit = &intel_limits[INTEL_LIMIT_ILK_SDVO_DAC];
++        limit = &intel_limits[INTEL_LIMIT_IGDNG_SDVO_DAC];
+ 
+     return limit;
+ }
+@@ -1253,7 +1253,7 @@ ilk_crtc_enable(xf86CrtcPtr crtc)
+     intel_wait_warmup(WARMUP_PCH_FDI_RECEIVER_PLL);
+     intel_wait_warmup(WARMUP_DMI_LATENCY);
+ 
+-    /* Enable CPU FDI TX PLL, always on for ILK */
++    /* Enable CPU FDI TX PLL, always on for IGDNG */
+     temp = INREG(fdi_tx_reg);
+     if ((temp & FDI_TX_PLL_ENABLE) == 0) {
+ 	OUTREG(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE);
+@@ -1492,7 +1492,7 @@ ilk_crtc_disable(xf86CrtcPtr crtc)
+ 
+     /* disable panel power -> output power down */
+ 
+-    /* ILK-B : disable cpu panel fitter ? */
++    /* IGDNG-B : disable cpu panel fitter ? */
+     temp = INREG(pf_ctl_reg);
+     if ((temp & PF_ENABLE) != 0) {
+ 	OUTREG(pf_ctl_reg, temp & ~PF_ENABLE);
+@@ -2118,7 +2118,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
+ 	FatalError("unknown display bpp\n");
+     }
+ 
+-    /* Ironlake's plane is forced to pipe, bit 24 is to
++    /* IGDNG's plane is forced to pipe, bit 24 is to
+        enable color space conversion */
+     if (!IS_IGDNG(pI830)) {
+        if (pipe == 0)
+@@ -2172,7 +2172,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
+ 	i830PrintPll(pScrn, "chosen", &clock);
+     }
+ 
+-    /* assign to Ironlake registers */
++    /* assign to IGDNG registers */
+     if (IS_IGDNG(pI830)) {
+        fp_reg = pch_fp_reg;
+        dpll_reg = pch_dpll_reg;
+@@ -2321,7 +2321,7 @@ i830_crtc_load_lut(xf86CrtcPtr crtc)
+     if (!crtc->enabled)
+ 	return;
+ 
+-    /* use legacy palette for Ironlake */
++    /* use legacy palette for IGDNG */
+     if (IS_IGDNG(pI830))
+        palreg = (intel_crtc->pipe == 0) ? LGC_PALETTE_A : LGC_PALETTE_B;
+ 
+--- src/i830_driver.c	2009-09-17 15:02:24.137203001 +0800
++++ src/i830_driver.c	2009-09-17 15:05:16.762079891 +0800
+@@ -4345,7 +4345,7 @@ I830EnterVT(int scrnIndex, int flags)
+ 	   I830InitHWCursor(pScrn);
+ 
+        /* Tell the BIOS that we're in control of mode setting now. */
+-       /* XXX check if Ironlake needs */
++       /* XXX check if IGDNG needs */
+        if (!IS_IGDNG(pI830))
+           i830_init_clock_gating(pScrn);
+ 
+--- src/i965_render.c	2009-09-17 14:55:10.839758869 +0800
++++ src/i965_render.c	2009-09-17 15:03:22.849457956 +0800
+@@ -390,7 +390,7 @@ static const uint32_t ps_kernel_masknoca
+ #include "exa_wm_write.g4b"
+ };
+ 
+-/* new programs for ILK */
++/* new programs for IGDNG */
+ static const uint32_t sf_kernel_static_gen5[][4] = {
+ #include "exa_sf.g4b.gen5"
+ };
+--- src/i965_video.c	2009-09-17 14:55:10.771906464 +0800
++++ src/i965_video.c	2009-09-17 15:03:22.850225957 +0800
+@@ -110,7 +110,7 @@ static const uint32_t ps_kernel_planar_s
+ #include "exa_wm_write.g4b"
+ };
+ 
+-/* new program for ILK */
++/* new program for IGDNG */
+ static const uint32_t sf_kernel_static_gen5[][4] = {
+ #include "exa_sf.g4b.gen5"
+ };
+
+--- src/cpu_display.c   2009-09-23 16:42:04.184134730 +0800
++++ src/cpu_display.c   2009-09-23 17:58:34.634831014 +0800
+@@ -227,7 +227,7 @@ intel_find_pll_ilk(const intel_limit_t *
+     intel_clock_t clock;
+     int  max_n;
+     Bool found = FALSE;
+-    int err_most = target * 0.0048;
++    int err_most = target * 0.0049;
+
+     if (target < limit->p2.dot_limit)
+        clock.p2 = limit->p2.p2_slow;
+--- src/i830_driver.c   2009-09-23 16:42:03.805488701 +0800
++++ src/i830_driver.c   2009-09-23 17:58:24.060568081 +0800
+@@ -4361,9 +4361,6 @@ I830EnterVT(int scrnIndex, int flags)
+              pScrn->virtualY * pScrn->displayWidth * pI830->cpp);
+    }
+
+-   if (!xf86SetDesiredModes (pScrn))
+-      return FALSE;
+-
+    if (!pI830->use_drm_mode) {
+        if (pI830->debug_modes) {
+           xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Hardware state at EnterVT:\n");
+@@ -4392,7 +4389,14 @@ I830EnterVT(int scrnIndex, int flags)
+               return FALSE;
+           }
+        }
++   }
++#endif
+
++   if (!xf86SetDesiredModes (pScrn))
++      return FALSE;
++
++#ifdef XF86DRI
++   if (pI830->directRenderingType == DRI_XF86DRI) {
+       /* Update buffer offsets in sarea and mappings, since buffer offsets
+        * may have changed.
+        */
+
+--- src/common.h	Mon Oct 12 12:29:15 2009
++++ src/common.h	Mon Oct 12 12:33:50 2009
+@@ -318,6 +318,11 @@
+ #define PCI_CHIP_G41_G_BRIDGE	0x2E30
+ #endif
+ 
++#ifndef PCI_CHIP_B43_G
++#define PCI_CHIP_B43_G 0x2E42
++#define PCI_CHIP_B43_G_BRIDGE 0x2E40
++#endif
++
+ #ifndef PCI_CHIP_IGDNG_D_G
+ #define PCI_CHIP_IGDNG_D_G	0x0042
+ #define PCI_CHIP_IGDNG_D_G_BRIDGE	0x0040
+@@ -363,7 +368,7 @@
+ #define IS_IGDG(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_IGD_G)
+ #define IS_IGD(pI810) (IS_IGDG(pI810) || IS_IGDGM(pI810))
+ #define IS_GM45(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_GM45_GM)
+-#define IS_G4X(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_IGD_E_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_G45_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_Q45_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_G41_G || IS_GM45(pI810))
++#define IS_G4X(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_IGD_E_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_G45_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_Q45_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_G41_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_B43_G || IS_GM45(pI810))
+ #define IS_I965GM(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GM || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GME)
+ #define IS_965_Q(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_Q)
+ #define IS_IGDNG_D(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_IGDNG_D_G)
+--- src/i810_driver.c	Mon Oct 12 12:29:20 2009
++++ src/i810_driver.c	Mon Oct 12 12:36:19 2009
+@@ -157,6 +157,7 @@
+    INTEL_DEVICE_MATCH (PCI_CHIP_G45_G, 0 ),
+    INTEL_DEVICE_MATCH (PCI_CHIP_Q45_G, 0 ),
+    INTEL_DEVICE_MATCH (PCI_CHIP_G41_G, 0 ),
++   INTEL_DEVICE_MATCH (PCI_CHIP_B43_G, 0 ),
+    INTEL_DEVICE_MATCH (PCI_CHIP_IGDNG_D_G, 0 ),
+    INTEL_DEVICE_MATCH (PCI_CHIP_IGDNG_M_G, 0 ),
+     { 0, 0, 0 },
+@@ -216,6 +217,7 @@
+    {PCI_CHIP_G45_G,		"G45/G43"},
+    {PCI_CHIP_Q45_G,		"Q45/Q43"},
+    {PCI_CHIP_G41_G,		"G41"},
++   {PCI_CHIP_B43_G,		"B43"},
+    {PCI_CHIP_IGDNG_D_G,		"IGDNG_D"},
+    {PCI_CHIP_IGDNG_M_G,		"IGDNG_M"},
+    {-1,				NULL}
+@@ -252,6 +254,7 @@
+    {PCI_CHIP_G45_G,		PCI_CHIP_G45_G,		RES_SHARED_VGA},
+    {PCI_CHIP_Q45_G,		PCI_CHIP_Q45_G,		RES_SHARED_VGA},
+    {PCI_CHIP_G41_G,		PCI_CHIP_G41_G,		RES_SHARED_VGA},
++   {PCI_CHIP_B43_G, 		PCI_CHIP_B43_G, 	RES_SHARED_VGA},
+    {PCI_CHIP_IGDNG_D_G,		PCI_CHIP_IGDNG_D_G,	RES_SHARED_VGA},
+    {PCI_CHIP_IGDNG_M_G,		PCI_CHIP_IGDNG_M_G,	RES_SHARED_VGA},
+    {-1,				-1, RES_UNDEFINED }
+--- src/i830_driver.c	Mon Oct 12 12:29:26 2009
++++ src/i830_driver.c	Mon Oct 12 12:37:57 2009
+@@ -258,6 +258,7 @@
+    {PCI_CHIP_G45_G,		"G45/G43"},
+    {PCI_CHIP_Q45_G,		"Q45/Q43"},
+    {PCI_CHIP_G41_G,		"G41"},
++   {PCI_CHIP_B43_G, 		"B43"},
+    {PCI_CHIP_IGDNG_D_G,		"IGDNG_D"},
+    {PCI_CHIP_IGDNG_M_G,		"IGDNG_M"},
+    {-1,				NULL}
+@@ -288,6 +289,7 @@
+    {PCI_CHIP_G45_G,		PCI_CHIP_G45_G,		RES_SHARED_VGA},
+    {PCI_CHIP_Q45_G,		PCI_CHIP_Q45_G,		RES_SHARED_VGA},
+    {PCI_CHIP_G41_G,		PCI_CHIP_G41_G,		RES_SHARED_VGA},
++   {PCI_CHIP_B43_G, 		PCI_CHIP_B43_G, 	RES_SHARED_VGA},
+    {PCI_CHIP_IGDNG_D_G,		PCI_CHIP_IGDNG_D_G,		RES_SHARED_VGA},
+    {PCI_CHIP_IGDNG_M_G,		PCI_CHIP_IGDNG_M_G,		RES_SHARED_VGA},
+    {-1,				-1,			RES_UNDEFINED}
+@@ -1439,6 +1441,9 @@
+     case PCI_CHIP_G41_G:
+ 	chipname = "G41";
+ 	break;
++    case PCI_CHIP_B43_G:
++	chipname = "B43";
++ 	break;
+     case PCI_CHIP_IGDNG_D_G:
+ 	chipname = "IGDNG_D";
+ 	break;
--- a/open-src/driver/xf86-video-intel/COPYING	Tue Oct 20 20:07:52 2009 -0700
+++ b/open-src/driver/xf86-video-intel/COPYING	Wed Oct 21 10:31:36 2009 -0700
@@ -474,5 +474,31 @@
 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+*************************************************************************
+
+Copyright ? 2009 Intel Corporation
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE
+
+Authors:
+     Zhenyu Wang <[email protected]>
 
 
+
--- a/open-src/driver/xf86-video-intel/Makefile	Tue Oct 20 20:07:52 2009 -0700
+++ b/open-src/driver/xf86-video-intel/Makefile	Wed Oct 21 10:31:36 2009 -0700
@@ -30,19 +30,19 @@
 # or other dealings in this Software without prior written authorization
 # of the copyright holder.
 #
-# @(#)Makefile	1.25	09/06/19
+# @(#)Makefile	1.26	09/10/19
 #
 
 # Package name used in tarballs
 MODULE_NAME=xf86-video-intel
 
 # Version number (used in path names)
-MODULE_VERSION=2.6.1
+MODULE_VERSION=2.6.3
 
 # Patches to apply to source after unpacking, in order
 SOURCE_PATCHES= build-dri.patch libraries.patch \
 		6538497_6554161.patch bugs.patch \
-		gem.patch
+                gem.patch 6872597.patch 
 
 # Man pages to apply Sun footer to & attributes to list
 SUNTOUCHED_MANPAGES=man/*.man
--- a/open-src/driver/xf86-video-intel/bugs.patch	Tue Oct 20 20:07:52 2009 -0700
+++ b/open-src/driver/xf86-video-intel/bugs.patch	Wed Oct 21 10:31:36 2009 -0700
@@ -1,17 +1,3 @@
-diff -urp -x '*~' -x '*.orig' src/i830_display.c src/i830_display.c
---- src/i830_display.c	2009-01-21 14:02:00.000000000 -0800
-+++ src/i830_display.c	2009-05-08 20:48:03.095075000 -0700
-@@ -801,10 +801,6 @@ i830_disable_vga_plane (xf86CrtcPtr crtc
- 
-     vgacntrl |= VGA_DISP_DISABLE;
- 
--    /* disable center mode */
--    if (IS_I9XX(pI830))
--	vgacntrl &= ~(3 << 24);
--
-     OUTREG(VGACNTRL, vgacntrl);
-     i830WaitForVblank(pScrn);
- 
 diff -urp -x '*~' -x '*.orig' src/i830_driver.c src/i830_driver.c
 --- src/i830_driver.c	2009-01-21 14:02:00.000000000 -0800
 +++ src/i830_driver.c	2009-05-08 20:48:03.093998000 -0700
--- a/open-src/lib/libdrm/Makefile	Tue Oct 20 20:07:52 2009 -0700
+++ b/open-src/lib/libdrm/Makefile	Wed Oct 21 10:31:36 2009 -0700
@@ -27,14 +27,14 @@
 # or other dealings in this Software without prior written authorization
 # of the copyright holder.
 #
-# @(#)Makefile	1.13	09/08/14
+# @(#)Makefile	1.14	09/10/19
 #
 
 # Package name used in tarballs
 MODULE_NAME=libdrm
 
 # Version number (used in path names)
-MODULE_VERSION=2.4.12
+MODULE_VERSION=2.4.14
 
 # Library name (used for specfiles/mapfiles)
 LIBNAME=drm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/open-src/lib/mesa/6872597.patch	Wed Oct 21 10:31:36 2009 -0700
@@ -0,0 +1,2280 @@
+--- src/mesa/drivers/dri/i965/brw_clip.c	2009-09-01 14:49:51.029003304 +0800
++++ src/mesa/drivers/dri/i965/brw_clip.c	2009-09-01 15:42:30.765873138 +0800
+@@ -65,21 +65,31 @@ static void compile_clip_prog( struct br
+    c.func.single_program_flow = 1;
+ 
+    c.key = *key;
+-
++   c.need_ff_sync = BRW_IS_IGDNG(brw);
+ 
+    /* Need to locate the two positions present in vertex + header.
+     * These are currently hardcoded:
+     */
+    c.header_position_offset = ATTR_SIZE;
+ 
+-   for (i = 0, delta = REG_SIZE; i < VERT_RESULT_MAX; i++)
++   if (BRW_IS_IGDNG(brw))
++       delta = 3 * REG_SIZE;
++   else
++       delta = REG_SIZE;
++
++   for (i = 0; i < VERT_RESULT_MAX; i++)
+       if (c.key.attrs & (1<<i)) {
+ 	 c.offset[i] = delta;
+ 	 delta += ATTR_SIZE;
+       }
+ 
+    c.nr_attrs = brw_count_bits(c.key.attrs);
+-   c.nr_regs = (c.nr_attrs + 1) / 2 + 1;  /* are vertices packed, or reg-aligned? */
++   
++   if (BRW_IS_IGDNG(brw))
++       c.nr_regs = (c.nr_attrs + 1) / 2 + 3;  /* are vertices packed, or reg-aligned? */
++   else
++       c.nr_regs = (c.nr_attrs + 1) / 2 + 1;  /* are vertices packed, or reg-aligned? */
++
+    c.nr_bytes = c.nr_regs * REG_SIZE;
+ 
+    c.prog_data.clip_mode = c.key.clip_mode; /* XXX */
+@@ -148,7 +158,11 @@ static void upload_clip_prog(struct brw_
+    key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT);
+    /* _NEW_TRANSFORM */
+    key.nr_userclip = brw_count_bits(ctx->Transform.ClipPlanesEnabled);
+-   key.clip_mode = BRW_CLIPMODE_NORMAL;
++
++   if (BRW_IS_IGDNG(brw))
++       key.clip_mode = BRW_CLIPMODE_KERNEL_CLIP;
++   else
++       key.clip_mode = BRW_CLIPMODE_NORMAL;
+ 
+    /* _NEW_POLYGON */
+    if (key.primitive == GL_TRIANGLES) {
+--- src/mesa/drivers/dri/i965/brw_clip.h	2009-09-01 14:49:51.029823476 +0800
++++ src/mesa/drivers/dri/i965/brw_clip.h	2009-09-01 15:42:30.766418766 +0800
+@@ -117,6 +117,7 @@ struct brw_clip_compile {
+ 
+    GLuint header_position_offset;
+    GLuint offset[VERT_ATTRIB_MAX];
++   GLboolean need_ff_sync;
+ };
+ 
+ #define ATTR_SIZE  (4*4)
+@@ -171,5 +172,5 @@ struct brw_reg get_tmp( struct brw_clip_
+ 
+ void brw_clip_project_position(struct brw_clip_compile *c,
+              struct brw_reg pos );
+-
++void brw_clip_ff_sync(struct brw_clip_compile *c);
+ #endif
+--- src/mesa/drivers/dri/i965/brw_clip_line.c	2009-09-01 14:49:51.030931767 +0800
++++ src/mesa/drivers/dri/i965/brw_clip_line.c	2009-09-01 15:42:30.767254247 +0800
+@@ -130,7 +130,7 @@ static void clip_and_emit_line( struct b
+    struct brw_instruction *plane_loop;
+    struct brw_instruction *plane_active;
+    struct brw_instruction *is_negative;
+-   struct brw_instruction *is_neg2;
++   struct brw_instruction *is_neg2 = NULL;
+    struct brw_instruction *not_culled;
+    struct brw_reg v1_null_ud = retype(vec1(brw_null_reg()), BRW_REGISTER_TYPE_UD);
+ 
+@@ -148,7 +148,7 @@ static void clip_and_emit_line( struct b
+    brw_clip_init_clipmask(c);
+ 
+    /* -ve rhw workaround */
+-   if (!BRW_IS_G4X(p->brw)) {
++   if (BRW_IS_965(p->brw)) {
+       brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+       brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
+               brw_imm_ud(1<<20));
+@@ -185,7 +185,7 @@ static void clip_and_emit_line( struct b
+               * Both can be negative on GM965/G965 due to RHW workaround
+               * if so, this object should be rejected.
+               */
+-             if (!BRW_IS_G4X(p->brw)) {
++             if (BRW_IS_965(p->brw)) {
+                  brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_LE, c->reg.dp0, brw_imm_f(0.0));
+                  is_neg2 = brw_IF(p, BRW_EXECUTE_1);
+                  {
+@@ -210,7 +210,7 @@ static void clip_and_emit_line( struct b
+ 
+              /* If both are positive, do nothing */
+              /* Only on GM965/G965 */
+-             if (!BRW_IS_G4X(p->brw)) {
++             if (BRW_IS_965(p->brw)) {
+                  brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.dp0, brw_imm_f(0.0));
+                  is_neg2 = brw_IF(p, BRW_EXECUTE_1);
+              }
+@@ -225,7 +225,7 @@ static void clip_and_emit_line( struct b
+                  brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+              }
+ 
+-             if (!BRW_IS_G4X(p->brw)) {
++             if (BRW_IS_965(p->brw)) {
+                  brw_ENDIF(p, is_neg2);
+              }
+          }
+@@ -246,6 +246,8 @@ static void clip_and_emit_line( struct b
+ 
+    brw_ADD(p, c->reg.t, c->reg.t0, c->reg.t1);
+    brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.t, brw_imm_f(1.0));
++   if (c->need_ff_sync)
++	   brw_clip_ff_sync(c);      
+    not_culled = brw_IF(p, BRW_EXECUTE_1);
+    {
+       brw_clip_interp_vertex(c, newvtx0, vtx0, vtx1, c->reg.t0, GL_FALSE);
+--- src/mesa/drivers/dri/i965/brw_clip_point.c	2009-09-01 14:49:51.034187520 +0800
++++ src/mesa/drivers/dri/i965/brw_clip_point.c	2009-09-01 15:42:30.767692593 +0800
+@@ -50,5 +50,7 @@ void brw_emit_point_clip( struct brw_cli
+    /* Send an empty message to kill the thread:
+     */
+    brw_clip_tri_alloc_regs(c, 0);
++   if (c->need_ff_sync)
++	   brw_clip_ff_sync(c);      
+    brw_clip_kill_thread(c);
+ }
+--- src/mesa/drivers/dri/i965/brw_clip_state.c	2009-09-01 14:49:51.034887251 +0800
++++ src/mesa/drivers/dri/i965/brw_clip_state.c	2009-09-01 15:42:30.768155611 +0800
+@@ -95,7 +95,14 @@ clip_unit_create_from_key(struct brw_con
+        * even number.
+        */
+       assert(key->nr_urb_entries % 2 == 0);
+-      clip.thread4.max_threads = 2 - 1;
++      
++      /* Although up to 16 concurrent Clip threads are allowed on IGDNG, 
++       * only 2 threads can output VUEs at a time.
++       */
++      if (BRW_IS_IGDNG(brw))
++         clip.thread4.max_threads = 16 - 1;        
++      else
++         clip.thread4.max_threads = 2 - 1;
+    } else {
+       assert(key->nr_urb_entries >= 5);
+       clip.thread4.max_threads = 1 - 1;
+--- src/mesa/drivers/dri/i965/brw_clip_tri.c	2009-09-01 14:49:51.041443020 +0800
++++ src/mesa/drivers/dri/i965/brw_clip_tri.c	2009-09-01 15:42:30.769713572 +0800
+@@ -77,6 +77,10 @@ void brw_clip_tri_alloc_regs( struct brw
+    if (c->nr_attrs & 1) {
+       for (j = 0; j < 3; j++) {
+ 	 GLuint delta = c->nr_attrs*16 + 32;
++
++         if (BRW_IS_IGDNG(c->func.brw))
++             delta = c->nr_attrs * 16 + 32 * 3;
++
+ 	 brw_MOV(&c->func, byte_offset(c->reg.vertex[j], delta), brw_imm_f(0));
+       }
+    }
+@@ -562,7 +566,7 @@ void brw_emit_tri_clip( struct brw_clip_
+ 
+    /* if -ve rhw workaround bit is set, 
+       do cliptest */
+-   if (!BRW_IS_G4X(p->brw)) {
++   if (BRW_IS_965(p->brw)) {
+       brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+       brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2), 
+               brw_imm_ud(1<<20));
+@@ -579,11 +583,14 @@ void brw_emit_tri_clip( struct brw_clip_
+    if (c->key.do_flat_shading) 
+       brw_clip_tri_flat_shade(c); 
+       
+-   if (c->key.clip_mode == BRW_CLIPMODE_NORMAL)
++   if ((c->key.clip_mode == BRW_CLIPMODE_NORMAL) ||
++       (c->key.clip_mode == BRW_CLIPMODE_KERNEL_CLIP))
+       do_clip_tri(c);
+    else 
+       maybe_do_clip_tri(c);
+-      
++
++   if (c->need_ff_sync)
++	   brw_clip_ff_sync(c);      
+    brw_clip_tri_emit_polygon(c);
+ 
+    /* Send an empty message to kill the thread:
+--- src/mesa/drivers/dri/i965/brw_clip_unfilled.c	2009-09-01 14:49:51.042586623 +0800
++++ src/mesa/drivers/dri/i965/brw_clip_unfilled.c	2009-09-01 15:42:30.770657542 +0800
+@@ -496,6 +496,8 @@ void brw_emit_unfilled_clip( struct brw_
+    }
+    brw_ENDIF(p, do_clip);
+    
++   if (c->need_ff_sync)
++	   brw_clip_ff_sync(c);      
+    emit_unfilled_primitives(c);
+    brw_clip_kill_thread(c);
+ }
+--- src/mesa/drivers/dri/i965/brw_clip_util.c	2009-09-01 14:49:51.044036587 +0800
++++ src/mesa/drivers/dri/i965/brw_clip_util.c	2009-09-01 15:42:30.771483207 +0800
+@@ -140,6 +140,10 @@ void brw_clip_interp_vertex( struct brw_
+ 
+    /* Just copy the vertex header:
+     */
++   /*
++    * After CLIP stage, only first 256 bits of the VUE are read
++    * back on IGDNG, so needn't change it
++    */
+    brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1);
+       
+    /* Iterate over each attribute (could be done in pairs?)
+@@ -147,6 +151,9 @@ void brw_clip_interp_vertex( struct brw_
+    for (i = 0; i < c->nr_attrs; i++) {
+       GLuint delta = i*16 + 32;
+ 
++      if (BRW_IS_IGDNG(p->brw))
++          delta = i * 16 + 32 * 3;
++
+       if (delta == c->offset[VERT_RESULT_EDGE]) {
+ 	 if (force_edgeflag) 
+ 	    brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1));
+@@ -177,6 +184,10 @@ void brw_clip_interp_vertex( struct brw_
+ 
+    if (i & 1) {
+       GLuint delta = i*16 + 32;
++
++      if (BRW_IS_IGDNG(p->brw))
++          delta = i * 16 + 32 * 3;
++
+       brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0));
+    }
+ 
+@@ -343,3 +354,19 @@ void brw_clip_init_clipmask( struct brw_
+    }
+ }
+ 
++void brw_clip_ff_sync(struct brw_clip_compile *c)
++{
++	struct brw_compile *p = &c->func;
++	brw_ff_sync(p, 
++				c->reg.R0,
++				0,
++				c->reg.R0,
++				1,	
++				1,		/* used */
++				1,  	/* msg length */
++				1,		/* response length */
++				0,		/* eot */
++				1,		/* write compelete */
++				0,		/* urb offset */
++				BRW_URB_SWIZZLE_NONE);
++}
+--- src/mesa/drivers/dri/i965/brw_defines.h	2009-09-01 14:49:51.053292209 +0800
++++ src/mesa/drivers/dri/i965/brw_defines.h	2009-09-01 15:42:30.772512151 +0800
+@@ -139,6 +139,7 @@
+ #define BRW_CLIPMODE_CLIP_NON_REJECTED   2
+ #define BRW_CLIPMODE_REJECT_ALL          3
+ #define BRW_CLIPMODE_ACCEPT_ALL          4
++#define BRW_CLIPMODE_KERNEL_CLIP         5
+ 
+ #define BRW_CLIP_NDCSPACE     0
+ #define BRW_CLIP_SCREENSPACE  1
+@@ -650,6 +651,25 @@
+ #define BRW_SAMPLER_MESSAGE_SIMD8_LD                  3
+ #define BRW_SAMPLER_MESSAGE_SIMD16_LD                 3
+ 
++#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_IGDNG            0
++#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_IGDNG          0
++#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_IGDNG           0
++#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_BIAS_IGDNG       1
++#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_BIAS_IGDNG     1
++#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS_IGDNG      1
++#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_LOD_IGDNG        2
++#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_LOD_IGDNG      2
++#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_LOD_IGDNG       2
++#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_COMPARE_IGDNG    3
++#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_COMPARE_IGDNG  3
++#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE_IGDNG   3
++
++/* for IGDNG only */
++#define BRW_SAMPLER_SIMD_MODE_SIMD4X2                   0
++#define BRW_SAMPLER_SIMD_MODE_SIMD8                     1
++#define BRW_SAMPLER_SIMD_MODE_SIMD16                    2
++#define BRW_SAMPLER_SIMD_MODE_SIMD32_64                 3
++
+ #define BRW_DATAPORT_OWORD_BLOCK_1_OWORDLOW   0
+ #define BRW_DATAPORT_OWORD_BLOCK_1_OWORDHIGH  1
+ #define BRW_DATAPORT_OWORD_BLOCK_2_OWORDS     2
+@@ -799,8 +819,11 @@
+ #include "intel_chipset.h"
+ 
+ #define BRW_IS_G4X(brw)         (IS_G4X((brw)->intel.intelScreen->deviceID))
+-#define CMD_PIPELINE_SELECT(brw)        (BRW_IS_G4X(brw) ? CMD_PIPELINE_SELECT_GM45 : CMD_PIPELINE_SELECT_965)
+-#define CMD_VF_STATISTICS(brw)          (BRW_IS_G4X(brw) ? CMD_VF_STATISTICS_GM45 : CMD_VF_STATISTICS_965)
+-#define URB_SIZES(brw)                  (BRW_IS_G4X(brw) ? 384 : 256)  /* 512 bit units */
++#define BRW_IS_IGDNG(brw)         (IS_IGDNG((brw)->intel.intelScreen->deviceID))
++#define BRW_IS_965(brw)         (!(BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw)))
++#define CMD_PIPELINE_SELECT(brw)        ((BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw)) ? CMD_PIPELINE_SELECT_GM45 : CMD_PIPELINE_SELECT_965)
++#define CMD_VF_STATISTICS(brw)          ((BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw)) ? CMD_VF_STATISTICS_GM45 : CMD_VF_STATISTICS_965)
++#define URB_SIZES(brw)                  (BRW_IS_IGDNG(brw) ? 1024 : \
++                                         (BRW_IS_G4X(brw) ? 384 : 256))  /* 512 bit units */
+ 
+ #endif
+--- src/mesa/drivers/dri/i965/brw_draw_upload.c	2009-09-01 14:49:51.054326255 +0800
++++ src/mesa/drivers/dri/i965/brw_draw_upload.c	2009-09-01 15:42:30.773291722 +0800
+@@ -491,7 +491,19 @@ static void brw_emit_vertices(struct brw
+       OUT_RELOC(input->bo,
+ 		I915_GEM_DOMAIN_VERTEX, 0,
+ 		input->offset);
+-      OUT_BATCH(brw->vb.max_index);
++      if (BRW_IS_IGDNG(brw)) {
++          if (input->stride) {
++              OUT_RELOC(input->bo,
++                        I915_GEM_DOMAIN_VERTEX, 0,
++                        input->offset + input->stride * input->count);
++          } else {
++              assert(input->count == 1);
++              OUT_RELOC(input->bo,
++                        I915_GEM_DOMAIN_VERTEX, 0,
++                        input->offset + input->element_size);
++          }
++      } else
++          OUT_BATCH(brw->vb.max_index);
+       OUT_BATCH(0); /* Instance data step rate */
+    }
+    ADVANCE_BATCH();
+@@ -520,11 +532,18 @@ static void brw_emit_vertices(struct brw
+ 		BRW_VE0_VALID |
+ 		(format << BRW_VE0_FORMAT_SHIFT) |
+ 		(0 << BRW_VE0_SRC_OFFSET_SHIFT));
+-      OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) |
+-		(comp1 << BRW_VE1_COMPONENT_1_SHIFT) |
+-		(comp2 << BRW_VE1_COMPONENT_2_SHIFT) |
+-		(comp3 << BRW_VE1_COMPONENT_3_SHIFT) |
+-		((i * 4) << BRW_VE1_DST_OFFSET_SHIFT));
++
++      if (BRW_IS_IGDNG(brw))
++          OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) |
++                    (comp1 << BRW_VE1_COMPONENT_1_SHIFT) |
++                    (comp2 << BRW_VE1_COMPONENT_2_SHIFT) |
++                    (comp3 << BRW_VE1_COMPONENT_3_SHIFT));
++      else
++          OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) |
++                    (comp1 << BRW_VE1_COMPONENT_1_SHIFT) |
++                    (comp2 << BRW_VE1_COMPONENT_2_SHIFT) |
++                    (comp3 << BRW_VE1_COMPONENT_3_SHIFT) |
++                    ((i * 4) << BRW_VE1_DST_OFFSET_SHIFT));
+    }
+    ADVANCE_BATCH();
+ }
+--- src/mesa/drivers/dri/i965/brw_eu.h	2009-09-01 14:49:51.063253137 +0800
++++ src/mesa/drivers/dri/i965/brw_eu.h	2009-09-01 15:42:30.774060916 +0800
+@@ -801,6 +801,19 @@ void brw_urb_WRITE(struct brw_compile *p
+ 		   GLuint offset,
+ 		   GLuint swizzle);
+ 
++void brw_ff_sync(struct brw_compile *p,
++		   struct brw_reg dest,
++		   GLuint msg_reg_nr,
++		   struct brw_reg src0,
++		   GLboolean allocate,
++		   GLboolean used,
++		   GLuint msg_length,
++		   GLuint response_length,
++		   GLboolean eot,
++		   GLboolean writes_complete,
++		   GLuint offset,
++		   GLuint swizzle);
++
+ void brw_fb_WRITE(struct brw_compile *p,
+ 		   struct brw_reg dest,
+ 		   GLuint msg_reg_nr,
+@@ -820,7 +833,9 @@ void brw_SAMPLE(struct brw_compile *p,
+ 		GLuint msg_type,
+ 		GLuint response_length,
+ 		GLuint msg_length,
+-		GLboolean eot);
++		GLboolean eot,
++		GLuint header_present,
++		GLuint simd_mode);
+ 
+ void brw_math_16( struct brw_compile *p,
+ 		  struct brw_reg dest,
+--- src/mesa/drivers/dri/i965/brw_eu_emit.c	2009-09-01 14:49:55.007896861 +0800
++++ src/mesa/drivers/dri/i965/brw_eu_emit.c	2009-09-01 16:09:13.529977045 +0800
+@@ -233,7 +233,8 @@ void brw_set_src1( struct brw_instructio
+ 
+ 
+ 
+-static void brw_set_math_message( struct brw_instruction *insn,
++static void brw_set_math_message( struct brw_context *brw,
++				  struct brw_instruction *insn,
+ 				  GLuint msg_length,
+ 				  GLuint response_length,
+ 				  GLuint function,
+@@ -244,18 +245,35 @@ static void brw_set_math_message( struct
+ {
+    brw_set_src1(insn, brw_imm_d(0));
+ 
+-   insn->bits3.math.function = function;
+-   insn->bits3.math.int_type = integer_type;
+-   insn->bits3.math.precision = low_precision;
+-   insn->bits3.math.saturate = saturate;
+-   insn->bits3.math.data_type = dataType;
+-   insn->bits3.math.response_length = response_length;
+-   insn->bits3.math.msg_length = msg_length;
+-   insn->bits3.math.msg_target = BRW_MESSAGE_TARGET_MATH;
+-   insn->bits3.math.end_of_thread = 0;
++   if (BRW_IS_IGDNG(brw)) {
++       insn->bits3.math_igdng.function = function;
++       insn->bits3.math_igdng.int_type = integer_type;
++       insn->bits3.math_igdng.precision = low_precision;
++       insn->bits3.math_igdng.saturate = saturate;
++       insn->bits3.math_igdng.data_type = dataType;
++       insn->bits3.math_igdng.snapshot = 0;
++       insn->bits3.math_igdng.header_present = 0;
++       insn->bits3.math_igdng.response_length = response_length;
++       insn->bits3.math_igdng.msg_length = msg_length;
++       insn->bits3.math_igdng.end_of_thread = 0;
++       insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_MATH;
++       insn->bits2.send_igdng.end_of_thread = 0;
++   } else {
++       insn->bits3.math.function = function;
++       insn->bits3.math.int_type = integer_type;
++       insn->bits3.math.precision = low_precision;
++       insn->bits3.math.saturate = saturate;
++       insn->bits3.math.data_type = dataType;
++       insn->bits3.math.response_length = response_length;
++       insn->bits3.math.msg_length = msg_length;
++       insn->bits3.math.msg_target = BRW_MESSAGE_TARGET_MATH;
++       insn->bits3.math.end_of_thread = 0;
++   }
+ }
+ 
+-static void brw_set_urb_message( struct brw_instruction *insn,
++
++static void brw_set_ff_sync_message( struct brw_context *brw,
++				 struct brw_instruction *insn,
+ 				 GLboolean allocate,
+ 				 GLboolean used,
+ 				 GLuint msg_length,
+@@ -265,21 +283,64 @@ static void brw_set_urb_message( struct 
+ 				 GLuint offset,
+ 				 GLuint swizzle_control )
+ {
+-   brw_set_src1(insn, brw_imm_d(0));
++	brw_set_src1(insn, brw_imm_d(0));
++
++	insn->bits3.urb_igdng.opcode = 1;
++	insn->bits3.urb_igdng.offset = offset;
++	insn->bits3.urb_igdng.swizzle_control = swizzle_control;
++	insn->bits3.urb_igdng.allocate = allocate;
++	insn->bits3.urb_igdng.used = used;
++	insn->bits3.urb_igdng.complete = complete;
++	insn->bits3.urb_igdng.header_present = 1;
++	insn->bits3.urb_igdng.response_length = response_length;
++	insn->bits3.urb_igdng.msg_length = msg_length;
++	insn->bits3.urb_igdng.end_of_thread = end_of_thread;
++	insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_URB;
++	insn->bits2.send_igdng.end_of_thread = end_of_thread;
++}
++
++static void brw_set_urb_message( struct brw_context *brw,
++				 struct brw_instruction *insn,
++				 GLboolean allocate,
++				 GLboolean used,
++				 GLuint msg_length,
++				 GLuint response_length,
++				 GLboolean end_of_thread,
++				 GLboolean complete,
++				 GLuint offset,
++				 GLuint swizzle_control )
++{
++    brw_set_src1(insn, brw_imm_d(0));
+ 
+-   insn->bits3.urb.opcode = 0;	/* ? */
+-   insn->bits3.urb.offset = offset;
+-   insn->bits3.urb.swizzle_control = swizzle_control;
+-   insn->bits3.urb.allocate = allocate;
+-   insn->bits3.urb.used = used;	/* ? */
+-   insn->bits3.urb.complete = complete;
+-   insn->bits3.urb.response_length = response_length;
+-   insn->bits3.urb.msg_length = msg_length;
+-   insn->bits3.urb.msg_target = BRW_MESSAGE_TARGET_URB;
+-   insn->bits3.urb.end_of_thread = end_of_thread;
++    if (BRW_IS_IGDNG(brw)) {
++        insn->bits3.urb_igdng.opcode = 0;	/* ? */
++        insn->bits3.urb_igdng.offset = offset;
++        insn->bits3.urb_igdng.swizzle_control = swizzle_control;
++        insn->bits3.urb_igdng.allocate = allocate;
++        insn->bits3.urb_igdng.used = used;	/* ? */
++        insn->bits3.urb_igdng.complete = complete;
++        insn->bits3.urb_igdng.header_present = 1;
++        insn->bits3.urb_igdng.response_length = response_length;
++        insn->bits3.urb_igdng.msg_length = msg_length;
++        insn->bits3.urb_igdng.end_of_thread = end_of_thread;
++        insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_URB;
++        insn->bits2.send_igdng.end_of_thread = end_of_thread;
++    } else {
++        insn->bits3.urb.opcode = 0;	/* ? */
++        insn->bits3.urb.offset = offset;
++        insn->bits3.urb.swizzle_control = swizzle_control;
++        insn->bits3.urb.allocate = allocate;
++        insn->bits3.urb.used = used;	/* ? */
++        insn->bits3.urb.complete = complete;
++        insn->bits3.urb.response_length = response_length;
++        insn->bits3.urb.msg_length = msg_length;
++        insn->bits3.urb.msg_target = BRW_MESSAGE_TARGET_URB;
++        insn->bits3.urb.end_of_thread = end_of_thread;
++    }
+ }
+ 
+-static void brw_set_dp_write_message( struct brw_instruction *insn,
++static void brw_set_dp_write_message( struct brw_context *brw,
++				      struct brw_instruction *insn,
+ 				      GLuint binding_table_index,
+ 				      GLuint msg_control,
+ 				      GLuint msg_type,
+@@ -290,18 +351,33 @@ static void brw_set_dp_write_message( st
+ {
+    brw_set_src1(insn, brw_imm_d(0));
+ 
+-   insn->bits3.dp_write.binding_table_index = binding_table_index;
+-   insn->bits3.dp_write.msg_control = msg_control;
+-   insn->bits3.dp_write.pixel_scoreboard_clear = pixel_scoreboard_clear;
+-   insn->bits3.dp_write.msg_type = msg_type;
+-   insn->bits3.dp_write.send_commit_msg = 0;
+-   insn->bits3.dp_write.response_length = response_length;
+-   insn->bits3.dp_write.msg_length = msg_length;
+-   insn->bits3.dp_write.msg_target = BRW_MESSAGE_TARGET_DATAPORT_WRITE;
+-   insn->bits3.urb.end_of_thread = end_of_thread;
++   if (BRW_IS_IGDNG(brw)) {
++       insn->bits3.dp_write_igdng.binding_table_index = binding_table_index;
++       insn->bits3.dp_write_igdng.msg_control = msg_control;
++       insn->bits3.dp_write_igdng.pixel_scoreboard_clear = pixel_scoreboard_clear;
++       insn->bits3.dp_write_igdng.msg_type = msg_type;
++       insn->bits3.dp_write_igdng.send_commit_msg = 0;
++       insn->bits3.dp_write_igdng.header_present = 1;
++       insn->bits3.dp_write_igdng.response_length = response_length;
++       insn->bits3.dp_write_igdng.msg_length = msg_length;
++       insn->bits3.dp_write_igdng.end_of_thread = end_of_thread;
++       insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_DATAPORT_WRITE;
++       insn->bits2.send_igdng.end_of_thread = end_of_thread;
++   } else {
++       insn->bits3.dp_write.binding_table_index = binding_table_index;
++       insn->bits3.dp_write.msg_control = msg_control;
++       insn->bits3.dp_write.pixel_scoreboard_clear = pixel_scoreboard_clear;
++       insn->bits3.dp_write.msg_type = msg_type;
++       insn->bits3.dp_write.send_commit_msg = 0;
++       insn->bits3.dp_write.response_length = response_length;
++       insn->bits3.dp_write.msg_length = msg_length;
++       insn->bits3.dp_write.msg_target = BRW_MESSAGE_TARGET_DATAPORT_WRITE;
++       insn->bits3.dp_write.end_of_thread = end_of_thread;
++   }
+ }
+ 
+-static void brw_set_dp_read_message( struct brw_instruction *insn,
++static void brw_set_dp_read_message( struct brw_context *brw,
++				      struct brw_instruction *insn,
+ 				      GLuint binding_table_index,
+ 				      GLuint msg_control,
+ 				      GLuint msg_type,
+@@ -312,14 +388,28 @@ static void brw_set_dp_read_message( str
+ {
+    brw_set_src1(insn, brw_imm_d(0));
+ 
+-   insn->bits3.dp_read.binding_table_index = binding_table_index;
+-   insn->bits3.dp_read.msg_control = msg_control;
+-   insn->bits3.dp_read.msg_type = msg_type;
+-   insn->bits3.dp_read.target_cache = target_cache;
+-   insn->bits3.dp_read.response_length = response_length;
+-   insn->bits3.dp_read.msg_length = msg_length;
+-   insn->bits3.dp_read.msg_target = BRW_MESSAGE_TARGET_DATAPORT_READ;
+-   insn->bits3.dp_read.end_of_thread = end_of_thread;
++   if (BRW_IS_IGDNG(brw)) {
++       insn->bits3.dp_read_igdng.binding_table_index = binding_table_index;
++       insn->bits3.dp_read_igdng.msg_control = msg_control;
++       insn->bits3.dp_read_igdng.msg_type = msg_type;
++       insn->bits3.dp_read_igdng.target_cache = target_cache;
++       insn->bits3.dp_read_igdng.header_present = 1;
++       insn->bits3.dp_read_igdng.response_length = response_length;
++       insn->bits3.dp_read_igdng.msg_length = msg_length;
++       insn->bits3.dp_read_igdng.pad1 = 0;
++       insn->bits3.dp_read_igdng.end_of_thread = end_of_thread;
++       insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_DATAPORT_READ;
++       insn->bits2.send_igdng.end_of_thread = end_of_thread;
++   } else {
++       insn->bits3.dp_read.binding_table_index = binding_table_index;
++       insn->bits3.dp_read.msg_control = msg_control;
++       insn->bits3.dp_read.msg_type = msg_type;
++       insn->bits3.dp_read.target_cache = target_cache;
++       insn->bits3.dp_read.response_length = response_length;
++       insn->bits3.dp_read.msg_length = msg_length;
++       insn->bits3.dp_read.msg_target = BRW_MESSAGE_TARGET_DATAPORT_READ;
++       insn->bits3.dp_read.end_of_thread = end_of_thread;
++   }
+ }
+ 
+ static void brw_set_sampler_message(struct brw_context *brw,
+@@ -329,11 +419,25 @@ static void brw_set_sampler_message(stru
+ 				     GLuint msg_type,
+ 				     GLuint response_length,
+ 				     GLuint msg_length,
+-				     GLboolean eot)
++                                     GLboolean eot,
++                                     GLuint header_present,
++                                     GLuint simd_mode)
+ {
++   assert(eot == 0);
+    brw_set_src1(insn, brw_imm_d(0));
+ 
+-   if (BRW_IS_G4X(brw)) {
++   if (BRW_IS_IGDNG(brw)) {
++      insn->bits3.sampler_igdng.binding_table_index = binding_table_index;
++      insn->bits3.sampler_igdng.sampler = sampler;
++      insn->bits3.sampler_igdng.msg_type = msg_type;
++      insn->bits3.sampler_igdng.simd_mode = simd_mode;
++      insn->bits3.sampler_igdng.header_present = header_present;
++      insn->bits3.sampler_igdng.response_length = response_length;
++      insn->bits3.sampler_igdng.msg_length = msg_length;
++      insn->bits3.sampler_igdng.end_of_thread = eot;
++      insn->bits2.send_igdng.sfid = BRW_MESSAGE_TARGET_SAMPLER;
++      insn->bits2.send_igdng.end_of_thread = eot;
++   } else if (BRW_IS_G4X(brw)) {
+       insn->bits3.sampler_g4x.binding_table_index = binding_table_index;
+       insn->bits3.sampler_g4x.sampler = sampler;
+       insn->bits3.sampler_g4x.msg_type = msg_type;
+@@ -531,6 +635,10 @@ struct brw_instruction *brw_ELSE(struct 
+ 				 struct brw_instruction *if_insn)
+ {
+    struct brw_instruction *insn;
++   GLuint br = 1;
++
++   if (BRW_IS_IGDNG(p->brw))
++      br = 2;
+ 
+    if (p->single_program_flow) {
+       insn = next_insn(p, BRW_OPCODE_ADD);
+@@ -557,7 +665,7 @@ struct brw_instruction *brw_ELSE(struct 
+    } else {
+       assert(if_insn->header.opcode == BRW_OPCODE_IF);
+ 
+-      if_insn->bits3.if_else.jump_count = insn - if_insn;
++      if_insn->bits3.if_else.jump_count = br * (insn - if_insn);
+       if_insn->bits3.if_else.pop_count = 1;
+       if_insn->bits3.if_else.pad0 = 0;
+    }
+@@ -568,6 +676,11 @@ struct brw_instruction *brw_ELSE(struct 
+ void brw_ENDIF(struct brw_compile *p, 
+ 	       struct brw_instruction *patch_insn)
+ {
++   GLuint br = 1;
++
++   if (BRW_IS_IGDNG(p->brw))
++      br = 2; 
++
+    if (p->single_program_flow) {
+       /* In single program flow mode, there's no need to execute an ENDIF,
+        * since we don't need to do any stack operations, and if we're executing
+@@ -599,11 +712,11 @@ void brw_ENDIF(struct brw_compile *p, 
+ 	 /* Automagically turn it into an IFF:
+ 	  */
+ 	 patch_insn->header.opcode = BRW_OPCODE_IFF;
+-	 patch_insn->bits3.if_else.jump_count = insn - patch_insn + 1;
++         patch_insn->bits3.if_else.jump_count = br * (insn - patch_insn + 1);
+ 	 patch_insn->bits3.if_else.pop_count = 0;
+ 	 patch_insn->bits3.if_else.pad0 = 0;
+       } else if (patch_insn->header.opcode == BRW_OPCODE_ELSE) {
+-	 patch_insn->bits3.if_else.jump_count = insn - patch_insn + 1;
++         patch_insn->bits3.if_else.jump_count = br * (insn - patch_insn + 1);
+ 	 patch_insn->bits3.if_else.pop_count = 1;
+ 	 patch_insn->bits3.if_else.pad0 = 0;
+       } else {
+@@ -677,6 +790,10 @@ struct brw_instruction *brw_WHILE(struct
+ 	       struct brw_instruction *do_insn)
+ {
+    struct brw_instruction *insn;
++   GLuint br = 1;
++
++   if (BRW_IS_IGDNG(p->brw))
++      br = 2;
+ 
+    if (p->single_program_flow)
+       insn = next_insn(p, BRW_OPCODE_ADD);
+@@ -697,7 +814,7 @@ struct brw_instruction *brw_WHILE(struct
+       insn->header.execution_size = do_insn->header.execution_size;
+ 
+       assert(do_insn->header.opcode == BRW_OPCODE_DO);
+-      insn->bits3.if_else.jump_count = do_insn - insn + 1;
++      insn->bits3.if_else.jump_count = br * (do_insn - insn + 1);
+       insn->bits3.if_else.pop_count = 0;
+       insn->bits3.if_else.pad0 = 0;
+    }
+@@ -716,11 +833,15 @@ void brw_land_fwd_jump(struct brw_compil
+ 		       struct brw_instruction *jmp_insn)
+ {
+    struct brw_instruction *landing = &p->store[p->nr_insn];
++   GLuint jmpi = 1;
++
++   if (BRW_IS_IGDNG(p->brw))
++       jmpi = 2;
+ 
+    assert(jmp_insn->header.opcode == BRW_OPCODE_JMPI);
+    assert(jmp_insn->bits1.da1.src1_reg_file = BRW_IMMEDIATE_VALUE);
+ 
+-   jmp_insn->bits3.ud = (landing - jmp_insn) - 1; 
++   jmp_insn->bits3.ud = jmpi * ((landing - jmp_insn) - 1);
+ }
+ 
+ 
+@@ -785,7 +906,8 @@ void brw_math( struct brw_compile *p,
+ 
+    brw_set_dest(insn, dest);
+    brw_set_src0(insn, src);
+-   brw_set_math_message(insn, 
++   brw_set_math_message(p->brw,
++			insn, 
+ 			msg_length, response_length, 
+ 			function,
+ 			BRW_MATH_INTEGER_UNSIGNED,
+@@ -819,7 +941,8 @@ void brw_math_16( struct brw_compile *p,
+ 
+    brw_set_dest(insn, dest);
+    brw_set_src0(insn, src);
+-   brw_set_math_message(insn, 
++   brw_set_math_message(p->brw,
++			insn, 
+ 			msg_length, response_length, 
+ 			function,
+ 			BRW_MATH_INTEGER_UNSIGNED,
+@@ -835,7 +958,8 @@ void brw_math_16( struct brw_compile *p,
+ 
+    brw_set_dest(insn, offset(dest,1));
+    brw_set_src0(insn, src);
+-   brw_set_math_message(insn, 
++   brw_set_math_message(p->brw, 
++			insn, 
+ 			msg_length, response_length, 
+ 			function,
+ 			BRW_MATH_INTEGER_UNSIGNED,
+@@ -878,7 +1002,8 @@ void brw_dp_WRITE_16( struct brw_compile
+       brw_set_dest(insn, dest);
+       brw_set_src0(insn, src);
+ 
+-      brw_set_dp_write_message(insn,
++      brw_set_dp_write_message(p->brw,
++			       insn,
+ 			       255, /* bti */
+ 			       BRW_DATAPORT_OWORD_BLOCK_4_OWORDS, /* msg_control */
+ 			       BRW_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE, /* msg_type */
+@@ -918,7 +1043,8 @@ void brw_dp_READ_16( struct brw_compile 
+       brw_set_dest(insn, dest);	/* UW? */
+       brw_set_src0(insn, retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW));
+ 
+-      brw_set_dp_read_message(insn,
++      brw_set_dp_read_message(p->brw,
++			      insn,
+ 			      255, /* bti */
+ 			      3,  /* msg_control */
+ 			      BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ, /* msg_type */
+@@ -947,7 +1073,8 @@ void brw_fb_WRITE(struct brw_compile *p,
+   
+    brw_set_dest(insn, dest);
+    brw_set_src0(insn, src0);
+-   brw_set_dp_write_message(insn,
++   brw_set_dp_write_message(p->brw,
++			    insn,
+ 			    binding_table_index,
+ 			    BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE, /* msg_control */
+ 			    BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE, /* msg_type */
+@@ -969,7 +1096,9 @@ void brw_SAMPLE(struct brw_compile *p,
+ 		GLuint msg_type,
+ 		GLuint response_length,
+ 		GLuint msg_length,
+-		GLboolean eot)
++		GLboolean eot,
++		GLuint header_present,
++		GLuint simd_mode)
+ {
+    GLboolean need_stall = 0;
+    
+@@ -1044,7 +1173,9 @@ void brw_SAMPLE(struct brw_compile *p,
+ 			      msg_type,
+ 			      response_length, 
+ 			      msg_length,
+-			      eot);
++			      eot,
++			      header_present,
++			      simd_mode);
+    }
+ 
+    if (need_stall)
+@@ -1088,7 +1219,8 @@ void brw_urb_WRITE(struct brw_compile *p
+ 
+    insn->header.destreg__conditonalmod = msg_reg_nr;
+ 
+-   brw_set_urb_message(insn,
++   brw_set_urb_message(p->brw,
++		       insn,
+ 		       allocate,
+ 		       used,
+ 		       msg_length,
+@@ -1099,3 +1231,37 @@ void brw_urb_WRITE(struct brw_compile *p
+ 		       swizzle);
+ }
+ 
++void brw_ff_sync(struct brw_compile *p,
++		   struct brw_reg dest,
++		   GLuint msg_reg_nr,
++		   struct brw_reg src0,
++		   GLboolean allocate,
++		   GLboolean used,
++		   GLuint msg_length,
++		   GLuint response_length,
++		   GLboolean eot,
++		   GLboolean writes_complete,
++		   GLuint offset,
++		   GLuint swizzle)
++{
++   struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
++
++   assert(msg_length < 16);
++
++   brw_set_dest(insn, dest);
++   brw_set_src0(insn, src0);
++   brw_set_src1(insn, brw_imm_d(0));
++
++   insn->header.destreg__conditonalmod = msg_reg_nr;
++
++   brw_set_ff_sync_message(p->brw,
++		       insn,
++		       allocate,
++		       used,
++		       msg_length,
++		       response_length, 
++		       eot, 
++		       writes_complete, 
++		       offset,
++		       swizzle);
++}
+--- src/mesa/drivers/dri/i965/brw_gs.c	2009-09-01 14:49:51.065847835 +0800
++++ src/mesa/drivers/dri/i965/brw_gs.c	2009-09-01 15:42:30.776677415 +0800
+@@ -54,12 +54,17 @@ static void compile_gs_prog( struct brw_
+    memset(&c, 0, sizeof(c));
+    
+    c.key = *key;
+-
++   c.need_ff_sync = BRW_IS_IGDNG(brw);
+    /* Need to locate the two positions present in vertex + header.
+     * These are currently hardcoded:
+     */
+    c.nr_attrs = brw_count_bits(c.key.attrs);
+-   c.nr_regs = (c.nr_attrs + 1) / 2 + 1;  /* are vertices packed, or reg-aligned? */
++
++   if (BRW_IS_IGDNG(brw))
++       c.nr_regs = (c.nr_attrs + 1) / 2 + 3;  /* are vertices packed, or reg-aligned? */
++   else
++       c.nr_regs = (c.nr_attrs + 1) / 2 + 1;  /* are vertices packed, or reg-aligned? */
++
+    c.nr_bytes = c.nr_regs * REG_SIZE;
+ 
+    
+--- src/mesa/drivers/dri/i965/brw_gs.h	2009-09-01 14:49:51.066548852 +0800
++++ src/mesa/drivers/dri/i965/brw_gs.h	2009-09-01 15:42:30.777095934 +0800
+@@ -62,6 +62,7 @@ struct brw_gs_compile {
+    GLuint nr_attrs;
+    GLuint nr_regs;
+    GLuint nr_bytes;
++   GLboolean need_ff_sync;
+ };
+ 
+ #define ATTR_SIZE  (4*4)
+--- src/mesa/drivers/dri/i965/brw_gs_emit.c	2009-09-01 14:49:51.067540026 +0800
++++ src/mesa/drivers/dri/i965/brw_gs_emit.c	2009-09-01 15:42:30.777846075 +0800
+@@ -101,6 +101,23 @@ static void brw_gs_emit_vue(struct brw_g
+ 		 BRW_URB_SWIZZLE_NONE);
+ }
+ 
++void brw_gs_ff_sync(struct brw_gs_compile *c, int num_prim)
++{
++	struct brw_compile *p = &c->func;
++	brw_MOV(p, get_element_ud(c->reg.R0, 1), brw_imm_ud(num_prim));
++	brw_ff_sync(p, 
++				c->reg.R0,
++				0,
++				c->reg.R0,
++				1,	
++				1,		/* used */
++				1,  	/* msg length */
++				1,		/* response length */
++				0,		/* eot */
++				1,		/* write compelete */
++				0,		/* urb offset */
++				BRW_URB_SWIZZLE_NONE);
++}
+ 
+ 
+ void brw_gs_quads( struct brw_gs_compile *c )
+@@ -110,6 +127,8 @@ void brw_gs_quads( struct brw_gs_compile
+    /* Use polygons for correct edgeflag behaviour. Note that vertex 3
+     * is the PV for quads, but vertex 0 for polygons:
+     */
++   if (c->need_ff_sync)
++	   brw_gs_ff_sync(c, 1);    
+    brw_gs_emit_vue(c, c->reg.vertex[3], 0, ((_3DPRIM_POLYGON << 2) | R02_PRIM_START));
+    brw_gs_emit_vue(c, c->reg.vertex[0], 0, (_3DPRIM_POLYGON << 2));
+    brw_gs_emit_vue(c, c->reg.vertex[1], 0, (_3DPRIM_POLYGON << 2)); 
+@@ -120,6 +139,8 @@ void brw_gs_quad_strip( struct brw_gs_co
+ {
+    brw_gs_alloc_regs(c, 4);
+    
++   if (c->need_ff_sync)
++	   brw_gs_ff_sync(c, 1);      
+    brw_gs_emit_vue(c, c->reg.vertex[2], 0, ((_3DPRIM_POLYGON << 2) | R02_PRIM_START));
+    brw_gs_emit_vue(c, c->reg.vertex[3], 0, (_3DPRIM_POLYGON << 2));
+    brw_gs_emit_vue(c, c->reg.vertex[0], 0, (_3DPRIM_POLYGON << 2)); 
+@@ -129,6 +150,9 @@ void brw_gs_quad_strip( struct brw_gs_co
+ void brw_gs_tris( struct brw_gs_compile *c )
+ {
+    brw_gs_alloc_regs(c, 3);
++
++   if (c->need_ff_sync)
++	   brw_gs_ff_sync(c, 1);      
+    brw_gs_emit_vue(c, c->reg.vertex[0], 0, ((_3DPRIM_TRILIST << 2) | R02_PRIM_START));
+    brw_gs_emit_vue(c, c->reg.vertex[1], 0, (_3DPRIM_TRILIST << 2));
+    brw_gs_emit_vue(c, c->reg.vertex[2], 1, ((_3DPRIM_TRILIST << 2) | R02_PRIM_END));
+@@ -137,6 +161,9 @@ void brw_gs_tris( struct brw_gs_compile 
+ void brw_gs_lines( struct brw_gs_compile *c )
+ {
+    brw_gs_alloc_regs(c, 2);
++
++   if (c->need_ff_sync)
++	   brw_gs_ff_sync(c, 1);      
+    brw_gs_emit_vue(c, c->reg.vertex[0], 0, ((_3DPRIM_LINESTRIP << 2) | R02_PRIM_START));
+    brw_gs_emit_vue(c, c->reg.vertex[1], 1, ((_3DPRIM_LINESTRIP << 2) | R02_PRIM_END));
+ }
+@@ -144,6 +171,9 @@ void brw_gs_lines( struct brw_gs_compile
+ void brw_gs_points( struct brw_gs_compile *c )
+ {
+    brw_gs_alloc_regs(c, 1);
++
++   if (c->need_ff_sync)
++	   brw_gs_ff_sync(c, 1);      
+    brw_gs_emit_vue(c, c->reg.vertex[0], 1, ((_3DPRIM_POINTLIST << 2) | R02_PRIM_START | R02_PRIM_END));
+ }
+ 
+--- src/mesa/drivers/dri/i965/brw_gs_state.c	2009-09-01 14:49:51.068404762 +0800
++++ src/mesa/drivers/dri/i965/brw_gs_state.c	2009-09-01 15:42:30.778282955 +0800
+@@ -95,6 +95,9 @@ gs_unit_create_from_key(struct brw_conte
+ 
+    gs.thread4.max_threads = 0; /* Hardware requirement */
+ 
++   if (BRW_IS_IGDNG(brw))
++      gs.thread4.rendering_enable = 1;
++
+    if (INTEL_DEBUG & DEBUG_STATS)
+       gs.thread4.stats_enable = 1;
+ 
+--- src/mesa/drivers/dri/i965/brw_misc_state.c	2009-09-01 14:49:51.069407222 +0800
++++ src/mesa/drivers/dri/i965/brw_misc_state.c	2009-09-01 15:42:30.779026931 +0800
+@@ -209,7 +209,7 @@ static void emit_depthbuffer(struct brw_
+ {
+    struct intel_context *intel = &brw->intel;
+    struct intel_region *region = brw->state.depth_region;
+-   unsigned int len = BRW_IS_G4X(brw) ? 6 : 5;
++   unsigned int len = (BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw)) ? 6 : 5;
+ 
+    if (region == NULL) {
+       BEGIN_BATCH(len, IGNORE_CLIPRECTS);
+@@ -220,7 +220,7 @@ static void emit_depthbuffer(struct brw_
+       OUT_BATCH(0);
+       OUT_BATCH(0);
+ 
+-      if (BRW_IS_G4X(brw))
++      if (BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw))
+          OUT_BATCH(0);
+ 
+       ADVANCE_BATCH();
+@@ -257,7 +257,7 @@ static void emit_depthbuffer(struct brw_
+ 		((region->height - 1) << 19));
+       OUT_BATCH(0);
+ 
+-      if (BRW_IS_G4X(brw))
++      if (BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw))
+          OUT_BATCH(0);
+ 
+       ADVANCE_BATCH();
+@@ -370,7 +370,7 @@ static void upload_aa_line_parameters(st
+ {
+    struct brw_aa_line_parameters balp;
+    
+-   if (!BRW_IS_G4X(brw))
++   if (BRW_IS_965(brw))
+       return;
+ 
+    /* use legacy aa line coverage computation */
+@@ -507,14 +507,27 @@ static void upload_state_base_address( s
+    /* Output the structure (brw_state_base_address) directly to the
+     * batchbuffer, so we can emit relocations inline.
+     */
+-   BEGIN_BATCH(6, IGNORE_CLIPRECTS);
+-   OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (6 - 2));
+-   OUT_BATCH(1); /* General state base address */
+-   OUT_BATCH(1); /* Surface state base address */
+-   OUT_BATCH(1); /* Indirect object base address */
+-   OUT_BATCH(1); /* General state upper bound */
+-   OUT_BATCH(1); /* Indirect object upper bound */
+-   ADVANCE_BATCH();
++   if (BRW_IS_IGDNG(brw)) {
++       BEGIN_BATCH(8, IGNORE_CLIPRECTS);
++       OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (8 - 2));
++       OUT_BATCH(1); /* General state base address */
++       OUT_BATCH(1); /* Surface state base address */
++       OUT_BATCH(1); /* Indirect object base address */
++       OUT_BATCH(1); /* Instruction base address */
++       OUT_BATCH(1); /* General state upper bound */
++       OUT_BATCH(1); /* Indirect object upper bound */
++       OUT_BATCH(1); /* Instruction access upper bound */
++       ADVANCE_BATCH();
++   } else {
++       BEGIN_BATCH(6, IGNORE_CLIPRECTS);
++       OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (6 - 2));
++       OUT_BATCH(1); /* General state base address */
++       OUT_BATCH(1); /* Surface state base address */
++       OUT_BATCH(1); /* Indirect object base address */
++       OUT_BATCH(1); /* General state upper bound */
++       OUT_BATCH(1); /* Indirect object upper bound */
++       ADVANCE_BATCH();
++   }
+ }
+ 
+ const struct brw_tracked_state brw_state_base_address = {
+--- src/mesa/drivers/dri/i965/brw_sf_emit.c	2009-09-01 14:49:55.147418312 +0800
++++ src/mesa/drivers/dri/i965/brw_sf_emit.c	2009-09-01 15:47:18.000772762 +0800
+@@ -151,6 +151,8 @@ static void do_flatshade_triangle( struc
+    struct brw_compile *p = &c->func;
+    struct brw_reg ip = brw_ip_reg();
+    GLuint nr = brw_count_bits(c->key.attrs & VERT_RESULT_COLOR_BITS);
++   GLuint jmpi = 1;
++
+    if (!nr)
+       return;
+ 
+@@ -159,18 +161,21 @@ static void do_flatshade_triangle( struc
+    if (c->key.primitive == SF_UNFILLED_TRIS)
+       return;
+ 
++   if (BRW_IS_IGDNG(p->brw))
++	jmpi = 2;
++
+    brw_push_insn_state(p);
+    
+-   brw_MUL(p, c->pv, c->pv, brw_imm_ud(nr*2+1));
++   brw_MUL(p, c->pv, c->pv, brw_imm_d(jmpi*(nr*2+1)));
+    brw_JMPI(p, ip, ip, c->pv);
+ 
+    copy_colors(c, c->vert[1], c->vert[0]);
+    copy_colors(c, c->vert[2], c->vert[0]);
+-   brw_JMPI(p, ip, ip, brw_imm_ud(nr*4+1));
++   brw_JMPI(p, ip, ip, brw_imm_d(jmpi*(nr*4+1)));
+ 
+    copy_colors(c, c->vert[0], c->vert[1]);
+    copy_colors(c, c->vert[2], c->vert[1]);
+-   brw_JMPI(p, ip, ip, brw_imm_ud(nr*2));
++   brw_JMPI(p, ip, ip, brw_imm_d(jmpi*nr*2));
+ 
+    copy_colors(c, c->vert[0], c->vert[2]);
+    copy_colors(c, c->vert[1], c->vert[2]);
+@@ -184,7 +189,8 @@ static void do_flatshade_line( struct br
+    struct brw_compile *p = &c->func;
+    struct brw_reg ip = brw_ip_reg();
+    GLuint nr = brw_count_bits(c->key.attrs & VERT_RESULT_COLOR_BITS);
+-   
++   GLuint jmpi = 1;
++
+    if (!nr)
+       return;
+ 
+@@ -193,13 +199,16 @@ static void do_flatshade_line( struct br
+    if (c->key.primitive == SF_UNFILLED_TRIS)
+       return;
+ 
++   if (BRW_IS_IGDNG(p->brw))
++	jmpi = 2;
++
+    brw_push_insn_state(p);
+    
+-   brw_MUL(p, c->pv, c->pv, brw_imm_ud(nr+1));
++   brw_MUL(p, c->pv, c->pv, brw_imm_d(jmpi*(nr+1)));
+    brw_JMPI(p, ip, ip, c->pv);
+    copy_colors(c, c->vert[1], c->vert[0]);
+ 
+-   brw_JMPI(p, ip, ip, brw_imm_ud(nr));
++   brw_JMPI(p, ip, ip, brw_imm_ud(jmpi*nr));
+    copy_colors(c, c->vert[0], c->vert[1]);
+ 
+    brw_pop_insn_state(p);
+--- src/mesa/drivers/dri/i965/brw_sf_state.c	2009-09-01 14:49:51.071499705 +0800
++++ src/mesa/drivers/dri/i965/brw_sf_state.c	2009-09-01 15:42:30.781125057 +0800
+@@ -157,7 +157,7 @@ sf_unit_create_from_key(struct brw_conte
+ {
+    struct brw_sf_unit_state sf;
+    dri_bo *bo;
+-
++   int chipset_max_threads;
+    memset(&sf, 0, sizeof(sf));
+ 
+    sf.thread0.grf_reg_count = ALIGN(key->total_grf, 16) / 16 - 1;
+@@ -166,13 +166,26 @@ sf_unit_create_from_key(struct brw_conte
+    sf.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
+ 
+    sf.thread3.dispatch_grf_start_reg = 3;
+-   sf.thread3.urb_entry_read_offset = 1;
++
++   if (BRW_IS_IGDNG(brw))
++       sf.thread3.urb_entry_read_offset = 3;
++   else
++       sf.thread3.urb_entry_read_offset = 1;
++
+    sf.thread3.urb_entry_read_length = key->urb_entry_read_length;
+ 
+    sf.thread4.nr_urb_entries = key->nr_urb_entries;
+    sf.thread4.urb_entry_allocation_size = key->sfsize - 1;
+-   /* Each SF thread produces 1 PUE, and there can be up to 24 threads */
+-   sf.thread4.max_threads = MIN2(24, key->nr_urb_entries) - 1;
++
++   /* Each SF thread produces 1 PUE, and there can be up to 24(Pre-IGDNG) or 
++    * 48(IGDNG) threads 
++    */
++   if (BRW_IS_IGDNG(brw))
++      chipset_max_threads = 48;
++   else
++      chipset_max_threads = 24;
++
++   sf.thread4.max_threads = MIN2(chipset_max_threads, key->nr_urb_entries) - 1;
+ 
+    if (INTEL_DEBUG & DEBUG_SINGLE_THREAD)
+       sf.thread4.max_threads = 0;
+--- src/mesa/drivers/dri/i965/brw_structs.h	2009-09-01 14:50:00.155743705 +0800
++++ src/mesa/drivers/dri/i965/brw_structs.h	2009-09-01 16:12:07.455754914 +0800
+@@ -33,6 +33,11 @@
+ #ifndef BRW_STRUCTS_H
+ #define BRW_STRUCTS_H
+ 
++/** Number of general purpose registers (VS, WM, etc) */
++#define BRW_MAX_GRF 128
++/** Number of message register file registers */
++#define BRW_MAX_MRF 16 
++
+ /* Command packets:
+  */
+ struct header 
+@@ -815,7 +820,9 @@ struct brw_gs_unit_state
+ 
+    struct
+    {
+-      GLuint pad0:10;
++      GLuint pad0:8;
++      GLuint rendering_enable:1; /* for IGDNG */
++      GLuint pad4:1;
+       GLuint stats_enable:1; 
+       GLuint nr_urb_entries:7; 
+       GLuint pad1:1;
+@@ -923,6 +930,28 @@ struct brw_wm_unit_state
+    
+    GLfloat global_depth_offset_constant;  
+    GLfloat global_depth_offset_scale;   
++   
++   /* for IGDNG only */
++   struct {
++      GLuint pad0:1;
++      GLuint grf_reg_count_1:3; 
++      GLuint pad1:2;
++      GLuint kernel_start_pointer_1:26;
++   } wm8;       
++
++   struct {
++      GLuint pad0:1;
++      GLuint grf_reg_count_2:3; 
++      GLuint pad1:2;
++      GLuint kernel_start_pointer_2:26;
++   } wm9;       
++
++   struct {
++      GLuint pad0:1;
++      GLuint grf_reg_count_3:3; 
++      GLuint pad1:2;
++      GLuint kernel_start_pointer_3:26;
++   } wm10;       
+ };
+ 
+ struct brw_sampler_default_color {
+@@ -1298,6 +1327,14 @@ struct brw_instruction
+ 	 GLuint pad1:6;
+       } ia16;
+ 
++       struct 
++       {
++           GLuint pad:26;
++           GLuint end_of_thread:1;
++           GLuint pad1:1;
++           GLuint sfid:4;
++       } send_igdng;  /* for IGDNG only */
++
+    } bits2;
+ 
+    union
+@@ -1385,6 +1422,21 @@ struct brw_instruction
+       } math;
+ 
+       struct {
++	 GLuint function:4;
++	 GLuint int_type:1;
++	 GLuint precision:1;
++	 GLuint saturate:1;
++	 GLuint data_type:1;
++	 GLuint snapshot:1;
++	 GLuint pad0:10;
++	 GLuint header_present:1;
++	 GLuint response_length:5;
++	 GLuint msg_length:4;
++	 GLuint pad1:2;
++	 GLuint end_of_thread:1;
++      } math_igdng;
++
++      struct {
+ 	 GLuint binding_table_index:8;
+ 	 GLuint sampler:4;
+ 	 GLuint return_format:2; 
+@@ -1407,9 +1459,38 @@ struct brw_instruction
+          GLuint end_of_thread:1;
+       } sampler_g4x;
+ 
++      struct {
++	 GLuint binding_table_index:8;
++	 GLuint sampler:4;
++	 GLuint msg_type:4;
++	 GLuint simd_mode:2;
++	 GLuint pad0:1;
++	 GLuint header_present:1;
++	 GLuint response_length:5;
++	 GLuint msg_length:4;
++	 GLuint pad1:2;
++	 GLuint end_of_thread:1;
++      } sampler_igdng;
++
+       struct brw_urb_immediate urb;
+ 
+       struct {
++	 GLuint opcode:4;
++	 GLuint offset:6;
++	 GLuint swizzle_control:2; 
++	 GLuint pad:1;
++	 GLuint allocate:1;
++	 GLuint used:1;
++	 GLuint complete:1;
++	 GLuint pad0:3;
++	 GLuint header_present:1;
++	 GLuint response_length:5;
++	 GLuint msg_length:4;
++	 GLuint pad1:2;
++	 GLuint end_of_thread:1;
++      } urb_igdng;
++
++      struct {
+ 	 GLuint binding_table_index:8;
+ 	 GLuint msg_control:4;  
+ 	 GLuint msg_type:2;  
+@@ -1423,6 +1504,19 @@ struct brw_instruction
+ 
+       struct {
+ 	 GLuint binding_table_index:8;
++	 GLuint msg_control:3;  
++	 GLuint msg_type:3;  
++	 GLuint target_cache:2;    
++	 GLuint pad0:3;
++	 GLuint header_present:1;
++	 GLuint response_length:5;
++	 GLuint msg_length:4;
++	 GLuint pad1:2;
++	 GLuint end_of_thread:1;
++      } dp_read_igdng;
++
++      struct {
++	 GLuint binding_table_index:8;
+ 	 GLuint msg_control:3;
+ 	 GLuint pixel_scoreboard_clear:1;
+ 	 GLuint msg_type:3;    
+@@ -1435,6 +1529,20 @@ struct brw_instruction
+       } dp_write;
+ 
+       struct {
++	 GLuint binding_table_index:8;
++	 GLuint msg_control:3;
++	 GLuint pixel_scoreboard_clear:1;
++	 GLuint msg_type:3;    
++	 GLuint send_commit_msg:1;
++	 GLuint pad0:3;
++	 GLuint header_present:1;
++	 GLuint response_length:5;
++	 GLuint msg_length:4;
++	 GLuint pad1:2;
++	 GLuint end_of_thread:1;
++      } dp_write_igdng;
++
++      struct {
+ 	 GLuint pad:16;
+ 	 GLuint response_length:4;
+ 	 GLuint msg_length:4;
+@@ -1443,6 +1551,15 @@ struct brw_instruction
+ 	 GLuint end_of_thread:1;
+       } generic;
+ 
++      struct {
++	 GLuint pad:19;
++	 GLuint header_present:1;
++	 GLuint response_length:5;
++	 GLuint msg_length:4;
++	 GLuint pad1:2;
++	 GLuint end_of_thread:1;
++      } generic_igdng;
++
+       GLint d;
+       GLuint ud;
+    } bits3;
+--- src/mesa/drivers/dri/i965/brw_tex_layout.c	2009-09-01 14:50:28.748709607 +0800
++++ src/mesa/drivers/dri/i965/brw_tex_layout.c	2009-09-01 16:12:58.560886250 +0800
+@@ -37,6 +37,7 @@
+ #include "intel_tex_layout.h"
+ #include "intel_context.h"
+ #include "main/macros.h"
++#include "intel_chipset.h"
+ 
+ #define FILE_DEBUG_FLAG DEBUG_MIPTREE
+ 
+@@ -48,6 +49,77 @@ GLboolean brw_miptree_layout( struct int
+ 
+    switch (mt->target) {
+    case GL_TEXTURE_CUBE_MAP: 
++      if (IS_IGDNG(intel->intelScreen->deviceID)) {
++	   GLuint align_h = 2, align_w = 4;
++	   GLuint level;
++	   GLuint x = 0;
++	   GLuint y = 0;
++	   GLuint width = mt->width0;
++	   GLuint height = mt->height0;
++	   GLuint qpitch = 0;
++	   GLuint y_pitch = 0;
++
++	   mt->pitch = mt->width0;
++	   intel_get_texture_alignment_unit(mt->internal_format, &align_w, &align_h);
++	   y_pitch = ALIGN(height, align_h);
++
++	   if (mt->compressed) {
++	       mt->pitch = ALIGN(mt->width0, align_w);
++	       qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4 * mt->pitch * mt->cpp;
++	       mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4 * 6;
++	   } else {
++	       qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) * mt->pitch * mt->cpp;
++	       mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) * 6;
++	   }
++
++	   if (mt->first_level != mt->last_level) {
++	       GLuint mip1_width;
++
++	       if (mt->compressed) {
++		   mip1_width = ALIGN(minify(mt->width0), align_w)
++		       + ALIGN(minify(minify(mt->width0)), align_w);
++	       } else {
++		   mip1_width = ALIGN(minify(mt->width0), align_w)
++		       + minify(minify(mt->width0));
++	       }
++
++	       if (mip1_width > mt->pitch) {
++		   mt->pitch = mip1_width;
++	       }
++	   }
++
++	   mt->pitch = intel_miptree_pitch_align(intel, mt, mt->pitch);
++
++	   for (level = mt->first_level; level <= mt->last_level; level++) {
++	       GLuint img_height;
++	       GLuint nr_images = 6;
++	       GLuint q = 0;
++
++	       intel_miptree_set_level_info(mt, level, nr_images, x, y, width,
++                                           height, 1);
++
++	       for (q = 0; q < nr_images; q++)
++		   intel_miptree_set_image_offset_ex(mt, level, q, x, y, q * qpitch);
++
++	       if (mt->compressed)
++		   img_height = MAX2(1, height/4);
++	       else
++		   img_height = ALIGN(height, align_h);
++
++	       if (level == mt->first_level + 1) {
++		   x += ALIGN(width, align_w);
++	       }
++	       else {
++		   y += img_height;
++	       }
++
++	       width  = minify(width);
++	       height = minify(height);
++	   }
++
++	   break;
++      }
++
+    case GL_TEXTURE_3D: {
+       GLuint width  = mt->width0;
+       GLuint height = mt->height0;
+@@ -59,9 +131,9 @@ GLboolean brw_miptree_layout( struct int
+       GLuint align_w = 4;
+ 
+       mt->total_height = 0;
++      intel_get_texture_alignment_unit(mt->internal_format, &align_w, &align_h);
+       
+       if (mt->compressed) {
+-          align_w = intel_compressed_alignment(mt->internal_format);
+           mt->pitch = ALIGN(width, align_w);
+           pack_y_pitch = (height + 3) / 4;
+       } else {
+--- src/mesa/drivers/dri/i965/brw_urb.c	2009-09-01 14:50:05.302182823 +0800
++++ src/mesa/drivers/dri/i965/brw_urb.c	2009-09-01 15:55:33.734662769 +0800
+@@ -143,6 +143,27 @@ static void recalculate_urb_fence( struc
+       brw->urb.nr_clip_entries = limits[CLP].preferred_nr_entries;
+       brw->urb.nr_sf_entries = limits[SF].preferred_nr_entries;	
+       brw->urb.nr_cs_entries = limits[CS].preferred_nr_entries;	
++
++      brw->urb.constrained = 0;
++      if (BRW_IS_IGDNG(brw)) {
++         brw->urb.nr_vs_entries = 128;
++         brw->urb.nr_sf_entries = 48;
++         if (check_urb_layout(brw)) {
++            goto done;
++         } else {
++            brw->urb.constrained = 1;
++            brw->urb.nr_vs_entries = limits[VS].preferred_nr_entries;
++            brw->urb.nr_sf_entries = limits[SF].preferred_nr_entries;
++         }
++      } else if (BRW_IS_G4X(brw)) {
++         brw->urb.nr_vs_entries = 64;
++         if (check_urb_layout(brw)) {
++            goto done;
++         } else {
++            brw->urb.constrained = 1;
++            brw->urb.nr_vs_entries = limits[VS].preferred_nr_entries;
++         }
++      }
+       
+       if (!check_urb_layout(brw)) {
+ 	 brw->urb.nr_vs_entries = limits[VS].min_nr_entries;	
+@@ -169,9 +190,8 @@ static void recalculate_urb_fence( struc
+ 	 if (INTEL_DEBUG & (DEBUG_URB|DEBUG_FALLBACKS))
+ 	    _mesa_printf("URB CONSTRAINED\n");
+       }
+-      else 
+-	 brw->urb.constrained = 0;
+ 
++done:
+       if (INTEL_DEBUG & DEBUG_URB)
+ 	 _mesa_printf("URB fence: %d ..VS.. %d ..GS.. %d ..CLP.. %d ..SF.. %d ..CS.. %d\n",
+ 		      brw->urb.vs_start,
+--- src/mesa/drivers/dri/i965/brw_vs_emit.c	2009-09-01 14:50:00.175453470 +0800
++++ src/mesa/drivers/dri/i965/brw_vs_emit.c	2009-09-01 16:25:49.315973365 +0800
+@@ -89,7 +89,12 @@ static void brw_vs_alloc_regs( struct br
+     */
+    c->nr_outputs = 0;
+    c->first_output = reg;
+-   mrf = 4;
++
++   if (BRW_IS_IGDNG(c->func.brw))
++	mrf = 8;
++   else
++	mrf = 4;
++
+    for (i = 0; i < VERT_RESULT_MAX; i++) {
+       if (c->prog_data.outputs_written & (1<<i)) {
+ 	 c->nr_outputs++;
+@@ -154,7 +159,12 @@ static void brw_vs_alloc_regs( struct br
+     */
+    c->prog_data.urb_read_length = (c->nr_inputs+1)/2;
+ 
+-   c->prog_data.urb_entry_size = (c->nr_outputs+2+3)/4;
++   if (BRW_IS_IGDNG(c->func.brw))
++       c->prog_data.urb_entry_size = (c->nr_outputs + 6 + 3) / 4;
++   else
++       c->prog_data.urb_entry_size = (c->nr_outputs + 2 + 3) / 4;
++
++
+    c->prog_data.total_grf = reg;
+ }
+ 
+@@ -863,6 +873,7 @@ static void emit_vertex_write( struct br
+    struct brw_reg m0 = brw_message_reg(0);
+    struct brw_reg pos = c->regs[PROGRAM_OUTPUT][VERT_RESULT_HPOS];
+    struct brw_reg ndc;
++   GLuint len_vertext_header = 2;
+ 
+    if (c->key.copy_edgeflag) {
+       brw_MOV(p, 
+@@ -879,7 +890,7 @@ static void emit_vertex_write( struct br
+     * workaround.
+     */
+    if ((c->prog_data.outputs_written & (1<<VERT_RESULT_PSIZ)) ||
+-       c->key.nr_userclip || !BRW_IS_G4X(p->brw))
++	c->key.nr_userclip || BRW_IS_965(p->brw))
+    {
+       struct brw_reg header1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
+       GLuint i;
+@@ -888,7 +899,8 @@ static void emit_vertex_write( struct br
+ 
+       brw_set_access_mode(p, BRW_ALIGN_16);	
+ 
+-      if (c->prog_data.outputs_written & (1<<VERT_RESULT_PSIZ)) {
++      if (c->prog_data.outputs_written & (1<<VERT_RESULT_PSIZ) ||
++	   c->key.nr_userclip || BRW_IS_965(p->brw)) {
+ 	 struct brw_reg psiz = c->regs[PROGRAM_OUTPUT][VERT_RESULT_PSIZ];
+ 	 brw_MUL(p, brw_writemask(header1, WRITEMASK_W), brw_swizzle1(psiz, 0), brw_imm_f(1<<11));
+ 	 brw_AND(p, brw_writemask(header1, WRITEMASK_W), header1, brw_imm_ud(0x7ff<<8));
+@@ -910,7 +922,7 @@ static void emit_vertex_write( struct br
+        * Later, clipping will detect ucp[6] and ensure the primitive is
+        * clipped against all fixed planes.
+        */
+-      if (!BRW_IS_G4X(p->brw)) {
++      if (BRW_IS_965(p->brw)) {
+ 	 brw_CMP(p,
+ 		 vec8(brw_null_reg()),
+ 		 BRW_CONDITIONAL_L,
+@@ -937,7 +949,21 @@ static void emit_vertex_write( struct br
+     */
+    brw_set_access_mode(p, BRW_ALIGN_1);
+    brw_MOV(p, offset(m0, 2), ndc);
+-   brw_MOV(p, offset(m0, 3), pos);
++
++   if (BRW_IS_IGDNG(p->brw)) {
++       /* There are 20 DWs (D0-D19) in VUE vertex header on IGDNG */
++       brw_MOV(p, offset(m0, 3), pos); /* a portion of vertex header */
++       /* m4, m5 contain the distances from vertex to the user clip planeXXX. 
++        * Seems it is useless for us.
++        * m6 is used for aligning, so that the remainder of vertex element is 
++        * reg-aligned.
++        */
++       brw_MOV(p, offset(m0, 7), pos); /* the remainder of vertex element */
++       len_vertext_header = 6;
++   } else {
++       brw_MOV(p, offset(m0, 3), pos);
++       len_vertext_header = 2;
++   }
+ 
+    brw_urb_WRITE(p, 
+ 		 brw_null_reg(), /* dest */
+@@ -945,7 +971,7 @@ static void emit_vertex_write( struct br
+ 		 c->r0,		/* src */
+ 		 0,		/* allocate */
+ 		 1,		/* used */
+-		 c->nr_outputs + 3, /* msg len */
++		 MIN2(c->nr_outputs + 1 + len_vertext_header, (BRW_MAX_MRF-1)), /* msg len */
+ 		 0,		/* response len */
+ 		 1, 		/* eot */
+ 		 1, 		/* writes complete */
+--- src/mesa/drivers/dri/i965/brw_vs_state.c	2009-09-01 14:49:51.077637689 +0800
++++ src/mesa/drivers/dri/i965/brw_vs_state.c	2009-09-01 15:42:30.787973828 +0800
+@@ -92,16 +92,25 @@ vs_unit_create_from_key(struct brw_conte
+     * brw_urb_WRITE() results.
+     */
+    vs.thread1.single_program_flow = 0;
++//   if (BRW_IS_IGDNG(brw))
++//      vs.thread1.binding_table_entry_count = 0; /* hardware requirement */
++
+    vs.thread3.urb_entry_read_length = key->urb_entry_read_length;
+    vs.thread3.const_urb_entry_read_length = key->curb_entry_read_length;
+    vs.thread3.dispatch_grf_start_reg = 1;
+    vs.thread3.urb_entry_read_offset = 0;
+    vs.thread3.const_urb_entry_read_offset = key->curbe_offset * 2;
+ 
+-   vs.thread4.nr_urb_entries = key->nr_urb_entries;
++   if (BRW_IS_IGDNG(brw))
++       vs.thread4.nr_urb_entries = key->nr_urb_entries >> 2;
++   else
++       vs.thread4.nr_urb_entries = key->nr_urb_entries;
++
+    vs.thread4.urb_entry_allocation_size = key->urb_size - 1;
+ 
+-   if (BRW_IS_G4X(brw))
++   if (BRW_IS_IGDNG(brw))
++      chipset_max_threads = 72;
++   else if (BRW_IS_G4X(brw))
+       chipset_max_threads = 32;
+    else
+       chipset_max_threads = 16;
+@@ -113,6 +122,8 @@ vs_unit_create_from_key(struct brw_conte
+ 
+    /* No samplers for ARB_vp programs:
+     */
++   /* It has to be set to 0 for IGDNG
++    */
+    vs.vs5.sampler_count = 0;
+ 
+    if (INTEL_DEBUG & DEBUG_STATS)
+--- src/mesa/drivers/dri/i965/brw_wm_emit.c	2009-09-01 14:49:55.168259184 +0800
++++ src/mesa/drivers/dri/i965/brw_wm_emit.c	2009-09-01 15:42:30.788924197 +0800
+@@ -702,6 +702,7 @@ static void emit_tex( struct brw_wm_comp
+    GLboolean shadow = (c->key.shadowtex_mask & (1<<inst->tex_unit)) ? 1 : 0;
+    GLuint i, nr;
+    GLuint emit;
++   GLuint msg_type;
+ 
+    /* How many input regs are there?
+     */
+@@ -739,6 +740,18 @@ static void emit_tex( struct brw_wm_comp
+ 
+    responseLength = 8;		/* always */
+ 
++   if (BRW_IS_IGDNG(p->brw)) {
++       if (shadow)
++           msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE_IGDNG;
++       else
++           msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_IGDNG;
++   } else {
++       if (shadow)
++           msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE;
++       else
++           msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE;
++   }
++
+    brw_SAMPLE(p, 
+ 	      retype(vec16(dst[0]), BRW_REGISTER_TYPE_UW),
+ 	      1,
+@@ -746,12 +759,12 @@ static void emit_tex( struct brw_wm_comp
+ 	      inst->tex_unit + MAX_DRAW_BUFFERS, /* surface */
+ 	      inst->tex_unit,	  /* sampler */
+ 	      inst->writemask,
+-	      (shadow ? 
+-	       BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE : 
+-	       BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE),
++	      msg_type,
+ 	      responseLength,
+ 	      msgLength,
+-	      0);	
++	      0,	
++	      1,
++	      BRW_SAMPLER_SIMD_MODE_SIMD16);
+ }
+ 
+ 
+@@ -763,7 +776,7 @@ static void emit_txb( struct brw_wm_comp
+ {
+    struct brw_compile *p = &c->func;
+    GLuint msgLength;
+-
++   GLuint msg_type;
+    /* Shadow ignored for txb.
+     */
+    switch (inst->tex_idx) {
+@@ -788,6 +801,11 @@ static void emit_txb( struct brw_wm_comp
+    brw_MOV(p, brw_message_reg(8), arg[3]);
+    msgLength = 9;
+ 
++   if (BRW_IS_IGDNG(p->brw))
++       msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS_IGDNG;
++   else
++       msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS;
++
+    brw_SAMPLE(p, 
+ 	      retype(vec16(dst[0]), BRW_REGISTER_TYPE_UW),
+ 	      1,
+@@ -795,10 +813,12 @@ static void emit_txb( struct brw_wm_comp
+ 	      inst->tex_unit + MAX_DRAW_BUFFERS, /* surface */
+ 	      inst->tex_unit,	  /* sampler */
+ 	      inst->writemask,
+-	      BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS,
++	      msg_type,
+ 	      8,		/* responseLength */
+ 	      msgLength,
+-	      0);	
++	      0,	
++	      1,
++	      BRW_SAMPLER_SIMD_MODE_SIMD16);	
+ }
+ 
+ 
+--- src/mesa/drivers/dri/i965/brw_wm_glsl.c	2009-09-01 14:50:10.957625931 +0800
++++ src/mesa/drivers/dri/i965/brw_wm_glsl.c	2009-09-01 16:11:30.759412112 +0800
+@@ -2208,8 +2208,9 @@ static void emit_txb(struct brw_wm_compi
+     struct brw_compile *p = &c->func;
+     struct brw_reg dst[4], src[4], payload_reg;
+     GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit];
+-
+     GLuint i;
++    GLuint msg_type;
++
+     payload_reg = get_reg(c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, 0, 1, 0, 0);
+     for (i = 0; i < 4; i++) 
+ 	dst[i] = get_dst_reg(c, inst, i, 1);
+@@ -2236,6 +2237,14 @@ static void emit_txb(struct brw_wm_compi
+     }
+     brw_MOV(p, brw_message_reg(5), src[3]);
+     brw_MOV(p, brw_message_reg(6), brw_imm_f(0));
++
++    if (BRW_IS_IGDNG(p->brw)) {
++        msg_type = BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_BIAS_IGDNG;
++    } else {
++        /* Does it work well on SIMD8? */
++        msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS;
++    }
++
+     brw_SAMPLE(p,
+ 	    retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW),
+ 	    1,
+@@ -2243,10 +2252,12 @@ static void emit_txb(struct brw_wm_compi
+ 	    unit + MAX_DRAW_BUFFERS, /* surface */
+ 	    unit,     /* sampler */
+ 	    inst->DstReg.WriteMask,
+-	    BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS,
++	    msg_type,
+ 	    4,
+ 	    4,
+-	    0);
++            0,                                           /* eot */
++            1,
++            BRW_SAMPLER_SIMD_MODE_SIMD8);
+ }
+ 
+ static void emit_tex(struct brw_wm_compile *c,
+@@ -2260,6 +2271,7 @@ static void emit_tex(struct brw_wm_compi
+     GLuint i, nr;
+     GLuint emit;
+     GLboolean shadow = (c->key.shadowtex_mask & (1<<unit)) ? 1 : 0;
++    GLuint msg_type;
+ 
+     payload_reg = get_reg(c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, 0, 1, 0, 0);
+ 
+@@ -2300,6 +2312,16 @@ static void emit_tex(struct brw_wm_compi
+ 	brw_MOV(p, brw_message_reg(6), src[2]);
+     }
+ 
++    if (BRW_IS_IGDNG(p->brw)) {
++        if (shadow)
++            msg_type = BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_COMPARE_IGDNG;
++        else
++            msg_type = BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_IGDNG;
++    } else {
++        /* Does it work for shadow on SIMD8 ? */
++        msg_type = BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE;
++    }
++    
+     brw_SAMPLE(p,
+ 	    retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW),
+ 	    1,
+@@ -2307,10 +2329,12 @@ static void emit_tex(struct brw_wm_compi
+ 	    unit + MAX_DRAW_BUFFERS, /* surface */
+ 	    unit,     /* sampler */
+ 	    inst->DstReg.WriteMask,
+-	    BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE,
++	    msg_type,
+ 	    4,
+ 	    shadow ? 6 : 4,
+-	    0);
++            0,                                          /* eot */
++            1,
++            BRW_SAMPLER_SIMD_MODE_SIMD8);
+ 
+     if (shadow)
+ 	brw_MOV(p, dst[3], brw_imm_f(1.0));
+@@ -2333,6 +2357,7 @@ static void brw_wm_emit_glsl(struct brw_
+     int i, if_insn = 0, loop_insn = 0;
+     struct brw_compile *p = &c->func;
+     struct brw_indirect stack_index = brw_indirect(0, 0);
++    GLuint br = 1;
+ 
+     c->reg_index = 0;
+     prealloc_reg(c);
+@@ -2542,6 +2567,9 @@ static void brw_wm_emit_glsl(struct brw_
+ 		brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+ 		break;
+ 	    case OPCODE_ENDLOOP: 
++                if (BRW_IS_IGDNG(brw))
++                   br = 2;
++
+ 		loop_insn--;
+ 		inst0 = inst1 = brw_WHILE(p, loop_inst[loop_insn]);
+ 		/* patch all the BREAK instructions from
+@@ -2549,10 +2577,10 @@ static void brw_wm_emit_glsl(struct brw_
+ 		while (inst0 > loop_inst[loop_insn]) {
+ 		    inst0--;
+ 		    if (inst0->header.opcode == BRW_OPCODE_BREAK) {
+-			inst0->bits3.if_else.jump_count = inst1 - inst0 + 1;
++			inst0->bits3.if_else.jump_count = br * (inst1 - inst0 + 1);
+ 			inst0->bits3.if_else.pop_count = 0;
+ 		    } else if (inst0->header.opcode == BRW_OPCODE_CONTINUE) {
+-                        inst0->bits3.if_else.jump_count = inst1 - inst0;
++			inst0->bits3.if_else.jump_count = br * (inst1 - inst0);
+                         inst0->bits3.if_else.pop_count = 0;
+                     }
+ 		}
+--- src/mesa/drivers/dri/i965/brw_wm_state.c	2009-09-01 14:49:51.092857033 +0800
++++ src/mesa/drivers/dri/i965/brw_wm_state.c	2009-09-01 15:42:30.791233754 +0800
+@@ -70,7 +70,9 @@ wm_unit_populate_key(struct brw_context 
+       key->max_threads = 1;
+    else {
+       /* WM maximum threads is number of EUs times number of threads per EU. */
+-      if (BRW_IS_G4X(brw))
++      if (BRW_IS_IGDNG(brw))
++         key->max_threads = 12 * 6;
++      else if (BRW_IS_G4X(brw))
+ 	 key->max_threads = 10 * 5;
+       else
+ 	 key->max_threads = 8 * 4;
+@@ -134,7 +136,11 @@ wm_unit_create_from_key(struct brw_conte
+    wm.thread0.kernel_start_pointer = brw->wm.prog_bo->offset >> 6; /* reloc */
+    wm.thread1.depth_coef_urb_read_offset = 1;
+    wm.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
+-   wm.thread1.binding_table_entry_count = key->nr_surfaces;
++
++   if (BRW_IS_IGDNG(brw))
++      wm.thread1.binding_table_entry_count = 0; /* hardware requirement */
++   else
++      wm.thread1.binding_table_entry_count = key->nr_surfaces;
+ 
+    if (key->total_scratch != 0) {
+       wm.thread2.scratch_space_base_pointer =
+@@ -151,7 +157,11 @@ wm_unit_create_from_key(struct brw_conte
+    wm.thread3.const_urb_entry_read_offset = key->curbe_offset * 2;
+    wm.thread3.urb_entry_read_offset = 0;
+ 
+-   wm.wm4.sampler_count = (key->sampler_count + 1) / 4;
++   if (BRW_IS_IGDNG(brw)) 
++      wm.wm4.sampler_count = 0; /* hardware requirement */
++   else
++      wm.wm4.sampler_count = (key->sampler_count + 1) / 4;
++
+    if (brw->wm.sampler_bo != NULL) {
+       /* reloc */
+       wm.wm4.sampler_state_pointer = brw->wm.sampler_bo->offset >> 5;
+--- src/mesa/drivers/dri/intel/intel_chipset.h	2009-09-01 14:49:51.095087890 +0800
++++ src/mesa/drivers/dri/intel/intel_chipset.h	2009-09-01 15:42:30.791705814 +0800
+@@ -67,13 +67,18 @@
+ #define PCI_CHIP_G45_G                  0x2E22
+ #define PCI_CHIP_G41_G                  0x2E32
+ 
++#define PCI_CHIP_ILD_G                  0x0042
++#define PCI_CHIP_ILM_G                  0x0046
++
+ #define IS_MOBILE(devid)	(devid == PCI_CHIP_I855_GM || \
+ 				 devid == PCI_CHIP_I915_GM || \
+ 				 devid == PCI_CHIP_I945_GM || \
+ 				 devid == PCI_CHIP_I945_GME || \
+ 				 devid == PCI_CHIP_I965_GM || \
+ 				 devid == PCI_CHIP_I965_GME || \
+-				 devid == PCI_CHIP_GM45_GM || IS_IGD(devid))
++				 devid == PCI_CHIP_GM45_GM || \
++				 IS_IGD(devid) || \
++				 devid == PCI_CHIP_ILM_G)
+ 
+ #define IS_G45(devid)           (devid == PCI_CHIP_IGD_E_G || \
+                                  devid == PCI_CHIP_Q45_G || \
+@@ -82,6 +87,10 @@
+ #define IS_GM45(devid)          (devid == PCI_CHIP_GM45_GM)
+ #define IS_G4X(devid)		(IS_G45(devid) || IS_GM45(devid))
+ 
++#define IS_ILD(devid)           (devid == PCI_CHIP_ILD_G)
++#define IS_ILM(devid)           (devid == PCI_CHIP_ILM_G)
++#define IS_IGDNG(devid)           (IS_ILD(devid) || IS_ILM(devid))
++
+ #define IS_915(devid)		(devid == PCI_CHIP_I915_G || \
+ 				 devid == PCI_CHIP_E7221_G || \
+ 				 devid == PCI_CHIP_I915_GM)
+@@ -99,7 +108,8 @@
+ 				 devid == PCI_CHIP_I965_GM || \
+ 				 devid == PCI_CHIP_I965_GME || \
+ 				 devid == PCI_CHIP_I946_GZ || \
+-				 IS_G4X(devid))
++				 IS_G4X(devid) || \
++				 IS_IGDNG(devid))
+ 
+ #define IS_9XX(devid)		(IS_915(devid) || \
+ 				 IS_945(devid) || \
+--- src/mesa/drivers/dri/intel/intel_context.c	2009-09-01 14:50:24.095371898 +0800
++++ src/mesa/drivers/dri/intel/intel_context.c	2009-09-01 15:42:30.792386215 +0800
+@@ -193,6 +193,12 @@ intelGetString(GLcontext * ctx, GLenum n
+       case PCI_CHIP_G41_G:
+          chipset = "Intel(R) G41";
+          break;
++      case PCI_CHIP_ILD_G:
++         chipset = "Intel(R) IGDNG_D";
++         break;
++      case PCI_CHIP_ILM_G:
++         chipset = "Intel(R) IGDNG_M";
++         break;
+       default:
+          chipset = "Unknown Intel Chipset";
+          break;
+--- src/mesa/drivers/dri/intel/intel_mipmap_tree.c	2009-09-01 14:50:15.674596991 +0800
++++ src/mesa/drivers/dri/intel/intel_mipmap_tree.c	2009-09-01 15:42:30.793204680 +0800
+@@ -328,23 +328,31 @@ intel_miptree_set_level_info(struct inte
+ }
+ 
+ 
+-
+ void
+-intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
+-			       GLuint level, GLuint img,
+-			       GLuint x, GLuint y)
++intel_miptree_set_image_offset_ex(struct intel_mipmap_tree *mt,
++                                  GLuint level, GLuint img,
++                                  GLuint x, GLuint y, 
++                                  GLuint offset)
+ {
+    if (img == 0 && level == 0)
+       assert(x == 0 && y == 0);
+ 
+    assert(img < mt->level[level].nr_images);
+ 
+-   mt->level[level].image_offset[img] = (x + y * mt->pitch) * mt->cpp;
++   mt->level[level].image_offset[img] = (x + y * mt->pitch) * mt->cpp + offset;
+ 
+    DBG("%s level %d img %d pos %d,%d image_offset %x\n",
+        __FUNCTION__, level, img, x, y, mt->level[level].image_offset[img]);
+ }
+ 
++void
++intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
++			       GLuint level, GLuint img,
++			       GLuint x, GLuint y)
++{
++    intel_miptree_set_image_offset_ex(mt, level, img, x, y, 0);
++}
++
+ 
+ /* Although we use the image_offset[] array to store relative offsets
+  * to cube faces, Mesa doesn't know anything about this and expects
+@@ -458,7 +466,7 @@ intel_miptree_image_data(struct intel_co
+    }
+ }
+ 
+-extern GLuint intel_compressed_alignment(GLenum);
++extern void intel_get_texture_alignment_unit(GLenum, GLuint *, GLuint *);
+ /* Copy mipmap image between trees
+  */
+ void
+@@ -477,9 +485,11 @@ intel_miptree_image_copy(struct intel_co
+    GLuint i;
+ 
+    if (dst->compressed) {
+-       GLuint alignment = intel_compressed_alignment(dst->internal_format);
++       GLuint align_w, align_h;
++
++       intel_get_texture_alignment_unit(dst->internal_format, &align_w, &align_h);
+        height = (height + 3) / 4;
+-       width = ((width + alignment - 1) & ~(alignment - 1));
++       width = ALIGN(width, align_w);
+    }
+ 
+    for (i = 0; i < depth; i++) {
+--- src/mesa/drivers/dri/intel/intel_mipmap_tree.h	2009-09-01 14:50:15.675041675 +0800
++++ src/mesa/drivers/dri/intel/intel_mipmap_tree.h	2009-09-01 15:42:30.793901896 +0800
+@@ -194,6 +194,11 @@ void intel_miptree_set_level_info(struct
+                                   GLuint x, GLuint y,
+                                   GLuint w, GLuint h, GLuint d);
+ 
++void intel_miptree_set_image_offset_ex(struct intel_mipmap_tree *mt,
++                                       GLuint level,
++                                       GLuint img, GLuint x, GLuint y,
++                                       GLuint offset);
++
+ void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
+                                     GLuint level,
+                                     GLuint img, GLuint x, GLuint y);
+--- src/mesa/drivers/dri/intel/intel_tex_layout.c	2009-09-01 14:50:15.683272116 +0800
++++ src/mesa/drivers/dri/intel/intel_tex_layout.c	2009-09-01 16:02:57.514568233 +0800
+@@ -35,26 +35,37 @@
+ #include "intel_context.h"
+ #include "main/macros.h"
+ 
+-GLuint intel_compressed_alignment(GLenum internalFormat)
++void intel_get_texture_alignment_unit(GLenum internalFormat, GLuint *w, GLuint *h)
+ {
+-    GLuint alignment = 4;
+-
+     switch (internalFormat) {
+     case GL_COMPRESSED_RGB_FXT1_3DFX:
+     case GL_COMPRESSED_RGBA_FXT1_3DFX:
+-        alignment = 8;
++	 *w = 8;
++	 *h = 4;
++	 break;
++
++    case GL_RGB_S3TC:
++    case GL_RGB4_S3TC:
++    case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
++    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
++    case GL_RGBA_S3TC:
++    case GL_RGBA4_S3TC:
++    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
++    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
++	 *w = 4;
++	 *h = 4;
+         break;
+ 
+     default:
++	 *w = 4;
++	 *h = 2;
+         break;
+     }
+-
+-    return alignment;
+ }
+ 
+ void i945_miptree_layout_2d( struct intel_context *intel, struct intel_mipmap_tree *mt )
+ {
+-   GLint align_h = 2, align_w = 4;
++   GLuint align_h = 2, align_w = 4;
+    GLuint level;
+    GLuint x = 0;
+    GLuint y = 0;
+@@ -62,9 +73,9 @@ void i945_miptree_layout_2d( struct inte
+    GLuint height = mt->height0;
+ 
+    mt->pitch = mt->width0;
++   intel_get_texture_alignment_unit(mt->internal_format, &align_w, &align_h);
+ 
+    if (mt->compressed) {
+-       align_w = intel_compressed_alignment(mt->internal_format);
+        mt->pitch = ALIGN(mt->width0, align_w);
+    }
+ 
+--- src/mesa/drivers/dri/intel/intel_tex_layout.h	2009-09-01 14:50:15.683629138 +0800
++++ src/mesa/drivers/dri/intel/intel_tex_layout.h	2009-09-01 16:03:57.845988073 +0800
+@@ -39,4 +39,4 @@ static GLuint minify( GLuint d )
+ }
+ 
+ extern void i945_miptree_layout_2d( struct intel_context *intel, struct intel_mipmap_tree *mt );
+-extern GLuint intel_compressed_alignment(GLenum);
++extern void intel_get_texture_alignment_unit(GLenum, GLuint *, GLuint *);
+
+--- src/mesa/drivers/dri/i965/brw_clip.h	2009-09-21 13:14:55.884775291 +0800
++++ src/mesa/drivers/dri/i965/brw_clip.h	2009-09-21 13:17:43.709734794 +0800
+@@ -100,6 +100,8 @@ struct brw_clip_compile {
+       
+       struct brw_reg fixed_planes;
+       struct brw_reg plane_equation;
++
++      struct brw_reg ff_sync;
+    } reg;
+ 
+    /* 3 different ways of expressing vertex size:
+@@ -173,4 +175,5 @@ struct brw_reg get_tmp( struct brw_clip_
+ void brw_clip_project_position(struct brw_clip_compile *c,
+              struct brw_reg pos );
+ void brw_clip_ff_sync(struct brw_clip_compile *c);
++void brw_clip_init_ff_sync(struct brw_clip_compile *c);
+ #endif
+--- src/mesa/drivers/dri/i965/brw_clip_line.c	2009-09-21 13:14:55.922810659 +0800
++++ src/mesa/drivers/dri/i965/brw_clip_line.c	2009-09-21 13:19:08.612749205 +0800
+@@ -85,6 +85,11 @@ static void brw_clip_line_alloc_regs( st
+       i++;
+    }
+ 
++   if (c->need_ff_sync) {
++       c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
++       i++;
++   }
++
+ 
+    c->first_tmp = i;
+    c->last_tmp = i;
+@@ -246,8 +251,6 @@ static void clip_and_emit_line( struct b
+ 
+    brw_ADD(p, c->reg.t, c->reg.t0, c->reg.t1);
+    brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.t, brw_imm_f(1.0));
+-   if (c->need_ff_sync)
+-	   brw_clip_ff_sync(c);      
+    not_culled = brw_IF(p, BRW_EXECUTE_1);
+    {
+       brw_clip_interp_vertex(c, newvtx0, vtx0, vtx1, c->reg.t0, GL_FALSE);
+@@ -265,6 +268,7 @@ static void clip_and_emit_line( struct b
+ void brw_emit_line_clip( struct brw_clip_compile *c )
+ {
+    brw_clip_line_alloc_regs(c);
++   brw_clip_init_ff_sync(c);
+ 
+    if (c->key.do_flat_shading)
+       brw_clip_copy_colors(c, 0, 1);
+--- src/mesa/drivers/dri/i965/brw_clip_point.c	2009-09-21 13:14:55.902331247 +0800
++++ src/mesa/drivers/dri/i965/brw_clip_point.c	2009-09-21 13:19:38.931669855 +0800
+@@ -50,7 +50,6 @@ void brw_emit_point_clip( struct brw_cli
+    /* Send an empty message to kill the thread:
+     */
+    brw_clip_tri_alloc_regs(c, 0);
+-   if (c->need_ff_sync)
+-	   brw_clip_ff_sync(c);      
++   brw_clip_init_ff_sync(c);
+    brw_clip_kill_thread(c);
+ }
+--- src/mesa/drivers/dri/i965/brw_clip_tri.c	2009-09-21 13:14:55.862015389 +0800
++++ src/mesa/drivers/dri/i965/brw_clip_tri.c	2009-09-21 13:20:58.554768097 +0800
+@@ -119,6 +119,11 @@ void brw_clip_tri_alloc_regs( struct brw
+       i++;
+    }
+ 
++   if (c->need_ff_sync) {
++      c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
++      i++;
++   }
++
+    c->first_tmp = i;
+    c->last_tmp = i;
+ 
+@@ -563,6 +568,7 @@ void brw_emit_tri_clip( struct brw_clip_
+    brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
+    brw_clip_tri_init_vertices(c);
+    brw_clip_init_clipmask(c);
++   brw_clip_init_ff_sync(c);
+ 
+    /* if -ve rhw workaround bit is set, 
+       do cliptest */
+@@ -589,8 +595,6 @@ void brw_emit_tri_clip( struct brw_clip_
+    else 
+       maybe_do_clip_tri(c);
+ 
+-   if (c->need_ff_sync)
+-	   brw_clip_ff_sync(c);      
+    brw_clip_tri_emit_polygon(c);
+ 
+    /* Send an empty message to kill the thread:
+--- src/mesa/drivers/dri/i965/brw_clip_unfilled.c	2009-09-21 13:14:55.907891517 +0800
++++ src/mesa/drivers/dri/i965/brw_clip_unfilled.c	2009-09-21 13:21:47.012502732 +0800
+@@ -453,6 +453,7 @@ void brw_emit_unfilled_clip( struct brw_
+ 
+    brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
+    brw_clip_tri_init_vertices(c);
++   brw_clip_init_ff_sync(c);
+ 
+    assert(c->offset[VERT_RESULT_EDGE]);
+ 
+@@ -496,8 +497,6 @@ void brw_emit_unfilled_clip( struct brw_
+    }
+    brw_ENDIF(p, do_clip);
+    
+-   if (c->need_ff_sync)
+-	   brw_clip_ff_sync(c);      
+    emit_unfilled_primitives(c);
+    brw_clip_kill_thread(c);
+ }
+--- src/mesa/drivers/dri/i965/brw_clip_util.c	2009-09-21 13:14:55.903414187 +0800
++++ src/mesa/drivers/dri/i965/brw_clip_util.c	2009-09-21 13:26:00.383481523 +0800
+@@ -213,6 +213,8 @@ void brw_clip_emit_vue(struct brw_clip_c
+    struct brw_compile *p = &c->func;
+    GLuint start = c->last_mrf;
+ 
++   brw_clip_ff_sync(c);
++
+    assert(!(allocate && eot));
+    
+    /* Cycle through mrf regs - probably futile as we have to wait for
+@@ -263,6 +265,7 @@ void brw_clip_kill_thread(struct brw_cli
+ {
+    struct brw_compile *p = &c->func;
+ 
++   brw_clip_ff_sync(c);
+    /* Send an empty message to kill the thread and release any
+     * allocated urb entry:
+     */
+@@ -356,17 +359,37 @@ void brw_clip_init_clipmask( struct brw_
+ 
+ void brw_clip_ff_sync(struct brw_clip_compile *c)
+ {
++   if (c->need_ff_sync) {
++       struct brw_compile *p = &c->func;
++       struct brw_instruction *need_ff_sync;
++
++       brw_set_conditionalmod(p, BRW_CONDITIONAL_Z);
++       brw_AND(p, brw_null_reg(), c->reg.ff_sync, brw_imm_ud(0x1));
++       need_ff_sync = brw_IF(p, BRW_EXECUTE_1);
++       {
++           brw_OR(p, c->reg.ff_sync, c->reg.ff_sync, brw_imm_ud(0x1));
++           brw_ff_sync(p,
++                   c->reg.R0,
++                   0,
++                   c->reg.R0,
++                   1,
++                   1, /* used */
++                   1, /* msg length */
++                   1, /* response length */
++                   0, /* eot */
++                   1, /* write compelete */
++                   0, /* urb offset */
++                   BRW_URB_SWIZZLE_NONE);
++        }
++        brw_ENDIF(p, need_ff_sync);
++        brw_set_predicate_control(p, BRW_PREDICATE_NONE);
++    }
++}
++
++void brw_clip_init_ff_sync(struct brw_clip_compile *c)
++{
++    if (c->need_ff_sync) {
+ 	struct brw_compile *p = &c->func;
+-	brw_ff_sync(p, 
+-				c->reg.R0,
+-				0,
+-				c->reg.R0,
+-				1,	
+-				1,		/* used */
+-				1,  	/* msg length */
+-				1,		/* response length */
+-				0,		/* eot */
+-				1,		/* write compelete */
+-				0,		/* urb offset */
+-				BRW_URB_SWIZZLE_NONE);
++        brw_MOV(p, c->reg.ff_sync, brw_imm_ud(0));
++    }
+ }
+--- src/mesa/drivers/dri/i965/brw_tex_layout.c	2009-09-21 13:14:55.921718283 +0800
++++ src/mesa/drivers/dri/i965/brw_tex_layout.c	2009-09-21 13:28:04.982370951 +0800
+@@ -65,11 +65,6 @@ GLboolean brw_miptree_layout( struct int
+ 
+ 	   if (mt->compressed) {
+ 	       mt->pitch = ALIGN(mt->width0, align_w);
+-	       qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4 * mt->pitch * mt->cpp;
+-	       mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4 * 6;
+-	   } else {
+-	       qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) * mt->pitch * mt->cpp;
+-	       mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) * 6;
+ 	   }
+ 
+ 	   if (mt->first_level != mt->last_level) {
+@@ -90,6 +85,14 @@ GLboolean brw_miptree_layout( struct int
+ 
+ 	   mt->pitch = intel_miptree_pitch_align(intel, mt, mt->pitch);
+ 
++	   if (mt->compressed) {
++	       qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4 * mt->pitch * mt->cpp;
++	       mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4 * 6;
++	   } else {
++               qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) * mt->pitch * mt->cpp;
++	       mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) * 6;
++	   }
++
+ 	   for (level = mt->first_level; level <= mt->last_level; level++) {
+ 	       GLuint img_height;
+ 	       GLuint nr_images = 6;
+--- src/mesa/drivers/dri/intel/intel_chipset.h	Mon Oct 12 12:38:31 2009
++++ src/mesa/drivers/dri/intel/intel_chipset.h	Mon Oct 12 12:41:44 2009
+@@ -66,6 +66,7 @@
+ #define PCI_CHIP_Q45_G                  0x2E12
+ #define PCI_CHIP_G45_G                  0x2E22
+ #define PCI_CHIP_G41_G                  0x2E32
++#define PCI_CHIP_B43_G 			0x2E42
+ 
+ #define PCI_CHIP_ILD_G                  0x0042
+ #define PCI_CHIP_ILM_G                  0x0046
+@@ -83,7 +84,8 @@
+ #define IS_G45(devid)           (devid == PCI_CHIP_IGD_E_G || \
+                                  devid == PCI_CHIP_Q45_G || \
+                                  devid == PCI_CHIP_G45_G || \
+-                                 devid == PCI_CHIP_G41_G)
++                                 devid == PCI_CHIP_G41_G || \
++				 devid == PCI_CHIP_B43_G)
+ #define IS_GM45(devid)          (devid == PCI_CHIP_GM45_GM)
+ #define IS_G4X(devid)		(IS_G45(devid) || IS_GM45(devid))
+ 
+--- src/mesa/drivers/dri/intel/intel_context.c	Mon Oct 12 12:39:38 2009
++++ src/mesa/drivers/dri/intel/intel_context.c	Mon Oct 12 12:42:23 2009
+@@ -193,6 +193,9 @@
+       case PCI_CHIP_G41_G:
+          chipset = "Intel(R) G41";
+          break;
++      case PCI_CHIP_B43_G:
++	 chipset = "Intel(R) B43";
++	 break;
+       case PCI_CHIP_ILD_G:
+          chipset = "Intel(R) IGDNG_D";
+          break;
--- a/open-src/lib/mesa/Makefile	Tue Oct 20 20:07:52 2009 -0700
+++ b/open-src/lib/mesa/Makefile	Wed Oct 21 10:31:36 2009 -0700
@@ -28,7 +28,7 @@
 # or other dealings in this Software without prior written authorization
 # of the copyright holder.
 #
-# @(#)Makefile	1.24	09/07/30
+# @(#)Makefile	1.25	09/10/19
 #
 
 # Package name used in tarballs
@@ -56,7 +56,8 @@
 SOURCE_PATCHES= \
 	install-pc-dir.patch,-p1 \
 	glu-no-mangled-exports.patch \
-	solaris-port.patch 6866668.patch
+	solaris-port.patch \
+	6872597.patch 6866668.patch
 
 # File created by running configure script
 AUTOCONF_TARGET=$(SOURCE_DIR)/configs/autoconf