summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorms148562 <none@none>2008-07-18 15:31:07 -0700
committerms148562 <none@none>2008-07-18 15:31:07 -0700
commit31c83a1b44505db718ee9088db1ce16bd9205d86 (patch)
tree46bfc366bcb160bea5ff35422964c41eda155e63 /usr/src
parenta85084cae26f3fc328f0704c75464ad44d6fdeb3 (diff)
downloadillumos-joyent-31c83a1b44505db718ee9088db1ce16bd9205d86.tar.gz
6583859 Need S3 support for Intel graphics devices
6644080 agptarget needs to support S/R
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/io/drm/drmP.h5
-rw-r--r--usr/src/uts/intel/io/agpgart/agptarget.c133
-rw-r--r--usr/src/uts/intel/io/drm/i915_dma.c15
-rw-r--r--usr/src/uts/intel/io/drm/i915_drv.c706
-rw-r--r--usr/src/uts/intel/io/drm/i915_drv.h505
5 files changed, 1311 insertions, 53 deletions
diff --git a/usr/src/uts/common/io/drm/drmP.h b/usr/src/uts/common/io/drm/drmP.h
index 72b682e945..49f92e773f 100644
--- a/usr/src/uts/common/io/drm/drmP.h
+++ b/usr/src/uts/common/io/drm/drmP.h
@@ -674,6 +674,11 @@ struct drm_device {
u32 *drw_bitfield;
unsigned int drw_info_length;
drm_drawable_info_t **drw_info;
+
+ /*
+ * Saving S3 context
+ */
+ void *s3_private;
};
/* Memory management support (drm_memory.c) */
diff --git a/usr/src/uts/intel/io/agpgart/agptarget.c b/usr/src/uts/intel/io/agpgart/agptarget.c
index 712f237df3..3f1f806f5e 100644
--- a/usr/src/uts/intel/io/agpgart/agptarget.c
+++ b/usr/src/uts/intel/io/agpgart/agptarget.c
@@ -52,6 +52,8 @@ typedef struct agp_target_softstate {
/* The offset of the ACAPID register */
off_t tsoft_acaptr;
kmutex_t tsoft_lock;
+ int tsoft_gms_off; /* GMS offset in config */
+ uint32_t tsoft_gms;
}agp_target_softstate_t;
/*
@@ -79,6 +81,7 @@ is_64bit_aper(agp_target_softstate_t *softstate)
{
return (softstate->tsoft_devid == AMD_BR_8151);
}
+
/*
* Check if it is an intel bridge
*/
@@ -363,6 +366,21 @@ static gms_mode_t gms_modes[] = {
{INTEL_BR_GM45, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
GMS_SIZE(gms_965GM), gms_965GM}
};
+static int
+get_chip_gms(uint32_t devid)
+{
+ int num_modes;
+ int i;
+
+ num_modes = (sizeof (gms_modes) / sizeof (gms_mode_t));
+
+ for (i = 0; i < num_modes; i++) {
+ if (gms_modes[i].gm_devid == devid)
+ break;
+ }
+
+ return ((i == num_modes) ? -1 : i);
+}
/* Returns the size (kbytes) of pre-allocated graphics memory */
static size_t
@@ -370,32 +388,26 @@ i8xx_biosmem_detect(agp_target_softstate_t *softstate)
{
uint8_t memval;
size_t kbytes;
- int i;
- int num_modes;
+ int gms_off;
kbytes = 0;
- /* get GMS modes list entry */
- num_modes = (sizeof (gms_modes) / sizeof (gms_mode_t));
- for (i = 0; i < num_modes; i++) {
- if (gms_modes[i].gm_devid == softstate->tsoft_devid)
- break;
- }
- if (i == num_modes)
- goto done;
+ gms_off = softstate->tsoft_gms_off;
+
/* fetch the GMS value from DRAM controller */
memval = pci_config_get8(softstate->tsoft_pcihdl,
- gms_modes[i].gm_regoff);
+ gms_modes[gms_off].gm_regoff);
TARGETDB_PRINT2((CE_NOTE, "i8xx_biosmem_detect: memval = %x", memval));
- memval = (memval & gms_modes[i].gm_mask) >> GMS_SHIFT;
+ memval = (memval & gms_modes[gms_off].gm_mask) >> GMS_SHIFT;
/* assuming zero byte for 0 or "reserved" GMS values */
- if (memval == 0 || memval > gms_modes[i].gm_num) {
+ if (memval == 0 || memval > gms_modes[gms_off].gm_num) {
TARGETDB_PRINT2((CE_WARN, "i8xx_biosmem_detect: "
"devid = %x, GMS = %x. assuming zero byte of "
- "pre-allocated memory", gms_modes[i].gm_devid, memval));
+ "pre-allocated memory",
+ gms_modes[gms_off].gm_devid, memval));
goto done;
}
memval--; /* use (GMS_value - 1) as index */
- kbytes = (gms_modes[i].gm_vec)[memval];
+ kbytes = (gms_modes[gms_off].gm_vec)[memval];
done:
TARGETDB_PRINT2((CE_NOTE,
@@ -439,45 +451,105 @@ static int agptarget_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd,
}
static int
+intel_br_resume(agp_target_softstate_t *softstate)
+{
+ int gms_off;
+
+ gms_off = softstate->tsoft_gms_off;
+
+ /*
+ * We recover the gmch graphics control register here
+ */
+ pci_config_put16(softstate->tsoft_pcihdl,
+ gms_modes[gms_off].gm_regoff, softstate->tsoft_gms);
+
+ return (DDI_SUCCESS);
+}
+static int
+intel_br_suspend(agp_target_softstate_t *softstate)
+{
+ int gms_off;
+
+ gms_off = softstate->tsoft_gms_off;
+ softstate->tsoft_gms = pci_config_get16(softstate->tsoft_pcihdl,
+ gms_modes[gms_off].gm_regoff);
+
+ return (DDI_SUCCESS);
+}
+
+static int
agp_target_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
agp_target_softstate_t *softstate;
int instance;
int status;
- if (cmd != DDI_ATTACH)
- return (DDI_FAILURE);
-
instance = ddi_get_instance(dip);
- if (ddi_soft_state_zalloc(agptarget_glob_soft_handle, instance) !=
- DDI_SUCCESS)
+ switch (cmd) {
+ case DDI_ATTACH:
+ break;
+ case DDI_RESUME:
+ softstate =
+ ddi_get_soft_state(agptarget_glob_soft_handle, instance);
+ return (intel_br_resume(softstate));
+ default:
+ TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
+ "only attach and resume ops are supported"));
+ return (DDI_FAILURE);
+ }
+
+ if (ddi_soft_state_zalloc(agptarget_glob_soft_handle,
+ instance) != DDI_SUCCESS) {
+ TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
+ "soft state zalloc failed"));
return (DDI_FAILURE);
+ }
softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
mutex_init(&softstate->tsoft_lock, NULL, MUTEX_DRIVER, NULL);
softstate->tsoft_dip = dip;
status = pci_config_setup(dip, &softstate->tsoft_pcihdl);
if (status != DDI_SUCCESS) {
- ddi_soft_state_free(agptarget_glob_soft_handle, instance);
+ TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
+ "pci config setup failed"));
+ ddi_soft_state_free(agptarget_glob_soft_handle,
+ instance);
return (DDI_FAILURE);
}
softstate->tsoft_devid = pci_config_get32(softstate->tsoft_pcihdl,
PCI_CONF_VENID);
+ softstate->tsoft_gms_off = get_chip_gms(softstate->tsoft_devid);
+ if (softstate->tsoft_gms_off < 0) {
+ TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
+ "read gms offset failed"));
+ pci_config_teardown(&softstate->tsoft_pcihdl);
+ ddi_soft_state_free(agptarget_glob_soft_handle,
+ instance);
+ return (DDI_FAILURE);
+ }
softstate->tsoft_acaptr = agp_target_cap_find(softstate->tsoft_pcihdl);
if (softstate->tsoft_acaptr == 0) {
/* Make a correction for some Intel chipsets */
if (is_intel_br(softstate))
softstate->tsoft_acaptr = AGP_CAP_OFF_DEF;
- else
+ else {
+ TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
+ "Not a supposed corretion"));
+ pci_config_teardown(&softstate->tsoft_pcihdl);
+ ddi_soft_state_free(agptarget_glob_soft_handle,
+ instance);
return (DDI_FAILURE);
+ }
}
status = ddi_create_minor_node(dip, AGPTARGET_NAME, S_IFCHR,
INST2NODENUM(instance), DDI_NT_AGP_TARGET, 0);
if (status != DDI_SUCCESS) {
+ TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
+ "Create minor node failed"));
pci_config_teardown(&softstate->tsoft_pcihdl);
ddi_soft_state_free(agptarget_glob_soft_handle, instance);
return (DDI_FAILURE);
@@ -493,13 +565,20 @@ agp_target_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
int instance;
agp_target_softstate_t *softstate;
- if (cmd != DDI_DETACH)
- return (DDI_FAILURE);
-
instance = ddi_get_instance(dip);
-
softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
+ if (cmd == DDI_SUSPEND) {
+ /* get GMS modes list entry */
+ return (intel_br_suspend(softstate));
+ }
+
+ if (cmd != DDI_DETACH) {
+ TARGETDB_PRINT2((CE_WARN, "agp_target_detach:"
+ "only detach and suspend ops are supported"));
+ return (DDI_FAILURE);
+ }
+
ddi_remove_minor_node(dip, AGPTARGET_NAME);
pci_config_teardown(&softstate->tsoft_pcihdl);
mutex_destroy(&softstate->tsoft_lock);
@@ -785,7 +864,7 @@ static struct dev_ops agp_target_ops = {
static struct modldrv modldrv = {
&mod_driverops,
- "AGP target driver v%I%",
+ "AGP target driver",
&agp_target_ops,
};
diff --git a/usr/src/uts/intel/io/drm/i915_dma.c b/usr/src/uts/intel/io/drm/i915_dma.c
index 6918e18a31..cf1326a5da 100644
--- a/usr/src/uts/intel/io/drm/i915_dma.c
+++ b/usr/src/uts/intel/io/drm/i915_dma.c
@@ -40,17 +40,6 @@
#include "i915_drm.h"
#include "i915_drv.h"
-#define IS_I965G(dev) (dev->pci_device == 0x2972 || \
- dev->pci_device == 0x2982 || \
- dev->pci_device == 0x2992 || \
- dev->pci_device == 0x29A2 || \
- dev->pci_device == 0x2A02 || \
- dev->pci_device == 0x2A12)
-
-#define IS_G33(dev) (dev->pci_device == 0x29b2 || \
- dev->pci_device == 0x29c2 || \
- dev->pci_device == 0x29d2)
-
/* Really want an OS-independent resettable timer. Would like to have
@@ -151,6 +140,10 @@ static int i915_initialize(drm_device_t * dev,
return (EINVAL);
}
+ /*
+ * mmio_map will be destoried after DMA clean up. We should not
+ * access mmio_map in suspend or resume process.
+ */
dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
if (!dev_priv->mmio_map) {
dev->dev_private = (void *)dev_priv;
diff --git a/usr/src/uts/intel/io/drm/i915_drv.c b/usr/src/uts/intel/io/drm/i915_drv.c
index c111b34add..178e6685ff 100644
--- a/usr/src/uts/intel/io/drm/i915_drv.c
+++ b/usr/src/uts/intel/io/drm/i915_drv.c
@@ -58,6 +58,21 @@
#define i915_max_ioctl 0x20 /* changed from 15 */
+/*
+ * copied from vgasubr.h
+ */
+
+struct vgaregmap {
+ uint8_t *addr;
+ ddi_acc_handle_t handle;
+ boolean_t mapped;
+};
+
+enum pipe {
+ PIPE_A = 0,
+ PIPE_B,
+};
+
/*
* cb_ops entrypoint
@@ -108,7 +123,7 @@ static struct dev_ops i915_dev_ops = {
static struct modldrv modldrv = {
&mod_driverops, /* drv_modops */
- "I915 DRM driver %I%", /* drv_linkinfo */
+ "I915 DRM driver", /* drv_linkinfo */
&i915_dev_ops, /* drv_dev_ops */
};
@@ -116,6 +131,11 @@ static struct modlinkage modlinkage = {
MODREV_1, (void *) &modldrv, NULL
};
+static ddi_device_acc_attr_t s3_attr = {
+ DDI_DEVICE_ATTR_V0,
+ DDI_NEVERSWAP_ACC,
+ DDI_STRICTORDER_ACC /* must be DDI_STRICTORDER_ACC */
+};
/*
* softstate head
@@ -163,34 +183,666 @@ _info(struct modinfo *modinfop)
} /* _info() */
+/*
+ * off range: 0x3b0 ~ 0x3ff
+ */
+
+static void
+vga_reg_put8(struct vgaregmap *regmap, uint16_t off, uint8_t val)
+{
+ ASSERT((off >= 0x3b0) && (off <= 0x3ff));
+
+ ddi_put8(regmap->handle, regmap->addr + off, val);
+}
+
+/*
+ * off range: 0x3b0 ~ 0x3ff
+ */
+static uint8_t
+vga_reg_get8(struct vgaregmap *regmap, uint16_t off)
+{
+
+ ASSERT((off >= 0x3b0) && (off <= 0x3ff));
+
+ return (ddi_get8(regmap->handle, regmap->addr + off));
+}
+
+static void
+i915_write_indexed(struct vgaregmap *regmap,
+ uint16_t index_port, uint16_t data_port, uint8_t index, uint8_t val)
+{
+ vga_reg_put8(regmap, index_port, index);
+ vga_reg_put8(regmap, data_port, val);
+}
+
+static uint8_t
+i915_read_indexed(struct vgaregmap *regmap,
+ uint16_t index_port, uint16_t data_port, uint8_t index)
+{
+ vga_reg_put8(regmap, index_port, index);
+ return (vga_reg_get8(regmap, data_port));
+}
+
+static void
+i915_write_ar(struct vgaregmap *regmap, uint16_t st01,
+ uint8_t reg, uint8_t val, uint8_t palette_enable)
+{
+ (void) vga_reg_get8(regmap, st01);
+ vga_reg_put8(regmap, VGA_AR_INDEX, palette_enable | reg);
+ vga_reg_put8(regmap, VGA_AR_DATA_WRITE, val);
+}
+
+static uint8_t
+i915_read_ar(struct vgaregmap *regmap, uint16_t st01,
+ uint8_t index, uint8_t palette_enable)
+{
+ (void) vga_reg_get8(regmap, st01);
+ vga_reg_put8(regmap, VGA_AR_INDEX, index | palette_enable);
+ return (vga_reg_get8(regmap, VGA_AR_DATA_READ));
+}
+
+static int
+i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
+{
+ struct s3_i915_private *s3_priv = dev->s3_private;
+
+ if (pipe == PIPE_A)
+ return (S3_READ(DPLL_A) & DPLL_VCO_ENABLE);
+ else
+ return (S3_READ(DPLL_B) & DPLL_VCO_ENABLE);
+}
+
+static void
+i915_save_palette(struct drm_device *dev, enum pipe pipe)
+{
+ struct s3_i915_private *s3_priv = dev->s3_private;
+ unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+ uint32_t *array;
+ int i;
+
+ if (!i915_pipe_enabled(dev, pipe))
+ return;
+
+ if (pipe == PIPE_A)
+ array = s3_priv->save_palette_a;
+ else
+ array = s3_priv->save_palette_b;
+
+ for(i = 0; i < 256; i++)
+ array[i] = S3_READ(reg + (i << 2));
+
+}
+
+static void
+i915_restore_palette(struct drm_device *dev, enum pipe pipe)
+{
+ struct s3_i915_private *s3_priv = dev->s3_private;
+ unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+ uint32_t *array;
+ int i;
+
+ if (!i915_pipe_enabled(dev, pipe))
+ return;
+
+ if (pipe == PIPE_A)
+ array = s3_priv->save_palette_a;
+ else
+ array = s3_priv->save_palette_b;
+
+ for(i = 0; i < 256; i++)
+ S3_WRITE(reg + (i << 2), array[i]);
+}
+
+static void
+i915_save_vga(struct drm_device *dev)
+{
+ struct s3_i915_private *s3_priv = dev->s3_private;
+ int i;
+ uint16_t cr_index, cr_data, st01;
+ struct vgaregmap regmap;
+
+ regmap.addr = (uint8_t *)s3_priv->saveAddr;
+ regmap.handle = s3_priv->saveHandle;
+
+ /* VGA color palette registers */
+ s3_priv->saveDACMASK = vga_reg_get8(&regmap, VGA_DACMASK);
+ /* DACCRX automatically increments during read */
+ vga_reg_put8(&regmap, VGA_DACRX, 0);
+ /* Read 3 bytes of color data from each index */
+ for (i = 0; i < 256 * 3; i++)
+ s3_priv->saveDACDATA[i] = vga_reg_get8(&regmap, VGA_DACDATA);
+
+ /* MSR bits */
+ s3_priv->saveMSR = vga_reg_get8(&regmap, VGA_MSR_READ);
+ if (s3_priv->saveMSR & VGA_MSR_CGA_MODE) {
+ cr_index = VGA_CR_INDEX_CGA;
+ cr_data = VGA_CR_DATA_CGA;
+ st01 = VGA_ST01_CGA;
+ } else {
+ cr_index = VGA_CR_INDEX_MDA;
+ cr_data = VGA_CR_DATA_MDA;
+ st01 = VGA_ST01_MDA;
+ }
+
+ /* CRT controller regs */
+ i915_write_indexed(&regmap, cr_index, cr_data, 0x11,
+ i915_read_indexed(&regmap, cr_index, cr_data, 0x11) & (~0x80));
+ for (i = 0; i < 0x24; i++)
+ s3_priv->saveCR[i] =
+ i915_read_indexed(&regmap, cr_index, cr_data, i);
+ /* Make sure we don't turn off CR group 0 writes */
+ s3_priv->saveCR[0x11] &= ~0x80;
+
+ /* Attribute controller registers */
+ (void) vga_reg_get8(&regmap, st01);
+ s3_priv->saveAR_INDEX = vga_reg_get8(&regmap, VGA_AR_INDEX);
+ for (i = 0; i < 20; i++)
+ s3_priv->saveAR[i] = i915_read_ar(&regmap, st01, i, 0);
+ (void) vga_reg_get8(&regmap, st01);
+ vga_reg_put8(&regmap, VGA_AR_INDEX, s3_priv->saveAR_INDEX);
+ (void) vga_reg_get8(&regmap, st01);
+
+ /* Graphics controller registers */
+ for (i = 0; i < 9; i++)
+ s3_priv->saveGR[i] =
+ i915_read_indexed(&regmap, VGA_GR_INDEX, VGA_GR_DATA, i);
+
+ s3_priv->saveGR[0x10] =
+ i915_read_indexed(&regmap, VGA_GR_INDEX, VGA_GR_DATA, 0x10);
+ s3_priv->saveGR[0x11] =
+ i915_read_indexed(&regmap, VGA_GR_INDEX, VGA_GR_DATA, 0x11);
+ s3_priv->saveGR[0x18] =
+ i915_read_indexed(&regmap, VGA_GR_INDEX, VGA_GR_DATA, 0x18);
+
+ /* Sequencer registers */
+ for (i = 0; i < 8; i++)
+ s3_priv->saveSR[i] =
+ i915_read_indexed(&regmap, VGA_SR_INDEX, VGA_SR_DATA, i);
+}
+
+static void
+i915_restore_vga(struct drm_device *dev)
+{
+ struct s3_i915_private *s3_priv = dev->s3_private;
+ int i;
+ uint16_t cr_index, cr_data, st01;
+ struct vgaregmap regmap;
+
+ regmap.addr = (uint8_t *)s3_priv->saveAddr;
+ regmap.handle = s3_priv->saveHandle;
+
+ /*
+ * I/O Address Select. This bit selects 3Bxh or 3Dxh as the
+ * I/O address for the CRT Controller registers,
+ * the Feature Control Register (FCR), and Input Status Register
+ * 1 (ST01). Presently ignored (whole range is claimed), but
+ * will "ignore" 3Bx for color configuration or 3Dx for monochrome.
+ * Note that it is typical in AGP chipsets to shadow this bit
+ * and properly steer I/O cycles to the proper bus for operation
+ * where a MDA exists on another bus such as ISA.
+ * 0 = Select 3Bxh I/O address (MDA emulation) (default).
+ * 1 = Select 3Dxh I/O address (CGA emulation).
+ */
+ vga_reg_put8(&regmap, VGA_MSR_WRITE, s3_priv->saveMSR);
+
+ if (s3_priv->saveMSR & VGA_MSR_CGA_MODE) {
+ cr_index = VGA_CR_INDEX_CGA;
+ cr_data = VGA_CR_DATA_CGA;
+ st01 = VGA_ST01_CGA;
+ } else {
+ cr_index = VGA_CR_INDEX_MDA;
+ cr_data = VGA_CR_DATA_MDA;
+ st01 = VGA_ST01_MDA;
+ }
+
+ /* Sequencer registers, don't write SR07 */
+ for (i = 0; i < 7; i++)
+ i915_write_indexed(&regmap, VGA_SR_INDEX, VGA_SR_DATA, i,
+ s3_priv->saveSR[i]);
+ /* CRT controller regs */
+ /* Enable CR group 0 writes */
+ i915_write_indexed(&regmap, cr_index, cr_data,
+ 0x11, s3_priv->saveCR[0x11]);
+ for (i = 0; i < 0x24; i++)
+ i915_write_indexed(&regmap, cr_index,
+ cr_data, i, s3_priv->saveCR[i]);
+
+ /* Graphics controller regs */
+ for (i = 0; i < 9; i++)
+ i915_write_indexed(&regmap, VGA_GR_INDEX, VGA_GR_DATA, i,
+ s3_priv->saveGR[i]);
+
+ i915_write_indexed(&regmap, VGA_GR_INDEX, VGA_GR_DATA, 0x10,
+ s3_priv->saveGR[0x10]);
+ i915_write_indexed(&regmap, VGA_GR_INDEX, VGA_GR_DATA, 0x11,
+ s3_priv->saveGR[0x11]);
+ i915_write_indexed(&regmap, VGA_GR_INDEX, VGA_GR_DATA, 0x18,
+ s3_priv->saveGR[0x18]);
+
+ /* Attribute controller registers */
+ (void) vga_reg_get8(&regmap, st01); /* switch back to index mode */
+ for (i = 0; i < 20; i++)
+ i915_write_ar(&regmap, st01, i, s3_priv->saveAR[i], 0);
+ (void) vga_reg_get8(&regmap, st01); /* switch back to index mode */
+ vga_reg_put8(&regmap, VGA_AR_INDEX, s3_priv->saveAR_INDEX | 0x20);
+ (void) vga_reg_get8(&regmap, st01); /* switch back to index mode */
+
+ /* VGA color palette registers */
+ vga_reg_put8(&regmap, VGA_DACMASK, s3_priv->saveDACMASK);
+ /* DACCRX automatically increments during read */
+ vga_reg_put8(&regmap, VGA_DACWX, 0);
+ /* Read 3 bytes of color data from each index */
+ for (i = 0; i < 256 * 3; i++)
+ vga_reg_put8(&regmap, VGA_DACDATA, s3_priv->saveDACDATA[i]);
+}
+
+static int
+i915_resume(struct drm_device *dev)
+{
+ ddi_acc_handle_t conf_hdl;
+ struct s3_i915_private *s3_priv = dev->s3_private;
+ int i;
+
+ if (pci_config_setup(dev->dip, &conf_hdl) != DDI_SUCCESS) {
+ DRM_ERROR(("i915_resume: pci_config_setup fail"));
+ return (DDI_FAILURE);
+ }
+ /*
+ * Nexus driver will resume pci config space and set the power state
+ * for its children. So we needn't resume them explicitly here.
+ * see pci_pre_resume for detail.
+ */
+ pci_config_put8(conf_hdl, LBB, s3_priv->saveLBB);
+ /*
+ * Pipe & plane A info
+ * Prime the clock
+ */
+ if (s3_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
+ S3_WRITE(DPLL_A, s3_priv->saveDPLL_A &
+ ~DPLL_VCO_ENABLE);
+ drv_usecwait(150);
+ }
+ S3_WRITE(FPA0, s3_priv->saveFPA0);
+ S3_WRITE(FPA1, s3_priv->saveFPA1);
+ /* Actually enable it */
+ S3_WRITE(DPLL_A, s3_priv->saveDPLL_A);
+ drv_usecwait(150);
+ if (IS_I965G(dev))
+ S3_WRITE(DPLL_A_MD, s3_priv->saveDPLL_A_MD);
+ drv_usecwait(150);
+
+ /* Restore mode */
+ S3_WRITE(HTOTAL_A, s3_priv->saveHTOTAL_A);
+ S3_WRITE(HBLANK_A, s3_priv->saveHBLANK_A);
+ S3_WRITE(HSYNC_A, s3_priv->saveHSYNC_A);
+ S3_WRITE(VTOTAL_A, s3_priv->saveVTOTAL_A);
+ S3_WRITE(VBLANK_A, s3_priv->saveVBLANK_A);
+ S3_WRITE(VSYNC_A, s3_priv->saveVSYNC_A);
+ S3_WRITE(BCLRPAT_A, s3_priv->saveBCLRPAT_A);
+
+ /* Restore plane info */
+ S3_WRITE(DSPASIZE, s3_priv->saveDSPASIZE);
+ S3_WRITE(DSPAPOS, s3_priv->saveDSPAPOS);
+ S3_WRITE(PIPEASRC, s3_priv->savePIPEASRC);
+ S3_WRITE(DSPABASE, s3_priv->saveDSPABASE);
+ S3_WRITE(DSPASTRIDE, s3_priv->saveDSPASTRIDE);
+ if (IS_I965G(dev)) {
+ S3_WRITE(DSPASURF, s3_priv->saveDSPASURF);
+ S3_WRITE(DSPATILEOFF, s3_priv->saveDSPATILEOFF);
+ }
+ S3_WRITE(PIPEACONF, s3_priv->savePIPEACONF);
+ i915_restore_palette(dev, PIPE_A);
+ /* Enable the plane */
+ S3_WRITE(DSPACNTR, s3_priv->saveDSPACNTR);
+ S3_WRITE(DSPABASE, S3_READ(DSPABASE));
+
+ /* Pipe & plane B info */
+ if (s3_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
+ S3_WRITE(DPLL_B, s3_priv->saveDPLL_B &
+ ~DPLL_VCO_ENABLE);
+ drv_usecwait(150);
+ }
+ S3_WRITE(FPB0, s3_priv->saveFPB0);
+ S3_WRITE(FPB1, s3_priv->saveFPB1);
+ /* Actually enable it */
+ S3_WRITE(DPLL_B, s3_priv->saveDPLL_B);
+ drv_usecwait(150);
+ if (IS_I965G(dev))
+ S3_WRITE(DPLL_B_MD, s3_priv->saveDPLL_B_MD);
+ drv_usecwait(150);
+
+ /* Restore mode */
+ S3_WRITE(HTOTAL_B, s3_priv->saveHTOTAL_B);
+ S3_WRITE(HBLANK_B, s3_priv->saveHBLANK_B);
+ S3_WRITE(HSYNC_B, s3_priv->saveHSYNC_B);
+ S3_WRITE(VTOTAL_B, s3_priv->saveVTOTAL_B);
+ S3_WRITE(VBLANK_B, s3_priv->saveVBLANK_B);
+ S3_WRITE(VSYNC_B, s3_priv->saveVSYNC_B);
+ S3_WRITE(BCLRPAT_B, s3_priv->saveBCLRPAT_B);
+
+ /* Restore plane info */
+ S3_WRITE(DSPBSIZE, s3_priv->saveDSPBSIZE);
+ S3_WRITE(DSPBPOS, s3_priv->saveDSPBPOS);
+ S3_WRITE(PIPEBSRC, s3_priv->savePIPEBSRC);
+ S3_WRITE(DSPBBASE, s3_priv->saveDSPBBASE);
+ S3_WRITE(DSPBSTRIDE, s3_priv->saveDSPBSTRIDE);
+ if (IS_I965G(dev)) {
+ S3_WRITE(DSPBSURF, s3_priv->saveDSPBSURF);
+ S3_WRITE(DSPBTILEOFF, s3_priv->saveDSPBTILEOFF);
+ }
+ S3_WRITE(PIPEBCONF, s3_priv->savePIPEBCONF);
+ i915_restore_palette(dev, PIPE_B);
+ /* Enable the plane */
+ S3_WRITE(DSPBCNTR, s3_priv->saveDSPBCNTR);
+ S3_WRITE(DSPBBASE, S3_READ(DSPBBASE));
+
+ /* CRT state */
+ S3_WRITE(ADPA, s3_priv->saveADPA);
+
+ /* LVDS state */
+ if (IS_I965G(dev))
+ S3_WRITE(BLC_PWM_CTL2, s3_priv->saveBLC_PWM_CTL2);
+ if (IS_MOBILE(dev) && !IS_I830(dev))
+ S3_WRITE(LVDS, s3_priv->saveLVDS);
+ if (!IS_I830(dev) && !IS_845G(dev))
+ S3_WRITE(PFIT_CONTROL, s3_priv->savePFIT_CONTROL);
+
+ S3_WRITE(PFIT_PGM_RATIOS, s3_priv->savePFIT_PGM_RATIOS);
+ S3_WRITE(BLC_PWM_CTL, s3_priv->saveBLC_PWM_CTL);
+ S3_WRITE(LVDSPP_ON, s3_priv->saveLVDSPP_ON);
+ S3_WRITE(LVDSPP_OFF, s3_priv->saveLVDSPP_OFF);
+ S3_WRITE(PP_CYCLE, s3_priv->savePP_CYCLE);
+ S3_WRITE(PP_CONTROL, s3_priv->savePP_CONTROL);
+
+ /* FIXME: restore TV & SDVO state */
+
+ /* FBC info */
+ S3_WRITE(FBC_CFB_BASE, s3_priv->saveFBC_CFB_BASE);
+ S3_WRITE(FBC_LL_BASE, s3_priv->saveFBC_LL_BASE);
+ S3_WRITE(FBC_CONTROL2, s3_priv->saveFBC_CONTROL2);
+ S3_WRITE(FBC_CONTROL, s3_priv->saveFBC_CONTROL);
+
+ /* VGA state */
+ S3_WRITE(VGACNTRL, s3_priv->saveVGACNTRL);
+ S3_WRITE(VCLK_DIVISOR_VGA0, s3_priv->saveVCLK_DIVISOR_VGA0);
+ S3_WRITE(VCLK_DIVISOR_VGA1, s3_priv->saveVCLK_DIVISOR_VGA1);
+ S3_WRITE(VCLK_POST_DIV, s3_priv->saveVCLK_POST_DIV);
+ drv_usecwait(150);
+
+ /* Clock gating state */
+ S3_WRITE (DSPCLK_GATE_D, s3_priv->saveDSPCLK_GATE_D);
+
+ /* Cache mode state */
+ S3_WRITE (CACHE_MODE_0, s3_priv->saveCACHE_MODE_0 | 0xffff0000);
+
+ /* Memory arbitration state */
+ S3_WRITE (MI_ARB_STATE, s3_priv->saveMI_ARB_STATE | 0xffff0000);
+
+ for (i = 0; i < 16; i++) {
+ S3_WRITE(SWF0 + (i << 2), s3_priv->saveSWF0[i]);
+ S3_WRITE(SWF10 + (i << 2), s3_priv->saveSWF1[i+7]);
+ }
+ for (i = 0; i < 3; i++)
+ S3_WRITE(SWF30 + (i << 2), s3_priv->saveSWF2[i]);
+
+ i915_restore_vga(dev);
+
+ S3_WRITE(I915REG_PGTBL_CTRL, s3_priv->pgtbl_ctl);
+
+ (void) pci_config_teardown(&conf_hdl);
+
+ return (DDI_SUCCESS);
+}
+static int
+i915_suspend(struct drm_device *dev)
+{
+ ddi_acc_handle_t conf_hdl;
+ struct s3_i915_private *s3_priv = dev->s3_private;
+ int i;
+
+
+ if (pci_config_setup(dev->dip, &conf_hdl) != DDI_SUCCESS) {
+ DRM_ERROR(("i915_suspend: pci_config_setup fail"));
+ return (DDI_FAILURE);
+ }
+
+ /*
+ * Nexus driver will resume pci config space for its children.
+ * So pci config registers are not saved here.
+ */
+ s3_priv->saveLBB = pci_config_get8(conf_hdl, LBB);
+
+ /*
+ * Pipe & plane A info.
+ */
+ s3_priv->savePIPEACONF = S3_READ(PIPEACONF);
+ s3_priv->savePIPEASRC = S3_READ(PIPEASRC);
+ s3_priv->saveFPA0 = S3_READ(FPA0);
+ s3_priv->saveFPA1 = S3_READ(FPA1);
+ s3_priv->saveDPLL_A = S3_READ(DPLL_A);
+ if (IS_I965G(dev))
+ s3_priv->saveDPLL_A_MD = S3_READ(DPLL_A_MD);
+ s3_priv->saveHTOTAL_A = S3_READ(HTOTAL_A);
+ s3_priv->saveHBLANK_A = S3_READ(HBLANK_A);
+ s3_priv->saveHSYNC_A = S3_READ(HSYNC_A);
+ s3_priv->saveVTOTAL_A = S3_READ(VTOTAL_A);
+ s3_priv->saveVBLANK_A = S3_READ(VBLANK_A);
+ s3_priv->saveVSYNC_A = S3_READ(VSYNC_A);
+ s3_priv->saveBCLRPAT_A = S3_READ(BCLRPAT_A);
+
+ s3_priv->saveDSPACNTR = S3_READ(DSPACNTR);
+ s3_priv->saveDSPASTRIDE = S3_READ(DSPASTRIDE);
+ s3_priv->saveDSPASIZE = S3_READ(DSPASIZE);
+ s3_priv->saveDSPAPOS = S3_READ(DSPAPOS);
+ s3_priv->saveDSPABASE = S3_READ(DSPABASE);
+ if (IS_I965G(dev)) {
+ s3_priv->saveDSPASURF = S3_READ(DSPASURF);
+ s3_priv->saveDSPATILEOFF = S3_READ(DSPATILEOFF);
+ }
+ i915_save_palette(dev, PIPE_A);
+ s3_priv->savePIPEASTAT = S3_READ(I915REG_PIPEASTAT);
+
+ /*
+ * Pipe & plane B info
+ */
+ s3_priv->savePIPEBCONF = S3_READ(PIPEBCONF);
+ s3_priv->savePIPEBSRC = S3_READ(PIPEBSRC);
+ s3_priv->saveFPB0 = S3_READ(FPB0);
+ s3_priv->saveFPB1 = S3_READ(FPB1);
+ s3_priv->saveDPLL_B = S3_READ(DPLL_B);
+ if (IS_I965G(dev))
+ s3_priv->saveDPLL_B_MD = S3_READ(DPLL_B_MD);
+ s3_priv->saveHTOTAL_B = S3_READ(HTOTAL_B);
+ s3_priv->saveHBLANK_B = S3_READ(HBLANK_B);
+ s3_priv->saveHSYNC_B = S3_READ(HSYNC_B);
+ s3_priv->saveVTOTAL_B = S3_READ(VTOTAL_B);
+ s3_priv->saveVBLANK_B = S3_READ(VBLANK_B);
+ s3_priv->saveVSYNC_B = S3_READ(VSYNC_B);
+ s3_priv->saveBCLRPAT_A = S3_READ(BCLRPAT_A);
+
+ s3_priv->saveDSPBCNTR = S3_READ(DSPBCNTR);
+ s3_priv->saveDSPBSTRIDE = S3_READ(DSPBSTRIDE);
+ s3_priv->saveDSPBSIZE = S3_READ(DSPBSIZE);
+ s3_priv->saveDSPBPOS = S3_READ(DSPBPOS);
+ s3_priv->saveDSPBBASE = S3_READ(DSPBBASE);
+ if (IS_I965GM(dev) || IS_IGD_GM(dev)) {
+ s3_priv->saveDSPBSURF = S3_READ(DSPBSURF);
+ s3_priv->saveDSPBTILEOFF = S3_READ(DSPBTILEOFF);
+ }
+ i915_save_palette(dev, PIPE_B);
+ s3_priv->savePIPEBSTAT = S3_READ(I915REG_PIPEBSTAT);
+
+ /*
+ * CRT state
+ */
+ s3_priv->saveADPA = S3_READ(ADPA);
+
+ /*
+ * LVDS state
+ */
+ s3_priv->savePP_CONTROL = S3_READ(PP_CONTROL);
+ s3_priv->savePFIT_PGM_RATIOS = S3_READ(PFIT_PGM_RATIOS);
+ s3_priv->saveBLC_PWM_CTL = S3_READ(BLC_PWM_CTL);
+ if (IS_I965G(dev))
+ s3_priv->saveBLC_PWM_CTL2 = S3_READ(BLC_PWM_CTL2);
+ if (IS_MOBILE(dev) && !IS_I830(dev))
+ s3_priv->saveLVDS = S3_READ(LVDS);
+ if (!IS_I830(dev) && !IS_845G(dev))
+ s3_priv->savePFIT_CONTROL = S3_READ(PFIT_CONTROL);
+ s3_priv->saveLVDSPP_ON = S3_READ(LVDSPP_ON);
+ s3_priv->saveLVDSPP_OFF = S3_READ(LVDSPP_OFF);
+ s3_priv->savePP_CYCLE = S3_READ(PP_CYCLE);
+
+ /* FIXME: save TV & SDVO state */
+
+ /* FBC state */
+ s3_priv->saveFBC_CFB_BASE = S3_READ(FBC_CFB_BASE);
+ s3_priv->saveFBC_LL_BASE = S3_READ(FBC_LL_BASE);
+ s3_priv->saveFBC_CONTROL2 = S3_READ(FBC_CONTROL2);
+ s3_priv->saveFBC_CONTROL = S3_READ(FBC_CONTROL);
+
+ /* Interrupt state */
+ s3_priv->saveIIR = S3_READ(I915REG_INT_IDENTITY_R);
+ s3_priv->saveIER = S3_READ(I915REG_INT_ENABLE_R);
+ s3_priv->saveIMR = S3_READ(I915REG_INT_MASK_R);
+
+ /* VGA state */
+ s3_priv->saveVCLK_DIVISOR_VGA0 = S3_READ(VCLK_DIVISOR_VGA0);
+ s3_priv->saveVCLK_DIVISOR_VGA1 = S3_READ(VCLK_DIVISOR_VGA1);
+ s3_priv->saveVCLK_POST_DIV = S3_READ(VCLK_POST_DIV);
+ s3_priv->saveVGACNTRL = S3_READ(VGACNTRL);
+
+ /* Clock gating state */
+ s3_priv->saveDSPCLK_GATE_D = S3_READ(DSPCLK_GATE_D);
+
+ /* Cache mode state */
+ s3_priv->saveCACHE_MODE_0 = S3_READ(CACHE_MODE_0);
+
+ /* Memory Arbitration state */
+ s3_priv->saveMI_ARB_STATE = S3_READ(MI_ARB_STATE);
+
+ /* Scratch space */
+ for (i = 0; i < 16; i++) {
+ s3_priv->saveSWF0[i] = S3_READ(SWF0 + (i << 2));
+ s3_priv->saveSWF1[i] = S3_READ(SWF10 + (i << 2));
+ }
+ for (i = 0; i < 3; i++)
+ s3_priv->saveSWF2[i] = S3_READ(SWF30 + (i << 2));
+
+
+ i915_save_vga(dev);
+ /*
+ * Save page table control register
+ */
+ s3_priv->pgtbl_ctl = S3_READ(I915REG_PGTBL_CTRL);
+
+ (void) pci_config_teardown(&conf_hdl);
+
+ return (DDI_SUCCESS);
+}
+
+/*
+ * This funtion check the length of memory mapped IO space to get the right bar. * And There are two possibilities here.
+ * 1. The MMIO registers is in memory map IO bar with 1M size. The bottom half
+ * of the 1M space is the MMIO registers.
+ * 2. The MMIO register is in memory map IO with 512K size. The whole 512K
+ * space is the MMIO registers.
+ */
+static int
+i915_map_regs(dev_info_t *dip, caddr_t *save_addr, ddi_acc_handle_t *handlep)
+{
+ int rnumber;
+ int nregs;
+ off_t size = 0;
+
+ if (ddi_dev_nregs(dip, &nregs)) {
+ cmn_err(CE_WARN, "i915_map_regs: failed to get nregs");
+ return (DDI_FAILURE);
+ }
+
+ for (rnumber = 1; rnumber < nregs; rnumber++) {
+ (void) ddi_dev_regsize(dip, rnumber, &size);
+ if ((size == 0x80000) ||
+ (size == 0x100000))
+ break;
+ }
+
+ if (rnumber >= nregs) {
+ cmn_err(CE_WARN,
+ "i915_map_regs: failed to find MMIO registers");
+ return (DDI_FAILURE);
+ }
+
+ if (ddi_regs_map_setup(dip, rnumber, save_addr,
+ 0, 0x80000, &s3_attr, handlep)) {
+ cmn_err(CE_WARN,
+ "i915_map_regs: failed to map bar %d", rnumber);
+ return (DDI_FAILURE);
+ }
+
+ return (DDI_SUCCESS);
+}
+static void
+i915_unmap_regs(ddi_acc_handle_t *handlep)
+{
+ ddi_regs_map_free(handlep);
+}
static int
i915_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
drm_device_t *statep;
+ s3_i915_private_t *s3_private;
void *handle;
int unit;
- if (cmd != DDI_ATTACH) {
- DRM_ERROR("i915_attach: only attach op supported");
+ unit = ddi_get_instance(dip);
+ switch (cmd) {
+ case DDI_ATTACH:
+ break;
+ case DDI_RESUME:
+ statep = ddi_get_soft_state(i915_statep, unit);
+ return (i915_resume(statep));
+ default:
+ DRM_ERROR("i915_attach: attach and resume ops are supported");
return (DDI_FAILURE);
+
}
- unit = ddi_get_instance(dip);
if (ddi_soft_state_zalloc(i915_statep, unit) != DDI_SUCCESS) {
- cmn_err(CE_WARN, "i915_attach: failed to alloc softstate");
- return (DDI_FAILURE);
+ cmn_err(CE_WARN,
+ "i915_attach: failed to alloc softstate");
+ return (DDI_FAILURE);
}
statep = ddi_get_soft_state(i915_statep, unit);
statep->dip = dip;
statep->driver = &i915_driver;
+ statep->s3_private = drm_alloc(sizeof(s3_i915_private_t),
+ DRM_MEM_DRIVER);
+
+ if (statep->s3_private == NULL) {
+ cmn_err(CE_WARN, "i915_attach: failed to allocate s3 priv");
+ goto err_exit1;
+ }
+
+ /*
+ * Map in the mmio register space for s3.
+ */
+ s3_private = (s3_i915_private_t *)statep->s3_private;
+
+ if (i915_map_regs(dip, &s3_private->saveAddr,
+ &s3_private->saveHandle)) {
+ cmn_err(CE_WARN, "i915_attach: failed to map MMIO");
+ goto err_exit2;
+ }
+
/*
* Call drm_supp_register to create minor nodes for us
*/
handle = drm_supp_register(dip, statep);
if ( handle == NULL) {
DRM_ERROR("i915_attach: drm_supp_register failed");
- goto err_exit1;
+ goto err_exit3;
}
statep->drm_handle = handle;
@@ -198,24 +850,30 @@ i915_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
* After drm_supp_register, we can call drm_xxx routine
*/
statep->drm_supported = DRM_UNSUPPORT;
- if (drm_probe(statep, i915_pciidlist) != DDI_SUCCESS) {
+ if (
+ drm_probe(statep, i915_pciidlist) != DDI_SUCCESS) {
DRM_ERROR("i915_open: "
"DRM current don't support this graphics card");
- goto err_exit2;
+ goto err_exit4;
}
statep->drm_supported = DRM_SUPPORT;
/* call common attach code */
if (drm_attach(statep) != DDI_SUCCESS) {
DRM_ERROR("i915_attach: drm_attach failed");
- goto err_exit2;
+ goto err_exit4;
}
return (DDI_SUCCESS);
-
-err_exit2:
+err_exit4:
(void) drm_supp_unregister(handle);
+err_exit3:
+ i915_unmap_regs(&s3_private->saveHandle);
+err_exit2:
+ drm_free(statep->s3_private, sizeof(s3_i915_private_t),
+ DRM_MEM_DRIVER);
err_exit1:
(void) ddi_soft_state_free(i915_statep, unit);
+
return (DDI_FAILURE);
} /* i915_attach() */
@@ -225,14 +883,32 @@ i915_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
drm_device_t *statep;
int unit;
+ s3_i915_private_t *s3_private;
- if (cmd != DDI_DETACH)
- return (DDI_FAILURE);
+ if ((cmd != DDI_SUSPEND) && (cmd != DDI_DETACH)) {
+ DRM_ERROR("i915_detach: "
+ "only detach and resume ops are supported");
+ return (DDI_FAILURE);
+ }
unit = ddi_get_instance(dip);
statep = ddi_get_soft_state(i915_statep, unit);
- if (statep == NULL)
+ if (statep == NULL) {
+ DRM_ERROR("i915_detach: can not get soft state");
return (DDI_FAILURE);
+ }
+
+ if (cmd == DDI_SUSPEND)
+ return (i915_suspend(statep));
+
+ s3_private = (s3_i915_private_t *)statep->s3_private;
+ ddi_regs_map_free(&s3_private->saveHandle);
+
+ /*
+ * Free the struct for context saving in S3
+ */
+ drm_free(statep->s3_private, sizeof(s3_i915_private_t),
+ DRM_MEM_DRIVER);
(void) drm_detach(statep);
(void) drm_supp_unregister(statep->drm_handle);
diff --git a/usr/src/uts/intel/io/drm/i915_drv.h b/usr/src/uts/intel/io/drm/i915_drv.h
index 87493707ef..913bcc002e 100644
--- a/usr/src/uts/intel/io/drm/i915_drv.h
+++ b/usr/src/uts/intel/io/drm/i915_drv.h
@@ -95,6 +95,97 @@ typedef struct _drm_i915_vbl_swap {
unsigned int sequence;
} drm_i915_vbl_swap_t;
+typedef struct s3_i915_private {
+ ddi_acc_handle_t saveHandle;
+ caddr_t saveAddr;
+ uint32_t pgtbl_ctl;
+ uint8_t saveLBB;
+ uint32_t saveDSPACNTR;
+ uint32_t saveDSPBCNTR;
+ uint32_t savePIPEACONF;
+ uint32_t savePIPEBCONF;
+ uint32_t savePIPEASRC;
+ uint32_t savePIPEBSRC;
+ uint32_t saveFPA0;
+ uint32_t saveFPA1;
+ uint32_t saveDPLL_A;
+ uint32_t saveDPLL_A_MD;
+ uint32_t saveHTOTAL_A;
+ uint32_t saveHBLANK_A;
+ uint32_t saveHSYNC_A;
+ uint32_t saveVTOTAL_A;
+ uint32_t saveVBLANK_A;
+ uint32_t saveVSYNC_A;
+ uint32_t saveBCLRPAT_A;
+ uint32_t saveDSPASTRIDE;
+ uint32_t saveDSPASIZE;
+ uint32_t saveDSPAPOS;
+ uint32_t saveDSPABASE;
+ uint32_t saveDSPASURF;
+ uint32_t saveDSPATILEOFF;
+ uint32_t savePFIT_PGM_RATIOS;
+ uint32_t saveBLC_PWM_CTL;
+ uint32_t saveBLC_PWM_CTL2;
+ uint32_t saveFPB0;
+ uint32_t saveFPB1;
+ uint32_t saveDPLL_B;
+ uint32_t saveDPLL_B_MD;
+ uint32_t saveHTOTAL_B;
+ uint32_t saveHBLANK_B;
+ uint32_t saveHSYNC_B;
+ uint32_t saveVTOTAL_B;
+ uint32_t saveVBLANK_B;
+ uint32_t saveVSYNC_B;
+ uint32_t saveBCLRPAT_B;
+ uint32_t saveDSPBSTRIDE;
+ uint32_t saveDSPBSIZE;
+ uint32_t saveDSPBPOS;
+ uint32_t saveDSPBBASE;
+ uint32_t saveDSPBSURF;
+ uint32_t saveDSPBTILEOFF;
+ uint32_t saveVCLK_DIVISOR_VGA0;
+ uint32_t saveVCLK_DIVISOR_VGA1;
+ uint32_t saveVCLK_POST_DIV;
+ uint32_t saveVGACNTRL;
+ uint32_t saveADPA;
+ uint32_t saveLVDS;
+ uint32_t saveLVDSPP_ON;
+ uint32_t saveLVDSPP_OFF;
+ uint32_t saveDVOA;
+ uint32_t saveDVOB;
+ uint32_t saveDVOC;
+ uint32_t savePP_ON;
+ uint32_t savePP_OFF;
+ uint32_t savePP_CONTROL;
+ uint32_t savePP_CYCLE;
+ uint32_t savePFIT_CONTROL;
+ uint32_t save_palette_a[256];
+ uint32_t save_palette_b[256];
+ uint32_t saveFBC_CFB_BASE;
+ uint32_t saveFBC_LL_BASE;
+ uint32_t saveFBC_CONTROL;
+ uint32_t saveFBC_CONTROL2;
+ uint32_t saveIER;
+ uint32_t saveIIR;
+ uint32_t saveIMR;
+ uint32_t saveDSPCLK_GATE_D;
+ uint32_t saveMI_ARB_STATE;
+ uint32_t savePIPEASTAT;
+ uint32_t savePIPEBSTAT;
+ uint32_t saveCACHE_MODE_0;
+ uint32_t saveSWF0[16];
+ uint32_t saveSWF1[16];
+ uint32_t saveSWF2[3];
+ uint8_t saveMSR;
+ uint8_t saveSR[8];
+ uint8_t saveGR[24];
+ uint8_t saveAR_INDEX;
+ uint8_t saveAR[20];
+ uint8_t saveDACMASK;
+ uint8_t saveDACDATA[256*3]; /* 256 3-byte colors */
+ uint8_t saveCR[36];
+} s3_i915_private_t;
+
typedef struct drm_i915_private {
drm_local_map_t *sarea;
drm_local_map_t *mmio_map;
@@ -143,6 +234,7 @@ typedef struct drm_i915_private {
spinlock_t swaps_lock;
drm_i915_vbl_swap_t vbl_swaps;
unsigned int swaps_pending;
+
} drm_i915_private_t;
enum intel_chip_family {
@@ -224,6 +316,10 @@ extern int i915_move(drm_buffer_object_t *bo, int evict,
#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg))
#define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, (reg), (val))
+#define S3_READ(reg) \
+ *(uint32_t volatile *)((uintptr_t)s3_priv->saveAddr + (reg))
+#define S3_WRITE(reg, val) \
+ *(uint32_t volatile *)((uintptr_t)s3_priv->saveAddr + (reg)) = (val)
#define RING_LOCALS unsigned int outring, ringmask, outcount; \
volatile unsigned char *virt;
@@ -252,6 +348,51 @@ extern int i915_move(drm_buffer_object_t *bo, int evict,
extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
+/* Extended config space */
+#define LBB 0xf4
+
+/* VGA stuff */
+
+#define VGA_ST01_MDA 0x3ba
+#define VGA_ST01_CGA 0x3da
+
+#define VGA_MSR_WRITE 0x3c2
+#define VGA_MSR_READ 0x3cc
+#define VGA_MSR_MEM_EN (1<<1)
+#define VGA_MSR_CGA_MODE (1<<0)
+
+#define VGA_SR_INDEX 0x3c4
+#define VGA_SR_DATA 0x3c5
+
+#define VGA_AR_INDEX 0x3c0
+#define VGA_AR_VID_EN (1<<5)
+#define VGA_AR_DATA_WRITE 0x3c0
+#define VGA_AR_DATA_READ 0x3c1
+
+#define VGA_GR_INDEX 0x3ce
+#define VGA_GR_DATA 0x3cf
+/* GR05 */
+#define VGA_GR_MEM_READ_MODE_SHIFT 3
+#define VGA_GR_MEM_READ_MODE_PLANE 1
+/* GR06 */
+#define VGA_GR_MEM_MODE_MASK 0xc
+#define VGA_GR_MEM_MODE_SHIFT 2
+#define VGA_GR_MEM_A0000_AFFFF 0
+#define VGA_GR_MEM_A0000_BFFFF 1
+#define VGA_GR_MEM_B0000_B7FFF 2
+#define VGA_GR_MEM_B0000_BFFFF 3
+
+#define VGA_DACMASK 0x3c6
+#define VGA_DACRX 0x3c7
+#define VGA_DACWX 0x3c8
+#define VGA_DACDATA 0x3c9
+
+#define VGA_CR_INDEX_MDA 0x3b4
+#define VGA_CR_DATA_MDA 0x3b5
+#define VGA_CR_INDEX_CGA 0x3d4
+#define VGA_CR_DATA_CGA 0x3d5
+
+
#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
#define CMD_REPORT_HEAD (7<<23)
@@ -272,6 +413,7 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
#define BB1_UNPROTECTED (0<<0)
#define BB2_END_ADDR_MASK (~0x7)
+#define I915REG_PGTBL_CTRL 0x2020
#define I915REG_HWSTAM 0x02098
#define I915REG_INT_IDENTITY_R 0x020a4
#define I915REG_INT_MASK_R 0x020a8
@@ -375,4 +517,367 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
#define READ_BREADCRUMB(dev_priv) (((volatile u32*)(dev_priv->hw_status_page))[5])
#define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hw_status_page))[reg])
+/*
+ * add here for S3 support
+ */
+#define DPLL_A 0x06014
+#define DPLL_B 0x06018
+# define DPLL_VCO_ENABLE 0x80000000 /* (1 << 31) */
+# define DPLL_DVO_HIGH_SPEED (1 << 30)
+# define DPLL_SYNCLOCK_ENABLE (1 << 29)
+# define DPLL_VGA_MODE_DIS (1 << 28)
+# define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */
+# define DPLLB_MODE_LVDS (2 << 26) /* i915 */
+# define DPLL_MODE_MASK (3 << 26)
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */
+# define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */
+# define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */
+
+/**
+ * The i830 generation, in DAC/serial mode, defines p1 as two plus this
+ * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000
+/**
+ * The i830 generation, in LVDS mode, defines P1 as the bit number set within
+ * this field (only one bit may be set).
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000
+# define DPLL_FPA01_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_TVCLKINBC (2 << 13) /* SDVO TVCLKIN */
+# define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
+# define PLL_REF_INPUT_MASK (3 << 13)
+# define PLL_LOAD_PULSE_PHASE_SHIFT 9
+/*
+ * Parallel to Serial Load Pulse phase selection.
+ * Selects the phase for the 10X DPLL clock for the PCIe
+ * digital display port. The range is 4 to 13; 10 or more
+ * is just a flip delay. The default is 6
+ */
+# define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
+# define DISPLAY_RATE_SELECT_FPA1 (1 << 8)
+
+/**
+ * SDVO multiplier for 945G/GM. Not used on 965.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+# define SDVO_MULTIPLIER_MASK 0x000000ff
+# define SDVO_MULTIPLIER_SHIFT_HIRES 4
+# define SDVO_MULTIPLIER_SHIFT_VGA 0
+
+/** @defgroup DPLL_MD
+ * @{
+ */
+/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_A_MD 0x0601c
+/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_B_MD 0x06020
+/**
+ * UDI pixel divider, controlling how many pixels are stuffed into a packet.
+ *
+ * Value is pixels minus 1. Must be set to 1 pixel for SDVO.
+ */
+# define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000
+# define DPLL_MD_UDI_DIVIDER_SHIFT 24
+/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
+# define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000
+# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16
+/**
+ * SDVO/UDI pixel multiplier.
+ *
+ * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
+ * clock rate is 10 times the DPLL clock. At low resolution/refresh rate
+ * modes, the bus rate would be below the limits, so SDVO allows for stuffing
+ * dummy bytes in the datastream at an increased clock rate, with both sides of
+ * the link knowing how many bytes are fill.
+ *
+ * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
+ * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be
+ * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
+ * through an SDVO command.
+ *
+ * This register field has values of multiplication factor minus 1, with
+ * a maximum multiplier of 5 for SDVO.
+ */
+# define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00
+# define DPLL_MD_UDI_MULTIPLIER_SHIFT 8
+/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
+ * This best be set to the default value (3) or the CRT won't work. No,
+ * I don't entirely understand what this does...
+ */
+# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f
+# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
+/** @} */
+
+#define DPLL_TEST 0x606c
+# define DPLLB_TEST_SDVO_DIV_1 (0 << 22)
+# define DPLLB_TEST_SDVO_DIV_2 (1 << 22)
+# define DPLLB_TEST_SDVO_DIV_4 (2 << 22)
+# define DPLLB_TEST_SDVO_DIV_MASK (3 << 22)
+# define DPLLB_TEST_N_BYPASS (1 << 19)
+# define DPLLB_TEST_M_BYPASS (1 << 18)
+# define DPLLB_INPUT_BUFFER_ENABLE (1 << 16)
+# define DPLLA_TEST_N_BYPASS (1 << 3)
+# define DPLLA_TEST_M_BYPASS (1 << 2)
+# define DPLLA_INPUT_BUFFER_ENABLE (1 << 0)
+
+/*
+ * Palette registers
+ */
+#define PALETTE_A 0x0a000
+#define PALETTE_B 0x0a800
+
+#define FPA0 0x06040
+#define FPA1 0x06044
+#define FPB0 0x06048
+#define FPB1 0x0604c
+
+#define DSPCLK_GATE_D 0x6200
+#define MI_ARB_STATE 0x20e4
+
+/*
+ * Cache mode 0 reg.
+ * - Manipulating render cache behaviour is central
+ * to the concept of zone rendering, tuning this reg can help avoid
+ * unnecessary render cache reads and even writes (for z/stencil)
+ * at beginning and end of scene.
+ *
+ * - To change a bit, write to this reg with a mask bit set and the
+ * bit of interest either set or cleared. EG: (BIT<<16) | BIT to set.
+ */
+#define CACHE_MODE_0 0x2120
+
+/* I830 CRTC registers */
+#define HTOTAL_A 0x60000
+#define HBLANK_A 0x60004
+#define HSYNC_A 0x60008
+#define VTOTAL_A 0x6000c
+#define VBLANK_A 0x60010
+#define VSYNC_A 0x60014
+#define PIPEASRC 0x6001c
+#define BCLRPAT_A 0x60020
+#define VSYNCSHIFT_A 0x60028
+
+#define HTOTAL_B 0x61000
+#define HBLANK_B 0x61004
+#define HSYNC_B 0x61008
+#define VTOTAL_B 0x6100c
+#define VBLANK_B 0x61010
+#define VSYNC_B 0x61014
+#define PIPEBSRC 0x6101c
+#define BCLRPAT_B 0x61020
+#define VSYNCSHIFT_B 0x61028
+
+#define DSPACNTR 0x70180
+#define DSPBCNTR 0x71180
+#define DISPLAY_PLANE_ENABLE (1<<31)
+#define DISPLAY_PLANE_DISABLE 0
+#define DISPPLANE_GAMMA_ENABLE (1<<30)
+#define DISPPLANE_GAMMA_DISABLE 0
+#define DISPPLANE_PIXFORMAT_MASK (0xf<<26)
+#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_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_SRC_KEY_ENABLE (1<<22)
+#define DISPPLANE_SRC_KEY_DISABLE 0
+#define DISPPLANE_LINE_DOUBLE (1<<20)
+#define DISPPLANE_NO_LINE_DOUBLE 0
+#define DISPPLANE_STEREO_POLARITY_FIRST 0
+#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
+/* plane B only */
+#define DISPPLANE_ALPHA_TRANS_ENABLE (1<<15)
+#define DISPPLANE_ALPHA_TRANS_DISABLE 0
+#define DISPPLANE_SPRITE_ABOVE_DISPLAYA 0
+#define DISPPLANE_SPRITE_ABOVE_OVERLAY (1)
+
+#define DSPABASE 0x70184
+#define DSPASTRIDE 0x70188
+
+#define DSPBBASE 0x71184
+#define DSPBADDR DSPBBASE
+#define DSPBSTRIDE 0x71188
+
+#define DSPAKEYVAL 0x70194
+#define DSPAKEYMASK 0x70198
+
+#define DSPAPOS 0x7018C /* reserved */
+#define DSPASIZE 0x70190
+#define DSPBPOS 0x7118C
+#define DSPBSIZE 0x71190
+
+#define DSPASURF 0x7019C
+#define DSPATILEOFF 0x701A4
+
+#define DSPBSURF 0x7119C
+#define DSPBTILEOFF 0x711A4
+
+#define PIPEACONF 0x70008
+#define PIPEACONF_ENABLE (1<<31)
+#define PIPEACONF_DISABLE 0
+#define PIPEACONF_DOUBLE_WIDE (1<<30)
+#define I965_PIPECONF_ACTIVE (1<<30)
+#define PIPEACONF_SINGLE_WIDE 0
+#define PIPEACONF_PIPE_UNLOCKED 0
+#define PIPEACONF_PIPE_LOCKED (1<<25)
+#define PIPEACONF_PALETTE 0
+#define PIPEACONF_GAMMA (1<<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)
+
+#define PIPEBCONF 0x71008
+#define PIPEBCONF_ENABLE (1<<31)
+#define PIPEBCONF_DISABLE 0
+#define PIPEBCONF_DOUBLE_WIDE (1<<30)
+#define PIPEBCONF_DISABLE 0
+#define PIPEBCONF_GAMMA (1<<24)
+#define PIPEBCONF_PALETTE 0
+
+#define BLC_PWM_CTL 0x61254
+#define BACKLIGHT_MODULATION_FREQ_SHIFT (17)
+
+#define BLC_PWM_CTL2 0x61250
+
+#define PFIT_CONTROL 0x61230
+#define PFIT_PGM_RATIOS 0x61234
+
+/**
+ * Indicates that all dependencies of the panel are on:
+ *
+ * - PLL enabled
+ * - pipe enabled
+ * - LVDS/DVOB/DVOC on
+ */
+# define PP_READY (1 << 30) # define PP_SEQUENCE_NONE (0 << 28)
+# define PP_SEQUENCE_ON (1 << 28) # define PP_SEQUENCE_OFF (2 << 28)
+# define PP_SEQUENCE_MASK 0x30000000
+#define PP_CONTROL 0x61204
+# define POWER_TARGET_ON (1 << 0)
+
+#define LVDSPP_ON 0x61208
+#define LVDSPP_OFF 0x6120c
+#define PP_CYCLE 0x61210
+
+/* Framebuffer compression */
+#define FBC_CFB_BASE 0x03200 /* 4k page aligned */
+#define FBC_LL_BASE 0x03204 /* 4k page aligned */
+#define FBC_CONTROL 0x03208
+
+#define VGACNTRL 0x71400
+
+#define VCLK_DIVISOR_VGA0 0x6000
+#define VCLK_DIVISOR_VGA1 0x6004
+#define VCLK_POST_DIV 0x6010
+
+/* Framebuffer compression */
+#define FBC_CFB_BASE 0x03200 /* 4k page aligned */
+#define FBC_LL_BASE 0x03204 /* 4k page aligned */
+#define FBC_CONTROL 0x03208
+#define FBC_CTL_EN (1<<31)
+#define FBC_CTL_PERIODIC (1<<30)
+#define FBC_CTL_INTERVAL_SHIFT (16)
+#define FBC_CTL_UNCOMPRESSIBLE (1<<14)
+#define FBC_CTL_STRIDE_SHIFT (5)
+#define FBC_CTL_FENCENO (1<<0) #define FBC_COMMAND 0x0320c
+#define FBC_CMD_COMPRESS (1<<0) #define FBC_STATUS 0x03210
+#define FBC_STAT_COMPRESSING (1<<31)
+#define FBC_STAT_COMPRESSED (1<<30)
+#define FBC_STAT_MODIFIED (1<<29)
+#define FBC_STAT_CURRENT_LINE (1<<0)
+#define FBC_CONTROL2 0x03214
+#define FBC_CTL_FENCE_DBL (0<<4)
+#define FBC_CTL_IDLE_IMM (0<<2)
+#define FBC_CTL_IDLE_FULL (1<<2)
+#define FBC_CTL_IDLE_LINE (2<<2)
+#define FBC_CTL_IDLE_DEBUG (3<<2)
+#define FBC_CTL_CPU_FENCE (1<<1)
+#define FBC_CTL_PLANEA (0<<0)
+#define FBC_CTL_PLANEB (1<<0)
+#define FBC_FENCE_OFF 0x0321b
+
+#define FBC_LL_SIZE (1536)
+#define FBC_LL_PAD (32)
+
+/*
+ * Some BIOS scratch area registers. The 845 (and 830?) store the amount
+ * of video memory available to the BIOS in SWF1.
+ */
+
+#define SWF0 0x71410
+
+/*
+ * 855 scratch registers.
+ */
+#define SWF10 0x70410
+
+#define SWF30 0x72414
+
+#define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577
+#define PCI_DEVICE_ID_INTEL_82845G_IG 0x2562
+#define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582
+#define PCI_DEVICE_ID_INTEL_82865_IG 0x2572
+#define PCI_DEVICE_ID_INTEL_82915G_IG 0x2582
+#define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592
+#define PCI_DEVICE_ID_INTEL_82945G_IG 0x2772
+#define PCI_DEVICE_ID_INTEL_82945GM_IG 0x27A2
+#define PCI_DEVICE_ID_INTEL_82946_GZ 0x2972
+#define PCI_DEVICE_ID_INTEL_82G35_IG 0x2982
+#define PCI_DEVICE_ID_INTEL_82Q963_IG 0x2992
+#define PCI_DEVICE_ID_INTEL_82G965_IG 0x29a2
+#define PCI_DEVICE_ID_INTEL_GM965_IG 0x2a02
+#define PCI_DEVICE_ID_INTEL_GME965_IG 0x2a12
+#define PCI_DEVICE_ID_INTEL_82G33_IG 0x29c2
+#define PCI_DEVICE_ID_INTEL_82Q35_IG 0x29b2
+#define PCI_DEVICE_ID_INTEL_82Q33_IG 0x29d2
+#define PCI_DEVICE_ID_INTEL_CANTIGA_IG 0x2a42
+
+
+#define IS_I830(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82830_CGC)
+#define IS_845G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82845G_IG)
+#define IS_I85X(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82855GM_IG)
+#define IS_I855(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82855GM_IG)
+#define IS_I865G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82865_IG)
+
+#define IS_I915G(dev) (dev->pci_device == PCI_DEVICE_ID_INTEL_82915G_IG)
+#define IS_I915GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82915GM_IG)
+#define IS_I945G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82945G_IG)
+#define IS_I945GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82945GM_IG)
+
+#define IS_I965G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82946_GZ || \
+ (dev)->pci_device == PCI_DEVICE_ID_INTEL_82G35_IG || \
+ (dev)->pci_device == PCI_DEVICE_ID_INTEL_82Q963_IG || \
+ (dev)->pci_device == PCI_DEVICE_ID_INTEL_82G965_IG || \
+ (dev)->pci_device == PCI_DEVICE_ID_INTEL_GM965_IG || \
+ (dev)->pci_device == PCI_DEVICE_ID_INTEL_GME965_IG)
+
+#define IS_I965GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_GM965_IG)
+
+#define IS_G33(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82G33_IG || \
+ (dev)->pci_device == PCI_DEVICE_ID_INTEL_82Q35_IG || \
+ (dev)->pci_device == PCI_DEVICE_ID_INTEL_82Q33_IG)
+
+#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \
+ IS_I945GM(dev) || IS_I965G(dev))
+
+#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
+ IS_I945GM(dev) || IS_I965GM(dev))
+
+#define IS_IGD_GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_CANTIGA_IG)
+
#endif /* _I915_DRV_H */