Commit b5cc6c03 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-next-2012-12-21' of...

Merge tag 'drm-intel-next-2012-12-21' of git://people.freedesktop.org/~danvet/drm-intel into drm-next

Daniel writes:
- seqno wrap fixes and debug infrastructure from Mika Kuoppala and Chris
  Wilson
- some leftover kill-agp on gen6+ patches from Ben
- hotplug improvements from Damien
- clear fb when allocated from stolen, avoids dirt on the fbcon (Chris)
- Stolen mem support from Chris Wilson, one of the many steps to get to
  real fastboot support.
- Some DDI code cleanups from Paulo.
- Some refactorings around lvds and dp code.
- some random little bits&pieces

* tag 'drm-intel-next-2012-12-21' of git://people.freedesktop.org/~danvet/drm-intel: (93 commits)
  drm/i915: Return the real error code from intel_set_mode()
  drm/i915: Make GSM void
  drm/i915: Move GSM mapping into dev_priv
  drm/i915: Move even more gtt code to i915_gem_gtt
  drm/i915: Make next_seqno debugs entry to use i915_gem_set_seqno
  drm/i915: Introduce i915_gem_set_seqno()
  drm/i915: Always clear semaphore mboxes on seqno wrap
  drm/i915: Initialize hardware semaphore state on ring init
  drm/i915: Introduce ring set_seqno
  drm/i915: Missed conversion to gtt_pte_t
  drm/i915: Bug on unsupported swizzled platforms
  drm/i915: BUG() if fences are used on unsupported platform
  drm/i915: fixup overlay stolen memory leak
  drm/i915: clean up PIPECONF bpc #defines
  drm/i915: add intel_dp_set_signal_levels
  drm/i915: remove leftover display.update_wm assignment
  drm/i915: check for the PCH when setting pch_transcoder
  drm/i915: Clear the stolen fb before enabling
  drm/i915: Access to snooped system memory through the GTT is incoherent
  drm/i915: Remove stale comment about intel_dp_detect()
  ...

Conflicts:
	drivers/gpu/drm/i915/intel_display.c
parents 9931faca c0c36b94
...@@ -602,7 +602,6 @@ static int intel_gtt_init(void) ...@@ -602,7 +602,6 @@ static int intel_gtt_init(void)
iounmap(intel_private.registers); iounmap(intel_private.registers);
return -ENOMEM; return -ENOMEM;
} }
intel_private.base.gtt = intel_private.gtt;
global_cache_flush(); /* FIXME: ? */ global_cache_flush(); /* FIXME: ? */
......
...@@ -102,20 +102,6 @@ int drm_mm_pre_get(struct drm_mm *mm) ...@@ -102,20 +102,6 @@ int drm_mm_pre_get(struct drm_mm *mm)
} }
EXPORT_SYMBOL(drm_mm_pre_get); EXPORT_SYMBOL(drm_mm_pre_get);
static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node)
{
return hole_node->start + hole_node->size;
}
static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
{
struct drm_mm_node *next_node =
list_entry(hole_node->node_list.next, struct drm_mm_node,
node_list);
return next_node->start;
}
static void drm_mm_insert_helper(struct drm_mm_node *hole_node, static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
struct drm_mm_node *node, struct drm_mm_node *node,
unsigned long size, unsigned alignment, unsigned long size, unsigned alignment,
...@@ -127,7 +113,7 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, ...@@ -127,7 +113,7 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
unsigned long adj_start = hole_start; unsigned long adj_start = hole_start;
unsigned long adj_end = hole_end; unsigned long adj_end = hole_end;
BUG_ON(!hole_node->hole_follows || node->allocated); BUG_ON(node->allocated);
if (mm->color_adjust) if (mm->color_adjust)
mm->color_adjust(hole_node, color, &adj_start, &adj_end); mm->color_adjust(hole_node, color, &adj_start, &adj_end);
...@@ -155,12 +141,57 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, ...@@ -155,12 +141,57 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
BUG_ON(node->start + node->size > adj_end); BUG_ON(node->start + node->size > adj_end);
node->hole_follows = 0; node->hole_follows = 0;
if (node->start + node->size < hole_end) { if (__drm_mm_hole_node_start(node) < hole_end) {
list_add(&node->hole_stack, &mm->hole_stack); list_add(&node->hole_stack, &mm->hole_stack);
node->hole_follows = 1; node->hole_follows = 1;
} }
} }
struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm,
unsigned long start,
unsigned long size,
bool atomic)
{
struct drm_mm_node *hole, *node;
unsigned long end = start + size;
unsigned long hole_start;
unsigned long hole_end;
drm_mm_for_each_hole(hole, mm, hole_start, hole_end) {
if (hole_start > start || hole_end < end)
continue;
node = drm_mm_kmalloc(mm, atomic);
if (unlikely(node == NULL))
return NULL;
node->start = start;
node->size = size;
node->mm = mm;
node->allocated = 1;
INIT_LIST_HEAD(&node->hole_stack);
list_add(&node->node_list, &hole->node_list);
if (start == hole_start) {
hole->hole_follows = 0;
list_del_init(&hole->hole_stack);
}
node->hole_follows = 0;
if (end != hole_end) {
list_add(&node->hole_stack, &mm->hole_stack);
node->hole_follows = 1;
}
return node;
}
WARN(1, "no hole found for block 0x%lx + 0x%lx\n", start, size);
return NULL;
}
EXPORT_SYMBOL(drm_mm_create_block);
struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node, struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node,
unsigned long size, unsigned long size,
unsigned alignment, unsigned alignment,
...@@ -251,7 +282,7 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, ...@@ -251,7 +282,7 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
BUG_ON(node->start + node->size > end); BUG_ON(node->start + node->size > end);
node->hole_follows = 0; node->hole_follows = 0;
if (node->start + node->size < hole_end) { if (__drm_mm_hole_node_start(node) < hole_end) {
list_add(&node->hole_stack, &mm->hole_stack); list_add(&node->hole_stack, &mm->hole_stack);
node->hole_follows = 1; node->hole_follows = 1;
} }
...@@ -325,12 +356,13 @@ void drm_mm_remove_node(struct drm_mm_node *node) ...@@ -325,12 +356,13 @@ void drm_mm_remove_node(struct drm_mm_node *node)
list_entry(node->node_list.prev, struct drm_mm_node, node_list); list_entry(node->node_list.prev, struct drm_mm_node, node_list);
if (node->hole_follows) { if (node->hole_follows) {
BUG_ON(drm_mm_hole_node_start(node) BUG_ON(__drm_mm_hole_node_start(node) ==
== drm_mm_hole_node_end(node)); __drm_mm_hole_node_end(node));
list_del(&node->hole_stack); list_del(&node->hole_stack);
} else } else
BUG_ON(drm_mm_hole_node_start(node) BUG_ON(__drm_mm_hole_node_start(node) !=
!= drm_mm_hole_node_end(node)); __drm_mm_hole_node_end(node));
if (!prev_node->hole_follows) { if (!prev_node->hole_follows) {
prev_node->hole_follows = 1; prev_node->hole_follows = 1;
...@@ -388,6 +420,8 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, ...@@ -388,6 +420,8 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
{ {
struct drm_mm_node *entry; struct drm_mm_node *entry;
struct drm_mm_node *best; struct drm_mm_node *best;
unsigned long adj_start;
unsigned long adj_end;
unsigned long best_size; unsigned long best_size;
BUG_ON(mm->scanned_blocks); BUG_ON(mm->scanned_blocks);
...@@ -395,17 +429,13 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, ...@@ -395,17 +429,13 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
best = NULL; best = NULL;
best_size = ~0UL; best_size = ~0UL;
list_for_each_entry(entry, &mm->hole_stack, hole_stack) { drm_mm_for_each_hole(entry, mm, adj_start, adj_end) {
unsigned long adj_start = drm_mm_hole_node_start(entry);
unsigned long adj_end = drm_mm_hole_node_end(entry);
if (mm->color_adjust) { if (mm->color_adjust) {
mm->color_adjust(entry, color, &adj_start, &adj_end); mm->color_adjust(entry, color, &adj_start, &adj_end);
if (adj_end <= adj_start) if (adj_end <= adj_start)
continue; continue;
} }
BUG_ON(!entry->hole_follows);
if (!check_free_hole(adj_start, adj_end, size, alignment)) if (!check_free_hole(adj_start, adj_end, size, alignment))
continue; continue;
...@@ -432,6 +462,8 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm, ...@@ -432,6 +462,8 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
{ {
struct drm_mm_node *entry; struct drm_mm_node *entry;
struct drm_mm_node *best; struct drm_mm_node *best;
unsigned long adj_start;
unsigned long adj_end;
unsigned long best_size; unsigned long best_size;
BUG_ON(mm->scanned_blocks); BUG_ON(mm->scanned_blocks);
...@@ -439,13 +471,11 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm, ...@@ -439,13 +471,11 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
best = NULL; best = NULL;
best_size = ~0UL; best_size = ~0UL;
list_for_each_entry(entry, &mm->hole_stack, hole_stack) { drm_mm_for_each_hole(entry, mm, adj_start, adj_end) {
unsigned long adj_start = drm_mm_hole_node_start(entry) < start ? if (adj_start < start)
start : drm_mm_hole_node_start(entry); adj_start = start;
unsigned long adj_end = drm_mm_hole_node_end(entry) > end ? if (adj_end > end)
end : drm_mm_hole_node_end(entry); adj_end = end;
BUG_ON(!entry->hole_follows);
if (mm->color_adjust) { if (mm->color_adjust) {
mm->color_adjust(entry, color, &adj_start, &adj_end); mm->color_adjust(entry, color, &adj_start, &adj_end);
......
...@@ -102,7 +102,7 @@ static const char *cache_level_str(int type) ...@@ -102,7 +102,7 @@ static const char *cache_level_str(int type)
static void static void
describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
{ {
seq_printf(m, "%p: %s%s %8zdKiB %04x %04x %d %d %d%s%s%s", seq_printf(m, "%p: %s%s %8zdKiB %02x %02x %d %d %d%s%s%s",
&obj->base, &obj->base,
get_pin_flag(obj), get_pin_flag(obj),
get_tiling_flag(obj), get_tiling_flag(obj),
...@@ -124,6 +124,8 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) ...@@ -124,6 +124,8 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
if (obj->gtt_space != NULL) if (obj->gtt_space != NULL)
seq_printf(m, " (gtt offset: %08x, size: %08x)", seq_printf(m, " (gtt offset: %08x, size: %08x)",
obj->gtt_offset, (unsigned int)obj->gtt_space->size); obj->gtt_offset, (unsigned int)obj->gtt_space->size);
if (obj->stolen)
seq_printf(m, " (stolen: %08lx)", obj->stolen->start);
if (obj->pin_mappable || obj->fault_mappable) { if (obj->pin_mappable || obj->fault_mappable) {
char s[3], *t = s; char s[3], *t = s;
if (obj->pin_mappable) if (obj->pin_mappable)
...@@ -387,7 +389,7 @@ static void i915_ring_seqno_info(struct seq_file *m, ...@@ -387,7 +389,7 @@ static void i915_ring_seqno_info(struct seq_file *m,
struct intel_ring_buffer *ring) struct intel_ring_buffer *ring)
{ {
if (ring->get_seqno) { if (ring->get_seqno) {
seq_printf(m, "Current sequence (%s): %d\n", seq_printf(m, "Current sequence (%s): %u\n",
ring->name, ring->get_seqno(ring, false)); ring->name, ring->get_seqno(ring, false));
} }
} }
...@@ -544,11 +546,11 @@ static int i915_hws_info(struct seq_file *m, void *data) ...@@ -544,11 +546,11 @@ static int i915_hws_info(struct seq_file *m, void *data)
struct drm_device *dev = node->minor->dev; struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_ring_buffer *ring; struct intel_ring_buffer *ring;
const volatile u32 __iomem *hws; const u32 *hws;
int i; int i;
ring = &dev_priv->ring[(uintptr_t)node->info_ent->data]; ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
hws = (volatile u32 __iomem *)ring->status_page.page_addr; hws = ring->status_page.page_addr;
if (hws == NULL) if (hws == NULL)
return 0; return 0;
...@@ -608,7 +610,7 @@ static void print_error_buffers(struct seq_file *m, ...@@ -608,7 +610,7 @@ static void print_error_buffers(struct seq_file *m,
seq_printf(m, "%s [%d]:\n", name, count); seq_printf(m, "%s [%d]:\n", name, count);
while (count--) { while (count--) {
seq_printf(m, " %08x %8u %04x %04x %x %x%s%s%s%s%s%s%s", seq_printf(m, " %08x %8u %02x %02x %x %x%s%s%s%s%s%s%s",
err->gtt_offset, err->gtt_offset,
err->size, err->size,
err->read_domains, err->read_domains,
...@@ -841,6 +843,77 @@ static const struct file_operations i915_error_state_fops = { ...@@ -841,6 +843,77 @@ static const struct file_operations i915_error_state_fops = {
.release = i915_error_state_release, .release = i915_error_state_release,
}; };
static ssize_t
i915_next_seqno_read(struct file *filp,
char __user *ubuf,
size_t max,
loff_t *ppos)
{
struct drm_device *dev = filp->private_data;
drm_i915_private_t *dev_priv = dev->dev_private;
char buf[80];
int len;
int ret;
ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
return ret;
len = snprintf(buf, sizeof(buf),
"next_seqno : 0x%x\n",
dev_priv->next_seqno);
mutex_unlock(&dev->struct_mutex);
if (len > sizeof(buf))
len = sizeof(buf);
return simple_read_from_buffer(ubuf, max, ppos, buf, len);
}
static ssize_t
i915_next_seqno_write(struct file *filp,
const char __user *ubuf,
size_t cnt,
loff_t *ppos)
{
struct drm_device *dev = filp->private_data;
char buf[20];
u32 val = 1;
int ret;
if (cnt > 0) {
if (cnt > sizeof(buf) - 1)
return -EINVAL;
if (copy_from_user(buf, ubuf, cnt))
return -EFAULT;
buf[cnt] = 0;
ret = kstrtouint(buf, 0, &val);
if (ret < 0)
return ret;
}
ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
return ret;
ret = i915_gem_set_seqno(dev, val);
mutex_unlock(&dev->struct_mutex);
return ret ?: cnt;
}
static const struct file_operations i915_next_seqno_fops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = i915_next_seqno_read,
.write = i915_next_seqno_write,
.llseek = default_llseek,
};
static int i915_rstdby_delays(struct seq_file *m, void *unused) static int i915_rstdby_delays(struct seq_file *m, void *unused)
{ {
struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_info_node *node = (struct drm_info_node *) m->private;
...@@ -1551,7 +1624,7 @@ static int i915_dpio_info(struct seq_file *m, void *data) ...@@ -1551,7 +1624,7 @@ static int i915_dpio_info(struct seq_file *m, void *data)
return 0; return 0;
} }
ret = mutex_lock_interruptible(&dev->mode_config.mutex); ret = mutex_lock_interruptible(&dev_priv->dpio_lock);
if (ret) if (ret)
return ret; return ret;
...@@ -1580,7 +1653,7 @@ static int i915_dpio_info(struct seq_file *m, void *data) ...@@ -1580,7 +1653,7 @@ static int i915_dpio_info(struct seq_file *m, void *data)
seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n", seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n",
intel_dpio_read(dev_priv, DPIO_FASTCLK_DISABLE)); intel_dpio_read(dev_priv, DPIO_FASTCLK_DISABLE));
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev_priv->dpio_lock);
return 0; return 0;
} }
...@@ -2105,6 +2178,12 @@ int i915_debugfs_init(struct drm_minor *minor) ...@@ -2105,6 +2178,12 @@ int i915_debugfs_init(struct drm_minor *minor)
if (ret) if (ret)
return ret; return ret;
ret = i915_debugfs_create(minor->debugfs_root, minor,
"i915_next_seqno",
&i915_next_seqno_fops);
if (ret)
return ret;
return drm_debugfs_create_files(i915_debugfs_list, return drm_debugfs_create_files(i915_debugfs_list,
I915_DEBUGFS_ENTRIES, I915_DEBUGFS_ENTRIES,
minor->debugfs_root, minor); minor->debugfs_root, minor);
...@@ -2128,6 +2207,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor) ...@@ -2128,6 +2207,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor)
1, minor); 1, minor);
drm_debugfs_remove_files((struct drm_info_list *) &i915_error_state_fops, drm_debugfs_remove_files((struct drm_info_list *) &i915_error_state_fops,
1, minor); 1, minor);
drm_debugfs_remove_files((struct drm_info_list *) &i915_next_seqno_fops,
1, minor);
} }
#endif /* CONFIG_DEBUG_FS */ #endif /* CONFIG_DEBUG_FS */
...@@ -1297,19 +1297,21 @@ static int i915_load_modeset_init(struct drm_device *dev) ...@@ -1297,19 +1297,21 @@ static int i915_load_modeset_init(struct drm_device *dev)
if (ret) if (ret)
goto cleanup_vga_switcheroo; goto cleanup_vga_switcheroo;
ret = drm_irq_install(dev);
if (ret)
goto cleanup_gem_stolen;
/* Important: The output setup functions called by modeset_init need
* working irqs for e.g. gmbus and dp aux transfers. */
intel_modeset_init(dev); intel_modeset_init(dev);
ret = i915_gem_init(dev); ret = i915_gem_init(dev);
if (ret) if (ret)
goto cleanup_gem_stolen; goto cleanup_irq;
intel_modeset_gem_init(dev);
INIT_WORK(&dev_priv->console_resume_work, intel_console_resume); INIT_WORK(&dev_priv->console_resume_work, intel_console_resume);
ret = drm_irq_install(dev); intel_modeset_gem_init(dev);
if (ret)
goto cleanup_gem;
/* Always safe in the mode setting case. */ /* Always safe in the mode setting case. */
/* FIXME: do pre/post-mode set stuff in core KMS code */ /* FIXME: do pre/post-mode set stuff in core KMS code */
...@@ -1317,7 +1319,25 @@ static int i915_load_modeset_init(struct drm_device *dev) ...@@ -1317,7 +1319,25 @@ static int i915_load_modeset_init(struct drm_device *dev)
ret = intel_fbdev_init(dev); ret = intel_fbdev_init(dev);
if (ret) if (ret)
goto cleanup_irq; goto cleanup_gem;
/* Only enable hotplug handling once the fbdev is fully set up. */
intel_hpd_init(dev);
/*
* Some ports require correctly set-up hpd registers for detection to
* work properly (leading to ghost connected connector status), e.g. VGA
* on gm45. Hence we can only set up the initial fbdev config after hpd
* irqs are fully enabled. Now we should scan for the initial config
* only once hotplug handling is enabled, but due to screwed-up locking
* around kms/fbdev init we can't protect the fdbev initial config
* scanning against hotplug events. Hence do this first and ignore the
* tiny window where we will loose hotplug notifactions.
*/
intel_fbdev_initial_config(dev);
/* Only enable hotplug handling once the fbdev is fully set up. */
dev_priv->enable_hotplug_processing = true;
drm_kms_helper_poll_init(dev); drm_kms_helper_poll_init(dev);
...@@ -1326,13 +1346,13 @@ static int i915_load_modeset_init(struct drm_device *dev) ...@@ -1326,13 +1346,13 @@ static int i915_load_modeset_init(struct drm_device *dev)
return 0; return 0;
cleanup_irq:
drm_irq_uninstall(dev);
cleanup_gem: cleanup_gem:
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
i915_gem_cleanup_ringbuffer(dev); i915_gem_cleanup_ringbuffer(dev);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
i915_gem_cleanup_aliasing_ppgtt(dev); i915_gem_cleanup_aliasing_ppgtt(dev);
cleanup_irq:
drm_irq_uninstall(dev);
cleanup_gem_stolen: cleanup_gem_stolen:
i915_gem_cleanup_stolen(dev); i915_gem_cleanup_stolen(dev);
cleanup_vga_switcheroo: cleanup_vga_switcheroo:
...@@ -1582,7 +1602,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1582,7 +1602,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->irq_lock);
spin_lock_init(&dev_priv->error_lock); spin_lock_init(&dev_priv->error_lock);
spin_lock_init(&dev_priv->rps.lock); spin_lock_init(&dev_priv->rps.lock);
spin_lock_init(&dev_priv->dpio_lock); mutex_init(&dev_priv->dpio_lock);
mutex_init(&dev_priv->rps.hw_lock); mutex_init(&dev_priv->rps.hw_lock);
...@@ -1614,9 +1634,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1614,9 +1634,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
intel_opregion_init(dev); intel_opregion_init(dev);
acpi_video_register(); acpi_video_register();
setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
(unsigned long) dev);
if (IS_GEN5(dev)) if (IS_GEN5(dev))
intel_gpu_ips_init(dev_priv); intel_gpu_ips_init(dev_priv);
...@@ -1723,9 +1740,6 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -1723,9 +1740,6 @@ int i915_driver_unload(struct drm_device *dev)
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
i915_gem_cleanup_aliasing_ppgtt(dev); i915_gem_cleanup_aliasing_ppgtt(dev);
i915_gem_cleanup_stolen(dev); i915_gem_cleanup_stolen(dev);
drm_mm_takedown(&dev_priv->mm.stolen);
intel_cleanup_overlay(dev);
if (!I915_NEED_GFX_HWS(dev)) if (!I915_NEED_GFX_HWS(dev))
i915_free_hws(dev); i915_free_hws(dev);
...@@ -1738,6 +1752,10 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -1738,6 +1752,10 @@ int i915_driver_unload(struct drm_device *dev)
intel_teardown_mchbar(dev); intel_teardown_mchbar(dev);
destroy_workqueue(dev_priv->wq); destroy_workqueue(dev_priv->wq);
pm_qos_remove_request(&dev_priv->pm_qos);
if (dev_priv->slab)
kmem_cache_destroy(dev_priv->slab);
pci_dev_put(dev_priv->bridge_dev); pci_dev_put(dev_priv->bridge_dev);
kfree(dev->dev_private); kfree(dev->dev_private);
......
...@@ -565,6 +565,7 @@ static int __i915_drm_thaw(struct drm_device *dev) ...@@ -565,6 +565,7 @@ static int __i915_drm_thaw(struct drm_device *dev)
intel_modeset_init_hw(dev); intel_modeset_init_hw(dev);
intel_modeset_setup_hw_state(dev, false); intel_modeset_setup_hw_state(dev, false);
drm_irq_install(dev); drm_irq_install(dev);
intel_hpd_init(dev);
} }
intel_opregion_init(dev); intel_opregion_init(dev);
...@@ -870,6 +871,7 @@ int i915_reset(struct drm_device *dev) ...@@ -870,6 +871,7 @@ int i915_reset(struct drm_device *dev)
drm_irq_uninstall(dev); drm_irq_uninstall(dev);
drm_irq_install(dev); drm_irq_install(dev);
intel_hpd_init(dev);
} else { } else {
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
} }
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#ifndef _I915_DRV_H_ #ifndef _I915_DRV_H_
#define _I915_DRV_H_ #define _I915_DRV_H_
#include <uapi/drm/i915_drm.h>
#include "i915_reg.h" #include "i915_reg.h"
#include "intel_bios.h" #include "intel_bios.h"
#include "intel_ringbuffer.h" #include "intel_ringbuffer.h"
...@@ -40,6 +42,7 @@ ...@@ -40,6 +42,7 @@
#include <linux/backlight.h> #include <linux/backlight.h>
#include <linux/intel-iommu.h> #include <linux/intel-iommu.h>
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/pm_qos.h>
/* General customization: /* General customization:
*/ */
...@@ -83,7 +86,12 @@ enum port { ...@@ -83,7 +86,12 @@ enum port {
}; };
#define port_name(p) ((p) + 'A') #define port_name(p) ((p) + 'A')
#define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) #define I915_GEM_GPU_DOMAINS \
(I915_GEM_DOMAIN_RENDER | \
I915_GEM_DOMAIN_SAMPLER | \
I915_GEM_DOMAIN_COMMAND | \
I915_GEM_DOMAIN_INSTRUCTION | \
I915_GEM_DOMAIN_VERTEX)
#define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++) #define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++)
...@@ -101,6 +109,19 @@ struct intel_pch_pll { ...@@ -101,6 +109,19 @@ struct intel_pch_pll {
}; };
#define I915_NUM_PLLS 2 #define I915_NUM_PLLS 2
/* Used by dp and fdi links */
struct intel_link_m_n {
uint32_t tu;
uint32_t gmch_m;
uint32_t gmch_n;
uint32_t link_m;
uint32_t link_n;
};
void intel_link_compute_m_n(int bpp, int nlanes,
int pixel_clock, int link_clock,
struct intel_link_m_n *m_n);
struct intel_ddi_plls { struct intel_ddi_plls {
int spll_refcount; int spll_refcount;
int wrpll1_refcount; int wrpll1_refcount;
...@@ -276,6 +297,7 @@ struct drm_i915_display_funcs { ...@@ -276,6 +297,7 @@ struct drm_i915_display_funcs {
struct drm_i915_gem_object *obj); struct drm_i915_gem_object *obj);
int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb, int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
int x, int y); int x, int y);
void (*hpd_irq_setup)(struct drm_device *dev);
/* clock updates for mode set */ /* clock updates for mode set */
/* cursor updates */ /* cursor updates */
/* render clock increase/decrease */ /* render clock increase/decrease */
...@@ -577,6 +599,9 @@ struct intel_gen6_power_mgmt { ...@@ -577,6 +599,9 @@ struct intel_gen6_power_mgmt {
struct mutex hw_lock; struct mutex hw_lock;
}; };
/* defined intel_pm.c */
extern spinlock_t mchdev_lock;
struct intel_ilk_power_mgmt { struct intel_ilk_power_mgmt {
u8 cur_delay; u8 cur_delay;
u8 min_delay; u8 min_delay;
...@@ -619,6 +644,7 @@ struct intel_l3_parity { ...@@ -619,6 +644,7 @@ struct intel_l3_parity {
typedef struct drm_i915_private { typedef struct drm_i915_private {
struct drm_device *dev; struct drm_device *dev;
struct kmem_cache *slab;
const struct intel_device_info *info; const struct intel_device_info *info;
...@@ -633,10 +659,11 @@ typedef struct drm_i915_private { ...@@ -633,10 +659,11 @@ typedef struct drm_i915_private {
/** forcewake_count is protected by gt_lock */ /** forcewake_count is protected by gt_lock */
unsigned forcewake_count; unsigned forcewake_count;
/** gt_lock is also taken in irq contexts. */ /** gt_lock is also taken in irq contexts. */
struct spinlock gt_lock; spinlock_t gt_lock;
struct intel_gmbus gmbus[GMBUS_NUM_PORTS]; struct intel_gmbus gmbus[GMBUS_NUM_PORTS];
/** gmbus_mutex protects against concurrent usage of the single hw gmbus /** gmbus_mutex protects against concurrent usage of the single hw gmbus
* controller on different i2c buses. */ * controller on different i2c buses. */
struct mutex gmbus_mutex; struct mutex gmbus_mutex;
...@@ -646,9 +673,11 @@ typedef struct drm_i915_private { ...@@ -646,9 +673,11 @@ typedef struct drm_i915_private {
*/ */
uint32_t gpio_mmio_base; uint32_t gpio_mmio_base;
wait_queue_head_t gmbus_wait_queue;
struct pci_dev *bridge_dev; struct pci_dev *bridge_dev;
struct intel_ring_buffer ring[I915_NUM_RINGS]; struct intel_ring_buffer ring[I915_NUM_RINGS];
uint32_t next_seqno; uint32_t last_seqno, next_seqno;
drm_dma_handle_t *status_page_dmah; drm_dma_handle_t *status_page_dmah;
struct resource mch_res; struct resource mch_res;
...@@ -658,8 +687,11 @@ typedef struct drm_i915_private { ...@@ -658,8 +687,11 @@ typedef struct drm_i915_private {
/* protects the irq masks */ /* protects the irq masks */
spinlock_t irq_lock; spinlock_t irq_lock;
/* To control wakeup latency, e.g. for irq-driven dp aux transfers. */
struct pm_qos_request pm_qos;
/* DPIO indirect register protection */ /* DPIO indirect register protection */
spinlock_t dpio_lock; struct mutex dpio_lock;
/** Cached value of IMR to avoid reads in updating the bitfield */ /** Cached value of IMR to avoid reads in updating the bitfield */
u32 pipestat[2]; u32 pipestat[2];
...@@ -669,6 +701,7 @@ typedef struct drm_i915_private { ...@@ -669,6 +701,7 @@ typedef struct drm_i915_private {
u32 hotplug_supported_mask; u32 hotplug_supported_mask;
struct work_struct hotplug_work; struct work_struct hotplug_work;
bool enable_hotplug_processing;
int num_pipe; int num_pipe;
int num_pch_pll; int num_pch_pll;
...@@ -710,7 +743,6 @@ typedef struct drm_i915_private { ...@@ -710,7 +743,6 @@ typedef struct drm_i915_private {
unsigned int display_clock_mode:1; unsigned int display_clock_mode:1;
int lvds_ssc_freq; int lvds_ssc_freq;
unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */ unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
unsigned int lvds_val; /* used for checking LVDS channel mode */
struct { struct {
int rate; int rate;
int lanes; int lanes;
...@@ -771,6 +803,10 @@ typedef struct drm_i915_private { ...@@ -771,6 +803,10 @@ typedef struct drm_i915_private {
unsigned long gtt_start; unsigned long gtt_start;
unsigned long gtt_mappable_end; unsigned long gtt_mappable_end;
unsigned long gtt_end; unsigned long gtt_end;
unsigned long stolen_base; /* limited to low memory (32-bit) */
/** "Graphics Stolen Memory" holds the global PTEs */
void __iomem *gsm;
struct io_mapping *gtt_mapping; struct io_mapping *gtt_mapping;
phys_addr_t gtt_base_addr; phys_addr_t gtt_base_addr;
...@@ -943,6 +979,8 @@ enum i915_cache_level { ...@@ -943,6 +979,8 @@ enum i915_cache_level {
I915_CACHE_LLC_MLC, /* gen6+, in docs at least! */ I915_CACHE_LLC_MLC, /* gen6+, in docs at least! */
}; };
#define I915_GTT_RESERVED ((struct drm_mm_node *)0x1)
struct drm_i915_gem_object_ops { struct drm_i915_gem_object_ops {
/* Interface between the GEM object and its backing storage. /* Interface between the GEM object and its backing storage.
* get_pages() is called once prior to the use of the associated set * get_pages() is called once prior to the use of the associated set
...@@ -968,6 +1006,8 @@ struct drm_i915_gem_object { ...@@ -968,6 +1006,8 @@ struct drm_i915_gem_object {
/** Current space allocated to this object in the GTT, if any. */ /** Current space allocated to this object in the GTT, if any. */
struct drm_mm_node *gtt_space; struct drm_mm_node *gtt_space;
/** Stolen memory for this object, instead of being backed by shmem. */
struct drm_mm_node *stolen;
struct list_head gtt_list; struct list_head gtt_list;
/** This object's place on the active/inactive lists */ /** This object's place on the active/inactive lists */
...@@ -1138,7 +1178,7 @@ struct drm_i915_gem_request { ...@@ -1138,7 +1178,7 @@ struct drm_i915_gem_request {
struct drm_i915_file_private { struct drm_i915_file_private {
struct { struct {
struct spinlock lock; spinlock_t lock;
struct list_head request_list; struct list_head request_list;
} mm; } mm;
struct idr context_idr; struct idr context_idr;
...@@ -1224,6 +1264,8 @@ struct drm_i915_file_private { ...@@ -1224,6 +1264,8 @@ struct drm_i915_file_private {
#define HAS_PIPE_CONTROL(dev) (INTEL_INFO(dev)->gen >= 5) #define HAS_PIPE_CONTROL(dev) (INTEL_INFO(dev)->gen >= 5)
#define HAS_DDI(dev) (IS_HASWELL(dev))
#define INTEL_PCH_DEVICE_ID_MASK 0xff00 #define INTEL_PCH_DEVICE_ID_MASK 0xff00
#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00 #define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00
#define INTEL_PCH_CPT_DEVICE_ID_TYPE 0x1c00 #define INTEL_PCH_CPT_DEVICE_ID_TYPE 0x1c00
...@@ -1320,6 +1362,7 @@ void i915_hangcheck_elapsed(unsigned long data); ...@@ -1320,6 +1362,7 @@ void i915_hangcheck_elapsed(unsigned long data);
void i915_handle_error(struct drm_device *dev, bool wedged); void i915_handle_error(struct drm_device *dev, bool wedged);
extern void intel_irq_init(struct drm_device *dev); extern void intel_irq_init(struct drm_device *dev);
extern void intel_hpd_init(struct drm_device *dev);
extern void intel_gt_init(struct drm_device *dev); extern void intel_gt_init(struct drm_device *dev);
extern void intel_gt_reset(struct drm_device *dev); extern void intel_gt_reset(struct drm_device *dev);
...@@ -1388,12 +1431,15 @@ int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, ...@@ -1388,12 +1431,15 @@ int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
int i915_gem_wait_ioctl(struct drm_device *dev, void *data, int i915_gem_wait_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
void i915_gem_load(struct drm_device *dev); void i915_gem_load(struct drm_device *dev);
void *i915_gem_object_alloc(struct drm_device *dev);
void i915_gem_object_free(struct drm_i915_gem_object *obj);
int i915_gem_init_object(struct drm_gem_object *obj); int i915_gem_init_object(struct drm_gem_object *obj);
void i915_gem_object_init(struct drm_i915_gem_object *obj, void i915_gem_object_init(struct drm_i915_gem_object *obj,
const struct drm_i915_gem_object_ops *ops); const struct drm_i915_gem_object_ops *ops);
struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
size_t size); size_t size);
void i915_gem_free_object(struct drm_gem_object *obj); void i915_gem_free_object(struct drm_gem_object *obj);
int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj, int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj,
uint32_t alignment, uint32_t alignment,
bool map_and_fenceable, bool map_and_fenceable,
...@@ -1451,8 +1497,8 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2) ...@@ -1451,8 +1497,8 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2)
return (int32_t)(seq1 - seq2) >= 0; return (int32_t)(seq1 - seq2) >= 0;
} }
extern int i915_gem_get_seqno(struct drm_device *dev, u32 *seqno); int __must_check i915_gem_get_seqno(struct drm_device *dev, u32 *seqno);
int __must_check i915_gem_set_seqno(struct drm_device *dev, u32 seqno);
int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj); int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj);
int __must_check i915_gem_object_put_fence(struct drm_i915_gem_object *obj); int __must_check i915_gem_object_put_fence(struct drm_i915_gem_object *obj);
...@@ -1559,10 +1605,9 @@ void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj, ...@@ -1559,10 +1605,9 @@ void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,
enum i915_cache_level cache_level); enum i915_cache_level cache_level);
void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj); void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj);
void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj); void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj);
void i915_gem_init_global_gtt(struct drm_device *dev, void i915_gem_init_global_gtt(struct drm_device *dev);
unsigned long start, void i915_gem_setup_global_gtt(struct drm_device *dev, unsigned long start,
unsigned long mappable_end, unsigned long mappable_end, unsigned long end);
unsigned long end);
int i915_gem_gtt_init(struct drm_device *dev); int i915_gem_gtt_init(struct drm_device *dev);
void i915_gem_gtt_fini(struct drm_device *dev); void i915_gem_gtt_fini(struct drm_device *dev);
static inline void i915_gem_chipset_flush(struct drm_device *dev) static inline void i915_gem_chipset_flush(struct drm_device *dev)
...@@ -1582,9 +1627,22 @@ int i915_gem_evict_everything(struct drm_device *dev); ...@@ -1582,9 +1627,22 @@ int i915_gem_evict_everything(struct drm_device *dev);
/* i915_gem_stolen.c */ /* i915_gem_stolen.c */
int i915_gem_init_stolen(struct drm_device *dev); int i915_gem_init_stolen(struct drm_device *dev);
int i915_gem_stolen_setup_compression(struct drm_device *dev, int size);
void i915_gem_stolen_cleanup_compression(struct drm_device *dev);
void i915_gem_cleanup_stolen(struct drm_device *dev); void i915_gem_cleanup_stolen(struct drm_device *dev);
struct drm_i915_gem_object *
i915_gem_object_create_stolen(struct drm_device *dev, u32 size);
void i915_gem_object_release_stolen(struct drm_i915_gem_object *obj);
/* i915_gem_tiling.c */ /* i915_gem_tiling.c */
inline static bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
{
drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
return dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 &&
obj->tiling_mode != I915_TILING_NONE;
}
void i915_gem_detect_bit_6_swizzle(struct drm_device *dev); void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj); void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj);
void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj); void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj);
......
This diff is collapsed.
...@@ -281,8 +281,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, ...@@ -281,8 +281,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
if (IS_ERR(attach)) if (IS_ERR(attach))
return ERR_CAST(attach); return ERR_CAST(attach);
obj = i915_gem_object_alloc(dev);
obj = kzalloc(sizeof(*obj), GFP_KERNEL);
if (obj == NULL) { if (obj == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
goto fail_detach; goto fail_detach;
...@@ -290,7 +289,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, ...@@ -290,7 +289,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
ret = drm_gem_private_object_init(dev, &obj->base, dma_buf->size); ret = drm_gem_private_object_init(dev, &obj->base, dma_buf->size);
if (ret) { if (ret) {
kfree(obj); i915_gem_object_free(obj);
goto fail_detach; goto fail_detach;
} }
......
...@@ -150,17 +150,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, ...@@ -150,17 +150,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
reloc->write_domain); reloc->write_domain);
return ret; return ret;
} }
if (unlikely(reloc->write_domain && target_obj->pending_write_domain &&
reloc->write_domain != target_obj->pending_write_domain)) {
DRM_DEBUG("Write domain conflict: "
"obj %p target %d offset %d "
"new %08x old %08x\n",
obj, reloc->target_handle,
(int) reloc->offset,
reloc->write_domain,
target_obj->pending_write_domain);
return ret;
}
target_obj->pending_read_domains |= reloc->read_domains; target_obj->pending_read_domains |= reloc->read_domains;
target_obj->pending_write_domain |= reloc->write_domain; target_obj->pending_write_domain |= reloc->write_domain;
...@@ -601,45 +590,12 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, ...@@ -601,45 +590,12 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
return ret; return ret;
} }
static int
i915_gem_execbuffer_wait_for_flips(struct intel_ring_buffer *ring, u32 flips)
{
u32 plane, flip_mask;
int ret;
/* Check for any pending flips. As we only maintain a flip queue depth
* of 1, we can simply insert a WAIT for the next display flip prior
* to executing the batch and avoid stalling the CPU.
*/
for (plane = 0; flips >> plane; plane++) {
if (((flips >> plane) & 1) == 0)
continue;
if (plane)
flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
else
flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
ret = intel_ring_begin(ring, 2);
if (ret)
return ret;
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
intel_ring_emit(ring, MI_NOOP);
intel_ring_advance(ring);
}
return 0;
}
static int static int
i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring, i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
struct list_head *objects) struct list_head *objects)
{ {
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
uint32_t flush_domains = 0; uint32_t flush_domains = 0;
uint32_t flips = 0;
int ret; int ret;
list_for_each_entry(obj, objects, exec_list) { list_for_each_entry(obj, objects, exec_list) {
...@@ -650,18 +606,9 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring, ...@@ -650,18 +606,9 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
if (obj->base.write_domain & I915_GEM_DOMAIN_CPU) if (obj->base.write_domain & I915_GEM_DOMAIN_CPU)
i915_gem_clflush_object(obj); i915_gem_clflush_object(obj);
if (obj->base.pending_write_domain)
flips |= atomic_read(&obj->pending_flip);
flush_domains |= obj->base.write_domain; flush_domains |= obj->base.write_domain;
} }
if (flips) {
ret = i915_gem_execbuffer_wait_for_flips(ring, flips);
if (ret)
return ret;
}
if (flush_domains & I915_GEM_DOMAIN_CPU) if (flush_domains & I915_GEM_DOMAIN_CPU)
i915_gem_chipset_flush(ring->dev); i915_gem_chipset_flush(ring->dev);
......
...@@ -282,7 +282,7 @@ void i915_gem_init_ppgtt(struct drm_device *dev) ...@@ -282,7 +282,7 @@ void i915_gem_init_ppgtt(struct drm_device *dev)
uint32_t pd_offset; uint32_t pd_offset;
struct intel_ring_buffer *ring; struct intel_ring_buffer *ring;
struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
uint32_t __iomem *pd_addr; gtt_pte_t __iomem *pd_addr;
uint32_t pd_entry; uint32_t pd_entry;
int i; int i;
...@@ -290,7 +290,7 @@ void i915_gem_init_ppgtt(struct drm_device *dev) ...@@ -290,7 +290,7 @@ void i915_gem_init_ppgtt(struct drm_device *dev)
return; return;
pd_addr = dev_priv->mm.gtt->gtt + ppgtt->pd_offset/sizeof(uint32_t); pd_addr = (gtt_pte_t __iomem*)dev_priv->mm.gsm + ppgtt->pd_offset/sizeof(gtt_pte_t);
for (i = 0; i < ppgtt->num_pd_entries; i++) { for (i = 0; i < ppgtt->num_pd_entries; i++) {
dma_addr_t pt_addr; dma_addr_t pt_addr;
...@@ -367,7 +367,7 @@ static void i915_ggtt_clear_range(struct drm_device *dev, ...@@ -367,7 +367,7 @@ static void i915_ggtt_clear_range(struct drm_device *dev,
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
gtt_pte_t scratch_pte; gtt_pte_t scratch_pte;
gtt_pte_t __iomem *gtt_base = dev_priv->mm.gtt->gtt + first_entry; gtt_pte_t __iomem *gtt_base = (gtt_pte_t __iomem *) dev_priv->mm.gsm + first_entry;
const int max_entries = dev_priv->mm.gtt->gtt_total_entries - first_entry; const int max_entries = dev_priv->mm.gtt->gtt_total_entries - first_entry;
int i; int i;
...@@ -432,7 +432,8 @@ static void gen6_ggtt_bind_object(struct drm_i915_gem_object *obj, ...@@ -432,7 +432,8 @@ static void gen6_ggtt_bind_object(struct drm_i915_gem_object *obj,
struct scatterlist *sg = st->sgl; struct scatterlist *sg = st->sgl;
const int first_entry = obj->gtt_space->start >> PAGE_SHIFT; const int first_entry = obj->gtt_space->start >> PAGE_SHIFT;
const int max_entries = dev_priv->mm.gtt->gtt_total_entries - first_entry; const int max_entries = dev_priv->mm.gtt->gtt_total_entries - first_entry;
gtt_pte_t __iomem *gtt_entries = dev_priv->mm.gtt->gtt + first_entry; gtt_pte_t __iomem *gtt_entries =
(gtt_pte_t __iomem *)dev_priv->mm.gsm + first_entry;
int unused, i = 0; int unused, i = 0;
unsigned int len, m = 0; unsigned int len, m = 0;
dma_addr_t addr; dma_addr_t addr;
...@@ -525,26 +526,103 @@ static void i915_gtt_color_adjust(struct drm_mm_node *node, ...@@ -525,26 +526,103 @@ static void i915_gtt_color_adjust(struct drm_mm_node *node,
} }
} }
void i915_gem_init_global_gtt(struct drm_device *dev, void i915_gem_setup_global_gtt(struct drm_device *dev,
unsigned long start, unsigned long start,
unsigned long mappable_end, unsigned long mappable_end,
unsigned long end) unsigned long end)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_mm_node *entry;
struct drm_i915_gem_object *obj;
unsigned long hole_start, hole_end;
/* Substract the guard page ... */ /* Subtract the guard page ... */
drm_mm_init(&dev_priv->mm.gtt_space, start, end - start - PAGE_SIZE); drm_mm_init(&dev_priv->mm.gtt_space, start, end - start - PAGE_SIZE);
if (!HAS_LLC(dev)) if (!HAS_LLC(dev))
dev_priv->mm.gtt_space.color_adjust = i915_gtt_color_adjust; dev_priv->mm.gtt_space.color_adjust = i915_gtt_color_adjust;
/* Mark any preallocated objects as occupied */
list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
DRM_DEBUG_KMS("reserving preallocated space: %x + %zx\n",
obj->gtt_offset, obj->base.size);
BUG_ON(obj->gtt_space != I915_GTT_RESERVED);
obj->gtt_space = drm_mm_create_block(&dev_priv->mm.gtt_space,
obj->gtt_offset,
obj->base.size,
false);
obj->has_global_gtt_mapping = 1;
}
dev_priv->mm.gtt_start = start; dev_priv->mm.gtt_start = start;
dev_priv->mm.gtt_mappable_end = mappable_end; dev_priv->mm.gtt_mappable_end = mappable_end;
dev_priv->mm.gtt_end = end; dev_priv->mm.gtt_end = end;
dev_priv->mm.gtt_total = end - start; dev_priv->mm.gtt_total = end - start;
dev_priv->mm.mappable_gtt_total = min(end, mappable_end) - start; dev_priv->mm.mappable_gtt_total = min(end, mappable_end) - start;
/* ... but ensure that we clear the entire range. */ /* Clear any non-preallocated blocks */
i915_ggtt_clear_range(dev, start / PAGE_SIZE, (end-start) / PAGE_SIZE); drm_mm_for_each_hole(entry, &dev_priv->mm.gtt_space,
hole_start, hole_end) {
DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
hole_start, hole_end);
i915_ggtt_clear_range(dev,
hole_start / PAGE_SIZE,
(hole_end-hole_start) / PAGE_SIZE);
}
/* And finally clear the reserved guard page */
i915_ggtt_clear_range(dev, end / PAGE_SIZE - 1, 1);
}
static bool
intel_enable_ppgtt(struct drm_device *dev)
{
if (i915_enable_ppgtt >= 0)
return i915_enable_ppgtt;
#ifdef CONFIG_INTEL_IOMMU
/* Disable ppgtt on SNB if VT-d is on. */
if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped)
return false;
#endif
return true;
}
void i915_gem_init_global_gtt(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long gtt_size, mappable_size;
int ret;
gtt_size = dev_priv->mm.gtt->gtt_total_entries << PAGE_SHIFT;
mappable_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) {
/* PPGTT pdes are stolen from global gtt ptes, so shrink the
* aperture accordingly when using aliasing ppgtt. */
gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size);
ret = i915_gem_init_aliasing_ppgtt(dev);
if (ret) {
mutex_unlock(&dev->struct_mutex);
return;
}
} else {
/* Let GEM Manage all of the aperture.
*
* However, leave one page at the end still bound to the scratch
* page. There are a number of places where the hardware
* apparently prefetches past the end of the object, and we've
* seen multiple hangs with the GPU head pointer stuck in a
* batchbuffer bound at the last page of the aperture. One page
* should be enough to keep any prefetching inside of the
* aperture.
*/
i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size);
}
} }
static int setup_scratch_page(struct drm_device *dev) static int setup_scratch_page(struct drm_device *dev)
...@@ -674,9 +752,9 @@ int i915_gem_gtt_init(struct drm_device *dev) ...@@ -674,9 +752,9 @@ int i915_gem_gtt_init(struct drm_device *dev)
goto err_out; goto err_out;
} }
dev_priv->mm.gtt->gtt = ioremap_wc(gtt_bus_addr, dev_priv->mm.gsm = ioremap_wc(gtt_bus_addr,
dev_priv->mm.gtt->gtt_total_entries * sizeof(gtt_pte_t)); dev_priv->mm.gtt->gtt_total_entries * sizeof(gtt_pte_t));
if (!dev_priv->mm.gtt->gtt) { if (!dev_priv->mm.gsm) {
DRM_ERROR("Failed to map the gtt page table\n"); DRM_ERROR("Failed to map the gtt page table\n");
teardown_scratch_page(dev); teardown_scratch_page(dev);
ret = -ENOMEM; ret = -ENOMEM;
...@@ -700,7 +778,7 @@ int i915_gem_gtt_init(struct drm_device *dev) ...@@ -700,7 +778,7 @@ int i915_gem_gtt_init(struct drm_device *dev)
void i915_gem_gtt_fini(struct drm_device *dev) void i915_gem_gtt_fini(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
iounmap(dev_priv->mm.gtt->gtt); iounmap(dev_priv->mm.gsm);
teardown_scratch_page(dev); teardown_scratch_page(dev);
if (INTEL_INFO(dev)->gen < 6) if (INTEL_INFO(dev)->gen < 6)
intel_gmch_remove(); intel_gmch_remove();
......
This diff is collapsed.
...@@ -396,6 +396,18 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, ...@@ -396,6 +396,18 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
/* we have to maintain this existing ABI... */ /* we have to maintain this existing ABI... */
args->stride = obj->stride; args->stride = obj->stride;
args->tiling_mode = obj->tiling_mode; args->tiling_mode = obj->tiling_mode;
/* Try to preallocate memory required to save swizzling on put-pages */
if (i915_gem_object_needs_bit17_swizzle(obj)) {
if (obj->bit_17 == NULL) {
obj->bit_17 = kmalloc(BITS_TO_LONGS(obj->base.size >> PAGE_SHIFT) *
sizeof(long), GFP_KERNEL);
}
} else {
kfree(obj->bit_17);
obj->bit_17 = NULL;
}
drm_gem_object_unreference(&obj->base); drm_gem_object_unreference(&obj->base);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
......
This diff is collapsed.
...@@ -142,6 +142,7 @@ ...@@ -142,6 +142,7 @@
#define VGA_MSR_CGA_MODE (1<<0) #define VGA_MSR_CGA_MODE (1<<0)
#define VGA_SR_INDEX 0x3c4 #define VGA_SR_INDEX 0x3c4
#define SR01 1
#define VGA_SR_DATA 0x3c5 #define VGA_SR_DATA 0x3c5
#define VGA_AR_INDEX 0x3c0 #define VGA_AR_INDEX 0x3c0
...@@ -940,23 +941,6 @@ ...@@ -940,23 +941,6 @@
#define DPLL_LOCK_VLV (1<<15) #define DPLL_LOCK_VLV (1<<15)
#define DPLL_INTEGRATED_CLOCK_VLV (1<<13) #define DPLL_INTEGRATED_CLOCK_VLV (1<<13)
#define SRX_INDEX 0x3c4
#define SRX_DATA 0x3c5
#define SR01 1
#define SR01_SCREEN_OFF (1<<5)
#define PPCR 0x61204
#define PPCR_ON (1<<0)
#define DVOB 0x61140
#define DVOB_ON (1<<31)
#define DVOC 0x61160
#define DVOC_ON (1<<31)
#define LVDS 0x61180
#define LVDS_ON (1<<31)
/* Scratch pad debug 0 reg:
*/
#define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 #define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000
/* /*
* The i830 generation, in LVDS mode, defines P1 as the bit number set within * The i830 generation, in LVDS mode, defines P1 as the bit number set within
...@@ -1893,8 +1877,6 @@ ...@@ -1893,8 +1877,6 @@
#define PFIT_SCALING_PILLAR (2 << 26) #define PFIT_SCALING_PILLAR (2 << 26)
#define PFIT_SCALING_LETTER (3 << 26) #define PFIT_SCALING_LETTER (3 << 26)
#define PFIT_PGM_RATIOS 0x61234 #define PFIT_PGM_RATIOS 0x61234
#define PFIT_VERT_SCALE_MASK 0xfff00000
#define PFIT_HORIZ_SCALE_MASK 0x0000fff0
/* Pre-965 */ /* Pre-965 */
#define PFIT_VERT_SCALE_SHIFT 20 #define PFIT_VERT_SCALE_SHIFT 20
#define PFIT_VERT_SCALE_MASK 0xfff00000 #define PFIT_VERT_SCALE_MASK 0xfff00000
...@@ -2668,11 +2650,11 @@ ...@@ -2668,11 +2650,11 @@
#define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */ #define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */
#define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */ #define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */
#define PIPECONF_CXSR_DOWNCLOCK (1<<16) #define PIPECONF_CXSR_DOWNCLOCK (1<<16)
#define PIPECONF_BPP_MASK (0x000000e0) #define PIPECONF_BPC_MASK (0x7 << 5)
#define PIPECONF_BPP_8 (0<<5) #define PIPECONF_8BPC (0<<5)
#define PIPECONF_BPP_10 (1<<5) #define PIPECONF_10BPC (1<<5)
#define PIPECONF_BPP_6 (2<<5) #define PIPECONF_6BPC (2<<5)
#define PIPECONF_BPP_12 (3<<5) #define PIPECONF_12BPC (3<<5)
#define PIPECONF_DITHER_EN (1<<4) #define PIPECONF_DITHER_EN (1<<4)
#define PIPECONF_DITHER_TYPE_MASK (0x0000000c) #define PIPECONF_DITHER_TYPE_MASK (0x0000000c)
#define PIPECONF_DITHER_TYPE_SP (0<<2) #define PIPECONF_DITHER_TYPE_SP (0<<2)
...@@ -2716,11 +2698,6 @@ ...@@ -2716,11 +2698,6 @@
#define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */ #define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */
#define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1) #define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1)
#define PIPE_OVERLAY_UPDATED_STATUS (1UL<<0) #define PIPE_OVERLAY_UPDATED_STATUS (1UL<<0)
#define PIPE_BPC_MASK (7 << 5) /* Ironlake */
#define PIPE_8BPC (0 << 5)
#define PIPE_10BPC (1 << 5)
#define PIPE_6BPC (2 << 5)
#define PIPE_12BPC (3 << 5)
#define PIPESRC(pipe) _PIPE(pipe, _PIPEASRC, _PIPEBSRC) #define PIPESRC(pipe) _PIPE(pipe, _PIPEASRC, _PIPEBSRC)
#define PIPECONF(tran) _TRANSCODER(tran, _PIPEACONF, _PIPEBCONF) #define PIPECONF(tran) _TRANSCODER(tran, _PIPEACONF, _PIPEBCONF)
...@@ -3578,27 +3555,30 @@ ...@@ -3578,27 +3555,30 @@
#define PORTD_PULSE_DURATION_6ms (2 << 18) #define PORTD_PULSE_DURATION_6ms (2 << 18)
#define PORTD_PULSE_DURATION_100ms (3 << 18) #define PORTD_PULSE_DURATION_100ms (3 << 18)
#define PORTD_PULSE_DURATION_MASK (3 << 18) #define PORTD_PULSE_DURATION_MASK (3 << 18)
#define PORTD_HOTPLUG_NO_DETECT (0) #define PORTD_HOTPLUG_STATUS_MASK (0x3 << 16)
#define PORTD_HOTPLUG_SHORT_DETECT (1 << 16) #define PORTD_HOTPLUG_NO_DETECT (0 << 16)
#define PORTD_HOTPLUG_LONG_DETECT (1 << 17) #define PORTD_HOTPLUG_SHORT_DETECT (1 << 16)
#define PORTD_HOTPLUG_LONG_DETECT (2 << 16)
#define PORTC_HOTPLUG_ENABLE (1 << 12) #define PORTC_HOTPLUG_ENABLE (1 << 12)
#define PORTC_PULSE_DURATION_2ms (0) #define PORTC_PULSE_DURATION_2ms (0)
#define PORTC_PULSE_DURATION_4_5ms (1 << 10) #define PORTC_PULSE_DURATION_4_5ms (1 << 10)
#define PORTC_PULSE_DURATION_6ms (2 << 10) #define PORTC_PULSE_DURATION_6ms (2 << 10)
#define PORTC_PULSE_DURATION_100ms (3 << 10) #define PORTC_PULSE_DURATION_100ms (3 << 10)
#define PORTC_PULSE_DURATION_MASK (3 << 10) #define PORTC_PULSE_DURATION_MASK (3 << 10)
#define PORTC_HOTPLUG_NO_DETECT (0) #define PORTC_HOTPLUG_STATUS_MASK (0x3 << 8)
#define PORTC_HOTPLUG_SHORT_DETECT (1 << 8) #define PORTC_HOTPLUG_NO_DETECT (0 << 8)
#define PORTC_HOTPLUG_LONG_DETECT (1 << 9) #define PORTC_HOTPLUG_SHORT_DETECT (1 << 8)
#define PORTC_HOTPLUG_LONG_DETECT (2 << 8)
#define PORTB_HOTPLUG_ENABLE (1 << 4) #define PORTB_HOTPLUG_ENABLE (1 << 4)
#define PORTB_PULSE_DURATION_2ms (0) #define PORTB_PULSE_DURATION_2ms (0)
#define PORTB_PULSE_DURATION_4_5ms (1 << 2) #define PORTB_PULSE_DURATION_4_5ms (1 << 2)
#define PORTB_PULSE_DURATION_6ms (2 << 2) #define PORTB_PULSE_DURATION_6ms (2 << 2)
#define PORTB_PULSE_DURATION_100ms (3 << 2) #define PORTB_PULSE_DURATION_100ms (3 << 2)
#define PORTB_PULSE_DURATION_MASK (3 << 2) #define PORTB_PULSE_DURATION_MASK (3 << 2)
#define PORTB_HOTPLUG_NO_DETECT (0) #define PORTB_HOTPLUG_STATUS_MASK (0x3 << 0)
#define PORTB_HOTPLUG_SHORT_DETECT (1 << 0) #define PORTB_HOTPLUG_NO_DETECT (0 << 0)
#define PORTB_HOTPLUG_LONG_DETECT (1 << 1) #define PORTB_HOTPLUG_SHORT_DETECT (1 << 0)
#define PORTB_HOTPLUG_LONG_DETECT (2 << 0)
#define PCH_GPIOA 0xc5010 #define PCH_GPIOA 0xc5010
#define PCH_GPIOB 0xc5014 #define PCH_GPIOB 0xc5014
...@@ -3817,8 +3797,6 @@ ...@@ -3817,8 +3797,6 @@
#define TRANS_FSYNC_DELAY_HB2 (1<<27) #define TRANS_FSYNC_DELAY_HB2 (1<<27)
#define TRANS_FSYNC_DELAY_HB3 (2<<27) #define TRANS_FSYNC_DELAY_HB3 (2<<27)
#define TRANS_FSYNC_DELAY_HB4 (3<<27) #define TRANS_FSYNC_DELAY_HB4 (3<<27)
#define TRANS_DP_AUDIO_ONLY (1<<26)
#define TRANS_DP_VIDEO_AUDIO (0<<26)
#define TRANS_INTERLACE_MASK (7<<21) #define TRANS_INTERLACE_MASK (7<<21)
#define TRANS_PROGRESSIVE (0<<21) #define TRANS_PROGRESSIVE (0<<21)
#define TRANS_INTERLACED (3<<21) #define TRANS_INTERLACED (3<<21)
......
...@@ -776,7 +776,7 @@ void intel_crt_init(struct drm_device *dev) ...@@ -776,7 +776,7 @@ void intel_crt_init(struct drm_device *dev)
crt->base.disable = intel_disable_crt; crt->base.disable = intel_disable_crt;
crt->base.enable = intel_enable_crt; crt->base.enable = intel_enable_crt;
if (IS_HASWELL(dev)) if (HAS_DDI(dev))
crt->base.get_hw_state = intel_ddi_get_hw_state; crt->base.get_hw_state = intel_ddi_get_hw_state;
else else
crt->base.get_hw_state = intel_crt_get_hw_state; crt->base.get_hw_state = intel_crt_get_hw_state;
......
...@@ -84,7 +84,8 @@ static enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) ...@@ -84,7 +84,8 @@ static enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
* in either FDI or DP modes only, as HDMI connections will work with both * in either FDI or DP modes only, as HDMI connections will work with both
* of those * of those
*/ */
void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, bool use_fdi_mode) static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port,
bool use_fdi_mode)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg; u32 reg;
...@@ -114,16 +115,17 @@ void intel_prepare_ddi(struct drm_device *dev) ...@@ -114,16 +115,17 @@ void intel_prepare_ddi(struct drm_device *dev)
{ {
int port; int port;
if (IS_HASWELL(dev)) { if (!HAS_DDI(dev))
for (port = PORT_A; port < PORT_E; port++) return;
intel_prepare_ddi_buffers(dev, port, false);
/* DDI E is the suggested one to work in FDI mode, so program is as such by for (port = PORT_A; port < PORT_E; port++)
* default. It will have to be re-programmed in case a digital DP output intel_prepare_ddi_buffers(dev, port, false);
* will be detected on it
*/ /* DDI E is the suggested one to work in FDI mode, so program is as such
intel_prepare_ddi_buffers(dev, PORT_E, true); * by default. It will have to be re-programmed in case a digital DP
} * output will be detected on it
*/
intel_prepare_ddi_buffers(dev, PORT_E, true);
} }
static const long hsw_ddi_buf_ctl_values[] = { static const long hsw_ddi_buf_ctl_values[] = {
...@@ -1069,7 +1071,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector) ...@@ -1069,7 +1071,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
if (port == PORT_A) if (port == PORT_A)
cpu_transcoder = TRANSCODER_EDP; cpu_transcoder = TRANSCODER_EDP;
else else
cpu_transcoder = pipe; cpu_transcoder = (enum transcoder) pipe;
tmp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); tmp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
......
This diff is collapsed.
This diff is collapsed.
...@@ -153,6 +153,7 @@ struct intel_encoder { ...@@ -153,6 +153,7 @@ struct intel_encoder {
bool cloneable; bool cloneable;
bool connectors_active; bool connectors_active;
void (*hot_plug)(struct intel_encoder *); void (*hot_plug)(struct intel_encoder *);
void (*pre_pll_enable)(struct intel_encoder *);
void (*pre_enable)(struct intel_encoder *); void (*pre_enable)(struct intel_encoder *);
void (*enable)(struct intel_encoder *); void (*enable)(struct intel_encoder *);
void (*disable)(struct intel_encoder *); void (*disable)(struct intel_encoder *);
...@@ -443,6 +444,7 @@ extern void intel_mark_idle(struct drm_device *dev); ...@@ -443,6 +444,7 @@ extern void intel_mark_idle(struct drm_device *dev);
extern void intel_mark_fb_busy(struct drm_i915_gem_object *obj); extern void intel_mark_fb_busy(struct drm_i915_gem_object *obj);
extern void intel_mark_fb_idle(struct drm_i915_gem_object *obj); extern void intel_mark_fb_idle(struct drm_i915_gem_object *obj);
extern bool intel_lvds_init(struct drm_device *dev); extern bool intel_lvds_init(struct drm_device *dev);
extern bool intel_is_dual_link_lvds(struct drm_device *dev);
extern void intel_dp_init(struct drm_device *dev, int output_reg, extern void intel_dp_init(struct drm_device *dev, int output_reg,
enum port port); enum port port);
extern void intel_dp_init_connector(struct intel_digital_port *intel_dig_port, extern void intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
...@@ -502,9 +504,10 @@ struct intel_set_config { ...@@ -502,9 +504,10 @@ struct intel_set_config {
bool mode_changed; bool mode_changed;
}; };
extern bool intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, extern int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
int x, int y, struct drm_framebuffer *old_fb); int x, int y, struct drm_framebuffer *old_fb);
extern void intel_modeset_disable(struct drm_device *dev); extern void intel_modeset_disable(struct drm_device *dev);
extern void intel_crtc_restore_mode(struct drm_crtc *crtc);
extern void intel_crtc_load_lut(struct drm_crtc *crtc); extern void intel_crtc_load_lut(struct drm_crtc *crtc);
extern void intel_crtc_update_dpms(struct drm_crtc *crtc); extern void intel_crtc_update_dpms(struct drm_crtc *crtc);
extern void intel_encoder_noop(struct drm_encoder *encoder); extern void intel_encoder_noop(struct drm_encoder *encoder);
...@@ -546,6 +549,9 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi) ...@@ -546,6 +549,9 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)
return container_of(intel_hdmi, struct intel_digital_port, hdmi); return container_of(intel_hdmi, struct intel_digital_port, hdmi);
} }
bool ibx_digital_port_connected(struct drm_i915_private *dev_priv,
struct intel_digital_port *port);
extern void intel_connector_attach_encoder(struct intel_connector *connector, extern void intel_connector_attach_encoder(struct intel_connector *connector,
struct intel_encoder *encoder); struct intel_encoder *encoder);
extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector); extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector);
...@@ -589,6 +595,7 @@ extern int intel_framebuffer_init(struct drm_device *dev, ...@@ -589,6 +595,7 @@ extern int intel_framebuffer_init(struct drm_device *dev,
struct drm_mode_fb_cmd2 *mode_cmd, struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_i915_gem_object *obj); struct drm_i915_gem_object *obj);
extern int intel_fbdev_init(struct drm_device *dev); extern int intel_fbdev_init(struct drm_device *dev);
extern void intel_fbdev_initial_config(struct drm_device *dev);
extern void intel_fbdev_fini(struct drm_device *dev); extern void intel_fbdev_fini(struct drm_device *dev);
extern void intel_fbdev_set_suspend(struct drm_device *dev, int state); extern void intel_fbdev_set_suspend(struct drm_device *dev, int state);
extern void intel_prepare_page_flip(struct drm_device *dev, int plane); extern void intel_prepare_page_flip(struct drm_device *dev, int plane);
......
...@@ -83,7 +83,9 @@ static int intelfb_create(struct intel_fbdev *ifbdev, ...@@ -83,7 +83,9 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
size = mode_cmd.pitches[0] * mode_cmd.height; size = mode_cmd.pitches[0] * mode_cmd.height;
size = ALIGN(size, PAGE_SIZE); size = ALIGN(size, PAGE_SIZE);
obj = i915_gem_alloc_object(dev, size); obj = i915_gem_object_create_stolen(dev, size);
if (obj == NULL)
obj = i915_gem_alloc_object(dev, size);
if (!obj) { if (!obj) {
DRM_ERROR("failed to allocate framebuffer\n"); DRM_ERROR("failed to allocate framebuffer\n");
ret = -ENOMEM; ret = -ENOMEM;
...@@ -153,6 +155,13 @@ static int intelfb_create(struct intel_fbdev *ifbdev, ...@@ -153,6 +155,13 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height);
/* If the object is shmemfs backed, it will have given us zeroed pages.
* If the object is stolen however, it will be full of whatever
* garbage was left in there.
*/
if (ifbdev->ifb.obj->stolen)
memset_io(info->screen_base, 0, info->screen_size);
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n",
...@@ -241,10 +250,18 @@ int intel_fbdev_init(struct drm_device *dev) ...@@ -241,10 +250,18 @@ int intel_fbdev_init(struct drm_device *dev)
} }
drm_fb_helper_single_add_all_connectors(&ifbdev->helper); drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
drm_fb_helper_initial_config(&ifbdev->helper, 32);
return 0; return 0;
} }
void intel_fbdev_initial_config(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
/* Due to peculiar init order wrt to hpd handling this is separate. */
drm_fb_helper_initial_config(&dev_priv->fbdev->helper, 32);
}
void intel_fbdev_fini(struct drm_device *dev) void intel_fbdev_fini(struct drm_device *dev)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
......
...@@ -48,7 +48,7 @@ assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi) ...@@ -48,7 +48,7 @@ assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t enabled_bits; uint32_t enabled_bits;
enabled_bits = IS_HASWELL(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE; enabled_bits = HAS_DDI(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE;
WARN(I915_READ(intel_hdmi->sdvox_reg) & enabled_bits, WARN(I915_READ(intel_hdmi->sdvox_reg) & enabled_bits,
"HDMI port enabled, expecting disabled\n"); "HDMI port enabled, expecting disabled\n");
...@@ -793,16 +793,21 @@ static bool g4x_hdmi_connected(struct intel_hdmi *intel_hdmi) ...@@ -793,16 +793,21 @@ static bool g4x_hdmi_connected(struct intel_hdmi *intel_hdmi)
static enum drm_connector_status static enum drm_connector_status
intel_hdmi_detect(struct drm_connector *connector, bool force) intel_hdmi_detect(struct drm_connector *connector, bool force)
{ {
struct drm_device *dev = connector->dev;
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
struct intel_digital_port *intel_dig_port = struct intel_digital_port *intel_dig_port =
hdmi_to_dig_port(intel_hdmi); hdmi_to_dig_port(intel_hdmi);
struct intel_encoder *intel_encoder = &intel_dig_port->base; struct intel_encoder *intel_encoder = &intel_dig_port->base;
struct drm_i915_private *dev_priv = connector->dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct edid *edid; struct edid *edid;
enum drm_connector_status status = connector_status_disconnected; enum drm_connector_status status = connector_status_disconnected;
if (IS_G4X(connector->dev) && !g4x_hdmi_connected(intel_hdmi))
if (IS_G4X(dev) && !g4x_hdmi_connected(intel_hdmi))
return status; return status;
else if (HAS_PCH_SPLIT(dev) &&
!ibx_digital_port_connected(dev_priv, intel_dig_port))
return status;
intel_hdmi->has_hdmi_sink = false; intel_hdmi->has_hdmi_sink = false;
intel_hdmi->has_audio = false; intel_hdmi->has_audio = false;
...@@ -912,11 +917,8 @@ intel_hdmi_set_property(struct drm_connector *connector, ...@@ -912,11 +917,8 @@ intel_hdmi_set_property(struct drm_connector *connector,
return -EINVAL; return -EINVAL;
done: done:
if (intel_dig_port->base.base.crtc) { if (intel_dig_port->base.base.crtc)
struct drm_crtc *crtc = intel_dig_port->base.base.crtc; intel_crtc_restore_mode(intel_dig_port->base.base.crtc);
intel_set_mode(crtc, &crtc->mode,
crtc->x, crtc->y, crtc->fb);
}
return 0; return 0;
} }
...@@ -1013,7 +1015,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, ...@@ -1013,7 +1015,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
intel_hdmi->set_infoframes = cpt_set_infoframes; intel_hdmi->set_infoframes = cpt_set_infoframes;
} }
if (IS_HASWELL(dev)) if (HAS_DDI(dev))
intel_connector->get_hw_state = intel_ddi_connector_get_hw_state; intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
else else
intel_connector->get_hw_state = intel_connector_get_hw_state; intel_connector->get_hw_state = intel_connector_get_hw_state;
......
...@@ -63,6 +63,7 @@ intel_i2c_reset(struct drm_device *dev) ...@@ -63,6 +63,7 @@ intel_i2c_reset(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
I915_WRITE(dev_priv->gpio_mmio_base + GMBUS0, 0); I915_WRITE(dev_priv->gpio_mmio_base + GMBUS0, 0);
I915_WRITE(dev_priv->gpio_mmio_base + GMBUS4, 0);
} }
static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable) static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable)
...@@ -202,6 +203,68 @@ intel_gpio_setup(struct intel_gmbus *bus, u32 pin) ...@@ -202,6 +203,68 @@ intel_gpio_setup(struct intel_gmbus *bus, u32 pin)
algo->data = bus; algo->data = bus;
} }
#define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->gen >= 4)
static int
gmbus_wait_hw_status(struct drm_i915_private *dev_priv,
u32 gmbus2_status,
u32 gmbus4_irq_en)
{
int i;
int reg_offset = dev_priv->gpio_mmio_base;
u32 gmbus2 = 0;
DEFINE_WAIT(wait);
/* Important: The hw handles only the first bit, so set only one! Since
* we also need to check for NAKs besides the hw ready/idle signal, we
* need to wake up periodically and check that ourselves. */
I915_WRITE(GMBUS4 + reg_offset, gmbus4_irq_en);
for (i = 0; i < msecs_to_jiffies(50) + 1; i++) {
prepare_to_wait(&dev_priv->gmbus_wait_queue, &wait,
TASK_UNINTERRUPTIBLE);
gmbus2 = I915_READ_NOTRACE(GMBUS2 + reg_offset);
if (gmbus2 & (GMBUS_SATOER | gmbus2_status))
break;
schedule_timeout(1);
}
finish_wait(&dev_priv->gmbus_wait_queue, &wait);
I915_WRITE(GMBUS4 + reg_offset, 0);
if (gmbus2 & GMBUS_SATOER)
return -ENXIO;
if (gmbus2 & gmbus2_status)
return 0;
return -ETIMEDOUT;
}
static int
gmbus_wait_idle(struct drm_i915_private *dev_priv)
{
int ret;
int reg_offset = dev_priv->gpio_mmio_base;
#define C ((I915_READ_NOTRACE(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0)
if (!HAS_GMBUS_IRQ(dev_priv->dev))
return wait_for(C, 10);
/* Important: The hw handles only the first bit, so set only one! */
I915_WRITE(GMBUS4 + reg_offset, GMBUS_IDLE_EN);
ret = wait_event_timeout(dev_priv->gmbus_wait_queue, C, 10);
I915_WRITE(GMBUS4 + reg_offset, 0);
if (ret)
return 0;
else
return -ETIMEDOUT;
#undef C
}
static int static int
gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
u32 gmbus1_index) u32 gmbus1_index)
...@@ -219,15 +282,11 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, ...@@ -219,15 +282,11 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
while (len) { while (len) {
int ret; int ret;
u32 val, loop = 0; u32 val, loop = 0;
u32 gmbus2;
ret = wait_for((gmbus2 = I915_READ(GMBUS2 + reg_offset)) & ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY,
(GMBUS_SATOER | GMBUS_HW_RDY), GMBUS_HW_RDY_EN);
50);
if (ret) if (ret)
return -ETIMEDOUT; return ret;
if (gmbus2 & GMBUS_SATOER)
return -ENXIO;
val = I915_READ(GMBUS3 + reg_offset); val = I915_READ(GMBUS3 + reg_offset);
do { do {
...@@ -261,7 +320,6 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) ...@@ -261,7 +320,6 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
while (len) { while (len) {
int ret; int ret;
u32 gmbus2;
val = loop = 0; val = loop = 0;
do { do {
...@@ -270,13 +328,10 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) ...@@ -270,13 +328,10 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
I915_WRITE(GMBUS3 + reg_offset, val); I915_WRITE(GMBUS3 + reg_offset, val);
ret = wait_for((gmbus2 = I915_READ(GMBUS2 + reg_offset)) & ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY,
(GMBUS_SATOER | GMBUS_HW_RDY), GMBUS_HW_RDY_EN);
50);
if (ret) if (ret)
return -ETIMEDOUT; return ret;
if (gmbus2 & GMBUS_SATOER)
return -ENXIO;
} }
return 0; return 0;
} }
...@@ -345,8 +400,6 @@ gmbus_xfer(struct i2c_adapter *adapter, ...@@ -345,8 +400,6 @@ gmbus_xfer(struct i2c_adapter *adapter,
I915_WRITE(GMBUS0 + reg_offset, bus->reg0); I915_WRITE(GMBUS0 + reg_offset, bus->reg0);
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
u32 gmbus2;
if (gmbus_is_index_read(msgs, i, num)) { if (gmbus_is_index_read(msgs, i, num)) {
ret = gmbus_xfer_index_read(dev_priv, &msgs[i]); ret = gmbus_xfer_index_read(dev_priv, &msgs[i]);
i += 1; /* set i to the index of the read xfer */ i += 1; /* set i to the index of the read xfer */
...@@ -361,13 +414,12 @@ gmbus_xfer(struct i2c_adapter *adapter, ...@@ -361,13 +414,12 @@ gmbus_xfer(struct i2c_adapter *adapter,
if (ret == -ENXIO) if (ret == -ENXIO)
goto clear_err; goto clear_err;
ret = wait_for((gmbus2 = I915_READ(GMBUS2 + reg_offset)) & ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_WAIT_PHASE,
(GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), GMBUS_HW_WAIT_EN);
50); if (ret == -ENXIO)
goto clear_err;
if (ret) if (ret)
goto timeout; goto timeout;
if (gmbus2 & GMBUS_SATOER)
goto clear_err;
} }
/* Generate a STOP condition on the bus. Note that gmbus can't generata /* Generate a STOP condition on the bus. Note that gmbus can't generata
...@@ -380,8 +432,7 @@ gmbus_xfer(struct i2c_adapter *adapter, ...@@ -380,8 +432,7 @@ gmbus_xfer(struct i2c_adapter *adapter,
* We will re-enable it at the start of the next xfer, * We will re-enable it at the start of the next xfer,
* till then let it sleep. * till then let it sleep.
*/ */
if (wait_for((I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0, if (gmbus_wait_idle(dev_priv)) {
10)) {
DRM_DEBUG_KMS("GMBUS [%s] timed out waiting for idle\n", DRM_DEBUG_KMS("GMBUS [%s] timed out waiting for idle\n",
adapter->name); adapter->name);
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
...@@ -405,8 +456,7 @@ gmbus_xfer(struct i2c_adapter *adapter, ...@@ -405,8 +456,7 @@ gmbus_xfer(struct i2c_adapter *adapter,
* it's slow responding and only answers on the 2nd retry. * it's slow responding and only answers on the 2nd retry.
*/ */
ret = -ENXIO; ret = -ENXIO;
if (wait_for((I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0, if (gmbus_wait_idle(dev_priv)) {
10)) {
DRM_DEBUG_KMS("GMBUS [%s] timed out after NAK\n", DRM_DEBUG_KMS("GMBUS [%s] timed out after NAK\n",
adapter->name); adapter->name);
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
...@@ -469,6 +519,7 @@ int intel_setup_gmbus(struct drm_device *dev) ...@@ -469,6 +519,7 @@ int intel_setup_gmbus(struct drm_device *dev)
dev_priv->gpio_mmio_base = 0; dev_priv->gpio_mmio_base = 0;
mutex_init(&dev_priv->gmbus_mutex); mutex_init(&dev_priv->gmbus_mutex);
init_waitqueue_head(&dev_priv->gmbus_wait_queue);
for (i = 0; i < GMBUS_NUM_PORTS; i++) { for (i = 0; i < GMBUS_NUM_PORTS; i++) {
struct intel_gmbus *bus = &dev_priv->gmbus[i]; struct intel_gmbus *bus = &dev_priv->gmbus[i];
......
...@@ -52,6 +52,8 @@ struct intel_lvds_encoder { ...@@ -52,6 +52,8 @@ struct intel_lvds_encoder {
u32 pfit_control; u32 pfit_control;
u32 pfit_pgm_ratios; u32 pfit_pgm_ratios;
bool pfit_dirty; bool pfit_dirty;
bool is_dual_link;
u32 reg;
struct intel_lvds_connector *attached_connector; struct intel_lvds_connector *attached_connector;
}; };
...@@ -71,15 +73,10 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder, ...@@ -71,15 +73,10 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
{ {
struct drm_device *dev = encoder->base.dev; struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 lvds_reg, tmp; struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
u32 tmp;
if (HAS_PCH_SPLIT(dev)) {
lvds_reg = PCH_LVDS;
} else {
lvds_reg = LVDS;
}
tmp = I915_READ(lvds_reg); tmp = I915_READ(lvds_encoder->reg);
if (!(tmp & LVDS_PORT_EN)) if (!(tmp & LVDS_PORT_EN))
return false; return false;
...@@ -92,6 +89,68 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder, ...@@ -92,6 +89,68 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
return true; return true;
} }
/* The LVDS pin pair needs to be on before the DPLLs are enabled.
* This is an exception to the general rule that mode_set doesn't turn
* things on.
*/
static void intel_pre_pll_enable_lvds(struct intel_encoder *encoder)
{
struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
struct drm_display_mode *fixed_mode =
lvds_encoder->attached_connector->base.panel.fixed_mode;
int pipe = intel_crtc->pipe;
u32 temp;
temp = I915_READ(lvds_encoder->reg);
temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
if (HAS_PCH_CPT(dev)) {
temp &= ~PORT_TRANS_SEL_MASK;
temp |= PORT_TRANS_SEL_CPT(pipe);
} else {
if (pipe == 1) {
temp |= LVDS_PIPEB_SELECT;
} else {
temp &= ~LVDS_PIPEB_SELECT;
}
}
/* set the corresponsding LVDS_BORDER bit */
temp |= dev_priv->lvds_border_bits;
/* Set the B0-B3 data pairs corresponding to whether we're going to
* set the DPLLs for dual-channel mode or not.
*/
if (lvds_encoder->is_dual_link)
temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
else
temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
* appropriately here, but we need to look more thoroughly into how
* panels behave in the two modes.
*/
/* Set the dithering flag on LVDS as needed, note that there is no
* special lvds dither control bit on pch-split platforms, dithering is
* only controlled through the PIPECONF reg. */
if (INTEL_INFO(dev)->gen == 4) {
if (dev_priv->lvds_dither)
temp |= LVDS_ENABLE_DITHER;
else
temp &= ~LVDS_ENABLE_DITHER;
}
temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
if (fixed_mode->flags & DRM_MODE_FLAG_NHSYNC)
temp |= LVDS_HSYNC_POLARITY;
if (fixed_mode->flags & DRM_MODE_FLAG_NVSYNC)
temp |= LVDS_VSYNC_POLARITY;
I915_WRITE(lvds_encoder->reg, temp);
}
/** /**
* Sets the power state for the panel. * Sets the power state for the panel.
*/ */
...@@ -101,19 +160,17 @@ static void intel_enable_lvds(struct intel_encoder *encoder) ...@@ -101,19 +160,17 @@ static void intel_enable_lvds(struct intel_encoder *encoder)
struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 ctl_reg, lvds_reg, stat_reg; u32 ctl_reg, stat_reg;
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
ctl_reg = PCH_PP_CONTROL; ctl_reg = PCH_PP_CONTROL;
lvds_reg = PCH_LVDS;
stat_reg = PCH_PP_STATUS; stat_reg = PCH_PP_STATUS;
} else { } else {
ctl_reg = PP_CONTROL; ctl_reg = PP_CONTROL;
lvds_reg = LVDS;
stat_reg = PP_STATUS; stat_reg = PP_STATUS;
} }
I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN); I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) | LVDS_PORT_EN);
if (lvds_encoder->pfit_dirty) { if (lvds_encoder->pfit_dirty) {
/* /*
...@@ -132,7 +189,7 @@ static void intel_enable_lvds(struct intel_encoder *encoder) ...@@ -132,7 +189,7 @@ static void intel_enable_lvds(struct intel_encoder *encoder)
} }
I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON); I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
POSTING_READ(lvds_reg); POSTING_READ(lvds_encoder->reg);
if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000)) if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000))
DRM_ERROR("timed out waiting for panel to power on\n"); DRM_ERROR("timed out waiting for panel to power on\n");
...@@ -144,15 +201,13 @@ static void intel_disable_lvds(struct intel_encoder *encoder) ...@@ -144,15 +201,13 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
struct drm_device *dev = encoder->base.dev; struct drm_device *dev = encoder->base.dev;
struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 ctl_reg, lvds_reg, stat_reg; u32 ctl_reg, stat_reg;
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
ctl_reg = PCH_PP_CONTROL; ctl_reg = PCH_PP_CONTROL;
lvds_reg = PCH_LVDS;
stat_reg = PCH_PP_STATUS; stat_reg = PCH_PP_STATUS;
} else { } else {
ctl_reg = PP_CONTROL; ctl_reg = PP_CONTROL;
lvds_reg = LVDS;
stat_reg = PP_STATUS; stat_reg = PP_STATUS;
} }
...@@ -167,8 +222,8 @@ static void intel_disable_lvds(struct intel_encoder *encoder) ...@@ -167,8 +222,8 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
lvds_encoder->pfit_dirty = true; lvds_encoder->pfit_dirty = true;
} }
I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN); I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) & ~LVDS_PORT_EN);
POSTING_READ(lvds_reg); POSTING_READ(lvds_encoder->reg);
} }
static int intel_lvds_mode_valid(struct drm_connector *connector, static int intel_lvds_mode_valid(struct drm_connector *connector,
...@@ -591,8 +646,7 @@ static int intel_lvds_set_property(struct drm_connector *connector, ...@@ -591,8 +646,7 @@ static int intel_lvds_set_property(struct drm_connector *connector,
* If the CRTC is enabled, the display will be changed * If the CRTC is enabled, the display will be changed
* according to the new panel fitting mode. * according to the new panel fitting mode.
*/ */
intel_set_mode(crtc, &crtc->mode, intel_crtc_restore_mode(crtc);
crtc->x, crtc->y, crtc->fb);
} }
} }
...@@ -903,6 +957,66 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev, ...@@ -903,6 +957,66 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev,
return false; return false;
} }
static int intel_dual_link_lvds_callback(const struct dmi_system_id *id)
{
DRM_INFO("Forcing lvds to dual link mode on %s\n", id->ident);
return 1;
}
static const struct dmi_system_id intel_dual_link_lvds[] = {
{
.callback = intel_dual_link_lvds_callback,
.ident = "Apple MacBook Pro (Core i5/i7 Series)",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"),
},
},
{ } /* terminating entry */
};
bool intel_is_dual_link_lvds(struct drm_device *dev)
{
struct intel_encoder *encoder;
struct intel_lvds_encoder *lvds_encoder;
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
if (encoder->type == INTEL_OUTPUT_LVDS) {
lvds_encoder = to_lvds_encoder(&encoder->base);
return lvds_encoder->is_dual_link;
}
}
return false;
}
static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
{
struct drm_device *dev = lvds_encoder->base.base.dev;
unsigned int val;
struct drm_i915_private *dev_priv = dev->dev_private;
/* use the module option value if specified */
if (i915_lvds_channel_mode > 0)
return i915_lvds_channel_mode == 2;
if (dmi_check_system(intel_dual_link_lvds))
return true;
/* BIOS should set the proper LVDS register value at boot, but
* in reality, it doesn't set the value when the lid is closed;
* we need to check "the value to be set" in VBT when LVDS
* register is uninitialized.
*/
val = I915_READ(lvds_encoder->reg);
if (!(val & ~(LVDS_PIPE_MASK | LVDS_DETECTED)))
val = dev_priv->bios_lvds_val;
return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
}
static bool intel_lvds_supported(struct drm_device *dev) static bool intel_lvds_supported(struct drm_device *dev)
{ {
/* With the introduction of the PCH we gained a dedicated /* With the introduction of the PCH we gained a dedicated
...@@ -988,6 +1102,7 @@ bool intel_lvds_init(struct drm_device *dev) ...@@ -988,6 +1102,7 @@ bool intel_lvds_init(struct drm_device *dev)
DRM_MODE_ENCODER_LVDS); DRM_MODE_ENCODER_LVDS);
intel_encoder->enable = intel_enable_lvds; intel_encoder->enable = intel_enable_lvds;
intel_encoder->pre_pll_enable = intel_pre_pll_enable_lvds;
intel_encoder->disable = intel_disable_lvds; intel_encoder->disable = intel_disable_lvds;
intel_encoder->get_hw_state = intel_lvds_get_hw_state; intel_encoder->get_hw_state = intel_lvds_get_hw_state;
intel_connector->get_hw_state = intel_connector_get_hw_state; intel_connector->get_hw_state = intel_connector_get_hw_state;
...@@ -1009,6 +1124,12 @@ bool intel_lvds_init(struct drm_device *dev) ...@@ -1009,6 +1124,12 @@ bool intel_lvds_init(struct drm_device *dev)
connector->interlace_allowed = false; connector->interlace_allowed = false;
connector->doublescan_allowed = false; connector->doublescan_allowed = false;
if (HAS_PCH_SPLIT(dev)) {
lvds_encoder->reg = PCH_LVDS;
} else {
lvds_encoder->reg = LVDS;
}
/* create the scaling mode property */ /* create the scaling mode property */
drm_mode_create_scaling_mode_property(dev); drm_mode_create_scaling_mode_property(dev);
drm_object_attach_property(&connector->base, drm_object_attach_property(&connector->base,
...@@ -1109,6 +1230,10 @@ bool intel_lvds_init(struct drm_device *dev) ...@@ -1109,6 +1230,10 @@ bool intel_lvds_init(struct drm_device *dev)
goto failed; goto failed;
out: out:
lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
DRM_DEBUG_KMS("detected %s-link lvds configuration\n",
lvds_encoder->is_dual_link ? "dual" : "single");
/* /*
* Unlock registers and just * Unlock registers and just
* leave them unlocked * leave them unlocked
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include <linux/fb.h> #include <linux/fb.h>
#include <drm/drm_edid.h> #include <drm/drm_edid.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_edid.h>
#include "intel_drv.h" #include "intel_drv.h"
#include "i915_drv.h" #include "i915_drv.h"
......
...@@ -1333,8 +1333,10 @@ void intel_setup_overlay(struct drm_device *dev) ...@@ -1333,8 +1333,10 @@ void intel_setup_overlay(struct drm_device *dev)
overlay->dev = dev; overlay->dev = dev;
reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE); reg_bo = i915_gem_object_create_stolen(dev, PAGE_SIZE);
if (!reg_bo) if (reg_bo == NULL)
reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
if (reg_bo == NULL)
goto out_free; goto out_free;
overlay->reg_bo = reg_bo; overlay->reg_bo = reg_bo;
......
...@@ -440,12 +440,6 @@ void intel_update_fbc(struct drm_device *dev) ...@@ -440,12 +440,6 @@ void intel_update_fbc(struct drm_device *dev)
dev_priv->no_fbc_reason = FBC_MODULE_PARAM; dev_priv->no_fbc_reason = FBC_MODULE_PARAM;
goto out_disable; goto out_disable;
} }
if (intel_fb->obj->base.size > dev_priv->cfb_size) {
DRM_DEBUG_KMS("framebuffer too large, disabling "
"compression\n");
dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
goto out_disable;
}
if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) || if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) ||
(crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) { (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) {
DRM_DEBUG_KMS("mode incompatible with compression, " DRM_DEBUG_KMS("mode incompatible with compression, "
...@@ -479,6 +473,14 @@ void intel_update_fbc(struct drm_device *dev) ...@@ -479,6 +473,14 @@ void intel_update_fbc(struct drm_device *dev)
if (in_dbg_master()) if (in_dbg_master())
goto out_disable; goto out_disable;
if (i915_gem_stolen_setup_compression(dev, intel_fb->obj->base.size)) {
DRM_INFO("not enough stolen space for compressed buffer (need %zd bytes), disabling\n", intel_fb->obj->base.size);
DRM_INFO("hint: you may be able to increase stolen memory size in the BIOS to avoid this\n");
DRM_DEBUG_KMS("framebuffer too large, disabling compression\n");
dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
goto out_disable;
}
/* If the scanout has not changed, don't modify the FBC settings. /* If the scanout has not changed, don't modify the FBC settings.
* Note that we make the fundamental assumption that the fb->obj * Note that we make the fundamental assumption that the fb->obj
* cannot be unpinned (and have its GTT offset and fence revoked) * cannot be unpinned (and have its GTT offset and fence revoked)
...@@ -526,6 +528,7 @@ void intel_update_fbc(struct drm_device *dev) ...@@ -526,6 +528,7 @@ void intel_update_fbc(struct drm_device *dev)
DRM_DEBUG_KMS("unsupported config, disabling FBC\n"); DRM_DEBUG_KMS("unsupported config, disabling FBC\n");
intel_disable_fbc(dev); intel_disable_fbc(dev);
} }
i915_gem_stolen_cleanup_compression(dev);
} }
static void i915_pineview_get_mem_freq(struct drm_device *dev) static void i915_pineview_get_mem_freq(struct drm_device *dev)
......
...@@ -601,6 +601,13 @@ gen6_add_request(struct intel_ring_buffer *ring) ...@@ -601,6 +601,13 @@ gen6_add_request(struct intel_ring_buffer *ring)
return 0; return 0;
} }
static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev,
u32 seqno)
{
struct drm_i915_private *dev_priv = dev->dev_private;
return dev_priv->last_seqno < seqno;
}
/** /**
* intel_ring_sync - sync the waiter to the signaller on seqno * intel_ring_sync - sync the waiter to the signaller on seqno
* *
...@@ -631,11 +638,20 @@ gen6_ring_sync(struct intel_ring_buffer *waiter, ...@@ -631,11 +638,20 @@ gen6_ring_sync(struct intel_ring_buffer *waiter,
if (ret) if (ret)
return ret; return ret;
intel_ring_emit(waiter, /* If seqno wrap happened, omit the wait with no-ops */
dw1 | signaller->semaphore_register[waiter->id]); if (likely(!i915_gem_has_seqno_wrapped(waiter->dev, seqno))) {
intel_ring_emit(waiter, seqno); intel_ring_emit(waiter,
intel_ring_emit(waiter, 0); dw1 |
intel_ring_emit(waiter, MI_NOOP); signaller->semaphore_register[waiter->id]);
intel_ring_emit(waiter, seqno);
intel_ring_emit(waiter, 0);
intel_ring_emit(waiter, MI_NOOP);
} else {
intel_ring_emit(waiter, MI_NOOP);
intel_ring_emit(waiter, MI_NOOP);
intel_ring_emit(waiter, MI_NOOP);
intel_ring_emit(waiter, MI_NOOP);
}
intel_ring_advance(waiter); intel_ring_advance(waiter);
return 0; return 0;
...@@ -716,6 +732,12 @@ ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) ...@@ -716,6 +732,12 @@ ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency)
return intel_read_status_page(ring, I915_GEM_HWS_INDEX); return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
} }
static void
ring_set_seqno(struct intel_ring_buffer *ring, u32 seqno)
{
intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno);
}
static u32 static u32
pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency)
{ {
...@@ -723,6 +745,13 @@ pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) ...@@ -723,6 +745,13 @@ pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency)
return pc->cpu_page[0]; return pc->cpu_page[0];
} }
static void
pc_render_set_seqno(struct intel_ring_buffer *ring, u32 seqno)
{
struct pipe_control *pc = ring->private;
pc->cpu_page[0] = seqno;
}
static bool static bool
gen5_ring_get_irq(struct intel_ring_buffer *ring) gen5_ring_get_irq(struct intel_ring_buffer *ring)
{ {
...@@ -1152,7 +1181,11 @@ static int intel_init_ring_buffer(struct drm_device *dev, ...@@ -1152,7 +1181,11 @@ static int intel_init_ring_buffer(struct drm_device *dev,
return ret; return ret;
} }
obj = i915_gem_alloc_object(dev, ring->size); obj = NULL;
if (!HAS_LLC(dev))
obj = i915_gem_object_create_stolen(dev, ring->size);
if (obj == NULL)
obj = i915_gem_alloc_object(dev, ring->size);
if (obj == NULL) { if (obj == NULL) {
DRM_ERROR("Failed to allocate ringbuffer\n"); DRM_ERROR("Failed to allocate ringbuffer\n");
ret = -ENOMEM; ret = -ENOMEM;
...@@ -1190,6 +1223,8 @@ static int intel_init_ring_buffer(struct drm_device *dev, ...@@ -1190,6 +1223,8 @@ static int intel_init_ring_buffer(struct drm_device *dev,
if (IS_I830(ring->dev) || IS_845G(ring->dev)) if (IS_I830(ring->dev) || IS_845G(ring->dev))
ring->effective_size -= 128; ring->effective_size -= 128;
intel_ring_init_seqno(ring, dev_priv->last_seqno);
return 0; return 0;
err_unmap: err_unmap:
...@@ -1398,11 +1433,31 @@ intel_ring_alloc_seqno(struct intel_ring_buffer *ring) ...@@ -1398,11 +1433,31 @@ intel_ring_alloc_seqno(struct intel_ring_buffer *ring)
return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_request); return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_request);
} }
static int __intel_ring_begin(struct intel_ring_buffer *ring,
int bytes)
{
int ret;
if (unlikely(ring->tail + bytes > ring->effective_size)) {
ret = intel_wrap_ring_buffer(ring);
if (unlikely(ret))
return ret;
}
if (unlikely(ring->space < bytes)) {
ret = ring_wait_for_space(ring, bytes);
if (unlikely(ret))
return ret;
}
ring->space -= bytes;
return 0;
}
int intel_ring_begin(struct intel_ring_buffer *ring, int intel_ring_begin(struct intel_ring_buffer *ring,
int num_dwords) int num_dwords)
{ {
drm_i915_private_t *dev_priv = ring->dev->dev_private; drm_i915_private_t *dev_priv = ring->dev->dev_private;
int n = 4*num_dwords;
int ret; int ret;
ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible);
...@@ -1414,20 +1469,21 @@ int intel_ring_begin(struct intel_ring_buffer *ring, ...@@ -1414,20 +1469,21 @@ int intel_ring_begin(struct intel_ring_buffer *ring,
if (ret) if (ret)
return ret; return ret;
if (unlikely(ring->tail + n > ring->effective_size)) { return __intel_ring_begin(ring, num_dwords * sizeof(uint32_t));
ret = intel_wrap_ring_buffer(ring); }
if (unlikely(ret))
return ret;
}
if (unlikely(ring->space < n)) { void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno)
ret = ring_wait_for_space(ring, n); {
if (unlikely(ret)) struct drm_i915_private *dev_priv = ring->dev->dev_private;
return ret;
BUG_ON(ring->outstanding_lazy_request);
if (INTEL_INFO(ring->dev)->gen >= 6) {
I915_WRITE(RING_SYNC_0(ring->mmio_base), 0);
I915_WRITE(RING_SYNC_1(ring->mmio_base), 0);
} }
ring->space -= n; ring->set_seqno(ring, seqno);
return 0;
} }
void intel_ring_advance(struct intel_ring_buffer *ring) void intel_ring_advance(struct intel_ring_buffer *ring)
...@@ -1592,6 +1648,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ...@@ -1592,6 +1648,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
ring->irq_put = gen6_ring_put_irq; ring->irq_put = gen6_ring_put_irq;
ring->irq_enable_mask = GT_USER_INTERRUPT; ring->irq_enable_mask = GT_USER_INTERRUPT;
ring->get_seqno = gen6_ring_get_seqno; ring->get_seqno = gen6_ring_get_seqno;
ring->set_seqno = ring_set_seqno;
ring->sync_to = gen6_ring_sync; ring->sync_to = gen6_ring_sync;
ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_INVALID; ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_INVALID;
ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_RV; ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_RV;
...@@ -1602,6 +1659,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ...@@ -1602,6 +1659,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
ring->add_request = pc_render_add_request; ring->add_request = pc_render_add_request;
ring->flush = gen4_render_ring_flush; ring->flush = gen4_render_ring_flush;
ring->get_seqno = pc_render_get_seqno; ring->get_seqno = pc_render_get_seqno;
ring->set_seqno = pc_render_set_seqno;
ring->irq_get = gen5_ring_get_irq; ring->irq_get = gen5_ring_get_irq;
ring->irq_put = gen5_ring_put_irq; ring->irq_put = gen5_ring_put_irq;
ring->irq_enable_mask = GT_USER_INTERRUPT | GT_PIPE_NOTIFY; ring->irq_enable_mask = GT_USER_INTERRUPT | GT_PIPE_NOTIFY;
...@@ -1612,6 +1670,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ...@@ -1612,6 +1670,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
else else
ring->flush = gen4_render_ring_flush; ring->flush = gen4_render_ring_flush;
ring->get_seqno = ring_get_seqno; ring->get_seqno = ring_get_seqno;
ring->set_seqno = ring_set_seqno;
if (IS_GEN2(dev)) { if (IS_GEN2(dev)) {
ring->irq_get = i8xx_ring_get_irq; ring->irq_get = i8xx_ring_get_irq;
ring->irq_put = i8xx_ring_put_irq; ring->irq_put = i8xx_ring_put_irq;
...@@ -1683,6 +1742,7 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size) ...@@ -1683,6 +1742,7 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)
else else
ring->flush = gen4_render_ring_flush; ring->flush = gen4_render_ring_flush;
ring->get_seqno = ring_get_seqno; ring->get_seqno = ring_get_seqno;
ring->set_seqno = ring_set_seqno;
if (IS_GEN2(dev)) { if (IS_GEN2(dev)) {
ring->irq_get = i8xx_ring_get_irq; ring->irq_get = i8xx_ring_get_irq;
ring->irq_put = i8xx_ring_put_irq; ring->irq_put = i8xx_ring_put_irq;
...@@ -1743,6 +1803,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) ...@@ -1743,6 +1803,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)
ring->flush = gen6_ring_flush; ring->flush = gen6_ring_flush;
ring->add_request = gen6_add_request; ring->add_request = gen6_add_request;
ring->get_seqno = gen6_ring_get_seqno; ring->get_seqno = gen6_ring_get_seqno;
ring->set_seqno = ring_set_seqno;
ring->irq_enable_mask = GEN6_BSD_USER_INTERRUPT; ring->irq_enable_mask = GEN6_BSD_USER_INTERRUPT;
ring->irq_get = gen6_ring_get_irq; ring->irq_get = gen6_ring_get_irq;
ring->irq_put = gen6_ring_put_irq; ring->irq_put = gen6_ring_put_irq;
...@@ -1758,6 +1819,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) ...@@ -1758,6 +1819,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)
ring->flush = bsd_ring_flush; ring->flush = bsd_ring_flush;
ring->add_request = i9xx_add_request; ring->add_request = i9xx_add_request;
ring->get_seqno = ring_get_seqno; ring->get_seqno = ring_get_seqno;
ring->set_seqno = ring_set_seqno;
if (IS_GEN5(dev)) { if (IS_GEN5(dev)) {
ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; ring->irq_enable_mask = GT_BSD_USER_INTERRUPT;
ring->irq_get = gen5_ring_get_irq; ring->irq_get = gen5_ring_get_irq;
...@@ -1787,6 +1849,7 @@ int intel_init_blt_ring_buffer(struct drm_device *dev) ...@@ -1787,6 +1849,7 @@ int intel_init_blt_ring_buffer(struct drm_device *dev)
ring->flush = blt_ring_flush; ring->flush = blt_ring_flush;
ring->add_request = gen6_add_request; ring->add_request = gen6_add_request;
ring->get_seqno = gen6_ring_get_seqno; ring->get_seqno = gen6_ring_get_seqno;
ring->set_seqno = ring_set_seqno;
ring->irq_enable_mask = GEN6_BLITTER_USER_INTERRUPT; ring->irq_enable_mask = GEN6_BLITTER_USER_INTERRUPT;
ring->irq_get = gen6_ring_get_irq; ring->irq_get = gen6_ring_get_irq;
ring->irq_put = gen6_ring_put_irq; ring->irq_put = gen6_ring_put_irq;
......
...@@ -90,6 +90,8 @@ struct intel_ring_buffer { ...@@ -90,6 +90,8 @@ struct intel_ring_buffer {
*/ */
u32 (*get_seqno)(struct intel_ring_buffer *ring, u32 (*get_seqno)(struct intel_ring_buffer *ring,
bool lazy_coherency); bool lazy_coherency);
void (*set_seqno)(struct intel_ring_buffer *ring,
u32 seqno);
int (*dispatch_execbuffer)(struct intel_ring_buffer *ring, int (*dispatch_execbuffer)(struct intel_ring_buffer *ring,
u32 offset, u32 length, u32 offset, u32 length,
unsigned flags); unsigned flags);
...@@ -178,6 +180,13 @@ intel_read_status_page(struct intel_ring_buffer *ring, ...@@ -178,6 +180,13 @@ intel_read_status_page(struct intel_ring_buffer *ring,
return ring->status_page.page_addr[reg]; return ring->status_page.page_addr[reg];
} }
static inline void
intel_write_status_page(struct intel_ring_buffer *ring,
int reg, u32 value)
{
ring->status_page.page_addr[reg] = value;
}
/** /**
* Reads a dword out of the status page, which is written to from the command * Reads a dword out of the status page, which is written to from the command
* queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or
...@@ -208,7 +217,7 @@ static inline void intel_ring_emit(struct intel_ring_buffer *ring, ...@@ -208,7 +217,7 @@ static inline void intel_ring_emit(struct intel_ring_buffer *ring,
} }
void intel_ring_advance(struct intel_ring_buffer *ring); void intel_ring_advance(struct intel_ring_buffer *ring);
int __must_check intel_ring_idle(struct intel_ring_buffer *ring); int __must_check intel_ring_idle(struct intel_ring_buffer *ring);
void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno);
int intel_ring_flush_all_caches(struct intel_ring_buffer *ring); int intel_ring_flush_all_caches(struct intel_ring_buffer *ring);
int intel_ring_invalidate_all_caches(struct intel_ring_buffer *ring); int intel_ring_invalidate_all_caches(struct intel_ring_buffer *ring);
......
...@@ -1997,11 +1997,8 @@ intel_sdvo_set_property(struct drm_connector *connector, ...@@ -1997,11 +1997,8 @@ intel_sdvo_set_property(struct drm_connector *connector,
done: done:
if (intel_sdvo->base.base.crtc) { if (intel_sdvo->base.base.crtc)
struct drm_crtc *crtc = intel_sdvo->base.base.crtc; intel_crtc_restore_mode(intel_sdvo->base.base.crtc);
intel_set_mode(crtc, &crtc->mode,
crtc->x, crtc->y, crtc->fb);
}
return 0; return 0;
#undef CHECK_PROPERTY #undef CHECK_PROPERTY
......
...@@ -1479,8 +1479,7 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop ...@@ -1479,8 +1479,7 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
} }
if (changed && crtc) if (changed && crtc)
intel_set_mode(crtc, &crtc->mode, intel_crtc_restore_mode(crtc);
crtc->x, crtc->y, crtc->fb);
out: out:
return ret; return ret;
} }
......
...@@ -89,6 +89,29 @@ static inline bool drm_mm_initialized(struct drm_mm *mm) ...@@ -89,6 +89,29 @@ static inline bool drm_mm_initialized(struct drm_mm *mm)
{ {
return mm->hole_stack.next; return mm->hole_stack.next;
} }
static inline unsigned long __drm_mm_hole_node_start(struct drm_mm_node *hole_node)
{
return hole_node->start + hole_node->size;
}
static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node)
{
BUG_ON(!hole_node->hole_follows);
return __drm_mm_hole_node_start(hole_node);
}
static inline unsigned long __drm_mm_hole_node_end(struct drm_mm_node *hole_node)
{
return list_entry(hole_node->node_list.next,
struct drm_mm_node, node_list)->start;
}
static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
{
return __drm_mm_hole_node_end(hole_node);
}
#define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \ #define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \
&(mm)->head_node.node_list, \ &(mm)->head_node.node_list, \
node_list) node_list)
...@@ -99,9 +122,26 @@ static inline bool drm_mm_initialized(struct drm_mm *mm) ...@@ -99,9 +122,26 @@ static inline bool drm_mm_initialized(struct drm_mm *mm)
entry != NULL; entry = next, \ entry != NULL; entry = next, \
next = entry ? list_entry(entry->node_list.next, \ next = entry ? list_entry(entry->node_list.next, \
struct drm_mm_node, node_list) : NULL) \ struct drm_mm_node, node_list) : NULL) \
/* Note that we need to unroll list_for_each_entry in order to inline
* setting hole_start and hole_end on each iteration and keep the
* macro sane.
*/
#define drm_mm_for_each_hole(entry, mm, hole_start, hole_end) \
for (entry = list_entry((mm)->hole_stack.next, struct drm_mm_node, hole_stack); \
&entry->hole_stack != &(mm)->hole_stack ? \
hole_start = drm_mm_hole_node_start(entry), \
hole_end = drm_mm_hole_node_end(entry), \
1 : 0; \
entry = list_entry(entry->hole_stack.next, struct drm_mm_node, hole_stack))
/* /*
* Basic range manager support (drm_mm.c) * Basic range manager support (drm_mm.c)
*/ */
extern struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm,
unsigned long start,
unsigned long size,
bool atomic);
extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
unsigned long size, unsigned long size,
unsigned alignment, unsigned alignment,
......
...@@ -18,8 +18,6 @@ struct intel_gtt { ...@@ -18,8 +18,6 @@ struct intel_gtt {
/* Share the scratch page dma with ppgtts. */ /* Share the scratch page dma with ppgtts. */
dma_addr_t scratch_page_dma; dma_addr_t scratch_page_dma;
struct page *scratch_page; struct page *scratch_page;
/* for ppgtt PDE access */
u32 __iomem *gtt;
/* needed for ioremap in drm/i915 */ /* needed for ioremap in drm/i915 */
phys_addr_t gma_bus_addr; phys_addr_t gma_bus_addr;
} *intel_gtt_get(void); } *intel_gtt_get(void);
......
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