Commit 4eab8a57 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'drm-intel-fixes' of git://anongit.freedesktop.org/~ickle/drm-intel

* 'drm-intel-fixes' of git://anongit.freedesktop.org/~ickle/drm-intel: (25 commits)
  intel_agp,i915: Add more sandybridge graphics device ids
  drm/i915: Enable MI_FLUSH on Sandybridge
  agp/intel: Fix cache control for Sandybridge
  agp/intel: use #ifdef idiom for intel-agp.h
  agp/intel: fix physical address mask bits for sandybridge
  drm/i915: Prevent double dpms on
  drm/i915: Avoid use of uninitialised values when disabling panel-fitter
  drm/i915: Avoid pageflipping freeze when we miss the flip prepare interrupt
  drm/i915: Tightly scope intel_encoder to prevent invalid use
  drm/i915: Allocate the PCI resource for the MCHBAR
  drm/i915/dp: Really try 5 times before giving up.
  drm/i915/sdvo: Restore guess of the DDC bus in absence of VBIOS
  drm/i915/dp: Boost timeout for enabling transcoder to 100ms
  drm/i915: Re-use set_base_atomic to share setting of the display registers
  drm/i915: Fix offset page-flips on i965+
  drm/i915: Include a generation number in the device info
  i915: return -EFAULT if copy_to_user fails
  i915: return -EFAULT if copy_to_user fails
  agp/intel: Promote warning about failure to setup flush to error.
  drm/i915: overlay on gen2 can't address above 1G
  ...
parents 6300d6d7 85540480
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <asm/smp.h> #include <asm/smp.h>
#include "agp.h" #include "agp.h"
#include "intel-agp.h" #include "intel-agp.h"
#include <linux/intel-gtt.h>
#include "intel-gtt.c" #include "intel-gtt.c"
...@@ -815,11 +816,19 @@ static const struct intel_driver_description { ...@@ -815,11 +816,19 @@ static const struct intel_driver_description {
"HD Graphics", NULL, &intel_i965_driver }, "HD Graphics", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, { PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
"HD Graphics", NULL, &intel_i965_driver }, "HD Graphics", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG, { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG,
"Sandybridge", NULL, &intel_gen6_driver }, "Sandybridge", NULL, &intel_gen6_driver },
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG, { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG,
"Sandybridge", NULL, &intel_gen6_driver }, "Sandybridge", NULL, &intel_gen6_driver },
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_D0_IG, { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG,
"Sandybridge", NULL, &intel_gen6_driver },
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG,
"Sandybridge", NULL, &intel_gen6_driver },
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG,
"Sandybridge", NULL, &intel_gen6_driver },
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG,
"Sandybridge", NULL, &intel_gen6_driver },
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG,
"Sandybridge", NULL, &intel_gen6_driver }, "Sandybridge", NULL, &intel_gen6_driver },
{ 0, 0, NULL, NULL, NULL } { 0, 0, NULL, NULL, NULL }
}; };
...@@ -1044,6 +1053,7 @@ static struct pci_device_id agp_intel_pci_table[] = { ...@@ -1044,6 +1053,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB), ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB),
ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB), ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB),
ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB),
{ } { }
}; };
......
/* /*
* Common Intel AGPGART and GTT definitions. * Common Intel AGPGART and GTT definitions.
*/ */
#ifndef _INTEL_AGP_H
#define _INTEL_AGP_H
/* Intel registers */ /* Intel registers */
#define INTEL_APSIZE 0xb4 #define INTEL_APSIZE 0xb4
...@@ -200,11 +202,16 @@ ...@@ -200,11 +202,16 @@
#define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062
#define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a #define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a
#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046 #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100 #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100 /* Desktop */
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG 0x0102 #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG 0x0102
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104 #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG 0x0112
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG 0x0106 #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG 0x0122
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_D0_IG 0x0126 #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104 /* Mobile */
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG 0x0106
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG 0x0116
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG 0x0126
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB 0x0108 /* Server */
#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG 0x010A
/* cover 915 and 945 variants */ /* cover 915 and 945 variants */
#define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \ #define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \
...@@ -231,7 +238,8 @@ ...@@ -231,7 +238,8 @@
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB) agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB)
#define IS_SNB (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \ #define IS_SNB (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB)
#define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \ #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \
...@@ -244,3 +252,5 @@ ...@@ -244,3 +252,5 @@
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB || \
IS_SNB) IS_SNB)
#endif
...@@ -49,6 +49,26 @@ static struct gatt_mask intel_i810_masks[] = ...@@ -49,6 +49,26 @@ static struct gatt_mask intel_i810_masks[] =
.type = INTEL_AGP_CACHED_MEMORY} .type = INTEL_AGP_CACHED_MEMORY}
}; };
#define INTEL_AGP_UNCACHED_MEMORY 0
#define INTEL_AGP_CACHED_MEMORY_LLC 1
#define INTEL_AGP_CACHED_MEMORY_LLC_GFDT 2
#define INTEL_AGP_CACHED_MEMORY_LLC_MLC 3
#define INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT 4
static struct gatt_mask intel_gen6_masks[] =
{
{.mask = I810_PTE_VALID | GEN6_PTE_UNCACHED,
.type = INTEL_AGP_UNCACHED_MEMORY },
{.mask = I810_PTE_VALID | GEN6_PTE_LLC,
.type = INTEL_AGP_CACHED_MEMORY_LLC },
{.mask = I810_PTE_VALID | GEN6_PTE_LLC | GEN6_PTE_GFDT,
.type = INTEL_AGP_CACHED_MEMORY_LLC_GFDT },
{.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC,
.type = INTEL_AGP_CACHED_MEMORY_LLC_MLC },
{.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC | GEN6_PTE_GFDT,
.type = INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT },
};
static struct _intel_private { static struct _intel_private {
struct pci_dev *pcidev; /* device one */ struct pci_dev *pcidev; /* device one */
u8 __iomem *registers; u8 __iomem *registers;
...@@ -178,13 +198,6 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem, ...@@ -178,13 +198,6 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem,
off_t pg_start, int mask_type) off_t pg_start, int mask_type)
{ {
int i, j; int i, j;
u32 cache_bits = 0;
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
{
cache_bits = GEN6_PTE_LLC_MLC;
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(agp_bridge, writel(agp_bridge->driver->mask_memory(agp_bridge,
...@@ -317,6 +330,23 @@ static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge, ...@@ -317,6 +330,23 @@ static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge,
return 0; return 0;
} }
static int intel_gen6_type_to_mask_type(struct agp_bridge_data *bridge,
int type)
{
unsigned int type_mask = type & ~AGP_USER_CACHED_MEMORY_GFDT;
unsigned int gfdt = type & AGP_USER_CACHED_MEMORY_GFDT;
if (type_mask == AGP_USER_UNCACHED_MEMORY)
return INTEL_AGP_UNCACHED_MEMORY;
else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC)
return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT :
INTEL_AGP_CACHED_MEMORY_LLC_MLC;
else /* set 'normal'/'cached' to LLC by default */
return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_GFDT :
INTEL_AGP_CACHED_MEMORY_LLC;
}
static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
int type) int type)
{ {
...@@ -588,8 +618,7 @@ static void intel_i830_init_gtt_entries(void) ...@@ -588,8 +618,7 @@ static void intel_i830_init_gtt_entries(void)
gtt_entries = 0; gtt_entries = 0;
break; break;
} }
} else if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || } else if (IS_SNB) {
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) {
/* /*
* SandyBridge has new memory control reg at 0x50.w * SandyBridge has new memory control reg at 0x50.w
*/ */
...@@ -1068,11 +1097,11 @@ static void intel_i9xx_setup_flush(void) ...@@ -1068,11 +1097,11 @@ static void intel_i9xx_setup_flush(void)
intel_i915_setup_chipset_flush(); intel_i915_setup_chipset_flush();
} }
if (intel_private.ifp_resource.start) { if (intel_private.ifp_resource.start)
intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE);
if (!intel_private.i9xx_flush_page) if (!intel_private.i9xx_flush_page)
dev_info(&intel_private.pcidev->dev, "can't ioremap flush page - no chipset flushing"); dev_err(&intel_private.pcidev->dev,
} "can't ioremap flush page - no chipset flushing\n");
} }
static int intel_i9xx_configure(void) static int intel_i9xx_configure(void)
...@@ -1163,7 +1192,7 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start, ...@@ -1163,7 +1192,7 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start,
mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY && if (!IS_SNB && mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
mask_type != INTEL_AGP_CACHED_MEMORY) mask_type != INTEL_AGP_CACHED_MEMORY)
goto out_err; goto out_err;
...@@ -1333,8 +1362,8 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, ...@@ -1333,8 +1362,8 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge, static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge,
dma_addr_t addr, int type) dma_addr_t addr, int type)
{ {
/* Shift high bits down */ /* gen6 has bit11-4 for physical addr bit39-32 */
addr |= (addr >> 28) & 0xff; addr |= (addr >> 28) & 0xff0;
/* Type checking must be done elsewhere */ /* Type checking must be done elsewhere */
return addr | bridge->driver->masks[type].mask; return addr | bridge->driver->masks[type].mask;
...@@ -1359,6 +1388,7 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) ...@@ -1359,6 +1388,7 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
break; break;
case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB: case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB:
case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB: case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB:
case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB:
*gtt_offset = MB(2); *gtt_offset = MB(2);
pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
...@@ -1563,7 +1593,7 @@ static const struct agp_bridge_driver intel_gen6_driver = { ...@@ -1563,7 +1593,7 @@ static const struct agp_bridge_driver intel_gen6_driver = {
.fetch_size = intel_i9xx_fetch_size, .fetch_size = intel_i9xx_fetch_size,
.cleanup = intel_i915_cleanup, .cleanup = intel_i915_cleanup,
.mask_memory = intel_gen6_mask_memory, .mask_memory = intel_gen6_mask_memory,
.masks = intel_i810_masks, .masks = intel_gen6_masks,
.agp_enable = intel_i810_agp_enable, .agp_enable = intel_i810_agp_enable,
.cache_flush = global_cache_flush, .cache_flush = global_cache_flush,
.create_gatt_table = intel_i965_create_gatt_table, .create_gatt_table = intel_i965_create_gatt_table,
...@@ -1576,7 +1606,7 @@ static const struct agp_bridge_driver intel_gen6_driver = { ...@@ -1576,7 +1606,7 @@ static const struct agp_bridge_driver intel_gen6_driver = {
.agp_alloc_pages = agp_generic_alloc_pages, .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page, .agp_destroy_page = agp_generic_destroy_page,
.agp_destroy_pages = agp_generic_destroy_pages, .agp_destroy_pages = agp_generic_destroy_pages,
.agp_type_to_mask_type = intel_i830_type_to_mask_type, .agp_type_to_mask_type = intel_gen6_type_to_mask_type,
.chipset_flush = intel_i915_chipset_flush, .chipset_flush = intel_i915_chipset_flush,
#ifdef USE_PCI_DMA_API #ifdef USE_PCI_DMA_API
.agp_map_page = intel_agp_map_page, .agp_map_page = intel_agp_map_page,
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include "drmP.h" #include "drmP.h"
#include "drm.h" #include "drm.h"
#include "intel_drv.h"
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.h" #include "i915_drv.h"
...@@ -121,6 +122,54 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) ...@@ -121,6 +122,54 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
return 0; return 0;
} }
static int i915_gem_pageflip_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;
unsigned long flags;
struct intel_crtc *crtc;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
const char *pipe = crtc->pipe ? "B" : "A";
const char *plane = crtc->plane ? "B" : "A";
struct intel_unpin_work *work;
spin_lock_irqsave(&dev->event_lock, flags);
work = crtc->unpin_work;
if (work == NULL) {
seq_printf(m, "No flip due on pipe %s (plane %s)\n",
pipe, plane);
} else {
if (!work->pending) {
seq_printf(m, "Flip queued on pipe %s (plane %s)\n",
pipe, plane);
} else {
seq_printf(m, "Flip pending (waiting for vsync) on pipe %s (plane %s)\n",
pipe, plane);
}
if (work->enable_stall_check)
seq_printf(m, "Stall check enabled, ");
else
seq_printf(m, "Stall check waiting for page flip ioctl, ");
seq_printf(m, "%d prepares\n", work->pending);
if (work->old_fb_obj) {
struct drm_i915_gem_object *obj_priv = to_intel_bo(work->old_fb_obj);
if(obj_priv)
seq_printf(m, "Old framebuffer gtt_offset 0x%08x\n", obj_priv->gtt_offset );
}
if (work->pending_flip_obj) {
struct drm_i915_gem_object *obj_priv = to_intel_bo(work->pending_flip_obj);
if(obj_priv)
seq_printf(m, "New framebuffer gtt_offset 0x%08x\n", obj_priv->gtt_offset );
}
}
spin_unlock_irqrestore(&dev->event_lock, flags);
}
return 0;
}
static int i915_gem_request_info(struct seq_file *m, void *data) static int i915_gem_request_info(struct seq_file *m, void *data)
{ {
struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_info_node *node = (struct drm_info_node *) m->private;
...@@ -777,6 +826,7 @@ static struct drm_info_list i915_debugfs_list[] = { ...@@ -777,6 +826,7 @@ static struct drm_info_list i915_debugfs_list[] = {
{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, {"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_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
{"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST}, {"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
{"i915_gem_pageflip", i915_gem_pageflip_info, 0},
{"i915_gem_request", i915_gem_request_info, 0}, {"i915_gem_request", i915_gem_request_info, 0},
{"i915_gem_seqno", i915_gem_seqno_info, 0}, {"i915_gem_seqno", i915_gem_seqno_info, 0},
{"i915_gem_fence_regs", i915_gem_fence_regs_info, 0}, {"i915_gem_fence_regs", i915_gem_fence_regs_info, 0},
......
...@@ -620,9 +620,11 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, ...@@ -620,9 +620,11 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
ret = copy_from_user(cliprects, batch->cliprects, ret = copy_from_user(cliprects, batch->cliprects,
batch->num_cliprects * batch->num_cliprects *
sizeof(struct drm_clip_rect)); sizeof(struct drm_clip_rect));
if (ret != 0) if (ret != 0) {
ret = -EFAULT;
goto fail_free; goto fail_free;
} }
}
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
ret = i915_dispatch_batchbuffer(dev, batch, cliprects); ret = i915_dispatch_batchbuffer(dev, batch, cliprects);
...@@ -662,8 +664,10 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, ...@@ -662,8 +664,10 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
return -ENOMEM; return -ENOMEM;
ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz); ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz);
if (ret != 0) if (ret != 0) {
ret = -EFAULT;
goto fail_batch_free; goto fail_batch_free;
}
if (cmdbuf->num_cliprects) { if (cmdbuf->num_cliprects) {
cliprects = kcalloc(cmdbuf->num_cliprects, cliprects = kcalloc(cmdbuf->num_cliprects,
...@@ -676,9 +680,11 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, ...@@ -676,9 +680,11 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
ret = copy_from_user(cliprects, cmdbuf->cliprects, ret = copy_from_user(cliprects, cmdbuf->cliprects,
cmdbuf->num_cliprects * cmdbuf->num_cliprects *
sizeof(struct drm_clip_rect)); sizeof(struct drm_clip_rect));
if (ret != 0) if (ret != 0) {
ret = -EFAULT;
goto fail_clip_free; goto fail_clip_free;
} }
}
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
ret = i915_dispatch_cmdbuffer(dev, cmdbuf, cliprects, batch_data); ret = i915_dispatch_cmdbuffer(dev, cmdbuf, cliprects, batch_data);
...@@ -885,7 +891,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev) ...@@ -885,7 +891,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915; int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
u32 temp_lo, temp_hi = 0; u32 temp_lo, temp_hi = 0;
u64 mchbar_addr; u64 mchbar_addr;
int ret = 0; int ret;
if (IS_I965G(dev)) if (IS_I965G(dev))
pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi); pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
...@@ -895,14 +901,15 @@ intel_alloc_mchbar_resource(struct drm_device *dev) ...@@ -895,14 +901,15 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
/* If ACPI doesn't have it, assume we need to allocate it ourselves */ /* If ACPI doesn't have it, assume we need to allocate it ourselves */
#ifdef CONFIG_PNP #ifdef CONFIG_PNP
if (mchbar_addr && if (mchbar_addr &&
pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) { pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE))
ret = 0; return 0;
goto out;
}
#endif #endif
/* Get some space for it */ /* Get some space for it */
ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, &dev_priv->mch_res, dev_priv->mch_res.name = "i915 MCHBAR";
dev_priv->mch_res.flags = IORESOURCE_MEM;
ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus,
&dev_priv->mch_res,
MCHBAR_SIZE, MCHBAR_SIZE, MCHBAR_SIZE, MCHBAR_SIZE,
PCIBIOS_MIN_MEM, PCIBIOS_MIN_MEM,
0, pcibios_align_resource, 0, pcibios_align_resource,
...@@ -910,7 +917,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev) ...@@ -910,7 +917,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
if (ret) { if (ret) {
DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret); DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret);
dev_priv->mch_res.start = 0; dev_priv->mch_res.start = 0;
goto out; return ret;
} }
if (IS_I965G(dev)) if (IS_I965G(dev))
...@@ -919,8 +926,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev) ...@@ -919,8 +926,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
pci_write_config_dword(dev_priv->bridge_dev, reg, pci_write_config_dword(dev_priv->bridge_dev, reg,
lower_32_bits(dev_priv->mch_res.start)); lower_32_bits(dev_priv->mch_res.start));
out: return 0;
return ret;
} }
/* Setup MCHBAR if possible, return true if we should disable it again */ /* Setup MCHBAR if possible, return true if we should disable it again */
...@@ -2082,6 +2088,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -2082,6 +2088,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
goto free_priv; goto free_priv;
} }
/* overlay on gen2 is broken and can't address above 1G */
if (IS_GEN2(dev))
dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(30));
dev_priv->regs = ioremap(base, size); dev_priv->regs = ioremap(base, size);
if (!dev_priv->regs) { if (!dev_priv->regs) {
DRM_ERROR("failed to map registers\n"); DRM_ERROR("failed to map registers\n");
......
...@@ -61,91 +61,86 @@ extern int intel_agp_enabled; ...@@ -61,91 +61,86 @@ extern int intel_agp_enabled;
.driver_data = (unsigned long) info } .driver_data = (unsigned long) info }
static const struct intel_device_info intel_i830_info = { static const struct intel_device_info intel_i830_info = {
.is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1, .gen = 2, .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1,
}; };
static const struct intel_device_info intel_845g_info = { static const struct intel_device_info intel_845g_info = {
.is_i8xx = 1, .gen = 2, .is_i8xx = 1,
}; };
static const struct intel_device_info intel_i85x_info = { static const struct intel_device_info intel_i85x_info = {
.is_i8xx = 1, .is_i85x = 1, .is_mobile = 1, .gen = 2, .is_i8xx = 1, .is_i85x = 1, .is_mobile = 1,
.cursor_needs_physical = 1, .cursor_needs_physical = 1,
}; };
static const struct intel_device_info intel_i865g_info = { static const struct intel_device_info intel_i865g_info = {
.is_i8xx = 1, .gen = 2, .is_i8xx = 1,
}; };
static const struct intel_device_info intel_i915g_info = { static const struct intel_device_info intel_i915g_info = {
.is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1, .gen = 3, .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1,
}; };
static const struct intel_device_info intel_i915gm_info = { static const struct intel_device_info intel_i915gm_info = {
.is_i9xx = 1, .is_mobile = 1, .gen = 3, .is_i9xx = 1, .is_mobile = 1,
.cursor_needs_physical = 1, .cursor_needs_physical = 1,
}; };
static const struct intel_device_info intel_i945g_info = { static const struct intel_device_info intel_i945g_info = {
.is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1, .gen = 3, .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1,
}; };
static const struct intel_device_info intel_i945gm_info = { static const struct intel_device_info intel_i945gm_info = {
.is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, .gen = 3, .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1,
.has_hotplug = 1, .cursor_needs_physical = 1, .has_hotplug = 1, .cursor_needs_physical = 1,
}; };
static const struct intel_device_info intel_i965g_info = { static const struct intel_device_info intel_i965g_info = {
.is_broadwater = 1, .is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1, .gen = 4, .is_broadwater = 1, .is_i965g = 1, .is_i9xx = 1,
.has_hotplug = 1,
}; };
static const struct intel_device_info intel_i965gm_info = { static const struct intel_device_info intel_i965gm_info = {
.is_crestline = 1, .is_i965g = 1, .is_i965gm = 1, .is_i9xx = 1, .gen = 4, .is_crestline = 1, .is_i965g = 1, .is_i965gm = 1, .is_i9xx = 1,
.is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1,
.has_hotplug = 1,
}; };
static const struct intel_device_info intel_g33_info = { static const struct intel_device_info intel_g33_info = {
.is_g33 = 1, .is_i9xx = 1, .need_gfx_hws = 1, .gen = 3, .is_g33 = 1, .is_i9xx = 1,
.has_hotplug = 1, .need_gfx_hws = 1, .has_hotplug = 1,
}; };
static const struct intel_device_info intel_g45_info = { static const struct intel_device_info intel_g45_info = {
.is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1, .gen = 4, .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1,
.has_pipe_cxsr = 1, .has_pipe_cxsr = 1, .has_hotplug = 1,
.has_hotplug = 1,
}; };
static const struct intel_device_info intel_gm45_info = { static const struct intel_device_info intel_gm45_info = {
.is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .gen = 4, .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1,
.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
.has_pipe_cxsr = 1, .has_pipe_cxsr = 1, .has_hotplug = 1,
.has_hotplug = 1,
}; };
static const struct intel_device_info intel_pineview_info = { static const struct intel_device_info intel_pineview_info = {
.is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1, .gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1,
.need_gfx_hws = 1, .need_gfx_hws = 1, .has_hotplug = 1,
.has_hotplug = 1,
}; };
static const struct intel_device_info intel_ironlake_d_info = { static const struct intel_device_info intel_ironlake_d_info = {
.is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1, .gen = 5, .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1,
.has_pipe_cxsr = 1, .need_gfx_hws = 1, .has_pipe_cxsr = 1, .has_hotplug = 1,
.has_hotplug = 1,
}; };
static const struct intel_device_info intel_ironlake_m_info = { static const struct intel_device_info intel_ironlake_m_info = {
.is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1, .gen = 5, .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1,
.need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1,
.has_hotplug = 1,
}; };
static const struct intel_device_info intel_sandybridge_d_info = { static const struct intel_device_info intel_sandybridge_d_info = {
.is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1, .gen = 6, .is_i965g = 1, .is_i9xx = 1,
.has_hotplug = 1, .is_gen6 = 1, .need_gfx_hws = 1, .has_hotplug = 1,
}; };
static const struct intel_device_info intel_sandybridge_m_info = { static const struct intel_device_info intel_sandybridge_m_info = {
.is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, .need_gfx_hws = 1, .gen = 6, .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1,
.has_hotplug = 1, .is_gen6 = 1, .need_gfx_hws = 1, .has_hotplug = 1,
}; };
static const struct pci_device_id pciidlist[] = { /* aka */ static const struct pci_device_id pciidlist[] = { /* aka */
...@@ -180,8 +175,12 @@ static const struct pci_device_id pciidlist[] = { /* aka */ ...@@ -180,8 +175,12 @@ static const struct pci_device_id pciidlist[] = { /* aka */
INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info), INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info),
INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info), INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info),
INTEL_VGA_DEVICE(0x0102, &intel_sandybridge_d_info), INTEL_VGA_DEVICE(0x0102, &intel_sandybridge_d_info),
INTEL_VGA_DEVICE(0x0112, &intel_sandybridge_d_info),
INTEL_VGA_DEVICE(0x0122, &intel_sandybridge_d_info),
INTEL_VGA_DEVICE(0x0106, &intel_sandybridge_m_info), INTEL_VGA_DEVICE(0x0106, &intel_sandybridge_m_info),
INTEL_VGA_DEVICE(0x0116, &intel_sandybridge_m_info),
INTEL_VGA_DEVICE(0x0126, &intel_sandybridge_m_info), INTEL_VGA_DEVICE(0x0126, &intel_sandybridge_m_info),
INTEL_VGA_DEVICE(0x010A, &intel_sandybridge_d_info),
{0, 0, 0} {0, 0, 0}
}; };
......
...@@ -191,6 +191,7 @@ struct drm_i915_display_funcs { ...@@ -191,6 +191,7 @@ struct drm_i915_display_funcs {
}; };
struct intel_device_info { struct intel_device_info {
u8 gen;
u8 is_mobile : 1; u8 is_mobile : 1;
u8 is_i8xx : 1; u8 is_i8xx : 1;
u8 is_i85x : 1; u8 is_i85x : 1;
...@@ -206,7 +207,6 @@ struct intel_device_info { ...@@ -206,7 +207,6 @@ struct intel_device_info {
u8 is_broadwater : 1; u8 is_broadwater : 1;
u8 is_crestline : 1; u8 is_crestline : 1;
u8 is_ironlake : 1; u8 is_ironlake : 1;
u8 is_gen6 : 1;
u8 has_fbc : 1; u8 has_fbc : 1;
u8 has_rc6 : 1; u8 has_rc6 : 1;
u8 has_pipe_cxsr : 1; u8 has_pipe_cxsr : 1;
...@@ -1162,7 +1162,6 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove ...@@ -1162,7 +1162,6 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove
#define IS_845G(dev) ((dev)->pci_device == 0x2562) #define IS_845G(dev) ((dev)->pci_device == 0x2562)
#define IS_I85X(dev) (INTEL_INFO(dev)->is_i85x) #define IS_I85X(dev) (INTEL_INFO(dev)->is_i85x)
#define IS_I865G(dev) ((dev)->pci_device == 0x2572) #define IS_I865G(dev) ((dev)->pci_device == 0x2572)
#define IS_GEN2(dev) (INTEL_INFO(dev)->is_i8xx)
#define IS_I915G(dev) (INTEL_INFO(dev)->is_i915g) #define IS_I915G(dev) (INTEL_INFO(dev)->is_i915g)
#define IS_I915GM(dev) ((dev)->pci_device == 0x2592) #define IS_I915GM(dev) ((dev)->pci_device == 0x2592)
#define IS_I945G(dev) ((dev)->pci_device == 0x2772) #define IS_I945G(dev) ((dev)->pci_device == 0x2772)
...@@ -1181,27 +1180,13 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove ...@@ -1181,27 +1180,13 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove
#define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046) #define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046)
#define IS_IRONLAKE(dev) (INTEL_INFO(dev)->is_ironlake) #define IS_IRONLAKE(dev) (INTEL_INFO(dev)->is_ironlake)
#define IS_I9XX(dev) (INTEL_INFO(dev)->is_i9xx) #define IS_I9XX(dev) (INTEL_INFO(dev)->is_i9xx)
#define IS_GEN6(dev) (INTEL_INFO(dev)->is_gen6)
#define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile)
#define IS_GEN3(dev) (IS_I915G(dev) || \ #define IS_GEN2(dev) (INTEL_INFO(dev)->gen == 2)
IS_I915GM(dev) || \ #define IS_GEN3(dev) (INTEL_INFO(dev)->gen == 3)
IS_I945G(dev) || \ #define IS_GEN4(dev) (INTEL_INFO(dev)->gen == 4)
IS_I945GM(dev) || \ #define IS_GEN5(dev) (INTEL_INFO(dev)->gen == 5)
IS_G33(dev) || \ #define IS_GEN6(dev) (INTEL_INFO(dev)->gen == 6)
IS_PINEVIEW(dev))
#define IS_GEN4(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 || \
(dev)->pci_device == 0x2E02 || \
(dev)->pci_device == 0x2E12 || \
(dev)->pci_device == 0x2E22 || \
(dev)->pci_device == 0x2E32 || \
(dev)->pci_device == 0x2A42 || \
(dev)->pci_device == 0x2E42)
#define HAS_BSD(dev) (IS_IRONLAKE(dev) || IS_G4X(dev)) #define HAS_BSD(dev) (IS_IRONLAKE(dev) || IS_G4X(dev))
#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/intel-gtt.h>
static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj); static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj);
static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
...@@ -135,12 +136,15 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, ...@@ -135,12 +136,15 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
return -ENOMEM; return -ENOMEM;
ret = drm_gem_handle_create(file_priv, obj, &handle); ret = drm_gem_handle_create(file_priv, obj, &handle);
if (ret) {
drm_gem_object_unreference_unlocked(obj); drm_gem_object_unreference_unlocked(obj);
if (ret)
return ret; return ret;
}
args->handle = handle; /* Sink the floating reference from kref_init(handlecount) */
drm_gem_object_handle_unreference_unlocked(obj);
args->handle = handle;
return 0; return 0;
} }
...@@ -3585,6 +3589,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, ...@@ -3585,6 +3589,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
if (ret != 0) { if (ret != 0) {
DRM_ERROR("copy %d cliprects failed: %d\n", DRM_ERROR("copy %d cliprects failed: %d\n",
args->num_cliprects, ret); args->num_cliprects, ret);
ret = -EFAULT;
goto pre_mutex_err; goto pre_mutex_err;
} }
} }
......
...@@ -887,6 +887,49 @@ static void i915_handle_error(struct drm_device *dev, bool wedged) ...@@ -887,6 +887,49 @@ static void i915_handle_error(struct drm_device *dev, bool wedged)
queue_work(dev_priv->wq, &dev_priv->error_work); queue_work(dev_priv->wq, &dev_priv->error_work);
} }
static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct drm_i915_gem_object *obj_priv;
struct intel_unpin_work *work;
unsigned long flags;
bool stall_detected;
/* Ignore early vblank irqs */
if (intel_crtc == NULL)
return;
spin_lock_irqsave(&dev->event_lock, flags);
work = intel_crtc->unpin_work;
if (work == NULL || work->pending || !work->enable_stall_check) {
/* Either the pending flip IRQ arrived, or we're too early. Don't check */
spin_unlock_irqrestore(&dev->event_lock, flags);
return;
}
/* Potential stall - if we see that the flip has happened, assume a missed interrupt */
obj_priv = to_intel_bo(work->pending_flip_obj);
if(IS_I965G(dev)) {
int dspsurf = intel_crtc->plane == 0 ? DSPASURF : DSPBSURF;
stall_detected = I915_READ(dspsurf) == obj_priv->gtt_offset;
} else {
int dspaddr = intel_crtc->plane == 0 ? DSPAADDR : DSPBADDR;
stall_detected = I915_READ(dspaddr) == (obj_priv->gtt_offset +
crtc->y * crtc->fb->pitch +
crtc->x * crtc->fb->bits_per_pixel/8);
}
spin_unlock_irqrestore(&dev->event_lock, flags);
if (stall_detected) {
DRM_DEBUG_DRIVER("Pageflip stall detected\n");
intel_prepare_page_flip(dev, intel_crtc->plane);
}
}
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
{ {
struct drm_device *dev = (struct drm_device *) arg; struct drm_device *dev = (struct drm_device *) arg;
...@@ -1004,16 +1047,20 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) ...@@ -1004,16 +1047,20 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
if (pipea_stats & vblank_status) { if (pipea_stats & vblank_status) {
vblank++; vblank++;
drm_handle_vblank(dev, 0); drm_handle_vblank(dev, 0);
if (!dev_priv->flip_pending_is_done) if (!dev_priv->flip_pending_is_done) {
i915_pageflip_stall_check(dev, 0);
intel_finish_page_flip(dev, 0); intel_finish_page_flip(dev, 0);
} }
}
if (pipeb_stats & vblank_status) { if (pipeb_stats & vblank_status) {
vblank++; vblank++;
drm_handle_vblank(dev, 1); drm_handle_vblank(dev, 1);
if (!dev_priv->flip_pending_is_done) if (!dev_priv->flip_pending_is_done) {
i915_pageflip_stall_check(dev, 1);
intel_finish_page_flip(dev, 1); intel_finish_page_flip(dev, 1);
} }
}
if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
(pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || (pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
......
...@@ -319,6 +319,7 @@ ...@@ -319,6 +319,7 @@
#define MI_MODE 0x0209c #define MI_MODE 0x0209c
# define VS_TIMER_DISPATCH (1 << 6) # define VS_TIMER_DISPATCH (1 << 6)
# define MI_FLUSH_ENABLE (1 << 11)
#define SCPD0 0x0209c /* 915+ only */ #define SCPD0 0x0209c /* 915+ only */
#define IER 0x020a0 #define IER 0x020a0
......
...@@ -990,6 +990,22 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe) ...@@ -990,6 +990,22 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
int pipestat_reg = (pipe == 0 ? PIPEASTAT : PIPEBSTAT); int pipestat_reg = (pipe == 0 ? PIPEASTAT : PIPEBSTAT);
/* Clear existing vblank status. Note this will clear any other
* sticky status fields as well.
*
* This races with i915_driver_irq_handler() with the result
* that either function could miss a vblank event. Here it is not
* fatal, as we will either wait upon the next vblank interrupt or
* timeout. Generally speaking intel_wait_for_vblank() is only
* called during modeset at which time the GPU should be idle and
* should *not* be performing page flips and thus not waiting on
* vblanks...
* Currently, the result of us stealing a vblank from the irq
* handler is that a single frame will be skipped during swapbuffers.
*/
I915_WRITE(pipestat_reg,
I915_READ(pipestat_reg) | PIPE_VBLANK_INTERRUPT_STATUS);
/* Wait for vblank interrupt bit to set */ /* Wait for vblank interrupt bit to set */
if (wait_for((I915_READ(pipestat_reg) & if (wait_for((I915_READ(pipestat_reg) &
PIPE_VBLANK_INTERRUPT_STATUS), PIPE_VBLANK_INTERRUPT_STATUS),
...@@ -1486,7 +1502,7 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -1486,7 +1502,7 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
dspcntr &= ~DISPPLANE_TILED; dspcntr &= ~DISPPLANE_TILED;
} }
if (IS_IRONLAKE(dev)) if (HAS_PCH_SPLIT(dev))
/* must disable */ /* must disable */
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
...@@ -1495,20 +1511,19 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -1495,20 +1511,19 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
Start = obj_priv->gtt_offset; Start = obj_priv->gtt_offset;
Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8); Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8);
DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
Start, Offset, x, y, fb->pitch);
I915_WRITE(dspstride, fb->pitch); I915_WRITE(dspstride, fb->pitch);
if (IS_I965G(dev)) { if (IS_I965G(dev)) {
I915_WRITE(dspbase, Offset);
I915_READ(dspbase);
I915_WRITE(dspsurf, Start); I915_WRITE(dspsurf, Start);
I915_READ(dspsurf);
I915_WRITE(dsptileoff, (y << 16) | x); I915_WRITE(dsptileoff, (y << 16) | x);
I915_WRITE(dspbase, Offset);
} else { } else {
I915_WRITE(dspbase, Start + Offset); I915_WRITE(dspbase, Start + Offset);
I915_READ(dspbase);
} }
POSTING_READ(dspbase);
if ((IS_I965G(dev) || plane == 0)) if (IS_I965G(dev) || plane == 0)
intel_update_fbc(crtc, &crtc->mode); intel_update_fbc(crtc, &crtc->mode);
intel_wait_for_vblank(dev, intel_crtc->pipe); intel_wait_for_vblank(dev, intel_crtc->pipe);
...@@ -1522,7 +1537,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, ...@@ -1522,7 +1537,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb) struct drm_framebuffer *old_fb)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv; struct drm_i915_master_private *master_priv;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_framebuffer *intel_fb; struct intel_framebuffer *intel_fb;
...@@ -1530,13 +1544,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, ...@@ -1530,13 +1544,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_gem_object *obj; struct drm_gem_object *obj;
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane; int plane = intel_crtc->plane;
unsigned long Start, Offset;
int dspbase = (plane == 0 ? DSPAADDR : DSPBADDR);
int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF);
int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE;
int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF);
int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
u32 dspcntr;
int ret; int ret;
/* no fb bound */ /* no fb bound */
...@@ -1572,71 +1579,18 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, ...@@ -1572,71 +1579,18 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
return ret; return ret;
} }
dspcntr = I915_READ(dspcntr_reg); ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y);
/* Mask out pixel format bits in case we change it */ if (ret) {
dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
switch (crtc->fb->bits_per_pixel) {
case 8:
dspcntr |= DISPPLANE_8BPP;
break;
case 16:
if (crtc->fb->depth == 15)
dspcntr |= DISPPLANE_15_16BPP;
else
dspcntr |= DISPPLANE_16BPP;
break;
case 24:
case 32:
if (crtc->fb->depth == 30)
dspcntr |= DISPPLANE_32BPP_30BIT_NO_ALPHA;
else
dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
break;
default:
DRM_ERROR("Unknown color depth\n");
i915_gem_object_unpin(obj); i915_gem_object_unpin(obj);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return -EINVAL; return ret;
}
if (IS_I965G(dev)) {
if (obj_priv->tiling_mode != I915_TILING_NONE)
dspcntr |= DISPPLANE_TILED;
else
dspcntr &= ~DISPPLANE_TILED;
}
if (HAS_PCH_SPLIT(dev))
/* must disable */
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
I915_WRITE(dspcntr_reg, dspcntr);
Start = obj_priv->gtt_offset;
Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
Start, Offset, x, y, crtc->fb->pitch);
I915_WRITE(dspstride, crtc->fb->pitch);
if (IS_I965G(dev)) {
I915_WRITE(dspsurf, Start);
I915_WRITE(dsptileoff, (y << 16) | x);
I915_WRITE(dspbase, Offset);
} else {
I915_WRITE(dspbase, Start + Offset);
} }
POSTING_READ(dspbase);
if ((IS_I965G(dev) || plane == 0))
intel_update_fbc(crtc, &crtc->mode);
intel_wait_for_vblank(dev, pipe);
if (old_fb) { if (old_fb) {
intel_fb = to_intel_framebuffer(old_fb); intel_fb = to_intel_framebuffer(old_fb);
obj_priv = to_intel_bo(intel_fb->obj); obj_priv = to_intel_bo(intel_fb->obj);
i915_gem_object_unpin(intel_fb->obj); i915_gem_object_unpin(intel_fb->obj);
} }
intel_increase_pllclock(crtc, true);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
...@@ -1911,9 +1865,6 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -1911,9 +1865,6 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL; int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL; int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF; int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1;
int pf_win_size = (pipe == 0) ? PFA_WIN_SZ : PFB_WIN_SZ;
int pf_win_pos = (pipe == 0) ? PFA_WIN_POS : PFB_WIN_POS;
int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
...@@ -1982,15 +1933,19 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -1982,15 +1933,19 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
} }
/* Enable panel fitting for LVDS */ /* Enable panel fitting for LVDS */
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) if (dev_priv->pch_pf_size &&
|| HAS_eDP || intel_pch_has_edp(crtc)) { (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)
if (dev_priv->pch_pf_size) { || HAS_eDP || intel_pch_has_edp(crtc))) {
temp = I915_READ(pf_ctl_reg); /* Force use of hard-coded filter coefficients
I915_WRITE(pf_ctl_reg, temp | PF_ENABLE | PF_FILTER_MED_3x3); * as some pre-programmed values are broken,
I915_WRITE(pf_win_pos, dev_priv->pch_pf_pos); * e.g. x201.
I915_WRITE(pf_win_size, dev_priv->pch_pf_size); */
} else I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1,
I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE); PF_ENABLE | PF_FILTER_MED_3x3);
I915_WRITE(pipe ? PFB_WIN_POS : PFA_WIN_POS,
dev_priv->pch_pf_pos);
I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ,
dev_priv->pch_pf_size);
} }
/* Enable CPU pipe */ /* Enable CPU pipe */
...@@ -2115,7 +2070,7 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -2115,7 +2070,7 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
I915_WRITE(transconf_reg, temp | TRANS_ENABLE); I915_WRITE(transconf_reg, temp | TRANS_ENABLE);
I915_READ(transconf_reg); I915_READ(transconf_reg);
if (wait_for(I915_READ(transconf_reg) & TRANS_STATE_ENABLE, 10, 0)) if (wait_for(I915_READ(transconf_reg) & TRANS_STATE_ENABLE, 100, 1))
DRM_ERROR("failed to enable transcoder\n"); DRM_ERROR("failed to enable transcoder\n");
} }
...@@ -2155,14 +2110,8 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -2155,14 +2110,8 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
udelay(100); udelay(100);
/* Disable PF */ /* Disable PF */
temp = I915_READ(pf_ctl_reg); I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0);
if ((temp & PF_ENABLE) != 0) { I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, 0);
I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE);
I915_READ(pf_ctl_reg);
}
I915_WRITE(pf_win_size, 0);
POSTING_READ(pf_win_size);
/* disable CPU FDI tx and PCH FDI rx */ /* disable CPU FDI tx and PCH FDI rx */
temp = I915_READ(fdi_tx_reg); temp = I915_READ(fdi_tx_reg);
...@@ -2421,6 +2370,9 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -2421,6 +2370,9 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
bool enabled; bool enabled;
if (intel_crtc->dpms_mode == mode)
return;
intel_crtc->dpms_mode = mode; intel_crtc->dpms_mode = mode;
intel_crtc->cursor_on = mode == DRM_MODE_DPMS_ON; intel_crtc->cursor_on = mode == DRM_MODE_DPMS_ON;
...@@ -3554,10 +3506,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3554,10 +3506,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
u32 dpll = 0, fp = 0, fp2 = 0, dspcntr, pipeconf; u32 dpll = 0, fp = 0, fp2 = 0, dspcntr, pipeconf;
bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false; bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false;
bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
bool is_edp = false; struct intel_encoder *has_edp_encoder = NULL;
struct drm_mode_config *mode_config = &dev->mode_config; struct drm_mode_config *mode_config = &dev->mode_config;
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct intel_encoder *intel_encoder = NULL;
const intel_limit_t *limit; const intel_limit_t *limit;
int ret; int ret;
struct fdi_m_n m_n = {0}; struct fdi_m_n m_n = {0};
...@@ -3578,12 +3529,12 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3578,12 +3529,12 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
drm_vblank_pre_modeset(dev, pipe); drm_vblank_pre_modeset(dev, pipe);
list_for_each_entry(encoder, &mode_config->encoder_list, head) { list_for_each_entry(encoder, &mode_config->encoder_list, head) {
struct intel_encoder *intel_encoder;
if (!encoder || encoder->crtc != crtc) if (encoder->crtc != crtc)
continue; continue;
intel_encoder = enc_to_intel_encoder(encoder); intel_encoder = enc_to_intel_encoder(encoder);
switch (intel_encoder->type) { switch (intel_encoder->type) {
case INTEL_OUTPUT_LVDS: case INTEL_OUTPUT_LVDS:
is_lvds = true; is_lvds = true;
...@@ -3607,7 +3558,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3607,7 +3558,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
is_dp = true; is_dp = true;
break; break;
case INTEL_OUTPUT_EDP: case INTEL_OUTPUT_EDP:
is_edp = true; has_edp_encoder = intel_encoder;
break; break;
} }
...@@ -3685,9 +3636,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3685,9 +3636,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
int lane = 0, link_bw, bpp; int lane = 0, link_bw, bpp;
/* eDP doesn't require FDI link, so just set DP M/N /* eDP doesn't require FDI link, so just set DP M/N
according to current link config */ according to current link config */
if (is_edp) { if (has_edp_encoder) {
target_clock = mode->clock; target_clock = mode->clock;
intel_edp_link_config(intel_encoder, intel_edp_link_config(has_edp_encoder,
&lane, &link_bw); &lane, &link_bw);
} else { } else {
/* DP over FDI requires target mode clock /* DP over FDI requires target mode clock
...@@ -3709,7 +3660,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3709,7 +3660,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
temp |= PIPE_8BPC; temp |= PIPE_8BPC;
else else
temp |= PIPE_6BPC; temp |= PIPE_6BPC;
} else if (is_edp || (is_dp && intel_pch_has_edp(crtc))) { } else if (has_edp_encoder || (is_dp && intel_pch_has_edp(crtc))) {
switch (dev_priv->edp_bpp/3) { switch (dev_priv->edp_bpp/3) {
case 8: case 8:
temp |= PIPE_8BPC; temp |= PIPE_8BPC;
...@@ -3782,7 +3733,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3782,7 +3733,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
udelay(200); udelay(200);
if (is_edp) { if (has_edp_encoder) {
if (dev_priv->lvds_use_ssc) { if (dev_priv->lvds_use_ssc) {
temp |= DREF_SSC1_ENABLE; temp |= DREF_SSC1_ENABLE;
I915_WRITE(PCH_DREF_CONTROL, temp); I915_WRITE(PCH_DREF_CONTROL, temp);
...@@ -3931,7 +3882,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -3931,7 +3882,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
dpll_reg = pch_dpll_reg; dpll_reg = pch_dpll_reg;
} }
if (!is_edp) { if (!has_edp_encoder) {
I915_WRITE(fp_reg, fp); I915_WRITE(fp_reg, fp);
I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
I915_READ(dpll_reg); I915_READ(dpll_reg);
...@@ -4026,7 +3977,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -4026,7 +3977,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
} }
} }
if (!is_edp) { if (!has_edp_encoder) {
I915_WRITE(fp_reg, fp); I915_WRITE(fp_reg, fp);
I915_WRITE(dpll_reg, dpll); I915_WRITE(dpll_reg, dpll);
I915_READ(dpll_reg); I915_READ(dpll_reg);
...@@ -4105,7 +4056,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -4105,7 +4056,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
I915_WRITE(link_m1_reg, m_n.link_m); I915_WRITE(link_m1_reg, m_n.link_m);
I915_WRITE(link_n1_reg, m_n.link_n); I915_WRITE(link_n1_reg, m_n.link_n);
if (is_edp) { if (has_edp_encoder) {
ironlake_set_pll_edp(crtc, adjusted_mode->clock); ironlake_set_pll_edp(crtc, adjusted_mode->clock);
} else { } else {
/* enable FDI RX PLL too */ /* enable FDI RX PLL too */
...@@ -4911,15 +4862,6 @@ static void intel_crtc_destroy(struct drm_crtc *crtc) ...@@ -4911,15 +4862,6 @@ static void intel_crtc_destroy(struct drm_crtc *crtc)
kfree(intel_crtc); kfree(intel_crtc);
} }
struct intel_unpin_work {
struct work_struct work;
struct drm_device *dev;
struct drm_gem_object *old_fb_obj;
struct drm_gem_object *pending_flip_obj;
struct drm_pending_vblank_event *event;
int pending;
};
static void intel_unpin_work_fn(struct work_struct *__work) static void intel_unpin_work_fn(struct work_struct *__work)
{ {
struct intel_unpin_work *work = struct intel_unpin_work *work =
...@@ -5007,7 +4949,8 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane) ...@@ -5007,7 +4949,8 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane)
spin_lock_irqsave(&dev->event_lock, flags); spin_lock_irqsave(&dev->event_lock, flags);
if (intel_crtc->unpin_work) { if (intel_crtc->unpin_work) {
intel_crtc->unpin_work->pending = 1; if ((++intel_crtc->unpin_work->pending) > 1)
DRM_ERROR("Prepared flip multiple times\n");
} else { } else {
DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n"); DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n");
} }
...@@ -5026,9 +4969,9 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, ...@@ -5026,9 +4969,9 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_unpin_work *work; struct intel_unpin_work *work;
unsigned long flags, offset; unsigned long flags, offset;
int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC; int pipe = intel_crtc->pipe;
int ret, pipesrc; u32 pf, pipesrc;
u32 flip_mask; int ret;
work = kzalloc(sizeof *work, GFP_KERNEL); work = kzalloc(sizeof *work, GFP_KERNEL);
if (work == NULL) if (work == NULL)
...@@ -5077,42 +5020,73 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, ...@@ -5077,42 +5020,73 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
atomic_inc(&obj_priv->pending_flip); atomic_inc(&obj_priv->pending_flip);
work->pending_flip_obj = obj; work->pending_flip_obj = obj;
if (IS_GEN3(dev) || IS_GEN2(dev)) {
u32 flip_mask;
if (intel_crtc->plane) if (intel_crtc->plane)
flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
else else
flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
if (IS_GEN3(dev) || IS_GEN2(dev)) {
BEGIN_LP_RING(2); BEGIN_LP_RING(2);
OUT_RING(MI_WAIT_FOR_EVENT | flip_mask); OUT_RING(MI_WAIT_FOR_EVENT | flip_mask);
OUT_RING(0); OUT_RING(0);
ADVANCE_LP_RING(); ADVANCE_LP_RING();
} }
work->enable_stall_check = true;
/* Offset into the new buffer for cases of shared fbs between CRTCs */ /* Offset into the new buffer for cases of shared fbs between CRTCs */
offset = obj_priv->gtt_offset; offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8;
offset += (crtc->y * fb->pitch) + (crtc->x * (fb->bits_per_pixel) / 8);
BEGIN_LP_RING(4); BEGIN_LP_RING(4);
if (IS_I965G(dev)) { switch(INTEL_INFO(dev)->gen) {
case 2:
OUT_RING(MI_DISPLAY_FLIP | OUT_RING(MI_DISPLAY_FLIP |
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
OUT_RING(fb->pitch); OUT_RING(fb->pitch);
OUT_RING(offset | obj_priv->tiling_mode); OUT_RING(obj_priv->gtt_offset + offset);
pipesrc = I915_READ(pipesrc_reg); OUT_RING(MI_NOOP);
OUT_RING(pipesrc & 0x0fff0fff); break;
} else if (IS_GEN3(dev)) {
case 3:
OUT_RING(MI_DISPLAY_FLIP_I915 | OUT_RING(MI_DISPLAY_FLIP_I915 |
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
OUT_RING(fb->pitch); OUT_RING(fb->pitch);
OUT_RING(offset); OUT_RING(obj_priv->gtt_offset + offset);
OUT_RING(MI_NOOP); OUT_RING(MI_NOOP);
} else { break;
case 4:
case 5:
/* i965+ uses the linear or tiled offsets from the
* Display Registers (which do not change across a page-flip)
* so we need only reprogram the base address.
*/
OUT_RING(MI_DISPLAY_FLIP | OUT_RING(MI_DISPLAY_FLIP |
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
OUT_RING(fb->pitch); OUT_RING(fb->pitch);
OUT_RING(offset); OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode);
OUT_RING(MI_NOOP);
/* XXX Enabling the panel-fitter across page-flip is so far
* untested on non-native modes, so ignore it for now.
* pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
*/
pf = 0;
pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff;
OUT_RING(pf | pipesrc);
break;
case 6:
OUT_RING(MI_DISPLAY_FLIP |
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
OUT_RING(fb->pitch | obj_priv->tiling_mode);
OUT_RING(obj_priv->gtt_offset);
pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff;
OUT_RING(pf | pipesrc);
break;
} }
ADVANCE_LP_RING(); ADVANCE_LP_RING();
...@@ -5193,7 +5167,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) ...@@ -5193,7 +5167,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base; dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
intel_crtc->cursor_addr = 0; intel_crtc->cursor_addr = 0;
intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF; intel_crtc->dpms_mode = -1;
drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
intel_crtc->busy = false; intel_crtc->busy = false;
......
...@@ -239,7 +239,6 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, ...@@ -239,7 +239,6 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
uint32_t ch_data = ch_ctl + 4; uint32_t ch_data = ch_ctl + 4;
int i; int i;
int recv_bytes; int recv_bytes;
uint32_t ctl;
uint32_t status; uint32_t status;
uint32_t aux_clock_divider; uint32_t aux_clock_divider;
int try, precharge; int try, precharge;
...@@ -263,16 +262,22 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, ...@@ -263,16 +262,22 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
else else
precharge = 5; precharge = 5;
if (I915_READ(ch_ctl) & DP_AUX_CH_CTL_SEND_BUSY) {
DRM_ERROR("dp_aux_ch not started status 0x%08x\n",
I915_READ(ch_ctl));
return -EBUSY;
}
/* Must try at least 3 times according to DP spec */ /* Must try at least 3 times according to DP spec */
for (try = 0; try < 5; try++) { for (try = 0; try < 5; try++) {
/* Load the send data into the aux channel data registers */ /* Load the send data into the aux channel data registers */
for (i = 0; i < send_bytes; i += 4) { for (i = 0; i < send_bytes; i += 4)
uint32_t d = pack_aux(send + i, send_bytes - i); I915_WRITE(ch_data + i,
pack_aux(send + i, send_bytes - i));
I915_WRITE(ch_data + i, d); /* Send the command and wait for it to complete */
} I915_WRITE(ch_ctl,
DP_AUX_CH_CTL_SEND_BUSY |
ctl = (DP_AUX_CH_CTL_SEND_BUSY |
DP_AUX_CH_CTL_TIME_OUT_400us | DP_AUX_CH_CTL_TIME_OUT_400us |
(send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
(precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
...@@ -280,24 +285,20 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, ...@@ -280,24 +285,20 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
DP_AUX_CH_CTL_DONE | DP_AUX_CH_CTL_DONE |
DP_AUX_CH_CTL_TIME_OUT_ERROR | DP_AUX_CH_CTL_TIME_OUT_ERROR |
DP_AUX_CH_CTL_RECEIVE_ERROR); DP_AUX_CH_CTL_RECEIVE_ERROR);
/* Send the command and wait for it to complete */
I915_WRITE(ch_ctl, ctl);
(void) I915_READ(ch_ctl);
for (;;) { for (;;) {
udelay(100);
status = I915_READ(ch_ctl); status = I915_READ(ch_ctl);
if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
break; break;
udelay(100);
} }
/* Clear done status and any errors */ /* Clear done status and any errors */
I915_WRITE(ch_ctl, (status | I915_WRITE(ch_ctl,
status |
DP_AUX_CH_CTL_DONE | DP_AUX_CH_CTL_DONE |
DP_AUX_CH_CTL_TIME_OUT_ERROR | DP_AUX_CH_CTL_TIME_OUT_ERROR |
DP_AUX_CH_CTL_RECEIVE_ERROR)); DP_AUX_CH_CTL_RECEIVE_ERROR);
(void) I915_READ(ch_ctl); if (status & DP_AUX_CH_CTL_DONE)
if ((status & DP_AUX_CH_CTL_TIME_OUT_ERROR) == 0)
break; break;
} }
...@@ -324,15 +325,12 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, ...@@ -324,15 +325,12 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
/* Unload any bytes sent back from the other side */ /* Unload any bytes sent back from the other side */
recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >>
DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
if (recv_bytes > recv_size) if (recv_bytes > recv_size)
recv_bytes = recv_size; recv_bytes = recv_size;
for (i = 0; i < recv_bytes; i += 4) { for (i = 0; i < recv_bytes; i += 4)
uint32_t d = I915_READ(ch_data + i); unpack_aux(I915_READ(ch_data + i),
recv + i, recv_bytes - i);
unpack_aux(d, recv + i, recv_bytes - i);
}
return recv_bytes; return recv_bytes;
} }
......
...@@ -176,6 +176,16 @@ struct intel_crtc { ...@@ -176,6 +176,16 @@ struct intel_crtc {
#define enc_to_intel_encoder(x) container_of(x, struct intel_encoder, enc) #define enc_to_intel_encoder(x) container_of(x, struct intel_encoder, enc)
#define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
struct intel_unpin_work {
struct work_struct work;
struct drm_device *dev;
struct drm_gem_object *old_fb_obj;
struct drm_gem_object *pending_flip_obj;
struct drm_pending_vblank_event *event;
int pending;
bool enable_stall_check;
};
struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
const char *name); const char *name);
void intel_i2c_destroy(struct i2c_adapter *adapter); void intel_i2c_destroy(struct i2c_adapter *adapter);
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
* *
* Derived from Xorg ddx, xf86-video-intel, src/i830_video.c * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c
*/ */
#include <linux/seq_file.h>
#include "drmP.h" #include "drmP.h"
#include "drm.h" #include "drm.h"
#include "i915_drm.h" #include "i915_drm.h"
......
...@@ -220,9 +220,13 @@ static int init_render_ring(struct drm_device *dev, ...@@ -220,9 +220,13 @@ static int init_render_ring(struct drm_device *dev,
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
int ret = init_ring_common(dev, ring); int ret = init_ring_common(dev, ring);
int mode;
if (IS_I9XX(dev) && !IS_GEN3(dev)) { if (IS_I9XX(dev) && !IS_GEN3(dev)) {
I915_WRITE(MI_MODE, mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH;
(VS_TIMER_DISPATCH) << 16 | VS_TIMER_DISPATCH); if (IS_GEN6(dev))
mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE;
I915_WRITE(MI_MODE, mode);
} }
return ret; return ret;
} }
......
...@@ -1061,8 +1061,9 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, ...@@ -1061,8 +1061,9 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode)) if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode))
return false; return false;
if (!intel_sdvo_set_input_timings_for_mode(intel_sdvo, mode, adjusted_mode)) (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo,
return false; mode,
adjusted_mode);
} else if (intel_sdvo->is_lvds) { } else if (intel_sdvo->is_lvds) {
drm_mode_set_crtcinfo(intel_sdvo->sdvo_lvds_fixed_mode, 0); drm_mode_set_crtcinfo(intel_sdvo->sdvo_lvds_fixed_mode, 0);
...@@ -1070,8 +1071,9 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, ...@@ -1070,8 +1071,9 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
intel_sdvo->sdvo_lvds_fixed_mode)) intel_sdvo->sdvo_lvds_fixed_mode))
return false; return false;
if (!intel_sdvo_set_input_timings_for_mode(intel_sdvo, mode, adjusted_mode)) (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo,
return false; mode,
adjusted_mode);
} }
/* Make the CRTC code factor in the SDVO pixel multiplier. The /* Make the CRTC code factor in the SDVO pixel multiplier. The
...@@ -1108,10 +1110,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, ...@@ -1108,10 +1110,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
in_out.in0 = intel_sdvo->attached_output; in_out.in0 = intel_sdvo->attached_output;
in_out.in1 = 0; in_out.in1 = 0;
if (!intel_sdvo_set_value(intel_sdvo, intel_sdvo_set_value(intel_sdvo,
SDVO_CMD_SET_IN_OUT_MAP, SDVO_CMD_SET_IN_OUT_MAP,
&in_out, sizeof(in_out))) &in_out, sizeof(in_out));
return;
if (intel_sdvo->is_hdmi) { if (intel_sdvo->is_hdmi) {
if (!intel_sdvo_set_avi_infoframe(intel_sdvo, mode)) if (!intel_sdvo_set_avi_infoframe(intel_sdvo, mode))
...@@ -1122,11 +1123,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, ...@@ -1122,11 +1123,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
/* We have tried to get input timing in mode_fixup, and filled into /* We have tried to get input timing in mode_fixup, and filled into
adjusted_mode */ adjusted_mode */
if (intel_sdvo->is_tv || intel_sdvo->is_lvds) {
intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
if (intel_sdvo->is_tv || intel_sdvo->is_lvds)
input_dtd.part2.sdvo_flags = intel_sdvo->sdvo_flags; input_dtd.part2.sdvo_flags = intel_sdvo->sdvo_flags;
} else
intel_sdvo_get_dtd_from_mode(&input_dtd, mode);
/* If it's a TV, we already set the output timing in mode_fixup. /* If it's a TV, we already set the output timing in mode_fixup.
* Otherwise, the output timing is equal to the input timing. * Otherwise, the output timing is equal to the input timing.
...@@ -1137,8 +1136,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, ...@@ -1137,8 +1136,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
intel_sdvo->attached_output)) intel_sdvo->attached_output))
return; return;
if (!intel_sdvo_set_output_timing(intel_sdvo, &input_dtd)) (void) intel_sdvo_set_output_timing(intel_sdvo, &input_dtd);
return;
} }
/* Set the input timing to the screen. Assume always input 0. */ /* Set the input timing to the screen. Assume always input 0. */
...@@ -1165,8 +1163,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, ...@@ -1165,8 +1163,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
intel_sdvo_set_input_timing(encoder, &input_dtd); intel_sdvo_set_input_timing(encoder, &input_dtd);
} }
#else #else
if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd)) (void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd);
return;
#endif #endif
sdvo_pixel_multiply = intel_sdvo_get_pixel_multiplier(mode); sdvo_pixel_multiply = intel_sdvo_get_pixel_multiplier(mode);
...@@ -1932,6 +1929,41 @@ static const struct drm_encoder_funcs intel_sdvo_enc_funcs = { ...@@ -1932,6 +1929,41 @@ static const struct drm_encoder_funcs intel_sdvo_enc_funcs = {
.destroy = intel_sdvo_enc_destroy, .destroy = intel_sdvo_enc_destroy,
}; };
static void
intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo)
{
uint16_t mask = 0;
unsigned int num_bits;
/* Make a mask of outputs less than or equal to our own priority in the
* list.
*/
switch (sdvo->controlled_output) {
case SDVO_OUTPUT_LVDS1:
mask |= SDVO_OUTPUT_LVDS1;
case SDVO_OUTPUT_LVDS0:
mask |= SDVO_OUTPUT_LVDS0;
case SDVO_OUTPUT_TMDS1:
mask |= SDVO_OUTPUT_TMDS1;
case SDVO_OUTPUT_TMDS0:
mask |= SDVO_OUTPUT_TMDS0;
case SDVO_OUTPUT_RGB1:
mask |= SDVO_OUTPUT_RGB1;
case SDVO_OUTPUT_RGB0:
mask |= SDVO_OUTPUT_RGB0;
break;
}
/* Count bits to find what number we are in the priority list. */
mask &= sdvo->caps.output_flags;
num_bits = hweight16(mask);
/* If more than 3 outputs, default to DDC bus 3 for now. */
if (num_bits > 3)
num_bits = 3;
/* Corresponds to SDVO_CONTROL_BUS_DDCx */
sdvo->ddc_bus = 1 << num_bits;
}
/** /**
* Choose the appropriate DDC bus for control bus switch command for this * Choose the appropriate DDC bus for control bus switch command for this
...@@ -1951,7 +1983,10 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv, ...@@ -1951,7 +1983,10 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv,
else else
mapping = &(dev_priv->sdvo_mappings[1]); mapping = &(dev_priv->sdvo_mappings[1]);
if (mapping->initialized)
sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4); sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4);
else
intel_sdvo_guess_ddc_bus(sdvo);
} }
static bool static bool
......
...@@ -1231,7 +1231,6 @@ intel_tv_detect_type (struct intel_tv *intel_tv) ...@@ -1231,7 +1231,6 @@ intel_tv_detect_type (struct intel_tv *intel_tv)
struct drm_encoder *encoder = &intel_tv->base.enc; struct drm_encoder *encoder = &intel_tv->base.enc;
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
unsigned long irqflags; unsigned long irqflags;
u32 tv_ctl, save_tv_ctl; u32 tv_ctl, save_tv_ctl;
u32 tv_dac, save_tv_dac; u32 tv_dac, save_tv_dac;
...@@ -1268,11 +1267,15 @@ intel_tv_detect_type (struct intel_tv *intel_tv) ...@@ -1268,11 +1267,15 @@ intel_tv_detect_type (struct intel_tv *intel_tv)
DAC_C_0_7_V); DAC_C_0_7_V);
I915_WRITE(TV_CTL, tv_ctl); I915_WRITE(TV_CTL, tv_ctl);
I915_WRITE(TV_DAC, tv_dac); I915_WRITE(TV_DAC, tv_dac);
intel_wait_for_vblank(dev, intel_crtc->pipe); POSTING_READ(TV_DAC);
msleep(20);
tv_dac = I915_READ(TV_DAC); tv_dac = I915_READ(TV_DAC);
I915_WRITE(TV_DAC, save_tv_dac); I915_WRITE(TV_DAC, save_tv_dac);
I915_WRITE(TV_CTL, save_tv_ctl); I915_WRITE(TV_CTL, save_tv_ctl);
intel_wait_for_vblank(dev, intel_crtc->pipe); POSTING_READ(TV_CTL);
msleep(20);
/* /*
* A B C * A B C
* 0 1 1 Composite * 0 1 1 Composite
......
/*
* Common Intel AGPGART and GTT definitions.
*/
#ifndef _INTEL_GTT_H
#define _INTEL_GTT_H
#include <linux/agp_backend.h>
/* This is for Intel only GTT controls.
*
* Sandybridge: AGP_USER_CACHED_MEMORY default to LLC only
*/
#define AGP_USER_CACHED_MEMORY_LLC_MLC (AGP_USER_TYPES + 2)
#define AGP_USER_UNCACHED_MEMORY (AGP_USER_TYPES + 4)
/* flag for GFDT type */
#define AGP_USER_CACHED_MEMORY_GFDT (1 << 3)
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment