Commit 9b553f72 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-intel-next' of git://people.freedesktop.org/~keithp/linux into drm-core-next

* 'drm-intel-next' of git://people.freedesktop.org/~keithp/linux: (72 commits)
  drm/i915/dp: Fix eDP on PCH DP on CPT/PPT
  drm/i915/dp: Introduce is_cpu_edp()
  drm/i915: use correct SPD type value
  drm/i915: fix ILK+ infoframe support
  drm/i915: add DP test request handling
  drm/i915: read full receiver capability field during DP hot plug
  drm/i915/dp: Remove eDP special cases from bandwidth checks
  drm/i915/dp: Fix the math in intel_dp_link_required
  drm/i915/panel: Always record the backlight level again (but cleverly)
  i915: Move i915_read/write out of line
  drm/i915: remove transcoder PLL mashing from mode_set per specs
  drm/i915: if transcoder disable fails, say which
  drm/i915: set watermarks for third pipe on IVB
  drm/i915: export a CPT mode set verification function
  drm/i915: fix transcoder PLL select masking
  drm/i915: fix IVB cursor support
  drm/i915: fix debug output for 3 pipe configs
  drm/i915: add PLL sharing support to handle 3 pipes
  drm/i915: fix PCH PLL assertion check for 3 pipes
  drm/i915: use transcoder select bits on VGA and HDMI on CPT
  ...
parents c5c42360 82d16555
...@@ -923,6 +923,9 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem, ...@@ -923,6 +923,9 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem,
{ {
int ret = -EINVAL; int ret = -EINVAL;
if (intel_private.base.do_idle_maps)
return -ENODEV;
if (intel_private.clear_fake_agp) { if (intel_private.clear_fake_agp) {
int start = intel_private.base.stolen_size / PAGE_SIZE; int start = intel_private.base.stolen_size / PAGE_SIZE;
int end = intel_private.base.gtt_mappable_entries; int end = intel_private.base.gtt_mappable_entries;
...@@ -985,6 +988,9 @@ static int intel_fake_agp_remove_entries(struct agp_memory *mem, ...@@ -985,6 +988,9 @@ static int intel_fake_agp_remove_entries(struct agp_memory *mem,
if (mem->page_count == 0) if (mem->page_count == 0)
return 0; return 0;
if (intel_private.base.do_idle_maps)
return -ENODEV;
intel_gtt_clear_range(pg_start, mem->page_count); intel_gtt_clear_range(pg_start, mem->page_count);
if (intel_private.base.needs_dmar) { if (intel_private.base.needs_dmar) {
...@@ -1177,6 +1183,25 @@ static void gen6_cleanup(void) ...@@ -1177,6 +1183,25 @@ static void gen6_cleanup(void)
{ {
} }
/* Certain Gen5 chipsets require require idling the GPU before
* unmapping anything from the GTT when VT-d is enabled.
*/
extern int intel_iommu_gfx_mapped;
static inline int needs_idle_maps(void)
{
const unsigned short gpu_devid = intel_private.pcidev->device;
/* Query intel_iommu to see if we need the workaround. Presumably that
* was loaded first.
*/
if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB ||
gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) &&
intel_iommu_gfx_mapped)
return 1;
return 0;
}
static int i9xx_setup(void) static int i9xx_setup(void)
{ {
u32 reg_addr; u32 reg_addr;
...@@ -1211,6 +1236,9 @@ static int i9xx_setup(void) ...@@ -1211,6 +1236,9 @@ static int i9xx_setup(void)
intel_private.gtt_bus_addr = reg_addr + gtt_offset; intel_private.gtt_bus_addr = reg_addr + gtt_offset;
} }
if (needs_idle_maps());
intel_private.base.do_idle_maps = 1;
intel_i9xx_setup_flush(); intel_i9xx_setup_flush();
return 0; return 0;
......
...@@ -2035,7 +2035,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -2035,7 +2035,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
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);
if (IS_MOBILE(dev) || !IS_GEN2(dev)) if (IS_IVYBRIDGE(dev))
dev_priv->num_pipe = 3;
else if (IS_MOBILE(dev) || !IS_GEN2(dev))
dev_priv->num_pipe = 2; dev_priv->num_pipe = 2;
else else
dev_priv->num_pipe = 1; dev_priv->num_pipe = 1;
......
...@@ -79,11 +79,11 @@ MODULE_PARM_DESC(lvds_downclock, ...@@ -79,11 +79,11 @@ MODULE_PARM_DESC(lvds_downclock,
"Use panel (LVDS/eDP) downclocking for power savings " "Use panel (LVDS/eDP) downclocking for power savings "
"(default: false)"); "(default: false)");
unsigned int i915_panel_use_ssc __read_mostly = 1; unsigned int i915_panel_use_ssc __read_mostly = -1;
module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600); module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
MODULE_PARM_DESC(lvds_use_ssc, MODULE_PARM_DESC(lvds_use_ssc,
"Use Spread Spectrum Clock with panels [LVDS/eDP] " "Use Spread Spectrum Clock with panels [LVDS/eDP] "
"(default: true)"); "(default: auto from VBT)");
int i915_vbt_sdvo_panel_type __read_mostly = -1; int i915_vbt_sdvo_panel_type __read_mostly = -1;
module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600); module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600);
...@@ -471,6 +471,9 @@ static int i915_drm_thaw(struct drm_device *dev) ...@@ -471,6 +471,9 @@ static int i915_drm_thaw(struct drm_device *dev)
error = i915_gem_init_ringbuffer(dev); error = i915_gem_init_ringbuffer(dev);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
if (HAS_PCH_SPLIT(dev))
ironlake_init_pch_refclk(dev);
drm_mode_config_reset(dev); drm_mode_config_reset(dev);
drm_irq_install(dev); drm_irq_install(dev);
...@@ -895,3 +898,43 @@ module_exit(i915_exit); ...@@ -895,3 +898,43 @@ module_exit(i915_exit);
MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL and additional rights"); MODULE_LICENSE("GPL and additional rights");
/* We give fast paths for the really cool registers */
#define NEEDS_FORCE_WAKE(dev_priv, reg) \
(((dev_priv)->info->gen >= 6) && \
((reg) < 0x40000) && \
((reg) != FORCEWAKE))
#define __i915_read(x, y) \
u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
u##x val = 0; \
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
gen6_gt_force_wake_get(dev_priv); \
val = read##y(dev_priv->regs + reg); \
gen6_gt_force_wake_put(dev_priv); \
} else { \
val = read##y(dev_priv->regs + reg); \
} \
trace_i915_reg_rw(false, reg, val, sizeof(val)); \
return val; \
}
__i915_read(8, b)
__i915_read(16, w)
__i915_read(32, l)
__i915_read(64, q)
#undef __i915_read
#define __i915_write(x, y) \
void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
trace_i915_reg_rw(true, reg, val, sizeof(val)); \
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
__gen6_gt_wait_for_fifo(dev_priv); \
} \
write##y(val, dev_priv->regs + reg); \
}
__i915_write(8, b)
__i915_write(16, w)
__i915_write(32, l)
__i915_write(64, q)
#undef __i915_write
...@@ -139,7 +139,6 @@ struct sdvo_device_mapping { ...@@ -139,7 +139,6 @@ struct sdvo_device_mapping {
u8 slave_addr; u8 slave_addr;
u8 dvo_wiring; u8 dvo_wiring;
u8 i2c_pin; u8 i2c_pin;
u8 i2c_speed;
u8 ddc_pin; u8 ddc_pin;
}; };
...@@ -349,7 +348,6 @@ typedef struct drm_i915_private { ...@@ -349,7 +348,6 @@ typedef struct drm_i915_private {
/* LVDS info */ /* LVDS info */
int backlight_level; /* restore backlight to this value */ int backlight_level; /* restore backlight to this value */
bool backlight_enabled; bool backlight_enabled;
struct drm_display_mode *panel_fixed_mode;
struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
...@@ -359,6 +357,7 @@ typedef struct drm_i915_private { ...@@ -359,6 +357,7 @@ typedef struct drm_i915_private {
unsigned int lvds_vbt:1; unsigned int lvds_vbt:1;
unsigned int int_crt_support:1; unsigned int int_crt_support:1;
unsigned int lvds_use_ssc:1; unsigned int lvds_use_ssc:1;
unsigned int display_clock_mode:1;
int lvds_ssc_freq; int lvds_ssc_freq;
struct { struct {
int rate; int rate;
...@@ -674,10 +673,9 @@ typedef struct drm_i915_private { ...@@ -674,10 +673,9 @@ typedef struct drm_i915_private {
unsigned int lvds_border_bits; unsigned int lvds_border_bits;
/* Panel fitter placement and size for Ironlake+ */ /* Panel fitter placement and size for Ironlake+ */
u32 pch_pf_pos, pch_pf_size; u32 pch_pf_pos, pch_pf_size;
int panel_t3, panel_t12;
struct drm_crtc *plane_to_crtc_mapping[2]; struct drm_crtc *plane_to_crtc_mapping[3];
struct drm_crtc *pipe_to_crtc_mapping[2]; struct drm_crtc *pipe_to_crtc_mapping[3];
wait_queue_head_t pending_flip_queue; wait_queue_head_t pending_flip_queue;
bool flip_pending_is_done; bool flip_pending_is_done;
...@@ -1303,6 +1301,7 @@ extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state); ...@@ -1303,6 +1301,7 @@ extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
extern bool intel_fbc_enabled(struct drm_device *dev); extern bool intel_fbc_enabled(struct drm_device *dev);
extern void intel_disable_fbc(struct drm_device *dev); extern void intel_disable_fbc(struct drm_device *dev);
extern bool ironlake_set_drps(struct drm_device *dev, u8 val); extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
extern void ironlake_init_pch_refclk(struct drm_device *dev);
extern void ironlake_enable_rc6(struct drm_device *dev); extern void ironlake_enable_rc6(struct drm_device *dev);
extern void gen6_set_rps(struct drm_device *dev, u8 val); extern void gen6_set_rps(struct drm_device *dev, u8 val);
extern void intel_detect_pch(struct drm_device *dev); extern void intel_detect_pch(struct drm_device *dev);
...@@ -1356,18 +1355,7 @@ void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv); ...@@ -1356,18 +1355,7 @@ void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv);
((reg) != FORCEWAKE)) ((reg) != FORCEWAKE))
#define __i915_read(x, y) \ #define __i915_read(x, y) \
static inline u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);
u##x val = 0; \
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
gen6_gt_force_wake_get(dev_priv); \
val = read##y(dev_priv->regs + reg); \
gen6_gt_force_wake_put(dev_priv); \
} else { \
val = read##y(dev_priv->regs + reg); \
} \
trace_i915_reg_rw(false, reg, val, sizeof(val)); \
return val; \
}
__i915_read(8, b) __i915_read(8, b)
__i915_read(16, w) __i915_read(16, w)
...@@ -1376,13 +1364,8 @@ __i915_read(64, q) ...@@ -1376,13 +1364,8 @@ __i915_read(64, q)
#undef __i915_read #undef __i915_read
#define __i915_write(x, y) \ #define __i915_write(x, y) \
static inline void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val);
trace_i915_reg_rw(true, reg, val, sizeof(val)); \
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
__gen6_gt_wait_for_fifo(dev_priv); \
} \
write##y(val, dev_priv->regs + reg); \
}
__i915_write(8, b) __i915_write(8, b)
__i915_write(16, w) __i915_write(16, w)
__i915_write(32, l) __i915_write(32, l)
......
...@@ -195,6 +195,8 @@ i915_gem_create(struct drm_file *file, ...@@ -195,6 +195,8 @@ i915_gem_create(struct drm_file *file,
u32 handle; u32 handle;
size = roundup(size, PAGE_SIZE); size = roundup(size, PAGE_SIZE);
if (size == 0)
return -EINVAL;
/* Allocate the new object */ /* Allocate the new object */
obj = i915_gem_alloc_object(dev, size); obj = i915_gem_alloc_object(dev, size);
...@@ -800,11 +802,11 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev, ...@@ -800,11 +802,11 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev,
if (IS_ERR(page)) if (IS_ERR(page))
return PTR_ERR(page); return PTR_ERR(page);
vaddr = kmap_atomic(page, KM_USER0); vaddr = kmap_atomic(page);
ret = __copy_from_user_inatomic(vaddr + page_offset, ret = __copy_from_user_inatomic(vaddr + page_offset,
user_data, user_data,
page_length); page_length);
kunmap_atomic(vaddr, KM_USER0); kunmap_atomic(vaddr);
set_page_dirty(page); set_page_dirty(page);
mark_page_accessed(page); mark_page_accessed(page);
...@@ -1476,7 +1478,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj, ...@@ -1476,7 +1478,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,
obj->pages[i] = page; obj->pages[i] = page;
} }
if (obj->tiling_mode != I915_TILING_NONE) if (i915_gem_object_needs_bit17_swizzle(obj))
i915_gem_object_do_bit_17_swizzle(obj); i915_gem_object_do_bit_17_swizzle(obj);
return 0; return 0;
...@@ -1498,7 +1500,7 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) ...@@ -1498,7 +1500,7 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj)
BUG_ON(obj->madv == __I915_MADV_PURGED); BUG_ON(obj->madv == __I915_MADV_PURGED);
if (obj->tiling_mode != I915_TILING_NONE) if (i915_gem_object_needs_bit17_swizzle(obj))
i915_gem_object_save_bit_17_swizzle(obj); i915_gem_object_save_bit_17_swizzle(obj);
if (obj->madv == I915_MADV_DONTNEED) if (obj->madv == I915_MADV_DONTNEED)
...@@ -2191,14 +2193,8 @@ int ...@@ -2191,14 +2193,8 @@ int
i915_gpu_idle(struct drm_device *dev) i915_gpu_idle(struct drm_device *dev)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
bool lists_empty;
int ret, i; int ret, i;
lists_empty = (list_empty(&dev_priv->mm.flushing_list) &&
list_empty(&dev_priv->mm.active_list));
if (lists_empty)
return 0;
/* Flush everything onto the inactive list. */ /* Flush everything onto the inactive list. */
for (i = 0; i < I915_NUM_RINGS; i++) { for (i = 0; i < I915_NUM_RINGS; i++) {
ret = i915_ring_idle(&dev_priv->ring[i]); ret = i915_ring_idle(&dev_priv->ring[i]);
......
...@@ -157,7 +157,7 @@ i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle) ...@@ -157,7 +157,7 @@ i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle)
for (page = 0; page < obj->size / PAGE_SIZE; page++) { for (page = 0; page < obj->size / PAGE_SIZE; page++) {
int i; int i;
backing_map = kmap_atomic(obj->pages[page], KM_USER0); backing_map = kmap_atomic(obj->pages[page]);
if (backing_map == NULL) { if (backing_map == NULL) {
DRM_ERROR("failed to map backing page\n"); DRM_ERROR("failed to map backing page\n");
...@@ -181,13 +181,13 @@ i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle) ...@@ -181,13 +181,13 @@ i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle)
} }
} }
} }
kunmap_atomic(backing_map, KM_USER0); kunmap_atomic(backing_map);
backing_map = NULL; backing_map = NULL;
} }
out: out:
if (backing_map != NULL) if (backing_map != NULL)
kunmap_atomic(backing_map, KM_USER0); kunmap_atomic(backing_map);
iounmap(gtt_mapping); iounmap(gtt_mapping);
/* give syslog time to catch up */ /* give syslog time to catch up */
......
...@@ -49,6 +49,28 @@ static unsigned int cache_level_to_agp_type(struct drm_device *dev, ...@@ -49,6 +49,28 @@ static unsigned int cache_level_to_agp_type(struct drm_device *dev,
} }
} }
static bool do_idling(struct drm_i915_private *dev_priv)
{
bool ret = dev_priv->mm.interruptible;
if (unlikely(dev_priv->mm.gtt->do_idle_maps)) {
dev_priv->mm.interruptible = false;
if (i915_gpu_idle(dev_priv->dev)) {
DRM_ERROR("Couldn't idle GPU\n");
/* Wait a bit, in hopes it avoids the hang */
udelay(10);
}
}
return ret;
}
static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible)
{
if (unlikely(dev_priv->mm.gtt->do_idle_maps))
dev_priv->mm.interruptible = interruptible;
}
void i915_gem_restore_gtt_mappings(struct drm_device *dev) void i915_gem_restore_gtt_mappings(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
...@@ -117,6 +139,12 @@ void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj, ...@@ -117,6 +139,12 @@ void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj) void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
{ {
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
bool interruptible;
interruptible = do_idling(dev_priv);
intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT, intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT,
obj->base.size >> PAGE_SHIFT); obj->base.size >> PAGE_SHIFT);
...@@ -124,4 +152,6 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj) ...@@ -124,4 +152,6 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
intel_gtt_unmap_memory(obj->sg_list, obj->num_sg); intel_gtt_unmap_memory(obj->sg_list, obj->num_sg);
obj->sg_list = NULL; obj->sg_list = NULL;
} }
undo_idling(dev_priv, interruptible);
} }
...@@ -92,7 +92,10 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) ...@@ -92,7 +92,10 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
if (INTEL_INFO(dev)->gen >= 5) { if (INTEL_INFO(dev)->gen >= 6) {
swizzle_x = I915_BIT_6_SWIZZLE_NONE;
swizzle_y = I915_BIT_6_SWIZZLE_NONE;
} else if (IS_GEN5(dev)) {
/* On Ironlake whatever DRAM config, GPU always do /* On Ironlake whatever DRAM config, GPU always do
* same swizzling setup. * same swizzling setup.
*/ */
...@@ -440,14 +443,9 @@ i915_gem_swizzle_page(struct page *page) ...@@ -440,14 +443,9 @@ i915_gem_swizzle_page(struct page *page)
void void
i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj) i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
{ {
struct drm_device *dev = obj->base.dev;
drm_i915_private_t *dev_priv = dev->dev_private;
int page_count = obj->base.size >> PAGE_SHIFT; int page_count = obj->base.size >> PAGE_SHIFT;
int i; int i;
if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
return;
if (obj->bit_17 == NULL) if (obj->bit_17 == NULL)
return; return;
...@@ -464,14 +462,9 @@ i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj) ...@@ -464,14 +462,9 @@ i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
void void
i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj) i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj)
{ {
struct drm_device *dev = obj->base.dev;
drm_i915_private_t *dev_priv = dev->dev_private;
int page_count = obj->base.size >> PAGE_SHIFT; int page_count = obj->base.size >> PAGE_SHIFT;
int i; int i;
if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17)
return;
if (obj->bit_17 == NULL) { if (obj->bit_17 == NULL) {
obj->bit_17 = kmalloc(BITS_TO_LONGS(page_count) * obj->bit_17 = kmalloc(BITS_TO_LONGS(page_count) *
sizeof(long), GFP_KERNEL); sizeof(long), GFP_KERNEL);
......
...@@ -383,6 +383,7 @@ static void gen6_pm_rps_work(struct work_struct *work) ...@@ -383,6 +383,7 @@ static void gen6_pm_rps_work(struct work_struct *work)
pm_iir = dev_priv->pm_iir; pm_iir = dev_priv->pm_iir;
dev_priv->pm_iir = 0; dev_priv->pm_iir = 0;
pm_imr = I915_READ(GEN6_PMIMR); pm_imr = I915_READ(GEN6_PMIMR);
I915_WRITE(GEN6_PMIMR, 0);
spin_unlock_irq(&dev_priv->rps_lock); spin_unlock_irq(&dev_priv->rps_lock);
if (!pm_iir) if (!pm_iir)
...@@ -420,7 +421,6 @@ static void gen6_pm_rps_work(struct work_struct *work) ...@@ -420,7 +421,6 @@ static void gen6_pm_rps_work(struct work_struct *work)
* an *extremely* unlikely race with gen6_rps_enable() that is prevented * an *extremely* unlikely race with gen6_rps_enable() that is prevented
* by holding struct_mutex for the duration of the write. * by holding struct_mutex for the duration of the write.
*/ */
I915_WRITE(GEN6_PMIMR, pm_imr & ~pm_iir);
mutex_unlock(&dev_priv->dev->struct_mutex); mutex_unlock(&dev_priv->dev->struct_mutex);
} }
...@@ -536,8 +536,9 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) ...@@ -536,8 +536,9 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&dev_priv->rps_lock, flags); spin_lock_irqsave(&dev_priv->rps_lock, flags);
WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n"); WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
I915_WRITE(GEN6_PMIMR, pm_iir);
dev_priv->pm_iir |= pm_iir; dev_priv->pm_iir |= pm_iir;
I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
POSTING_READ(GEN6_PMIMR);
spin_unlock_irqrestore(&dev_priv->rps_lock, flags); spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
queue_work(dev_priv->wq, &dev_priv->rps_work); queue_work(dev_priv->wq, &dev_priv->rps_work);
} }
...@@ -649,8 +650,9 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) ...@@ -649,8 +650,9 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&dev_priv->rps_lock, flags); spin_lock_irqsave(&dev_priv->rps_lock, flags);
WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n"); WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
I915_WRITE(GEN6_PMIMR, pm_iir);
dev_priv->pm_iir |= pm_iir; dev_priv->pm_iir |= pm_iir;
I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
POSTING_READ(GEN6_PMIMR);
spin_unlock_irqrestore(&dev_priv->rps_lock, flags); spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
queue_work(dev_priv->wq, &dev_priv->rps_work); queue_work(dev_priv->wq, &dev_priv->rps_work);
} }
...@@ -1777,6 +1779,26 @@ static void ironlake_irq_preinstall(struct drm_device *dev) ...@@ -1777,6 +1779,26 @@ static void ironlake_irq_preinstall(struct drm_device *dev)
POSTING_READ(SDEIER); POSTING_READ(SDEIER);
} }
/*
* Enable digital hotplug on the PCH, and configure the DP short pulse
* duration to 2ms (which is the minimum in the Display Port spec)
*
* This register is the same on all known PCH chips.
*/
static void ironlake_enable_pch_hotplug(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u32 hotplug;
hotplug = I915_READ(PCH_PORT_HOTPLUG);
hotplug &= ~(PORTD_PULSE_DURATION_MASK|PORTC_PULSE_DURATION_MASK|PORTB_PULSE_DURATION_MASK);
hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms;
hotplug |= PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_2ms;
hotplug |= PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_2ms;
I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
}
static int ironlake_irq_postinstall(struct drm_device *dev) static int ironlake_irq_postinstall(struct drm_device *dev)
{ {
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
...@@ -1839,6 +1861,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev) ...@@ -1839,6 +1861,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
I915_WRITE(SDEIER, hotplug_mask); I915_WRITE(SDEIER, hotplug_mask);
POSTING_READ(SDEIER); POSTING_READ(SDEIER);
ironlake_enable_pch_hotplug(dev);
if (IS_IRONLAKE_M(dev)) { if (IS_IRONLAKE_M(dev)) {
/* Clear & enable PCU event interrupts */ /* Clear & enable PCU event interrupts */
I915_WRITE(DEIIR, DE_PCU_EVENT); I915_WRITE(DEIIR, DE_PCU_EVENT);
...@@ -1896,6 +1920,8 @@ static int ivybridge_irq_postinstall(struct drm_device *dev) ...@@ -1896,6 +1920,8 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)
I915_WRITE(SDEIER, hotplug_mask); I915_WRITE(SDEIER, hotplug_mask);
POSTING_READ(SDEIER); POSTING_READ(SDEIER);
ironlake_enable_pch_hotplug(dev);
return 0; return 0;
} }
...@@ -2020,6 +2046,10 @@ static void ironlake_irq_uninstall(struct drm_device *dev) ...@@ -2020,6 +2046,10 @@ static void ironlake_irq_uninstall(struct drm_device *dev)
I915_WRITE(GTIMR, 0xffffffff); I915_WRITE(GTIMR, 0xffffffff);
I915_WRITE(GTIER, 0x0); I915_WRITE(GTIER, 0x0);
I915_WRITE(GTIIR, I915_READ(GTIIR)); I915_WRITE(GTIIR, I915_READ(GTIIR));
I915_WRITE(SDEIMR, 0xffffffff);
I915_WRITE(SDEIER, 0x0);
I915_WRITE(SDEIIR, I915_READ(SDEIIR));
} }
static void i915_driver_irq_uninstall(struct drm_device * dev) static void i915_driver_irq_uninstall(struct drm_device * dev)
......
...@@ -242,16 +242,22 @@ ...@@ -242,16 +242,22 @@
#define ASYNC_FLIP (1<<22) #define ASYNC_FLIP (1<<22)
#define DISPLAY_PLANE_A (0<<20) #define DISPLAY_PLANE_A (0<<20)
#define DISPLAY_PLANE_B (1<<20) #define DISPLAY_PLANE_B (1<<20)
#define GFX_OP_PIPE_CONTROL ((0x3<<29)|(0x3<<27)|(0x2<<24)|2) #define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2))
#define PIPE_CONTROL_QW_WRITE (1<<14) #define PIPE_CONTROL_CS_STALL (1<<20)
#define PIPE_CONTROL_DEPTH_STALL (1<<13) #define PIPE_CONTROL_QW_WRITE (1<<14)
#define PIPE_CONTROL_WC_FLUSH (1<<12) #define PIPE_CONTROL_DEPTH_STALL (1<<13)
#define PIPE_CONTROL_IS_FLUSH (1<<11) /* MBZ on Ironlake */ #define PIPE_CONTROL_WRITE_FLUSH (1<<12)
#define PIPE_CONTROL_TC_FLUSH (1<<10) /* GM45+ only */ #define PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH (1<<12) /* gen6+ */
#define PIPE_CONTROL_ISP_DIS (1<<9) #define PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE (1<<11) /* MBZ on Ironlake */
#define PIPE_CONTROL_NOTIFY (1<<8) #define PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE (1<<10) /* GM45+ only */
#define PIPE_CONTROL_INDIRECT_STATE_DISABLE (1<<9)
#define PIPE_CONTROL_NOTIFY (1<<8)
#define PIPE_CONTROL_VF_CACHE_INVALIDATE (1<<4)
#define PIPE_CONTROL_CONST_CACHE_INVALIDATE (1<<3)
#define PIPE_CONTROL_STATE_CACHE_INVALIDATE (1<<2)
#define PIPE_CONTROL_STALL_AT_SCOREBOARD (1<<1)
#define PIPE_CONTROL_DEPTH_CACHE_FLUSH (1<<0)
#define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */ #define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
#define PIPE_CONTROL_STALL_EN (1<<1) /* in addr word, Ironlake+ only */
/* /*
...@@ -2429,6 +2435,7 @@ ...@@ -2429,6 +2435,7 @@
#define WM0_PIPE_CURSOR_MASK (0x1f) #define WM0_PIPE_CURSOR_MASK (0x1f)
#define WM0_PIPEB_ILK 0x45104 #define WM0_PIPEB_ILK 0x45104
#define WM0_PIPEC_IVB 0x45200
#define WM1_LP_ILK 0x45108 #define WM1_LP_ILK 0x45108
#define WM1_LP_SR_EN (1<<31) #define WM1_LP_SR_EN (1<<31)
#define WM1_LP_LATENCY_SHIFT 24 #define WM1_LP_LATENCY_SHIFT 24
...@@ -2567,10 +2574,18 @@ ...@@ -2567,10 +2574,18 @@
#define _CURBBASE 0x700c4 #define _CURBBASE 0x700c4
#define _CURBPOS 0x700c8 #define _CURBPOS 0x700c8
#define _CURBCNTR_IVB 0x71080
#define _CURBBASE_IVB 0x71084
#define _CURBPOS_IVB 0x71088
#define CURCNTR(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR) #define CURCNTR(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR)
#define CURBASE(pipe) _PIPE(pipe, _CURABASE, _CURBBASE) #define CURBASE(pipe) _PIPE(pipe, _CURABASE, _CURBBASE)
#define CURPOS(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS) #define CURPOS(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS)
#define CURCNTR_IVB(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR_IVB)
#define CURBASE_IVB(pipe) _PIPE(pipe, _CURABASE, _CURBBASE_IVB)
#define CURPOS_IVB(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS_IVB)
/* Display A control */ /* Display A control */
#define _DSPACNTR 0x70180 #define _DSPACNTR 0x70180
#define DISPLAY_PLANE_ENABLE (1<<31) #define DISPLAY_PLANE_ENABLE (1<<31)
...@@ -2916,12 +2931,13 @@ ...@@ -2916,12 +2931,13 @@
#define SDEIER 0xc400c #define SDEIER 0xc400c
/* digital port hotplug */ /* digital port hotplug */
#define PCH_PORT_HOTPLUG 0xc4030 #define PCH_PORT_HOTPLUG 0xc4030 /* SHOTPLUG_CTL */
#define PORTD_HOTPLUG_ENABLE (1 << 20) #define PORTD_HOTPLUG_ENABLE (1 << 20)
#define PORTD_PULSE_DURATION_2ms (0) #define PORTD_PULSE_DURATION_2ms (0)
#define PORTD_PULSE_DURATION_4_5ms (1 << 18) #define PORTD_PULSE_DURATION_4_5ms (1 << 18)
#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_HOTPLUG_NO_DETECT (0) #define PORTD_HOTPLUG_NO_DETECT (0)
#define PORTD_HOTPLUG_SHORT_DETECT (1 << 16) #define PORTD_HOTPLUG_SHORT_DETECT (1 << 16)
#define PORTD_HOTPLUG_LONG_DETECT (1 << 17) #define PORTD_HOTPLUG_LONG_DETECT (1 << 17)
...@@ -2930,6 +2946,7 @@ ...@@ -2930,6 +2946,7 @@
#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_HOTPLUG_NO_DETECT (0) #define PORTC_HOTPLUG_NO_DETECT (0)
#define PORTC_HOTPLUG_SHORT_DETECT (1 << 8) #define PORTC_HOTPLUG_SHORT_DETECT (1 << 8)
#define PORTC_HOTPLUG_LONG_DETECT (1 << 9) #define PORTC_HOTPLUG_LONG_DETECT (1 << 9)
...@@ -2938,6 +2955,7 @@ ...@@ -2938,6 +2955,7 @@
#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_HOTPLUG_NO_DETECT (0) #define PORTB_HOTPLUG_NO_DETECT (0)
#define PORTB_HOTPLUG_SHORT_DETECT (1 << 0) #define PORTB_HOTPLUG_SHORT_DETECT (1 << 0)
#define PORTB_HOTPLUG_LONG_DETECT (1 << 1) #define PORTB_HOTPLUG_LONG_DETECT (1 << 1)
...@@ -2958,15 +2976,15 @@ ...@@ -2958,15 +2976,15 @@
#define _PCH_DPLL_A 0xc6014 #define _PCH_DPLL_A 0xc6014
#define _PCH_DPLL_B 0xc6018 #define _PCH_DPLL_B 0xc6018
#define PCH_DPLL(pipe) _PIPE(pipe, _PCH_DPLL_A, _PCH_DPLL_B) #define PCH_DPLL(pipe) (pipe == 0 ? _PCH_DPLL_A : _PCH_DPLL_B)
#define _PCH_FPA0 0xc6040 #define _PCH_FPA0 0xc6040
#define FP_CB_TUNE (0x3<<22) #define FP_CB_TUNE (0x3<<22)
#define _PCH_FPA1 0xc6044 #define _PCH_FPA1 0xc6044
#define _PCH_FPB0 0xc6048 #define _PCH_FPB0 0xc6048
#define _PCH_FPB1 0xc604c #define _PCH_FPB1 0xc604c
#define PCH_FP0(pipe) _PIPE(pipe, _PCH_FPA0, _PCH_FPB0) #define PCH_FP0(pipe) (pipe == 0 ? _PCH_FPA0 : _PCH_FPB0)
#define PCH_FP1(pipe) _PIPE(pipe, _PCH_FPA1, _PCH_FPB1) #define PCH_FP1(pipe) (pipe == 0 ? _PCH_FPA1 : _PCH_FPB1)
#define PCH_DPLL_TEST 0xc606c #define PCH_DPLL_TEST 0xc606c
...@@ -3180,6 +3198,7 @@ ...@@ -3180,6 +3198,7 @@
#define FDI_LINK_TRAIN_NONE_IVB (3<<8) #define FDI_LINK_TRAIN_NONE_IVB (3<<8)
/* both Tx and Rx */ /* both Tx and Rx */
#define FDI_COMPOSITE_SYNC (1<<11)
#define FDI_LINK_TRAIN_AUTO (1<<10) #define FDI_LINK_TRAIN_AUTO (1<<10)
#define FDI_SCRAMBLING_ENABLE (0<<7) #define FDI_SCRAMBLING_ENABLE (0<<7)
#define FDI_SCRAMBLING_DISABLE (1<<7) #define FDI_SCRAMBLING_DISABLE (1<<7)
...@@ -3321,15 +3340,35 @@ ...@@ -3321,15 +3340,35 @@
#define PCH_PP_STATUS 0xc7200 #define PCH_PP_STATUS 0xc7200
#define PCH_PP_CONTROL 0xc7204 #define PCH_PP_CONTROL 0xc7204
#define PANEL_UNLOCK_REGS (0xabcd << 16) #define PANEL_UNLOCK_REGS (0xabcd << 16)
#define PANEL_UNLOCK_MASK (0xffff << 16)
#define EDP_FORCE_VDD (1 << 3) #define EDP_FORCE_VDD (1 << 3)
#define EDP_BLC_ENABLE (1 << 2) #define EDP_BLC_ENABLE (1 << 2)
#define PANEL_POWER_RESET (1 << 1) #define PANEL_POWER_RESET (1 << 1)
#define PANEL_POWER_OFF (0 << 0) #define PANEL_POWER_OFF (0 << 0)
#define PANEL_POWER_ON (1 << 0) #define PANEL_POWER_ON (1 << 0)
#define PCH_PP_ON_DELAYS 0xc7208 #define PCH_PP_ON_DELAYS 0xc7208
#define PANEL_PORT_SELECT_MASK (3 << 30)
#define PANEL_PORT_SELECT_LVDS (0 << 30)
#define PANEL_PORT_SELECT_DPA (1 << 30)
#define EDP_PANEL (1 << 30) #define EDP_PANEL (1 << 30)
#define PANEL_PORT_SELECT_DPC (2 << 30)
#define PANEL_PORT_SELECT_DPD (3 << 30)
#define PANEL_POWER_UP_DELAY_MASK (0x1fff0000)
#define PANEL_POWER_UP_DELAY_SHIFT 16
#define PANEL_LIGHT_ON_DELAY_MASK (0x1fff)
#define PANEL_LIGHT_ON_DELAY_SHIFT 0
#define PCH_PP_OFF_DELAYS 0xc720c #define PCH_PP_OFF_DELAYS 0xc720c
#define PANEL_POWER_DOWN_DELAY_MASK (0x1fff0000)
#define PANEL_POWER_DOWN_DELAY_SHIFT 16
#define PANEL_LIGHT_OFF_DELAY_MASK (0x1fff)
#define PANEL_LIGHT_OFF_DELAY_SHIFT 0
#define PCH_PP_DIVISOR 0xc7210 #define PCH_PP_DIVISOR 0xc7210
#define PP_REFERENCE_DIVIDER_MASK (0xffffff00)
#define PP_REFERENCE_DIVIDER_SHIFT 8
#define PANEL_POWER_CYCLE_DELAY_MASK (0x1f)
#define PANEL_POWER_CYCLE_DELAY_SHIFT 0
#define PCH_DP_B 0xe4100 #define PCH_DP_B 0xe4100
#define PCH_DPB_AUX_CH_CTL 0xe4110 #define PCH_DPB_AUX_CH_CTL 0xe4110
......
/* /*
* Copyright 2006 Intel Corporation * Copyright © 2006 Intel Corporation
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
...@@ -309,6 +309,13 @@ parse_general_features(struct drm_i915_private *dev_priv, ...@@ -309,6 +309,13 @@ parse_general_features(struct drm_i915_private *dev_priv,
dev_priv->lvds_use_ssc = general->enable_ssc; dev_priv->lvds_use_ssc = general->enable_ssc;
dev_priv->lvds_ssc_freq = dev_priv->lvds_ssc_freq =
intel_bios_ssc_frequency(dev, general->ssc_freq); intel_bios_ssc_frequency(dev, general->ssc_freq);
dev_priv->display_clock_mode = general->display_clock_mode;
DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d\n",
dev_priv->int_tv_support,
dev_priv->int_crt_support,
dev_priv->lvds_use_ssc,
dev_priv->lvds_ssc_freq,
dev_priv->display_clock_mode);
} }
} }
...@@ -396,15 +403,13 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, ...@@ -396,15 +403,13 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
p_mapping->dvo_wiring = p_child->dvo_wiring; p_mapping->dvo_wiring = p_child->dvo_wiring;
p_mapping->ddc_pin = p_child->ddc_pin; p_mapping->ddc_pin = p_child->ddc_pin;
p_mapping->i2c_pin = p_child->i2c_pin; p_mapping->i2c_pin = p_child->i2c_pin;
p_mapping->i2c_speed = p_child->i2c_speed;
p_mapping->initialized = 1; p_mapping->initialized = 1;
DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d, i2c_speed=%d\n", DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",
p_mapping->dvo_port, p_mapping->dvo_port,
p_mapping->slave_addr, p_mapping->slave_addr,
p_mapping->dvo_wiring, p_mapping->dvo_wiring,
p_mapping->ddc_pin, p_mapping->ddc_pin,
p_mapping->i2c_pin, p_mapping->i2c_pin);
p_mapping->i2c_speed);
} else { } else {
DRM_DEBUG_KMS("Maybe one SDVO port is shared by " DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
"two SDVO device.\n"); "two SDVO device.\n");
...@@ -610,7 +615,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) ...@@ -610,7 +615,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
/* Default to using SSC */ /* Default to using SSC */
dev_priv->lvds_use_ssc = 1; dev_priv->lvds_use_ssc = 1;
dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1); dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
DRM_DEBUG("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq); DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);
/* eDP data */ /* eDP data */
dev_priv->edp.bpp = 18; dev_priv->edp.bpp = 18;
...@@ -639,7 +644,7 @@ intel_parse_bios(struct drm_device *dev) ...@@ -639,7 +644,7 @@ intel_parse_bios(struct drm_device *dev)
if (dev_priv->opregion.vbt) { if (dev_priv->opregion.vbt) {
struct vbt_header *vbt = dev_priv->opregion.vbt; struct vbt_header *vbt = dev_priv->opregion.vbt;
if (memcmp(vbt->signature, "$VBT", 4) == 0) { if (memcmp(vbt->signature, "$VBT", 4) == 0) {
DRM_DEBUG_DRIVER("Using VBT from OpRegion: %20s\n", DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",
vbt->signature); vbt->signature);
bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset); bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);
} else } else
......
/* /*
* Copyright 2006 Intel Corporation * Copyright © 2006 Intel Corporation
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
...@@ -120,7 +120,9 @@ struct bdb_general_features { ...@@ -120,7 +120,9 @@ struct bdb_general_features {
u8 ssc_freq:1; u8 ssc_freq:1;
u8 enable_lfp_on_override:1; u8 enable_lfp_on_override:1;
u8 disable_ssc_ddt:1; u8 disable_ssc_ddt:1;
u8 rsvd8:3; /* finish byte */ u8 rsvd7:1;
u8 display_clock_mode:1;
u8 rsvd8:1; /* finish byte */
/* bits 3 */ /* bits 3 */
u8 disable_smooth_vision:1; u8 disable_smooth_vision:1;
...@@ -133,7 +135,10 @@ struct bdb_general_features { ...@@ -133,7 +135,10 @@ struct bdb_general_features {
/* bits 5 */ /* bits 5 */
u8 int_crt_support:1; u8 int_crt_support:1;
u8 int_tv_support:1; u8 int_tv_support:1;
u8 rsvd11:6; /* finish byte */ u8 int_efp_support:1;
u8 dp_ssc_enb:1; /* PCH attached eDP supports SSC */
u8 dp_ssc_freq:1; /* SSC freq for PCH attached eDP */
u8 rsvd11:3; /* finish byte */
} __attribute__((packed)); } __attribute__((packed));
/* pre-915 */ /* pre-915 */
...@@ -197,8 +202,7 @@ struct bdb_general_features { ...@@ -197,8 +202,7 @@ struct bdb_general_features {
struct child_device_config { struct child_device_config {
u16 handle; u16 handle;
u16 device_type; u16 device_type;
u8 i2c_speed; u8 device_id[10]; /* ascii string */
u8 rsvd[9];
u16 addin_offset; u16 addin_offset;
u8 dvo_port; /* See Device_PORT_* above */ u8 dvo_port; /* See Device_PORT_* above */
u8 i2c_pin; u8 i2c_pin;
...@@ -446,11 +450,11 @@ struct bdb_driver_features { ...@@ -446,11 +450,11 @@ struct bdb_driver_features {
#define EDP_VSWING_1_2V 3 #define EDP_VSWING_1_2V 3
struct edp_power_seq { struct edp_power_seq {
u16 t3; u16 t1_t3;
u16 t7; u16 t8;
u16 t9; u16 t9;
u16 t10; u16 t10;
u16 t12; u16 t11_t12;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct edp_link_params { struct edp_link_params {
......
...@@ -152,17 +152,13 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, ...@@ -152,17 +152,13 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
adpa |= ADPA_VSYNC_ACTIVE_HIGH; adpa |= ADPA_VSYNC_ACTIVE_HIGH;
if (intel_crtc->pipe == 0) { /* For CPT allow 3 pipe config, for others just use A or B */
if (HAS_PCH_CPT(dev)) if (HAS_PCH_CPT(dev))
adpa |= PORT_TRANS_A_SEL_CPT; adpa |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
else else if (intel_crtc->pipe == 0)
adpa |= ADPA_PIPE_A_SELECT; adpa |= ADPA_PIPE_A_SELECT;
} else { else
if (HAS_PCH_CPT(dev)) adpa |= ADPA_PIPE_B_SELECT;
adpa |= PORT_TRANS_B_SEL_CPT;
else
adpa |= ADPA_PIPE_B_SELECT;
}
if (!HAS_PCH_SPLIT(dev)) if (!HAS_PCH_SPLIT(dev))
I915_WRITE(BCLRPAT(intel_crtc->pipe), 0); I915_WRITE(BCLRPAT(intel_crtc->pipe), 0);
......
This diff is collapsed.
This diff is collapsed.
...@@ -171,6 +171,9 @@ struct intel_crtc { ...@@ -171,6 +171,9 @@ struct intel_crtc {
int16_t cursor_width, cursor_height; int16_t cursor_width, cursor_height;
bool cursor_visible; bool cursor_visible;
unsigned int bpp; unsigned int bpp;
bool no_pll; /* tertiary pipe for IVB */
bool use_pll_a;
}; };
#define to_intel_crtc(x) container_of(x, struct intel_crtc, base) #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
...@@ -184,7 +187,7 @@ struct intel_crtc { ...@@ -184,7 +187,7 @@ struct intel_crtc {
#define DIP_VERSION_AVI 0x2 #define DIP_VERSION_AVI 0x2
#define DIP_LEN_AVI 13 #define DIP_LEN_AVI 13
#define DIP_TYPE_SPD 0x3 #define DIP_TYPE_SPD 0x83
#define DIP_VERSION_SPD 0x1 #define DIP_VERSION_SPD 0x1
#define DIP_LEN_SPD 25 #define DIP_LEN_SPD 25
#define DIP_SPD_UNKNOWN 0 #define DIP_SPD_UNKNOWN 0
...@@ -379,4 +382,6 @@ extern void intel_fb_restore_mode(struct drm_device *dev); ...@@ -379,4 +382,6 @@ extern void intel_fb_restore_mode(struct drm_device *dev);
extern void intel_init_clock_gating(struct drm_device *dev); extern void intel_init_clock_gating(struct drm_device *dev);
extern void intel_write_eld(struct drm_encoder *encoder, extern void intel_write_eld(struct drm_encoder *encoder,
struct drm_display_mode *mode); struct drm_display_mode *mode);
extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe);
#endif /* __INTEL_DRV_H__ */ #endif /* __INTEL_DRV_H__ */
...@@ -69,8 +69,7 @@ void intel_dip_infoframe_csum(struct dip_infoframe *frame) ...@@ -69,8 +69,7 @@ void intel_dip_infoframe_csum(struct dip_infoframe *frame)
frame->checksum = 0; frame->checksum = 0;
frame->ecc = 0; frame->ecc = 0;
/* Header isn't part of the checksum */ for (i = 0; i < frame->len + DIP_HEADER_SIZE; i++)
for (i = 5; i < frame->len; i++)
sum += data[i]; sum += data[i];
frame->checksum = 0x100 - sum; frame->checksum = 0x100 - sum;
...@@ -104,7 +103,7 @@ static u32 intel_infoframe_flags(struct dip_infoframe *frame) ...@@ -104,7 +103,7 @@ static u32 intel_infoframe_flags(struct dip_infoframe *frame)
flags |= VIDEO_DIP_ENABLE_AVI | VIDEO_DIP_FREQ_VSYNC; flags |= VIDEO_DIP_ENABLE_AVI | VIDEO_DIP_FREQ_VSYNC;
break; break;
case DIP_TYPE_SPD: case DIP_TYPE_SPD:
flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_2VSYNC; flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_VSYNC;
break; break;
default: default:
DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
...@@ -165,9 +164,9 @@ static void ironlake_write_infoframe(struct drm_encoder *encoder, ...@@ -165,9 +164,9 @@ static void ironlake_write_infoframe(struct drm_encoder *encoder,
flags = intel_infoframe_index(frame); flags = intel_infoframe_index(frame);
val &= ~VIDEO_DIP_SELECT_MASK; val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
I915_WRITE(reg, val | flags); I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
for (i = 0; i < len; i += 4) { for (i = 0; i < len; i += 4) {
I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
...@@ -252,12 +251,10 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, ...@@ -252,12 +251,10 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
intel_write_eld(encoder, adjusted_mode); intel_write_eld(encoder, adjusted_mode);
} }
if (intel_crtc->pipe == 1) { if (HAS_PCH_CPT(dev))
if (HAS_PCH_CPT(dev)) sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe);
sdvox |= PORT_TRANS_B_SEL_CPT; else if (intel_crtc->pipe == 1)
else sdvox |= SDVO_PIPE_B_SELECT;
sdvox |= SDVO_PIPE_B_SELECT;
}
I915_WRITE(intel_hdmi->sdvox_reg, sdvox); I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
POSTING_READ(intel_hdmi->sdvox_reg); POSTING_READ(intel_hdmi->sdvox_reg);
...@@ -489,6 +486,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) ...@@ -489,6 +486,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector; struct intel_connector *intel_connector;
struct intel_hdmi *intel_hdmi; struct intel_hdmi *intel_hdmi;
int i;
intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL); intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL);
if (!intel_hdmi) if (!intel_hdmi)
...@@ -514,7 +512,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) ...@@ -514,7 +512,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
connector->polled = DRM_CONNECTOR_POLL_HPD; connector->polled = DRM_CONNECTOR_POLL_HPD;
connector->interlace_allowed = 0; connector->interlace_allowed = 0;
connector->doublescan_allowed = 0; connector->doublescan_allowed = 0;
intel_encoder->crtc_mask = (1 << 0) | (1 << 1); intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
/* Set up the DDC bus. */ /* Set up the DDC bus. */
if (sdvox_reg == SDVOB) { if (sdvox_reg == SDVOB) {
...@@ -541,10 +539,14 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) ...@@ -541,10 +539,14 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
intel_hdmi->sdvox_reg = sdvox_reg; intel_hdmi->sdvox_reg = sdvox_reg;
if (!HAS_PCH_SPLIT(dev)) if (!HAS_PCH_SPLIT(dev)) {
intel_hdmi->write_infoframe = i9xx_write_infoframe; intel_hdmi->write_infoframe = i9xx_write_infoframe;
else I915_WRITE(VIDEO_DIP_CTL, 0);
} else {
intel_hdmi->write_infoframe = ironlake_write_infoframe; intel_hdmi->write_infoframe = ironlake_write_infoframe;
for_each_pipe(i)
I915_WRITE(TVIDEO_DIP_CTL(i), 0);
}
drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs); drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
......
...@@ -422,13 +422,7 @@ void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed) ...@@ -422,13 +422,7 @@ void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed)
{ {
struct intel_gmbus *bus = to_intel_gmbus(adapter); struct intel_gmbus *bus = to_intel_gmbus(adapter);
/* speed: bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | speed;
* 0x0 = 100 KHz
* 0x1 = 50 KHz
* 0x2 = 400 KHz
* 0x3 = 1000 Khz
*/
bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | (speed << 8);
} }
void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit) void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
......
...@@ -888,9 +888,11 @@ bool intel_lvds_init(struct drm_device *dev) ...@@ -888,9 +888,11 @@ bool intel_lvds_init(struct drm_device *dev)
intel_encoder->type = INTEL_OUTPUT_LVDS; intel_encoder->type = INTEL_OUTPUT_LVDS;
intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
intel_encoder->crtc_mask = (1 << 1); if (HAS_PCH_SPLIT(dev))
if (INTEL_INFO(dev)->gen >= 5) intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
intel_encoder->crtc_mask |= (1 << 0); else
intel_encoder->crtc_mask = (1 << 1);
drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
connector->display_info.subpixel_order = SubPixelHorizontalRGB; connector->display_info.subpixel_order = SubPixelHorizontalRGB;
......
...@@ -226,7 +226,7 @@ static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level) ...@@ -226,7 +226,7 @@ static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level)
I915_WRITE(BLC_PWM_CPU_CTL, val | level); I915_WRITE(BLC_PWM_CPU_CTL, val | level);
} }
void intel_panel_set_backlight(struct drm_device *dev, u32 level) static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 tmp; u32 tmp;
...@@ -254,16 +254,21 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level) ...@@ -254,16 +254,21 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level)
I915_WRITE(BLC_PWM_CTL, tmp | level); I915_WRITE(BLC_PWM_CTL, tmp | level);
} }
void intel_panel_disable_backlight(struct drm_device *dev) void intel_panel_set_backlight(struct drm_device *dev, u32 level)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
if (dev_priv->backlight_enabled) { dev_priv->backlight_level = level;
dev_priv->backlight_level = intel_panel_get_backlight(dev); if (dev_priv->backlight_enabled)
dev_priv->backlight_enabled = false; intel_panel_actually_set_backlight(dev, level);
} }
void intel_panel_disable_backlight(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
intel_panel_set_backlight(dev, 0); dev_priv->backlight_enabled = false;
intel_panel_actually_set_backlight(dev, 0);
} }
void intel_panel_enable_backlight(struct drm_device *dev) void intel_panel_enable_backlight(struct drm_device *dev)
...@@ -273,8 +278,8 @@ void intel_panel_enable_backlight(struct drm_device *dev) ...@@ -273,8 +278,8 @@ void intel_panel_enable_backlight(struct drm_device *dev)
if (dev_priv->backlight_level == 0) if (dev_priv->backlight_level == 0)
dev_priv->backlight_level = intel_panel_get_max_backlight(dev); dev_priv->backlight_level = intel_panel_get_max_backlight(dev);
intel_panel_set_backlight(dev, dev_priv->backlight_level);
dev_priv->backlight_enabled = true; dev_priv->backlight_enabled = true;
intel_panel_actually_set_backlight(dev, dev_priv->backlight_level);
} }
static void intel_panel_init_backlight(struct drm_device *dev) static void intel_panel_init_backlight(struct drm_device *dev)
......
...@@ -34,6 +34,16 @@ ...@@ -34,6 +34,16 @@
#include "i915_trace.h" #include "i915_trace.h"
#include "intel_drv.h" #include "intel_drv.h"
/*
* 965+ support PIPE_CONTROL commands, which provide finer grained control
* over cache flushing.
*/
struct pipe_control {
struct drm_i915_gem_object *obj;
volatile u32 *cpu_page;
u32 gtt_offset;
};
static inline int ring_space(struct intel_ring_buffer *ring) static inline int ring_space(struct intel_ring_buffer *ring)
{ {
int space = (ring->head & HEAD_ADDR) - (ring->tail + 8); int space = (ring->head & HEAD_ADDR) - (ring->tail + 8);
...@@ -123,6 +133,118 @@ render_ring_flush(struct intel_ring_buffer *ring, ...@@ -123,6 +133,118 @@ render_ring_flush(struct intel_ring_buffer *ring,
return 0; return 0;
} }
/**
* Emits a PIPE_CONTROL with a non-zero post-sync operation, for
* implementing two workarounds on gen6. From section 1.4.7.1
* "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1:
*
* [DevSNB-C+{W/A}] Before any depth stall flush (including those
* produced by non-pipelined state commands), software needs to first
* send a PIPE_CONTROL with no bits set except Post-Sync Operation !=
* 0.
*
* [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable
* =1, a PIPE_CONTROL with any non-zero post-sync-op is required.
*
* And the workaround for these two requires this workaround first:
*
* [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent
* BEFORE the pipe-control with a post-sync op and no write-cache
* flushes.
*
* And this last workaround is tricky because of the requirements on
* that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM
* volume 2 part 1:
*
* "1 of the following must also be set:
* - Render Target Cache Flush Enable ([12] of DW1)
* - Depth Cache Flush Enable ([0] of DW1)
* - Stall at Pixel Scoreboard ([1] of DW1)
* - Depth Stall ([13] of DW1)
* - Post-Sync Operation ([13] of DW1)
* - Notify Enable ([8] of DW1)"
*
* The cache flushes require the workaround flush that triggered this
* one, so we can't use it. Depth stall would trigger the same.
* Post-sync nonzero is what triggered this second workaround, so we
* can't use that one either. Notify enable is IRQs, which aren't
* really our business. That leaves only stall at scoreboard.
*/
static int
intel_emit_post_sync_nonzero_flush(struct intel_ring_buffer *ring)
{
struct pipe_control *pc = ring->private;
u32 scratch_addr = pc->gtt_offset + 128;
int ret;
ret = intel_ring_begin(ring, 6);
if (ret)
return ret;
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
intel_ring_emit(ring, PIPE_CONTROL_CS_STALL |
PIPE_CONTROL_STALL_AT_SCOREBOARD);
intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
intel_ring_emit(ring, 0); /* low dword */
intel_ring_emit(ring, 0); /* high dword */
intel_ring_emit(ring, MI_NOOP);
intel_ring_advance(ring);
ret = intel_ring_begin(ring, 6);
if (ret)
return ret;
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE);
intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
intel_ring_emit(ring, 0);
intel_ring_emit(ring, 0);
intel_ring_emit(ring, MI_NOOP);
intel_ring_advance(ring);
return 0;
}
static int
gen6_render_ring_flush(struct intel_ring_buffer *ring,
u32 invalidate_domains, u32 flush_domains)
{
u32 flags = 0;
struct pipe_control *pc = ring->private;
u32 scratch_addr = pc->gtt_offset + 128;
int ret;
/* Force SNB workarounds for PIPE_CONTROL flushes */
intel_emit_post_sync_nonzero_flush(ring);
/* Just flush everything. Experiments have shown that reducing the
* number of bits based on the write domains has little performance
* impact.
*/
flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
ret = intel_ring_begin(ring, 6);
if (ret)
return ret;
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
intel_ring_emit(ring, flags);
intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
intel_ring_emit(ring, 0); /* lower dword */
intel_ring_emit(ring, 0); /* uppwer dword */
intel_ring_emit(ring, MI_NOOP);
intel_ring_advance(ring);
return 0;
}
static void ring_write_tail(struct intel_ring_buffer *ring, static void ring_write_tail(struct intel_ring_buffer *ring,
u32 value) u32 value)
{ {
...@@ -206,16 +328,6 @@ static int init_ring_common(struct intel_ring_buffer *ring) ...@@ -206,16 +328,6 @@ static int init_ring_common(struct intel_ring_buffer *ring)
return 0; return 0;
} }
/*
* 965+ support PIPE_CONTROL commands, which provide finer grained control
* over cache flushing.
*/
struct pipe_control {
struct drm_i915_gem_object *obj;
volatile u32 *cpu_page;
u32 gtt_offset;
};
static int static int
init_pipe_control(struct intel_ring_buffer *ring) init_pipe_control(struct intel_ring_buffer *ring)
{ {
...@@ -296,8 +408,7 @@ static int init_render_ring(struct intel_ring_buffer *ring) ...@@ -296,8 +408,7 @@ static int init_render_ring(struct intel_ring_buffer *ring)
GFX_MODE_ENABLE(GFX_REPLAY_MODE)); GFX_MODE_ENABLE(GFX_REPLAY_MODE));
} }
if (INTEL_INFO(dev)->gen >= 6) { if (INTEL_INFO(dev)->gen >= 5) {
} else if (IS_GEN5(dev)) {
ret = init_pipe_control(ring); ret = init_pipe_control(ring);
if (ret) if (ret)
return ret; return ret;
...@@ -438,8 +549,8 @@ gen6_blt_ring_sync_to(struct intel_ring_buffer *waiter, ...@@ -438,8 +549,8 @@ gen6_blt_ring_sync_to(struct intel_ring_buffer *waiter,
#define PIPE_CONTROL_FLUSH(ring__, addr__) \ #define PIPE_CONTROL_FLUSH(ring__, addr__) \
do { \ do { \
intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | \ intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \
PIPE_CONTROL_DEPTH_STALL | 2); \ PIPE_CONTROL_DEPTH_STALL); \
intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \ intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \
intel_ring_emit(ring__, 0); \ intel_ring_emit(ring__, 0); \
intel_ring_emit(ring__, 0); \ intel_ring_emit(ring__, 0); \
...@@ -467,8 +578,9 @@ pc_render_add_request(struct intel_ring_buffer *ring, ...@@ -467,8 +578,9 @@ pc_render_add_request(struct intel_ring_buffer *ring,
if (ret) if (ret)
return ret; return ret;
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH); PIPE_CONTROL_WRITE_FLUSH |
PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE);
intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT); intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
intel_ring_emit(ring, seqno); intel_ring_emit(ring, seqno);
intel_ring_emit(ring, 0); intel_ring_emit(ring, 0);
...@@ -483,8 +595,9 @@ pc_render_add_request(struct intel_ring_buffer *ring, ...@@ -483,8 +595,9 @@ pc_render_add_request(struct intel_ring_buffer *ring,
PIPE_CONTROL_FLUSH(ring, scratch_addr); PIPE_CONTROL_FLUSH(ring, scratch_addr);
scratch_addr += 128; scratch_addr += 128;
PIPE_CONTROL_FLUSH(ring, scratch_addr); PIPE_CONTROL_FLUSH(ring, scratch_addr);
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH | PIPE_CONTROL_WRITE_FLUSH |
PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
PIPE_CONTROL_NOTIFY); PIPE_CONTROL_NOTIFY);
intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT); intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
intel_ring_emit(ring, seqno); intel_ring_emit(ring, seqno);
...@@ -1358,6 +1471,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ...@@ -1358,6 +1471,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
*ring = render_ring; *ring = render_ring;
if (INTEL_INFO(dev)->gen >= 6) { if (INTEL_INFO(dev)->gen >= 6) {
ring->add_request = gen6_add_request; ring->add_request = gen6_add_request;
ring->flush = gen6_render_ring_flush;
ring->irq_get = gen6_render_ring_get_irq; ring->irq_get = gen6_render_ring_get_irq;
ring->irq_put = gen6_render_ring_put_irq; ring->irq_put = gen6_render_ring_put_irq;
} else if (IS_GEN5(dev)) { } else if (IS_GEN5(dev)) {
......
...@@ -1232,8 +1232,7 @@ static bool ...@@ -1232,8 +1232,7 @@ static bool
intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo) intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo)
{ {
/* Is there more than one type of output? */ /* Is there more than one type of output? */
int caps = intel_sdvo->caps.output_flags & 0xf; return hweight16(intel_sdvo->caps.output_flags) > 1;
return caps & -caps;
} }
static struct edid * static struct edid *
...@@ -1254,7 +1253,7 @@ intel_sdvo_get_analog_edid(struct drm_connector *connector) ...@@ -1254,7 +1253,7 @@ intel_sdvo_get_analog_edid(struct drm_connector *connector)
} }
enum drm_connector_status enum drm_connector_status
intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
{ {
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
enum drm_connector_status status; enum drm_connector_status status;
...@@ -1349,7 +1348,7 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) ...@@ -1349,7 +1348,7 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
if ((intel_sdvo_connector->output_flag & response) == 0) if ((intel_sdvo_connector->output_flag & response) == 0)
ret = connector_status_disconnected; ret = connector_status_disconnected;
else if (IS_TMDS(intel_sdvo_connector)) else if (IS_TMDS(intel_sdvo_connector))
ret = intel_sdvo_hdmi_sink_detect(connector); ret = intel_sdvo_tmds_sink_detect(connector);
else { else {
struct edid *edid; struct edid *edid;
...@@ -1896,7 +1895,7 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, ...@@ -1896,7 +1895,7 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
struct intel_sdvo *sdvo, u32 reg) struct intel_sdvo *sdvo, u32 reg)
{ {
struct sdvo_device_mapping *mapping; struct sdvo_device_mapping *mapping;
u8 pin, speed; u8 pin;
if (IS_SDVOB(reg)) if (IS_SDVOB(reg))
mapping = &dev_priv->sdvo_mappings[0]; mapping = &dev_priv->sdvo_mappings[0];
...@@ -1904,18 +1903,16 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, ...@@ -1904,18 +1903,16 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
mapping = &dev_priv->sdvo_mappings[1]; mapping = &dev_priv->sdvo_mappings[1];
pin = GMBUS_PORT_DPB; pin = GMBUS_PORT_DPB;
speed = GMBUS_RATE_1MHZ >> 8; if (mapping->initialized)
if (mapping->initialized) {
pin = mapping->i2c_pin; pin = mapping->i2c_pin;
speed = mapping->i2c_speed;
}
if (pin < GMBUS_NUM_PORTS) { if (pin < GMBUS_NUM_PORTS) {
sdvo->i2c = &dev_priv->gmbus[pin].adapter; sdvo->i2c = &dev_priv->gmbus[pin].adapter;
intel_gmbus_set_speed(sdvo->i2c, speed); intel_gmbus_set_speed(sdvo->i2c, GMBUS_RATE_1MHZ);
intel_gmbus_force_bit(sdvo->i2c, true); intel_gmbus_force_bit(sdvo->i2c, true);
} else } else {
sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter; sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter;
}
} }
static bool static bool
...@@ -2206,7 +2203,7 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags) ...@@ -2206,7 +2203,7 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags)
bytes[0], bytes[1]); bytes[0], bytes[1]);
return false; return false;
} }
intel_sdvo->base.crtc_mask = (1 << 0) | (1 << 1); intel_sdvo->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
return true; return true;
} }
......
...@@ -404,6 +404,9 @@ static int dmar_forcedac; ...@@ -404,6 +404,9 @@ static int dmar_forcedac;
static int intel_iommu_strict; static int intel_iommu_strict;
static int intel_iommu_superpage = 1; static int intel_iommu_superpage = 1;
int intel_iommu_gfx_mapped;
EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1)) #define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
static DEFINE_SPINLOCK(device_domain_lock); static DEFINE_SPINLOCK(device_domain_lock);
static LIST_HEAD(device_domain_list); static LIST_HEAD(device_domain_list);
...@@ -3226,9 +3229,6 @@ static void __init init_no_remapping_devices(void) ...@@ -3226,9 +3229,6 @@ static void __init init_no_remapping_devices(void)
} }
} }
if (dmar_map_gfx)
return;
for_each_drhd_unit(drhd) { for_each_drhd_unit(drhd) {
int i; int i;
if (drhd->ignored || drhd->include_all) if (drhd->ignored || drhd->include_all)
...@@ -3236,18 +3236,23 @@ static void __init init_no_remapping_devices(void) ...@@ -3236,18 +3236,23 @@ static void __init init_no_remapping_devices(void)
for (i = 0; i < drhd->devices_cnt; i++) for (i = 0; i < drhd->devices_cnt; i++)
if (drhd->devices[i] && if (drhd->devices[i] &&
!IS_GFX_DEVICE(drhd->devices[i])) !IS_GFX_DEVICE(drhd->devices[i]))
break; break;
if (i < drhd->devices_cnt) if (i < drhd->devices_cnt)
continue; continue;
/* bypass IOMMU if it is just for gfx devices */ /* This IOMMU has *only* gfx devices. Either bypass it or
drhd->ignored = 1; set the gfx_mapped flag, as appropriate */
for (i = 0; i < drhd->devices_cnt; i++) { if (dmar_map_gfx) {
if (!drhd->devices[i]) intel_iommu_gfx_mapped = 1;
continue; } else {
drhd->devices[i]->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO; drhd->ignored = 1;
for (i = 0; i < drhd->devices_cnt; i++) {
if (!drhd->devices[i])
continue;
drhd->devices[i]->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
}
} }
} }
} }
...@@ -3950,7 +3955,11 @@ static void __devinit quirk_calpella_no_shadow_gtt(struct pci_dev *dev) ...@@ -3950,7 +3955,11 @@ static void __devinit quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
if (!(ggc & GGC_MEMORY_VT_ENABLED)) { if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
printk(KERN_INFO "DMAR: BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n"); printk(KERN_INFO "DMAR: BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
dmar_map_gfx = 0; dmar_map_gfx = 0;
} } else if (dmar_map_gfx) {
/* we have to ensure the gfx device is idle before we flush */
printk(KERN_INFO "DMAR: Disabling batched IOTLB flush on Ironlake\n");
intel_iommu_strict = 1;
}
} }
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
......
...@@ -74,6 +74,20 @@ ...@@ -74,6 +74,20 @@
#define DP_TRAINING_AUX_RD_INTERVAL 0x00e #define DP_TRAINING_AUX_RD_INTERVAL 0x00e
#define DP_PSR_SUPPORT 0x070
# define DP_PSR_IS_SUPPORTED 1
#define DP_PSR_CAPS 0x071
# define DP_PSR_NO_TRAIN_ON_EXIT 1
# define DP_PSR_SETUP_TIME_330 (0 << 1)
# define DP_PSR_SETUP_TIME_275 (1 << 1)
# define DP_PSR_SETUP_TIME_220 (2 << 1)
# define DP_PSR_SETUP_TIME_165 (3 << 1)
# define DP_PSR_SETUP_TIME_110 (4 << 1)
# define DP_PSR_SETUP_TIME_55 (5 << 1)
# define DP_PSR_SETUP_TIME_0 (6 << 1)
# define DP_PSR_SETUP_TIME_MASK (7 << 1)
# define DP_PSR_SETUP_TIME_SHIFT 1
/* link configuration */ /* link configuration */
#define DP_LINK_BW_SET 0x100 #define DP_LINK_BW_SET 0x100
# define DP_LINK_BW_1_62 0x06 # define DP_LINK_BW_1_62 0x06
...@@ -133,6 +147,18 @@ ...@@ -133,6 +147,18 @@
#define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108 #define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108
# define DP_SET_ANSI_8B10B (1 << 0) # define DP_SET_ANSI_8B10B (1 << 0)
#define DP_PSR_EN_CFG 0x170
# define DP_PSR_ENABLE (1 << 0)
# define DP_PSR_MAIN_LINK_ACTIVE (1 << 1)
# define DP_PSR_CRC_VERIFICATION (1 << 2)
# define DP_PSR_FRAME_CAPTURE (1 << 3)
#define DP_DEVICE_SERVICE_IRQ_VECTOR 0x201
# define DP_REMOTE_CONTROL_COMMAND_PENDING (1 << 0)
# define DP_AUTOMATED_TEST_REQUEST (1 << 1)
# define DP_CP_IRQ (1 << 2)
# define DP_SINK_SPECIFIC_IRQ (1 << 6)
#define DP_LANE0_1_STATUS 0x202 #define DP_LANE0_1_STATUS 0x202
#define DP_LANE2_3_STATUS 0x203 #define DP_LANE2_3_STATUS 0x203
# define DP_LANE_CR_DONE (1 << 0) # define DP_LANE_CR_DONE (1 << 0)
...@@ -165,10 +191,45 @@ ...@@ -165,10 +191,45 @@
# define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0 # define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0
# define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6 # define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6
#define DP_TEST_REQUEST 0x218
# define DP_TEST_LINK_TRAINING (1 << 0)
# define DP_TEST_LINK_PATTERN (1 << 1)
# define DP_TEST_LINK_EDID_READ (1 << 2)
# define DP_TEST_LINK_PHY_TEST_PATTERN (1 << 3) /* DPCD >= 1.1 */
#define DP_TEST_LINK_RATE 0x219
# define DP_LINK_RATE_162 (0x6)
# define DP_LINK_RATE_27 (0xa)
#define DP_TEST_LANE_COUNT 0x220
#define DP_TEST_PATTERN 0x221
#define DP_TEST_RESPONSE 0x260
# define DP_TEST_ACK (1 << 0)
# define DP_TEST_NAK (1 << 1)
# define DP_TEST_EDID_CHECKSUM_WRITE (1 << 2)
#define DP_SET_POWER 0x600 #define DP_SET_POWER 0x600
# define DP_SET_POWER_D0 0x1 # define DP_SET_POWER_D0 0x1
# define DP_SET_POWER_D3 0x2 # define DP_SET_POWER_D3 0x2
#define DP_PSR_ERROR_STATUS 0x2006
# define DP_PSR_LINK_CRC_ERROR (1 << 0)
# define DP_PSR_RFB_STORAGE_ERROR (1 << 1)
#define DP_PSR_ESI 0x2007
# define DP_PSR_CAPS_CHANGE (1 << 0)
#define DP_PSR_STATUS 0x2008
# define DP_PSR_SINK_INACTIVE 0
# define DP_PSR_SINK_ACTIVE_SRC_SYNCED 1
# define DP_PSR_SINK_ACTIVE_RFB 2
# define DP_PSR_SINK_ACTIVE_SINK_SYNCED 3
# define DP_PSR_SINK_ACTIVE_RESYNC 4
# define DP_PSR_SINK_INTERNAL_ERROR 7
# define DP_PSR_SINK_STATE_MASK 0x07
#define MODE_I2C_START 1 #define MODE_I2C_START 1
#define MODE_I2C_WRITE 2 #define MODE_I2C_WRITE 2
#define MODE_I2C_READ 4 #define MODE_I2C_READ 4
......
...@@ -13,6 +13,8 @@ const struct intel_gtt { ...@@ -13,6 +13,8 @@ const struct intel_gtt {
unsigned int gtt_mappable_entries; unsigned int gtt_mappable_entries;
/* Whether i915 needs to use the dmar apis or not. */ /* Whether i915 needs to use the dmar apis or not. */
unsigned int needs_dmar : 1; unsigned int needs_dmar : 1;
/* Whether we idle the gpu before mapping/unmapping */
unsigned int do_idle_maps : 1;
} *intel_gtt_get(void); } *intel_gtt_get(void);
void intel_gtt_chipset_flush(void); void intel_gtt_chipset_flush(void);
......
...@@ -117,6 +117,8 @@ io_mapping_unmap(void __iomem *vaddr) ...@@ -117,6 +117,8 @@ io_mapping_unmap(void __iomem *vaddr)
#else #else
#include <linux/uaccess.h>
/* this struct isn't actually defined anywhere */ /* this struct isn't actually defined anywhere */
struct io_mapping; struct io_mapping;
...@@ -138,12 +140,14 @@ static inline void __iomem * ...@@ -138,12 +140,14 @@ static inline void __iomem *
io_mapping_map_atomic_wc(struct io_mapping *mapping, io_mapping_map_atomic_wc(struct io_mapping *mapping,
unsigned long offset) unsigned long offset)
{ {
pagefault_disable();
return ((char __force __iomem *) mapping) + offset; return ((char __force __iomem *) mapping) + offset;
} }
static inline void static inline void
io_mapping_unmap_atomic(void __iomem *vaddr) io_mapping_unmap_atomic(void __iomem *vaddr)
{ {
pagefault_enable();
} }
/* Non-atomic map/unmap */ /* Non-atomic map/unmap */
......
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