aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r--drivers/gpu/drm/i915/Makefile2
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c (renamed from drivers/gpu/drm/i915/i915_gem_debugfs.c)91
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c120
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c9
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h63
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c14
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c80
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c21
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h144
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c4
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c8
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c28
-rw-r--r--drivers/gpu/drm/i915/intel_display.c624
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h8
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c737
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c8
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c22
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c331
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c30
19 files changed, 1322 insertions, 1022 deletions
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 30d6b99fb30..5269dfa5f62 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -4,10 +4,10 @@
ccflags-y := -Iinclude/drm
i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
+ i915_debugfs.o \
i915_suspend.o \
i915_gem.o \
i915_gem_debug.o \
- i915_gem_debugfs.o \
i915_gem_tiling.o \
intel_display.o \
intel_crt.o \
diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index cb3b97405fb..1e3bdcee863 100644
--- a/drivers/gpu/drm/i915/i915_gem_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -158,16 +158,37 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
- seq_printf(m, "Interrupt enable: %08x\n",
- I915_READ(IER));
- seq_printf(m, "Interrupt identity: %08x\n",
- I915_READ(IIR));
- seq_printf(m, "Interrupt mask: %08x\n",
- I915_READ(IMR));
- seq_printf(m, "Pipe A stat: %08x\n",
- I915_READ(PIPEASTAT));
- seq_printf(m, "Pipe B stat: %08x\n",
- I915_READ(PIPEBSTAT));
+ if (!IS_IGDNG(dev)) {
+ seq_printf(m, "Interrupt enable: %08x\n",
+ I915_READ(IER));
+ seq_printf(m, "Interrupt identity: %08x\n",
+ I915_READ(IIR));
+ seq_printf(m, "Interrupt mask: %08x\n",
+ I915_READ(IMR));
+ seq_printf(m, "Pipe A stat: %08x\n",
+ I915_READ(PIPEASTAT));
+ seq_printf(m, "Pipe B stat: %08x\n",
+ I915_READ(PIPEBSTAT));
+ } else {
+ seq_printf(m, "North Display Interrupt enable: %08x\n",
+ I915_READ(DEIER));
+ seq_printf(m, "North Display Interrupt identity: %08x\n",
+ I915_READ(DEIIR));
+ seq_printf(m, "North Display Interrupt mask: %08x\n",
+ I915_READ(DEIMR));
+ seq_printf(m, "South Display Interrupt enable: %08x\n",
+ I915_READ(SDEIER));
+ seq_printf(m, "South Display Interrupt identity: %08x\n",
+ I915_READ(SDEIIR));
+ seq_printf(m, "South Display Interrupt mask: %08x\n",
+ I915_READ(SDEIMR));
+ seq_printf(m, "Graphics Interrupt enable: %08x\n",
+ I915_READ(GTIER));
+ seq_printf(m, "Graphics Interrupt identity: %08x\n",
+ I915_READ(GTIIR));
+ seq_printf(m, "Graphics Interrupt mask: %08x\n",
+ I915_READ(GTIMR));
+ }
seq_printf(m, "Interrupts received: %d\n",
atomic_read(&dev_priv->irq_received));
if (dev_priv->hw_status_page != NULL) {
@@ -312,15 +333,13 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
- unsigned int head, tail, mask;
+ unsigned int head, tail;
head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
- mask = dev_priv->ring.tail_mask;
seq_printf(m, "RingHead : %08x\n", head);
seq_printf(m, "RingTail : %08x\n", tail);
- seq_printf(m, "RingMask : %08x\n", mask);
seq_printf(m, "RingSize : %08lx\n", dev_priv->ring.Size);
seq_printf(m, "Acthd : %08x\n", I915_READ(IS_I965G(dev) ? ACTHD_I965 : ACTHD));
@@ -363,7 +382,37 @@ out:
return 0;
}
-static struct drm_info_list i915_gem_debugfs_list[] = {
+static int i915_registers_info(struct seq_file *m, void *data) {
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_device *dev = node->minor->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ uint32_t reg;
+
+#define DUMP_RANGE(start, end) \
+ for (reg=start; reg < end; reg += 4) \
+ seq_printf(m, "%08x\t%08x\n", reg, I915_READ(reg));
+
+ DUMP_RANGE(0x00000, 0x00fff); /* VGA registers */
+ DUMP_RANGE(0x02000, 0x02fff); /* instruction, memory, interrupt control registers */
+ DUMP_RANGE(0x03000, 0x031ff); /* FENCE and PPGTT control registers */
+ DUMP_RANGE(0x03200, 0x03fff); /* frame buffer compression registers */
+ DUMP_RANGE(0x05000, 0x05fff); /* I/O control registers */
+ DUMP_RANGE(0x06000, 0x06fff); /* clock control registers */
+ DUMP_RANGE(0x07000, 0x07fff); /* 3D internal debug registers */
+ DUMP_RANGE(0x07400, 0x088ff); /* GPE debug registers */
+ DUMP_RANGE(0x0a000, 0x0afff); /* display palette registers */
+ DUMP_RANGE(0x10000, 0x13fff); /* MMIO MCHBAR */
+ DUMP_RANGE(0x30000, 0x3ffff); /* overlay registers */
+ DUMP_RANGE(0x60000, 0x6ffff); /* display engine pipeline registers */
+ DUMP_RANGE(0x70000, 0x72fff); /* display and cursor registers */
+ DUMP_RANGE(0x73000, 0x73fff); /* performance counters */
+
+ return 0;
+}
+
+
+static struct drm_info_list i915_debugfs_list[] = {
+ {"i915_regs", i915_registers_info, 0},
{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
{"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
{"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
@@ -377,19 +426,19 @@ static struct drm_info_list i915_gem_debugfs_list[] = {
{"i915_batchbuffers", i915_batchbuffer_info, 0},
{"i915_error_state", i915_error_state, 0},
};
-#define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list)
+#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
-int i915_gem_debugfs_init(struct drm_minor *minor)
+int i915_debugfs_init(struct drm_minor *minor)
{
- return drm_debugfs_create_files(i915_gem_debugfs_list,
- I915_GEM_DEBUGFS_ENTRIES,
+ return drm_debugfs_create_files(i915_debugfs_list,
+ I915_DEBUGFS_ENTRIES,
minor->debugfs_root, minor);
}
-void i915_gem_debugfs_cleanup(struct drm_minor *minor)
+void i915_debugfs_cleanup(struct drm_minor *minor)
{
- drm_debugfs_remove_files(i915_gem_debugfs_list,
- I915_GEM_DEBUGFS_ENTRIES, minor);
+ drm_debugfs_remove_files(i915_debugfs_list,
+ I915_DEBUGFS_ENTRIES, minor);
}
#endif /* CONFIG_DEBUG_FS */
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 50d1f782768..5a49a1867b3 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -29,11 +29,11 @@
#include "drmP.h"
#include "drm.h"
#include "drm_crtc_helper.h"
+#include "drm_fb_helper.h"
#include "intel_drv.h"
#include "i915_drm.h"
#include "i915_drv.h"
-
-#define I915_DRV "i915_drv"
+#include <linux/vgaarb.h>
/* Really want an OS-independent resettable timer. Would like to have
* this loop run for (eg) 3 sec, but have the timer reset every time
@@ -80,6 +80,34 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
return -EBUSY;
}
+/* As a ringbuffer is only allowed to wrap between instructions, fill
+ * the tail with NOOPs.
+ */
+int i915_wrap_ring(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ volatile unsigned int *virt;
+ int rem;
+
+ rem = dev_priv->ring.Size - dev_priv->ring.tail;
+ if (dev_priv->ring.space < rem) {
+ int ret = i915_wait_ring(dev, rem, __func__);
+ if (ret)
+ return ret;
+ }
+ dev_priv->ring.space -= rem;
+
+ virt = (unsigned int *)
+ (dev_priv->ring.virtual_start + dev_priv->ring.tail);
+ rem /= 4;
+ while (rem--)
+ *virt++ = MI_NOOP;
+
+ dev_priv->ring.tail = 0;
+
+ return 0;
+}
+
/**
* Sets up the hardware status page for devices that need a physical address
* in the register.
@@ -101,7 +129,7 @@ static int i915_init_phys_hws(struct drm_device *dev)
memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
- DRM_DEBUG_DRIVER(I915_DRV, "Enabled hardware status page\n");
+ DRM_DEBUG_DRIVER("Enabled hardware status page\n");
return 0;
}
@@ -187,8 +215,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
master_priv->sarea_priv = (drm_i915_sarea_t *)
((u8 *)master_priv->sarea->handle + init->sarea_priv_offset);
} else {
- DRM_DEBUG_DRIVER(I915_DRV,
- "sarea not found assuming DRI2 userspace\n");
+ DRM_DEBUG_DRIVER("sarea not found assuming DRI2 userspace\n");
}
if (init->ring_size != 0) {
@@ -200,7 +227,6 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
}
dev_priv->ring.Size = init->ring_size;
- dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
dev_priv->ring.map.offset = init->ring_start;
dev_priv->ring.map.size = init->ring_size;
@@ -238,7 +264,7 @@ static int i915_dma_resume(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- DRM_DEBUG_DRIVER(I915_DRV, "%s\n", __func__);
+ DRM_DEBUG_DRIVER("%s\n", __func__);
if (dev_priv->ring.map.handle == NULL) {
DRM_ERROR("can not ioremap virtual address for"
@@ -251,14 +277,14 @@ static int i915_dma_resume(struct drm_device * dev)
DRM_ERROR("Can not find hardware status page\n");
return -EINVAL;
}
- DRM_DEBUG_DRIVER(I915_DRV, "hw status page @ %p\n",
+ DRM_DEBUG_DRIVER("hw status page @ %p\n",
dev_priv->hw_status_page);
if (dev_priv->status_gfx_addr != 0)
I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
else
I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
- DRM_DEBUG_DRIVER(I915_DRV, "Enabled hardware status page\n");
+ DRM_DEBUG_DRIVER("Enabled hardware status page\n");
return 0;
}
@@ -552,7 +578,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
if (!master_priv->sarea_priv)
return -EINVAL;
- DRM_DEBUG_DRIVER(I915_DRV, "%s: page=%d pfCurrentPage=%d\n",
+ DRM_DEBUG_DRIVER("%s: page=%d pfCurrentPage=%d\n",
__func__,
dev_priv->current_page,
master_priv->sarea_priv->pf_current_page);
@@ -633,8 +659,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
return -EINVAL;
}
- DRM_DEBUG_DRIVER(I915_DRV,
- "i915 batchbuffer, start %x used %d cliprects %d\n",
+ DRM_DEBUG_DRIVER("i915 batchbuffer, start %x used %d cliprects %d\n",
batch->start, batch->used, batch->num_cliprects);
RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
@@ -681,8 +706,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
void *batch_data;
int ret;
- DRM_DEBUG_DRIVER(I915_DRV,
- "i915 cmdbuffer, buf %p sz %d cliprects %d\n",
+ DRM_DEBUG_DRIVER("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
@@ -735,7 +759,7 @@ static int i915_flip_bufs(struct drm_device *dev, void *data,
{
int ret;
- DRM_DEBUG_DRIVER(I915_DRV, "%s\n", __func__);
+ DRM_DEBUG_DRIVER("%s\n", __func__);
RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
@@ -778,7 +802,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
break;
default:
- DRM_DEBUG_DRIVER(I915_DRV, "Unknown parameter %d\n",
+ DRM_DEBUG_DRIVER("Unknown parameter %d\n",
param->param);
return -EINVAL;
}
@@ -819,7 +843,7 @@ static int i915_setparam(struct drm_device *dev, void *data,
dev_priv->fence_reg_start = param->value;
break;
default:
- DRM_DEBUG_DRIVER(I915_DRV, "unknown parameter %d\n",
+ DRM_DEBUG_DRIVER("unknown parameter %d\n",
param->param);
return -EINVAL;
}
@@ -846,7 +870,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
return 0;
}
- DRM_DEBUG("set status page addr 0x%08x\n", (u32)hws->addr);
+ DRM_DEBUG_DRIVER("set status page addr 0x%08x\n", (u32)hws->addr);
dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
@@ -868,13 +892,25 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
- DRM_DEBUG_DRIVER(I915_DRV, "load hws HWS_PGA with gfx mem 0x%x\n",
+ DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n",
dev_priv->status_gfx_addr);
- DRM_DEBUG_DRIVER(I915_DRV, "load hws at %p\n",
+ DRM_DEBUG_DRIVER("load hws at %p\n",
dev_priv->hw_status_page);
return 0;
}
+static int i915_get_bridge_dev(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
+ if (!dev_priv->bridge_dev) {
+ DRM_ERROR("bridge device not found\n");
+ return -1;
+ }
+ return 0;
+}
+
/**
* i915_probe_agp - get AGP bootup configuration
* @pdev: PCI device
@@ -888,20 +924,13 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
uint32_t *preallocated_size)
{
- struct pci_dev *bridge_dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
u16 tmp = 0;
unsigned long overhead;
unsigned long stolen;
- bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
- if (!bridge_dev) {
- DRM_ERROR("bridge device not found\n");
- return -1;
- }
-
/* Get the fb aperture size and "stolen" memory amount. */
- pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
- pci_dev_put(bridge_dev);
+ pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &tmp);
*aperture_size = 1024 * 1024;
*preallocated_size = 1024 * 1024;
@@ -984,6 +1013,19 @@ static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
return 0;
}
+/* true = enable decode, false = disable decoder */
+static unsigned int i915_vga_set_decode(void *cookie, bool state)
+{
+ struct drm_device *dev = cookie;
+
+ intel_modeset_vga_set_state(dev, state);
+ if (state)
+ return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
+ VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
+ else
+ return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
+}
+
static int i915_load_modeset_init(struct drm_device *dev,
unsigned long prealloc_size,
unsigned long agp_size)
@@ -1029,6 +1071,11 @@ static int i915_load_modeset_init(struct drm_device *dev,
if (ret)
DRM_INFO("failed to find VBIOS tables\n");
+ /* if we have > 1 VGA cards, then disable the radeon VGA resources */
+ ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
+ if (ret)
+ goto destroy_ringbuffer;
+
ret = drm_irq_install(dev);
if (ret)
goto destroy_ringbuffer;
@@ -1153,11 +1200,16 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
base = drm_get_resource_start(dev, mmio_bar);
size = drm_get_resource_len(dev, mmio_bar);
+ if (i915_get_bridge_dev(dev)) {
+ ret = -EIO;
+ goto free_priv;
+ }
+
dev_priv->regs = ioremap(base, size);
if (!dev_priv->regs) {
DRM_ERROR("failed to map registers\n");
ret = -EIO;
- goto free_priv;
+ goto put_bridge;
}
dev_priv->mm.gtt_mapping =
@@ -1269,6 +1321,8 @@ out_iomapfree:
io_mapping_free(dev_priv->mm.gtt_mapping);
out_rmmap:
iounmap(dev_priv->regs);
+put_bridge:
+ pci_dev_put(dev_priv->bridge_dev);
free_priv:
kfree(dev_priv);
return ret;
@@ -1289,6 +1343,7 @@ int i915_driver_unload(struct drm_device *dev)
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
drm_irq_uninstall(dev);
+ vga_client_register(dev->pdev, NULL, NULL, NULL);
}
if (dev->pdev->msi_enabled)
@@ -1312,6 +1367,7 @@ int i915_driver_unload(struct drm_device *dev)
i915_gem_lastclose(dev);
}
+ pci_dev_put(dev_priv->bridge_dev);
kfree(dev->dev_private);
return 0;
@@ -1321,7 +1377,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
{
struct drm_i915_file_private *i915_file_priv;
- DRM_DEBUG_DRIVER(I915_DRV, "\n");
+ DRM_DEBUG_DRIVER("\n");
i915_file_priv = (struct drm_i915_file_private *)
kmalloc(sizeof(*i915_file_priv), GFP_KERNEL);
@@ -1352,7 +1408,7 @@ void i915_driver_lastclose(struct drm_device * dev)
drm_i915_private_t *dev_priv = dev->dev_private;
if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) {
- intelfb_restore();
+ drm_fb_helper_restore();
return;
}
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index fc4b68aa2d0..dbe568c9327 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -37,12 +37,15 @@
#include <linux/console.h>
#include "drm_crtc_helper.h"
-static unsigned int i915_modeset = -1;
+static int i915_modeset = -1;
module_param_named(modeset, i915_modeset, int, 0400);
unsigned int i915_fbpercrtc = 0;
module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
+unsigned int i915_powersave = 1;
+module_param_named(powersave, i915_powersave, int, 0400);
+
static struct drm_driver driver;
static struct pci_device_id pciidlist[] = {
@@ -188,8 +191,8 @@ static struct drm_driver driver = {
.master_create = i915_master_create,
.master_destroy = i915_master_destroy,
#if defined(CONFIG_DEBUG_FS)
- .debugfs_init = i915_gem_debugfs_init,
- .debugfs_cleanup = i915_gem_debugfs_cleanup,
+ .debugfs_init = i915_debugfs_init,
+ .debugfs_cleanup = i915_debugfs_cleanup,
#endif
.gem_init_object = i915_gem_init_object,
.gem_free_object = i915_gem_free_object,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 5b4f87e5562..a0632f8e76a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -85,7 +85,6 @@ struct drm_i915_gem_phys_object {
};
typedef struct _drm_i915_ring_buffer {
- int tail_mask;
unsigned long Size;
u8 *virtual_start;
int head;
@@ -156,6 +155,7 @@ typedef struct drm_i915_private {
void __iomem *regs;
+ struct pci_dev *bridge_dev;
drm_i915_ring_buffer_t ring;
drm_dma_handle_t *status_page_dmah;
@@ -311,7 +311,7 @@ typedef struct drm_i915_private {
u32 saveIMR;
u32 saveCACHE_MODE_0;
u32 saveD_STATE;
- u32 saveCG_2D_DIS;
+ u32 saveDSPCLK_GATE_D;
u32 saveMI_ARB_STATE;
u32 saveSWF0[16];
u32 saveSWF1[16];
@@ -443,6 +443,14 @@ typedef struct drm_i915_private {
struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT];
} mm;
struct sdvo_device_mapping sdvo_mappings[2];
+
+ /* Reclocking support */
+ bool render_reclock_avail;
+ bool lvds_downclock_avail;
+ struct work_struct idle_work;
+ struct timer_list idle_timer;
+ bool busy;
+ u16 orig_clock;
} drm_i915_private_t;
/** driver private structure attached to each drm_gem_object */
@@ -575,6 +583,7 @@ enum intel_chip_family {
extern struct drm_ioctl_desc i915_ioctls[];
extern int i915_max_ioctl;
extern unsigned int i915_fbpercrtc;
+extern unsigned int i915_powersave;
extern int i915_master_create(struct drm_device *dev, struct drm_master *master);
extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master);
@@ -730,8 +739,8 @@ void i915_gem_dump_object(struct drm_gem_object *obj, int len,
void i915_dump_lru(struct drm_device *dev, const char *where);
/* i915_debugfs.c */
-int i915_gem_debugfs_init(struct drm_minor *minor);
-void i915_gem_debugfs_cleanup(struct drm_minor *minor);
+int i915_debugfs_init(struct drm_minor *minor);
+void i915_debugfs_cleanup(struct drm_minor *minor);
/* i915_suspend.c */
extern int i915_save_state(struct drm_device *dev);
@@ -757,6 +766,7 @@ static inline void opregion_enable_asle(struct drm_device *dev) { return; }
/* modesetting */
extern void intel_modeset_init(struct drm_device *dev);
extern void intel_modeset_cleanup(struct drm_device *dev);
+extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
/**
* Lock test for when it's just for synchronization of ring access.
@@ -781,33 +791,32 @@ extern void intel_modeset_cleanup(struct drm_device *dev);
#define I915_VERBOSE 0
-#define RING_LOCALS unsigned int outring, ringmask, outcount; \
- volatile char *virt;
-
-#define BEGIN_LP_RING(n) do { \
- if (I915_VERBOSE) \
- DRM_DEBUG("BEGIN_LP_RING(%d)\n", (n)); \
- if (dev_priv->ring.space < (n)*4) \
- i915_wait_ring(dev, (n)*4, __func__); \
- outcount = 0; \
- outring = dev_priv->ring.tail; \
- ringmask = dev_priv->ring.tail_mask; \
- virt = dev_priv->ring.virtual_start; \
+#define RING_LOCALS volatile unsigned int *ring_virt__;
+
+#define BEGIN_LP_RING(n) do { \
+ int bytes__ = 4*(n); \
+ if (I915_VERBOSE) DRM_DEBUG("BEGIN_LP_RING(%d)\n", (n)); \
+ /* a wrap must occur between instructions so pad beforehand */ \
+ if (unlikely (dev_priv->ring.tail + bytes__ > dev_priv->ring.Size)) \
+ i915_wrap_ring(dev); \
+ if (unlikely (dev_priv->ring.space < bytes__)) \
+ i915_wait_ring(dev, bytes__, __func__); \
+ ring_virt__ = (unsigned int *) \
+ (dev_priv->ring.virtual_start + dev_priv->ring.tail); \
+ dev_priv->ring.tail += bytes__; \
+ dev_priv->ring.tail &= dev_priv->ring.Size - 1; \
+ dev_priv->ring.space -= bytes__; \
} while (0)
-#define OUT_RING(n) do { \
+#define OUT_RING(n) do { \
if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \
- *(volatile unsigned int *)(virt + outring) = (n); \
- outcount++; \
- outring += 4; \
- outring &= ringmask; \
+ *ring_virt__++ = (n); \
} while (0)
#define ADVANCE_LP_RING() do { \
- if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring); \
- dev_priv->ring.tail = outring; \
- dev_priv->ring.space -= outcount * 4; \
- I915_WRITE(PRB0_TAIL, outring); \
+ if (I915_VERBOSE) \
+ DRM_DEBUG("ADVANCE_LP_RING %x\n", dev_priv->ring.tail); \
+ I915_WRITE(PRB0_TAIL, dev_priv->ring.tail); \
} while(0)
/**
@@ -830,6 +839,7 @@ extern void intel_modeset_cleanup(struct drm_device *dev);
#define I915_GEM_HWS_INDEX 0x20
#define I915_BREADCRUMB_INDEX 0x21
+extern int i915_wrap_ring(struct drm_device * dev);
extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define IS_I830(dev) ((dev)->pci_device == 0x3577)
@@ -903,6 +913,9 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
/* dsparb controlled by hw only */
#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IGDNG(dev))
+#define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IGDNG(dev))
+#define HAS_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IGDNG(dev))
+
#define PRIMARY_RINGBUFFER_SIZE (128*1024)
#endif
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 80e5ba490dc..c67317112f4 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -29,6 +29,7 @@
#include "drm.h"
#include "i915_drm.h"
#include "i915_drv.h"
+#include "intel_drv.h"
#include <linux/swap.h>
#include <linux/pci.h>
@@ -111,7 +112,8 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_gem_create *args = data;
struct drm_gem_object *obj;
- int handle, ret;
+ int ret;
+ u32 handle;
args->size = roundup(args->size, PAGE_SIZE);
@@ -981,6 +983,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_set_domain *args = data;
struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
uint32_t read_domains = args->read_domains;
uint32_t write_domain = args->write_domain;
int ret;
@@ -1004,15 +1007,17 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL)
return -EBADF;
+ obj_priv = obj->driver_private;
mutex_lock(&dev->struct_mutex);
+
+ intel_mark_busy(dev, obj);
+
#if WATCH_BUF
DRM_INFO("set_domain_ioctl %p(%zd), %08x %08x\n",
obj, obj->size, read_domains, write_domain);
#endif
if (read_domains & I915_GEM_DOMAIN_GTT) {
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
-
ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
/* Update the LRU on the fence for the CPU access that's
@@ -2776,6 +2781,8 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj)
BUG_ON(obj->pending_read_domains & I915_GEM_DOMAIN_CPU);
BUG_ON(obj->pending_write_domain == I915_GEM_DOMAIN_CPU);
+ intel_mark_busy(dev, obj);
+
#if WATCH_BUF
DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n",
__func__, obj,
@@ -4093,7 +4100,6 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
/* Set up the kernel mapping for the ring. */
ring->Size = obj->size;
- ring->tail_mask = obj->size - 1;
ring->map.offset = dev->agp->base + obj_priv->gtt_offset;
ring->map.size = obj->size;
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index a2d527b22ec..200e398453c 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -94,23 +94,15 @@
static int
intel_alloc_mchbar_resource(struct drm_device *dev)
{
- struct pci_dev *bridge_dev;
drm_i915_private_t *dev_priv = dev->dev_private;
int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
u32 temp_lo, temp_hi = 0;
u64 mchbar_addr;
int ret = 0;
- bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
- if (!bridge_dev) {
- DRM_DEBUG("no bridge dev?!\n");
- ret = -ENODEV;
- goto out;
- }
-
if (IS_I965G(dev))
- pci_read_config_dword(bridge_dev, reg + 4, &temp_hi);
- pci_read_config_dword(bridge_dev, reg, &temp_lo);
+ pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
+ pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
/* If ACPI doesn't have it, assume we need to allocate it ourselves */
@@ -118,30 +110,28 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
if (mchbar_addr &&
pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
ret = 0;
- goto out_put;
+ goto out;
}
#endif
/* Get some space for it */
- ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res,
+ ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, &dev_priv->mch_res,
MCHBAR_SIZE, MCHBAR_SIZE,
PCIBIOS_MIN_MEM,
0, pcibios_align_resource,
- bridge_dev);
+ dev_priv->bridge_dev);
if (ret) {
DRM_DEBUG("failed bus alloc: %d\n", ret);
dev_priv->mch_res.start = 0;
- goto out_put;
+ goto out;
}
if (IS_I965G(dev))
- pci_write_config_dword(bridge_dev, reg + 4,
+ pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
upper_32_bits(dev_priv->mch_res.start));
- pci_write_config_dword(bridge_dev, reg,
+ pci_write_config_dword(dev_priv->bridge_dev, reg,
lower_32_bits(dev_priv->mch_res.start));
-out_put:
- pci_dev_put(bridge_dev);
out:
return ret;
}
@@ -150,44 +140,36 @@ out:
static bool
intel_setup_mchbar(struct drm_device *dev)
{
- struct pci_dev *bridge_dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
u32 temp;
bool need_disable = false, enabled;
- bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
- if (!bridge_dev) {
- DRM_DEBUG("no bridge dev?!\n");
- goto out;
- }
-
if (IS_I915G(dev) || IS_I915GM(dev)) {
- pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
+ pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
enabled = !!(temp & DEVEN_MCHBAR_EN);
} else {
- pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
+ pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
enabled = temp & 1;
}
/* If it's already enabled, don't have to do anything */
if (enabled)
- goto out_put;
+ goto out;
if (intel_alloc_mchbar_resource(dev))
- goto out_put;
+ goto out;
need_disable = true;
/* Space is allocated or reserved, so enable it. */
if (IS_I915G(dev) || IS_I915GM(dev)) {
- pci_write_config_dword(bridge_dev, DEVEN_REG,
+ pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG,
temp | DEVEN_MCHBAR_EN);
} else {
- pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
- pci_write_config_dword(bridge_dev, mchbar_reg, temp | 1);
+ pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
+ pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1);
}
-out_put:
- pci_dev_put(bridge_dev);
out:
return need_disable;
}
@@ -196,25 +178,18 @@ static void
intel_teardown_mchbar(struct drm_device *dev, bool disable)
{
drm_i915_private_t *dev_priv = dev->dev_private;
- struct pci_dev *bridge_dev;
int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
u32 temp;
- bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
- if (!bridge_dev) {
- DRM_DEBUG("no bridge dev?!\n");
- return;
- }
-
if (disable) {
if (IS_I915G(dev) || IS_I915GM(dev)) {
- pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
+ pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
temp &= ~DEVEN_MCHBAR_EN;
- pci_write_config_dword(bridge_dev, DEVEN_REG, temp);
+ pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG, temp);
} else {
- pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
+ pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
temp &= ~1;
- pci_write_config_dword(bridge_dev, mchbar_reg, temp);
+ pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp);
}
}
@@ -234,7 +209,13 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
bool need_disable;
- if (!IS_I9XX(dev)) {
+ if (IS_IGDNG(dev)) {
+ /* On IGDNG whatever DRAM config, GPU always do
+ * same swizzling setup.
+ */
+ swizzle_x = I915_BIT_6_SWIZZLE_9_10;
+ swizzle_y = I915_BIT_6_SWIZZLE_9;
+ } else if (!IS_I9XX(dev)) {
/* As far as we know, the 865 doesn't have these bit 6
* swizzling issues.
*/
@@ -317,13 +298,6 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
}
}
- /* FIXME: check with memory config on IGDNG */
- if (IS_IGDNG(dev)) {
- DRM_ERROR("disable tiling on IGDNG...\n");
- swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
- swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
- }
-
dev_priv->mm.bit_6_swizzle_x = swizzle_x;
dev_priv->mm.bit_6_swizzle_y = swizzle_y;
}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 7ebc84c2881..6c89f2ff249 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -565,6 +565,27 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
I915_READ(PORT_HOTPLUG_STAT);
+
+ /* EOS interrupts occurs */
+ if (IS_IGD(dev) &