--- /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;
--- /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;