diff options
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r-- | drivers/gpu/drm/i915/Makefile | 2 | ||||
-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.c | 120 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 63 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_tiling.c | 80 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 144 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_suspend.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_crt.c | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 624 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_fb.c | 737 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_i2c.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 331 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_tv.c | 30 |
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) & |