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);
......
...@@ -803,6 +803,19 @@ static void assert_pch_pll(struct drm_i915_private *dev_priv, ...@@ -803,6 +803,19 @@ static void assert_pch_pll(struct drm_i915_private *dev_priv,
u32 val; u32 val;
bool cur_state; bool cur_state;
if (HAS_PCH_CPT(dev_priv->dev)) {
u32 pch_dpll;
pch_dpll = I915_READ(PCH_DPLL_SEL);
/* Make sure the selected PLL is enabled to the transcoder */
WARN(!((pch_dpll >> (4 * pipe)) & 8),
"transcoder %d PLL not enabled\n", pipe);
/* Convert the transcoder pipe number to a pll pipe number */
pipe = (pch_dpll >> (4 * pipe)) & 1;
}
reg = PCH_DPLL(pipe); reg = PCH_DPLL(pipe);
val = I915_READ(reg); val = I915_READ(reg);
cur_state = !!(val & DPLL_VCO_ENABLE); cur_state = !!(val & DPLL_VCO_ENABLE);
...@@ -1172,6 +1185,9 @@ static void intel_enable_pch_pll(struct drm_i915_private *dev_priv, ...@@ -1172,6 +1185,9 @@ static void intel_enable_pch_pll(struct drm_i915_private *dev_priv,
int reg; int reg;
u32 val; u32 val;
if (pipe > 1)
return;
/* PCH only available on ILK+ */ /* PCH only available on ILK+ */
BUG_ON(dev_priv->info->gen < 5); BUG_ON(dev_priv->info->gen < 5);
...@@ -1192,6 +1208,9 @@ static void intel_disable_pch_pll(struct drm_i915_private *dev_priv, ...@@ -1192,6 +1208,9 @@ static void intel_disable_pch_pll(struct drm_i915_private *dev_priv,
int reg; int reg;
u32 val; u32 val;
if (pipe > 1)
return;
/* PCH only available on ILK+ */ /* PCH only available on ILK+ */
BUG_ON(dev_priv->info->gen < 5); BUG_ON(dev_priv->info->gen < 5);
...@@ -1257,7 +1276,7 @@ static void intel_disable_transcoder(struct drm_i915_private *dev_priv, ...@@ -1257,7 +1276,7 @@ static void intel_disable_transcoder(struct drm_i915_private *dev_priv,
I915_WRITE(reg, val); I915_WRITE(reg, val);
/* wait for PCH transcoder off, transcoder state */ /* wait for PCH transcoder off, transcoder state */
if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50)) if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50))
DRM_ERROR("failed to disable transcoder\n"); DRM_ERROR("failed to disable transcoder %d\n", pipe);
} }
/** /**
...@@ -2086,6 +2105,7 @@ static int ironlake_update_plane(struct drm_crtc *crtc, ...@@ -2086,6 +2105,7 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
switch (plane) { switch (plane) {
case 0: case 0:
case 1: case 1:
case 2:
break; break;
default: default:
DRM_ERROR("Can't update plane %d in SAREA\n", plane); DRM_ERROR("Can't update plane %d in SAREA\n", plane);
...@@ -2185,6 +2205,10 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, ...@@ -2185,6 +2205,10 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
case 0: case 0:
case 1: case 1:
break; break;
case 2:
if (IS_IVYBRIDGE(dev))
break;
/* fall through otherwise */
default: default:
DRM_ERROR("no plane for crtc\n"); DRM_ERROR("no plane for crtc\n");
return -EINVAL; return -EINVAL;
...@@ -2601,6 +2625,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) ...@@ -2601,6 +2625,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
temp |= FDI_LINK_TRAIN_PATTERN_1_IVB; temp |= FDI_LINK_TRAIN_PATTERN_1_IVB;
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
temp |= FDI_COMPOSITE_SYNC;
I915_WRITE(reg, temp | FDI_TX_ENABLE); I915_WRITE(reg, temp | FDI_TX_ENABLE);
reg = FDI_RX_CTL(pipe); reg = FDI_RX_CTL(pipe);
...@@ -2608,6 +2633,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) ...@@ -2608,6 +2633,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
temp &= ~FDI_LINK_TRAIN_AUTO; temp &= ~FDI_LINK_TRAIN_AUTO;
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
temp |= FDI_COMPOSITE_SYNC;
I915_WRITE(reg, temp | FDI_RX_ENABLE); I915_WRITE(reg, temp | FDI_RX_ENABLE);
POSTING_READ(reg); POSTING_READ(reg);
...@@ -2867,7 +2893,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) ...@@ -2867,7 +2893,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
u32 reg, temp; u32 reg, temp, transc_sel;
/* For PCH output, training FDI link */ /* For PCH output, training FDI link */
dev_priv->display.fdi_link_train(crtc); dev_priv->display.fdi_link_train(crtc);
...@@ -2875,12 +2901,21 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) ...@@ -2875,12 +2901,21 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
intel_enable_pch_pll(dev_priv, pipe); intel_enable_pch_pll(dev_priv, pipe);
if (HAS_PCH_CPT(dev)) { if (HAS_PCH_CPT(dev)) {
transc_sel = intel_crtc->use_pll_a ? TRANSC_DPLLA_SEL :
TRANSC_DPLLB_SEL;
/* Be sure PCH DPLL SEL is set */ /* Be sure PCH DPLL SEL is set */
temp = I915_READ(PCH_DPLL_SEL); temp = I915_READ(PCH_DPLL_SEL);
if (pipe == 0 && (temp & TRANSA_DPLL_ENABLE) == 0) if (pipe == 0) {
temp &= ~(TRANSA_DPLLB_SEL);
temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL); temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL);
else if (pipe == 1 && (temp & TRANSB_DPLL_ENABLE) == 0) } else if (pipe == 1) {
temp &= ~(TRANSB_DPLLB_SEL);
temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
} else if (pipe == 2) {
temp &= ~(TRANSC_DPLLB_SEL);
temp |= (TRANSC_DPLL_ENABLE | transc_sel);
}
I915_WRITE(PCH_DPLL_SEL, temp); I915_WRITE(PCH_DPLL_SEL, temp);
} }
...@@ -2936,6 +2971,24 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) ...@@ -2936,6 +2971,24 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
intel_enable_transcoder(dev_priv, pipe); intel_enable_transcoder(dev_priv, pipe);
} }
void intel_cpt_verify_modeset(struct drm_device *dev, int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int dslreg = PIPEDSL(pipe), tc2reg = TRANS_CHICKEN2(pipe);
u32 temp;
temp = I915_READ(dslreg);
udelay(500);
if (wait_for(I915_READ(dslreg) != temp, 5)) {
/* Without this, mode sets may fail silently on FDI */
I915_WRITE(tc2reg, TRANS_AUTOTRAIN_GEN_STALL_DIS);
udelay(250);
I915_WRITE(tc2reg, 0);
if (wait_for(I915_READ(dslreg) != temp, 5))
DRM_ERROR("mode set failed: pipe %d stuck\n", pipe);
}
}
static void ironlake_crtc_enable(struct drm_crtc *crtc) static void ironlake_crtc_enable(struct drm_crtc *crtc)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
...@@ -3046,13 +3099,13 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) ...@@ -3046,13 +3099,13 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
temp = I915_READ(PCH_DPLL_SEL); temp = I915_READ(PCH_DPLL_SEL);
switch (pipe) { switch (pipe) {
case 0: case 0:
temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL); temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL);
break; break;
case 1: case 1:
temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
break; break;
case 2: case 2:
/* FIXME: manage transcoder PLLs? */ /* C shares PLL A or B */
temp &= ~(TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL); temp &= ~(TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL);
break; break;
default: default:
...@@ -3062,7 +3115,8 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) ...@@ -3062,7 +3115,8 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
} }
/* disable PCH DPLL */ /* disable PCH DPLL */
intel_disable_pch_pll(dev_priv, pipe); if (!intel_crtc->no_pll)
intel_disable_pch_pll(dev_priv, pipe);
/* Switch from PCDclk to Rawclk */ /* Switch from PCDclk to Rawclk */
reg = FDI_RX_CTL(pipe); reg = FDI_RX_CTL(pipe);
...@@ -3304,8 +3358,15 @@ void intel_encoder_prepare(struct drm_encoder *encoder) ...@@ -3304,8 +3358,15 @@ void intel_encoder_prepare(struct drm_encoder *encoder)
void intel_encoder_commit(struct drm_encoder *encoder) void intel_encoder_commit(struct drm_encoder *encoder)
{ {
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
struct drm_device *dev = encoder->dev;
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
/* lvds has its own version of commit see intel_lvds_commit */ /* lvds has its own version of commit see intel_lvds_commit */
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
if (HAS_PCH_CPT(dev))
intel_cpt_verify_modeset(dev, intel_crtc->pipe);
} }
void intel_encoder_destroy(struct drm_encoder *encoder) void intel_encoder_destroy(struct drm_encoder *encoder)
...@@ -4479,6 +4540,20 @@ static void sandybridge_update_wm(struct drm_device *dev) ...@@ -4479,6 +4540,20 @@ static void sandybridge_update_wm(struct drm_device *dev)
enabled |= 2; enabled |= 2;
} }
/* IVB has 3 pipes */
if (IS_IVYBRIDGE(dev) &&
g4x_compute_wm0(dev, 2,
&sandybridge_display_wm_info, latency,
&sandybridge_cursor_wm_info, latency,
&plane_wm, &cursor_wm)) {
I915_WRITE(WM0_PIPEC_IVB,
(plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
DRM_DEBUG_KMS("FIFO watermarks For pipe C -"
" plane %d, cursor: %d\n",
plane_wm, cursor_wm);
enabled |= 3;
}
/* /*
* Calculate and update the self-refresh watermark only when one * Calculate and update the self-refresh watermark only when one
* display plane is used. * display plane is used.
...@@ -4585,7 +4660,9 @@ static void intel_update_watermarks(struct drm_device *dev) ...@@ -4585,7 +4660,9 @@ static void intel_update_watermarks(struct drm_device *dev)
static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
{ {
return dev_priv->lvds_use_ssc && i915_panel_use_ssc if (i915_panel_use_ssc >= 0)
return i915_panel_use_ssc != 0;
return dev_priv->lvds_use_ssc
&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE); && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
} }
...@@ -5108,36 +5185,52 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, ...@@ -5108,36 +5185,52 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
return ret; return ret;
} }
static void ironlake_update_pch_refclk(struct drm_device *dev) /*
* Initialize reference clocks when the driver loads
*/
void ironlake_init_pch_refclk(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_mode_config *mode_config = &dev->mode_config; struct drm_mode_config *mode_config = &dev->mode_config;
struct drm_crtc *crtc;
struct intel_encoder *encoder; struct intel_encoder *encoder;
struct intel_encoder *has_edp_encoder = NULL;
u32 temp; u32 temp;
bool has_lvds = false; bool has_lvds = false;
bool has_cpu_edp = false;
bool has_pch_edp = false;
bool has_panel = false;
bool has_ck505 = false;
bool can_ssc = false;
/* We need to take the global config into account */ /* We need to take the global config into account */
list_for_each_entry(crtc, &mode_config->crtc_list, head) { list_for_each_entry(encoder, &mode_config->encoder_list,
if (!crtc->enabled) base.head) {
continue; switch (encoder->type) {
case INTEL_OUTPUT_LVDS:
list_for_each_entry(encoder, &mode_config->encoder_list, has_panel = true;
base.head) { has_lvds = true;
if (encoder->base.crtc != crtc) break;
continue; case INTEL_OUTPUT_EDP:
has_panel = true;
switch (encoder->type) { if (intel_encoder_is_pch_edp(&encoder->base))
case INTEL_OUTPUT_LVDS: has_pch_edp = true;
has_lvds = true; else
case INTEL_OUTPUT_EDP: has_cpu_edp = true;
has_edp_encoder = encoder; break;
break;
}
} }
} }
if (HAS_PCH_IBX(dev)) {
has_ck505 = dev_priv->display_clock_mode;
can_ssc = has_ck505;
} else {
has_ck505 = false;
can_ssc = true;
}
DRM_DEBUG_KMS("has_panel %d has_lvds %d has_pch_edp %d has_cpu_edp %d has_ck505 %d\n",
has_panel, has_lvds, has_pch_edp, has_cpu_edp,
has_ck505);
/* Ironlake: try to setup display ref clock before DPLL /* Ironlake: try to setup display ref clock before DPLL
* enabling. This is only under driver's control after * enabling. This is only under driver's control after
* PCH B stepping, previous chipset stepping should be * PCH B stepping, previous chipset stepping should be
...@@ -5146,41 +5239,100 @@ static void ironlake_update_pch_refclk(struct drm_device *dev) ...@@ -5146,41 +5239,100 @@ static void ironlake_update_pch_refclk(struct drm_device *dev)
temp = I915_READ(PCH_DREF_CONTROL); temp = I915_READ(PCH_DREF_CONTROL);
/* Always enable nonspread source */ /* Always enable nonspread source */
temp &= ~DREF_NONSPREAD_SOURCE_MASK; temp &= ~DREF_NONSPREAD_SOURCE_MASK;
temp |= DREF_NONSPREAD_SOURCE_ENABLE;
temp &= ~DREF_SSC_SOURCE_MASK;
temp |= DREF_SSC_SOURCE_ENABLE;
I915_WRITE(PCH_DREF_CONTROL, temp);
POSTING_READ(PCH_DREF_CONTROL); if (has_ck505)
udelay(200); temp |= DREF_NONSPREAD_CK505_ENABLE;
else
temp |= DREF_NONSPREAD_SOURCE_ENABLE;
if (has_edp_encoder) { if (has_panel) {
if (intel_panel_use_ssc(dev_priv)) { temp &= ~DREF_SSC_SOURCE_MASK;
temp |= DREF_SSC1_ENABLE; temp |= DREF_SSC_SOURCE_ENABLE;
I915_WRITE(PCH_DREF_CONTROL, temp);
POSTING_READ(PCH_DREF_CONTROL); /* SSC must be turned on before enabling the CPU output */
udelay(200); if (intel_panel_use_ssc(dev_priv) && can_ssc) {
DRM_DEBUG_KMS("Using SSC on panel\n");
temp |= DREF_SSC1_ENABLE;
} }
/* Get SSC going before enabling the outputs */
I915_WRITE(PCH_DREF_CONTROL, temp);
POSTING_READ(PCH_DREF_CONTROL);
udelay(200);
temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
/* Enable CPU source on CPU attached eDP */ /* Enable CPU source on CPU attached eDP */
if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) { if (has_cpu_edp) {
if (intel_panel_use_ssc(dev_priv)) if (intel_panel_use_ssc(dev_priv) && can_ssc) {
DRM_DEBUG_KMS("Using SSC on eDP\n");
temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
}
else else
temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
} else { } else
/* Enable SSC on PCH eDP if needed */ temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
if (intel_panel_use_ssc(dev_priv)) {
DRM_ERROR("enabling SSC on PCH\n");
temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
}
}
I915_WRITE(PCH_DREF_CONTROL, temp); I915_WRITE(PCH_DREF_CONTROL, temp);
POSTING_READ(PCH_DREF_CONTROL); POSTING_READ(PCH_DREF_CONTROL);
udelay(200); udelay(200);
} else {
DRM_DEBUG_KMS("Disabling SSC entirely\n");
temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
/* Turn off CPU output */
temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
I915_WRITE(PCH_DREF_CONTROL, temp);
POSTING_READ(PCH_DREF_CONTROL);
udelay(200);
/* Turn off the SSC source */
temp &= ~DREF_SSC_SOURCE_MASK;
temp |= DREF_SSC_SOURCE_DISABLE;
/* Turn off SSC1 */
temp &= ~ DREF_SSC1_ENABLE;
I915_WRITE(PCH_DREF_CONTROL, temp);
POSTING_READ(PCH_DREF_CONTROL);
udelay(200);
}
}
static int ironlake_get_refclk(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_encoder *encoder;
struct drm_mode_config *mode_config = &dev->mode_config;
struct intel_encoder *edp_encoder = NULL;
int num_connectors = 0;
bool is_lvds = false;
list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
if (encoder->base.crtc != crtc)
continue;
switch (encoder->type) {
case INTEL_OUTPUT_LVDS:
is_lvds = true;
break;
case INTEL_OUTPUT_EDP:
edp_encoder = encoder;
break;
}
num_connectors++;
} }
if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
dev_priv->lvds_ssc_freq);
return dev_priv->lvds_ssc_freq * 1000;
}
return 120000;
} }
static int ironlake_crtc_mode_set(struct drm_crtc *crtc, static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
...@@ -5242,16 +5394,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, ...@@ -5242,16 +5394,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
num_connectors++; num_connectors++;
} }
if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { refclk = ironlake_get_refclk(crtc);
refclk = dev_priv->lvds_ssc_freq * 1000;
DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
refclk / 1000);
} else {
refclk = 96000;
if (!has_edp_encoder ||
intel_encoder_is_pch_edp(&has_edp_encoder->base))
refclk = 120000; /* 120Mhz refclk */
}
/* /*
* Returns a set of divisors for the desired target clock with the given * Returns a set of divisors for the desired target clock with the given
...@@ -5378,8 +5521,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, ...@@ -5378,8 +5521,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw, ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
&m_n); &m_n);
ironlake_update_pch_refclk(dev);
fp = clock.n << 16 | clock.m1 << 8 | clock.m2; fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
if (has_reduced_clock) if (has_reduced_clock)
fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 | fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
...@@ -5451,39 +5592,32 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, ...@@ -5451,39 +5592,32 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
/* Set up the display plane register */ /* Set up the display plane register */
dspcntr = DISPPLANE_GAMMA_ENABLE; dspcntr = DISPPLANE_GAMMA_ENABLE;
DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
drm_mode_debug_printmodeline(mode); drm_mode_debug_printmodeline(mode);
/* PCH eDP needs FDI, but CPU eDP does not */ /* PCH eDP needs FDI, but CPU eDP does not */
if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { if (!intel_crtc->no_pll) {
I915_WRITE(PCH_FP0(pipe), fp); if (!has_edp_encoder ||
I915_WRITE(PCH_DPLL(pipe), dpll & ~DPLL_VCO_ENABLE); intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
I915_WRITE(PCH_FP0(pipe), fp);
POSTING_READ(PCH_DPLL(pipe)); I915_WRITE(PCH_DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
udelay(150);
}
/* enable transcoder DPLL */ POSTING_READ(PCH_DPLL(pipe));
if (HAS_PCH_CPT(dev)) { udelay(150);
temp = I915_READ(PCH_DPLL_SEL); }
switch (pipe) { } else {
case 0: if (dpll == (I915_READ(PCH_DPLL(0)) & 0x7fffffff) &&
temp |= TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL; fp == I915_READ(PCH_FP0(0))) {
break; intel_crtc->use_pll_a = true;
case 1: DRM_DEBUG_KMS("using pipe a dpll\n");
temp |= TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL; } else if (dpll == (I915_READ(PCH_DPLL(1)) & 0x7fffffff) &&
break; fp == I915_READ(PCH_FP0(1))) {
case 2: intel_crtc->use_pll_a = false;
/* FIXME: manage transcoder PLLs? */ DRM_DEBUG_KMS("using pipe b dpll\n");
temp |= TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL; } else {
break; DRM_DEBUG_KMS("no matching PLL configuration for pipe 2\n");
default: return -EINVAL;
BUG();
} }
I915_WRITE(PCH_DPLL_SEL, temp);
POSTING_READ(PCH_DPLL_SEL);
udelay(150);
} }
/* The LVDS pin pair needs to be on before the DPLLs are enabled. /* The LVDS pin pair needs to be on before the DPLLs are enabled.
...@@ -5493,17 +5627,13 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, ...@@ -5493,17 +5627,13 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
if (is_lvds) { if (is_lvds) {
temp = I915_READ(PCH_LVDS); temp = I915_READ(PCH_LVDS);
temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
if (pipe == 1) { if (HAS_PCH_CPT(dev))
if (HAS_PCH_CPT(dev)) temp |= PORT_TRANS_SEL_CPT(pipe);
temp |= PORT_TRANS_B_SEL_CPT; else if (pipe == 1)
else temp |= LVDS_PIPEB_SELECT;
temp |= LVDS_PIPEB_SELECT; else
} else { temp &= ~LVDS_PIPEB_SELECT;
if (HAS_PCH_CPT(dev))
temp &= ~PORT_TRANS_SEL_MASK;
else
temp &= ~LVDS_PIPEB_SELECT;
}
/* set the corresponsding LVDS_BORDER bit */ /* set the corresponsding LVDS_BORDER bit */
temp |= dev_priv->lvds_border_bits; temp |= dev_priv->lvds_border_bits;
/* Set the B0-B3 data pairs corresponding to whether we're going to /* Set the B0-B3 data pairs corresponding to whether we're going to
...@@ -5553,8 +5683,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, ...@@ -5553,8 +5683,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
I915_WRITE(TRANSDPLINK_N1(pipe), 0); I915_WRITE(TRANSDPLINK_N1(pipe), 0);
} }
if (!has_edp_encoder || if (!intel_crtc->no_pll &&
intel_encoder_is_pch_edp(&has_edp_encoder->base)) { (!has_edp_encoder ||
intel_encoder_is_pch_edp(&has_edp_encoder->base))) {
I915_WRITE(PCH_DPLL(pipe), dpll); I915_WRITE(PCH_DPLL(pipe), dpll);
/* Wait for the clocks to stabilize. */ /* Wait for the clocks to stabilize. */
...@@ -5570,18 +5701,20 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, ...@@ -5570,18 +5701,20 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
} }
intel_crtc->lowfreq_avail = false; intel_crtc->lowfreq_avail = false;
if (is_lvds && has_reduced_clock && i915_powersave) { if (!intel_crtc->no_pll) {
I915_WRITE(PCH_FP1(pipe), fp2); if (is_lvds && has_reduced_clock && i915_powersave) {
intel_crtc->lowfreq_avail = true; I915_WRITE(PCH_FP1(pipe), fp2);
if (HAS_PIPE_CXSR(dev)) { intel_crtc->lowfreq_avail = true;
DRM_DEBUG_KMS("enabling CxSR downclocking\n"); if (HAS_PIPE_CXSR(dev)) {
pipeconf |= PIPECONF_CXSR_DOWNCLOCK; DRM_DEBUG_KMS("enabling CxSR downclocking\n");
} pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
} else { }
I915_WRITE(PCH_FP1(pipe), fp); } else {
if (HAS_PIPE_CXSR(dev)) { I915_WRITE(PCH_FP1(pipe), fp);
DRM_DEBUG_KMS("disabling CxSR downclocking\n"); if (HAS_PIPE_CXSR(dev)) {
pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; DRM_DEBUG_KMS("disabling CxSR downclocking\n");
pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
}
} }
} }
...@@ -5884,6 +6017,31 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) ...@@ -5884,6 +6017,31 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
I915_WRITE(CURBASE(pipe), base); I915_WRITE(CURBASE(pipe), base);
} }
static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
bool visible = base != 0;
if (intel_crtc->cursor_visible != visible) {
uint32_t cntl = I915_READ(CURCNTR_IVB(pipe));
if (base) {
cntl &= ~CURSOR_MODE;
cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
} else {
cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
cntl |= CURSOR_MODE_DISABLE;
}
I915_WRITE(CURCNTR_IVB(pipe), cntl);
intel_crtc->cursor_visible = visible;
}
/* and commit changes on next vblank */
I915_WRITE(CURBASE_IVB(pipe), base);
}
/* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
static void intel_crtc_update_cursor(struct drm_crtc *crtc, static void intel_crtc_update_cursor(struct drm_crtc *crtc,
bool on) bool on)
...@@ -5931,11 +6089,16 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, ...@@ -5931,11 +6089,16 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
if (!visible && !intel_crtc->cursor_visible) if (!visible && !intel_crtc->cursor_visible)
return; return;
I915_WRITE(CURPOS(pipe), pos); if (IS_IVYBRIDGE(dev)) {
if (IS_845G(dev) || IS_I865G(dev)) I915_WRITE(CURPOS_IVB(pipe), pos);
i845_update_cursor(crtc, base); ivb_update_cursor(crtc, base);
else } else {
i9xx_update_cursor(crtc, base); I915_WRITE(CURPOS(pipe), pos);
if (IS_845G(dev) || IS_I865G(dev))
i845_update_cursor(crtc, base);
else
i9xx_update_cursor(crtc, base);
}
if (visible) if (visible)
intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj); intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj);
...@@ -7197,6 +7360,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) ...@@ -7197,6 +7360,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
intel_crtc->bpp = 24; /* default for pre-Ironlake */ intel_crtc->bpp = 24; /* default for pre-Ironlake */
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
if (pipe == 2 && IS_IVYBRIDGE(dev))
intel_crtc->no_pll = true;
intel_helper_funcs.prepare = ironlake_crtc_prepare; intel_helper_funcs.prepare = ironlake_crtc_prepare;
intel_helper_funcs.commit = ironlake_crtc_commit; intel_helper_funcs.commit = ironlake_crtc_commit;
} else { } else {
...@@ -7376,6 +7541,9 @@ static void intel_setup_outputs(struct drm_device *dev) ...@@ -7376,6 +7541,9 @@ static void intel_setup_outputs(struct drm_device *dev)
/* disable all the possible outputs/crtcs before entering KMS mode */ /* disable all the possible outputs/crtcs before entering KMS mode */
drm_helper_disable_unused_functions(dev); drm_helper_disable_unused_functions(dev);
if (HAS_PCH_SPLIT(dev))
ironlake_init_pch_refclk(dev);
} }
static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
...@@ -7620,6 +7788,10 @@ void gen6_disable_rps(struct drm_device *dev) ...@@ -7620,6 +7788,10 @@ void gen6_disable_rps(struct drm_device *dev)
I915_WRITE(GEN6_RPNSWREQ, 1 << 31); I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
I915_WRITE(GEN6_PMINTRMSK, 0xffffffff); I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
I915_WRITE(GEN6_PMIER, 0); I915_WRITE(GEN6_PMIER, 0);
/* Complete PM interrupt masking here doesn't race with the rps work
* item again unmasking PM interrupts because that is using a different
* register (PMIMR) to mask PM interrupts. The only risk is in leaving
* stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
spin_lock_irq(&dev_priv->rps_lock); spin_lock_irq(&dev_priv->rps_lock);
dev_priv->pm_iir = 0; dev_priv->pm_iir = 0;
...@@ -8617,6 +8789,7 @@ void intel_modeset_cleanup(struct drm_device *dev) ...@@ -8617,6 +8789,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
* enqueue unpin/hotplug work. */ * enqueue unpin/hotplug work. */
drm_irq_uninstall(dev); drm_irq_uninstall(dev);
cancel_work_sync(&dev_priv->hotplug_work); cancel_work_sync(&dev_priv->hotplug_work);
cancel_work_sync(&dev_priv->rps_work);
/* flush any delayed tasks or pending work */ /* flush any delayed tasks or pending work */
flush_scheduled_work(); flush_scheduled_work();
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#include "i915_drv.h" #include "i915_drv.h"
#include "drm_dp_helper.h" #include "drm_dp_helper.h"
#define DP_RECEIVER_CAP_SIZE 0xf
#define DP_LINK_STATUS_SIZE 6 #define DP_LINK_STATUS_SIZE 6
#define DP_LINK_CHECK_TIMEOUT (10 * 1000) #define DP_LINK_CHECK_TIMEOUT (10 * 1000)
...@@ -53,12 +53,21 @@ struct intel_dp { ...@@ -53,12 +53,21 @@ struct intel_dp {
int dpms_mode; int dpms_mode;
uint8_t link_bw; uint8_t link_bw;
uint8_t lane_count; uint8_t lane_count;
uint8_t dpcd[8]; uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
struct i2c_adapter adapter; struct i2c_adapter adapter;
struct i2c_algo_dp_aux_data algo; struct i2c_algo_dp_aux_data algo;
bool is_pch_edp; bool is_pch_edp;
uint8_t train_set[4]; uint8_t train_set[4];
uint8_t link_status[DP_LINK_STATUS_SIZE]; uint8_t link_status[DP_LINK_STATUS_SIZE];
int panel_power_up_delay;
int panel_power_down_delay;
int panel_power_cycle_delay;
int backlight_on_delay;
int backlight_off_delay;
struct drm_display_mode *panel_fixed_mode; /* for eDP */
struct delayed_work panel_vdd_work;
bool want_panel_vdd;
unsigned long panel_off_jiffies;
}; };
/** /**
...@@ -86,6 +95,17 @@ static bool is_pch_edp(struct intel_dp *intel_dp) ...@@ -86,6 +95,17 @@ static bool is_pch_edp(struct intel_dp *intel_dp)
return intel_dp->is_pch_edp; return intel_dp->is_pch_edp;
} }
/**
* is_cpu_edp - is the port on the CPU and attached to an eDP panel?
* @intel_dp: DP struct
*
* Returns true if the given DP struct corresponds to a CPU eDP port.
*/
static bool is_cpu_edp(struct intel_dp *intel_dp)
{
return is_edp(intel_dp) && !is_pch_edp(intel_dp);
}
static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder) static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
{ {
return container_of(encoder, struct intel_dp, base.base); return container_of(encoder, struct intel_dp, base.base);
...@@ -175,9 +195,25 @@ intel_dp_link_clock(uint8_t link_bw) ...@@ -175,9 +195,25 @@ intel_dp_link_clock(uint8_t link_bw)
return 162000; return 162000;
} }
/* I think this is a fiction */ /*
* The units on the numbers in the next two are... bizarre. Examples will
* make it clearer; this one parallels an example in the eDP spec.
*
* intel_dp_max_data_rate for one lane of 2.7GHz evaluates as:
*
* 270000 * 1 * 8 / 10 == 216000
*
* The actual data capacity of that configuration is 2.16Gbit/s, so the
* units are decakilobits. ->clock in a drm_display_mode is in kilohertz -
* or equivalently, kilopixels per second - so for 1680x1050R it'd be
* 119000. At 18bpp that's 2142000 kilobits per second.
*
* Thus the strange-looking division by 10 in intel_dp_link_required, to
* get the result in decakilobits instead of kilobits.
*/
static int static int
intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pixel_clock) intel_dp_link_required(struct intel_dp *intel_dp, int pixel_clock)
{ {
struct drm_crtc *crtc = intel_dp->base.base.crtc; struct drm_crtc *crtc = intel_dp->base.base.crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
...@@ -186,7 +222,7 @@ intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pi ...@@ -186,7 +222,7 @@ intel_dp_link_required(struct drm_device *dev, struct intel_dp *intel_dp, int pi
if (intel_crtc) if (intel_crtc)
bpp = intel_crtc->bpp; bpp = intel_crtc->bpp;
return (pixel_clock * bpp + 7) / 8; return (pixel_clock * bpp + 9) / 10;
} }
static int static int
...@@ -200,24 +236,19 @@ intel_dp_mode_valid(struct drm_connector *connector, ...@@ -200,24 +236,19 @@ intel_dp_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode) struct drm_display_mode *mode)
{ {
struct intel_dp *intel_dp = intel_attached_dp(connector); struct intel_dp *intel_dp = intel_attached_dp(connector);
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp));
int max_lanes = intel_dp_max_lane_count(intel_dp); int max_lanes = intel_dp_max_lane_count(intel_dp);
if (is_edp(intel_dp) && dev_priv->panel_fixed_mode) { if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
if (mode->hdisplay > dev_priv->panel_fixed_mode->hdisplay) if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay)
return MODE_PANEL; return MODE_PANEL;
if (mode->vdisplay > dev_priv->panel_fixed_mode->vdisplay) if (mode->vdisplay > intel_dp->panel_fixed_mode->vdisplay)
return MODE_PANEL; return MODE_PANEL;
} }
/* only refuse the mode on non eDP since we have seen some weird eDP panels if (intel_dp_link_required(intel_dp, mode->clock)
which are outside spec tolerances but somehow work by magic */ > intel_dp_max_data_rate(max_link_clock, max_lanes))
if (!is_edp(intel_dp) &&
(intel_dp_link_required(connector->dev, intel_dp, mode->clock)
> intel_dp_max_data_rate(max_link_clock, max_lanes)))
return MODE_CLOCK_HIGH; return MODE_CLOCK_HIGH;
if (mode->clock < 10000) if (mode->clock < 10000)
...@@ -279,6 +310,38 @@ intel_hrawclk(struct drm_device *dev) ...@@ -279,6 +310,38 @@ intel_hrawclk(struct drm_device *dev)
} }
} }
static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
return (I915_READ(PCH_PP_STATUS) & PP_ON) != 0;
}
static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
return (I915_READ(PCH_PP_CONTROL) & EDP_FORCE_VDD) != 0;
}
static void
intel_dp_check_edp(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
if (!is_edp(intel_dp))
return;
if (!ironlake_edp_have_panel_power(intel_dp) && !ironlake_edp_have_panel_vdd(intel_dp)) {
WARN(1, "eDP powered off while attempting aux channel communication.\n");
DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n",
I915_READ(PCH_PP_STATUS),
I915_READ(PCH_PP_CONTROL));
}
}
static int static int
intel_dp_aux_ch(struct intel_dp *intel_dp, intel_dp_aux_ch(struct intel_dp *intel_dp,
uint8_t *send, int send_bytes, uint8_t *send, int send_bytes,
...@@ -295,6 +358,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, ...@@ -295,6 +358,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
uint32_t aux_clock_divider; uint32_t aux_clock_divider;
int try, precharge; int try, precharge;
intel_dp_check_edp(intel_dp);
/* The clock divider is based off the hrawclk, /* The clock divider is based off the hrawclk,
* and would like to run at 2MHz. So, take the * and would like to run at 2MHz. So, take the
* hrawclk value and divide by 2 and use that * hrawclk value and divide by 2 and use that
...@@ -302,7 +366,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, ...@@ -302,7 +366,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
* Note that PCH attached eDP panels should use a 125MHz input * Note that PCH attached eDP panels should use a 125MHz input
* clock divider. * clock divider.
*/ */
if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) { if (is_cpu_edp(intel_dp)) {
if (IS_GEN6(dev)) if (IS_GEN6(dev))
aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */ aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */
else else
...@@ -408,6 +472,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp, ...@@ -408,6 +472,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp,
int msg_bytes; int msg_bytes;
uint8_t ack; uint8_t ack;
intel_dp_check_edp(intel_dp);
if (send_bytes > 16) if (send_bytes > 16)
return -1; return -1;
msg[0] = AUX_NATIVE_WRITE << 4; msg[0] = AUX_NATIVE_WRITE << 4;
...@@ -450,6 +515,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, ...@@ -450,6 +515,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp,
uint8_t ack; uint8_t ack;
int ret; int ret;
intel_dp_check_edp(intel_dp);
msg[0] = AUX_NATIVE_READ << 4; msg[0] = AUX_NATIVE_READ << 4;
msg[1] = address >> 8; msg[1] = address >> 8;
msg[2] = address & 0xff; msg[2] = address & 0xff;
...@@ -493,6 +559,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, ...@@ -493,6 +559,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
int reply_bytes; int reply_bytes;
int ret; int ret;
intel_dp_check_edp(intel_dp);
/* Set up the command byte */ /* Set up the command byte */
if (mode & MODE_I2C_READ) if (mode & MODE_I2C_READ)
msg[0] = AUX_I2C_READ << 4; msg[0] = AUX_I2C_READ << 4;
...@@ -573,10 +640,15 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, ...@@ -573,10 +640,15 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
return -EREMOTEIO; return -EREMOTEIO;
} }
static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
static int static int
intel_dp_i2c_init(struct intel_dp *intel_dp, intel_dp_i2c_init(struct intel_dp *intel_dp,
struct intel_connector *intel_connector, const char *name) struct intel_connector *intel_connector, const char *name)
{ {
int ret;
DRM_DEBUG_KMS("i2c_init %s\n", name); DRM_DEBUG_KMS("i2c_init %s\n", name);
intel_dp->algo.running = false; intel_dp->algo.running = false;
intel_dp->algo.address = 0; intel_dp->algo.address = 0;
...@@ -590,7 +662,10 @@ intel_dp_i2c_init(struct intel_dp *intel_dp, ...@@ -590,7 +662,10 @@ intel_dp_i2c_init(struct intel_dp *intel_dp,
intel_dp->adapter.algo_data = &intel_dp->algo; intel_dp->adapter.algo_data = &intel_dp->algo;
intel_dp->adapter.dev.parent = &intel_connector->base.kdev; intel_dp->adapter.dev.parent = &intel_connector->base.kdev;
return i2c_dp_aux_add_bus(&intel_dp->adapter); ironlake_edp_panel_vdd_on(intel_dp);
ret = i2c_dp_aux_add_bus(&intel_dp->adapter);
ironlake_edp_panel_vdd_off(intel_dp, false);
return ret;
} }
static bool static bool
...@@ -598,29 +673,28 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -598,29 +673,28 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
int lane_count, clock; int lane_count, clock;
int max_lane_count = intel_dp_max_lane_count(intel_dp); int max_lane_count = intel_dp_max_lane_count(intel_dp);
int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0; int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
if (is_edp(intel_dp) && dev_priv->panel_fixed_mode) { if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
intel_fixed_panel_mode(dev_priv->panel_fixed_mode, adjusted_mode); intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode);
intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN, intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN,
mode, adjusted_mode); mode, adjusted_mode);
/* /*
* the mode->clock is used to calculate the Data&Link M/N * the mode->clock is used to calculate the Data&Link M/N
* of the pipe. For the eDP the fixed clock should be used. * of the pipe. For the eDP the fixed clock should be used.
*/ */
mode->clock = dev_priv->panel_fixed_mode->clock; mode->clock = intel_dp->panel_fixed_mode->clock;
} }
for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
for (clock = 0; clock <= max_clock; clock++) { for (clock = 0; clock <= max_clock; clock++) {
int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
if (intel_dp_link_required(encoder->dev, intel_dp, mode->clock) if (intel_dp_link_required(intel_dp, mode->clock)
<= link_avail) { <= link_avail) {
intel_dp->link_bw = bws[clock]; intel_dp->link_bw = bws[clock];
intel_dp->lane_count = lane_count; intel_dp->lane_count = lane_count;
...@@ -634,19 +708,6 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -634,19 +708,6 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
} }
} }
if (is_edp(intel_dp)) {
/* okay we failed just pick the highest */
intel_dp->lane_count = max_lane_count;
intel_dp->link_bw = bws[max_clock];
adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw);
DRM_DEBUG_KMS("Force picking display port link bw %02x lane "
"count %d clock %d\n",
intel_dp->link_bw, intel_dp->lane_count,
adjusted_mode->clock);
return true;
}
return false; return false;
} }
...@@ -740,6 +801,9 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, ...@@ -740,6 +801,9 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
} }
} }
static void ironlake_edp_pll_on(struct drm_encoder *encoder);
static void ironlake_edp_pll_off(struct drm_encoder *encoder);
static void static void
intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
...@@ -749,6 +813,14 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -749,6 +813,14 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
struct drm_crtc *crtc = intel_dp->base.base.crtc; struct drm_crtc *crtc = intel_dp->base.base.crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
/* Turn on the eDP PLL if needed */
if (is_edp(intel_dp)) {
if (!is_pch_edp(intel_dp))
ironlake_edp_pll_on(encoder);
else
ironlake_edp_pll_off(encoder);
}
intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
intel_dp->DP |= intel_dp->color_range; intel_dp->DP |= intel_dp->color_range;
...@@ -757,7 +829,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -757,7 +829,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
intel_dp->DP |= DP_SYNC_VS_HIGH; intel_dp->DP |= DP_SYNC_VS_HIGH;
if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
else else
intel_dp->DP |= DP_LINK_TRAIN_OFF; intel_dp->DP |= DP_LINK_TRAIN_OFF;
...@@ -798,7 +870,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -798,7 +870,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
if (intel_crtc->pipe == 1 && !HAS_PCH_CPT(dev)) if (intel_crtc->pipe == 1 && !HAS_PCH_CPT(dev))
intel_dp->DP |= DP_PIPEB_SELECT; intel_dp->DP |= DP_PIPEB_SELECT;
if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) { if (is_cpu_edp(intel_dp)) {
/* don't miss out required setting for eDP */ /* don't miss out required setting for eDP */
intel_dp->DP |= DP_PLL_ENABLE; intel_dp->DP |= DP_PLL_ENABLE;
if (adjusted_mode->clock < 200000) if (adjusted_mode->clock < 200000)
...@@ -808,58 +880,150 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -808,58 +880,150 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
} }
} }
static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
{
unsigned long off_time;
unsigned long delay;
DRM_DEBUG_KMS("Wait for panel power off time\n");
if (ironlake_edp_have_panel_power(intel_dp) ||
ironlake_edp_have_panel_vdd(intel_dp))
{
DRM_DEBUG_KMS("Panel still on, no delay needed\n");
return;
}
off_time = intel_dp->panel_off_jiffies + msecs_to_jiffies(intel_dp->panel_power_down_delay);
if (time_after(jiffies, off_time)) {
DRM_DEBUG_KMS("Time already passed");
return;
}
delay = jiffies_to_msecs(off_time - jiffies);
if (delay > intel_dp->panel_power_down_delay)
delay = intel_dp->panel_power_down_delay;
DRM_DEBUG_KMS("Waiting an additional %ld ms\n", delay);
msleep(delay);
}
static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
{ {
struct drm_device *dev = intel_dp->base.base.dev; struct drm_device *dev = intel_dp->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp; u32 pp;
/* if (!is_edp(intel_dp))
* If the panel wasn't on, make sure there's not a currently return;
* active PP sequence before enabling AUX VDD. DRM_DEBUG_KMS("Turn eDP VDD on\n");
*/
if (!(I915_READ(PCH_PP_STATUS) & PP_ON))
msleep(dev_priv->panel_t3);
WARN(intel_dp->want_panel_vdd,
"eDP VDD already requested on\n");
intel_dp->want_panel_vdd = true;
if (ironlake_edp_have_panel_vdd(intel_dp)) {
DRM_DEBUG_KMS("eDP VDD already on\n");
return;
}
ironlake_wait_panel_off(intel_dp);
pp = I915_READ(PCH_PP_CONTROL); pp = I915_READ(PCH_PP_CONTROL);
pp &= ~PANEL_UNLOCK_MASK;
pp |= PANEL_UNLOCK_REGS;
pp |= EDP_FORCE_VDD; pp |= EDP_FORCE_VDD;
I915_WRITE(PCH_PP_CONTROL, pp); I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL); POSTING_READ(PCH_PP_CONTROL);
DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n",
I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL));
/*
* If the panel wasn't on, delay before accessing aux channel
*/
if (!ironlake_edp_have_panel_power(intel_dp)) {
DRM_DEBUG_KMS("eDP was not running\n");
msleep(intel_dp->panel_power_up_delay);
}
} }
static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp) static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
{ {
struct drm_device *dev = intel_dp->base.base.dev; struct drm_device *dev = intel_dp->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp; u32 pp;
pp = I915_READ(PCH_PP_CONTROL); if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) {
pp &= ~EDP_FORCE_VDD; pp = I915_READ(PCH_PP_CONTROL);
I915_WRITE(PCH_PP_CONTROL, pp); pp &= ~PANEL_UNLOCK_MASK;
POSTING_READ(PCH_PP_CONTROL); pp |= PANEL_UNLOCK_REGS;
pp &= ~EDP_FORCE_VDD;
I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL);
/* Make sure sequencer is idle before allowing subsequent activity */
DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n",
I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL));
intel_dp->panel_off_jiffies = jiffies;
}
}
/* Make sure sequencer is idle before allowing subsequent activity */ static void ironlake_panel_vdd_work(struct work_struct *__work)
msleep(dev_priv->panel_t12); {
struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
struct intel_dp, panel_vdd_work);
struct drm_device *dev = intel_dp->base.base.dev;
mutex_lock(&dev->struct_mutex);
ironlake_panel_vdd_off_sync(intel_dp);
mutex_unlock(&dev->struct_mutex);
}
static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
{
if (!is_edp(intel_dp))
return;
DRM_DEBUG_KMS("Turn eDP VDD off %d\n", intel_dp->want_panel_vdd);
WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on");
intel_dp->want_panel_vdd = false;
if (sync) {
ironlake_panel_vdd_off_sync(intel_dp);
} else {
/*
* Queue the timer to fire a long
* time from now (relative to the power down delay)
* to keep the panel power up across a sequence of operations
*/
schedule_delayed_work(&intel_dp->panel_vdd_work,
msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
}
} }
/* Returns true if the panel was already on when called */ /* Returns true if the panel was already on when called */
static bool ironlake_edp_panel_on(struct intel_dp *intel_dp) static void ironlake_edp_panel_on(struct intel_dp *intel_dp)
{ {
struct drm_device *dev = intel_dp->base.base.dev; struct drm_device *dev = intel_dp->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE; u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE;
if (I915_READ(PCH_PP_STATUS) & PP_ON) if (!is_edp(intel_dp))
return true; return;
if (ironlake_edp_have_panel_power(intel_dp))
return;
ironlake_wait_panel_off(intel_dp);
pp = I915_READ(PCH_PP_CONTROL); pp = I915_READ(PCH_PP_CONTROL);
pp &= ~PANEL_UNLOCK_MASK;
pp |= PANEL_UNLOCK_REGS;
if (IS_GEN5(dev)) {
/* ILK workaround: disable reset around power sequence */
pp &= ~PANEL_POWER_RESET;
I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL);
}
/* ILK workaround: disable reset around power sequence */ pp |= POWER_TARGET_ON;
pp &= ~PANEL_POWER_RESET;
I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL);
pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON;
I915_WRITE(PCH_PP_CONTROL, pp); I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL); POSTING_READ(PCH_PP_CONTROL);
...@@ -868,44 +1032,64 @@ static bool ironlake_edp_panel_on(struct intel_dp *intel_dp) ...@@ -868,44 +1032,64 @@ static bool ironlake_edp_panel_on(struct intel_dp *intel_dp)
DRM_ERROR("panel on wait timed out: 0x%08x\n", DRM_ERROR("panel on wait timed out: 0x%08x\n",
I915_READ(PCH_PP_STATUS)); I915_READ(PCH_PP_STATUS));
pp |= PANEL_POWER_RESET; /* restore panel reset bit */ if (IS_GEN5(dev)) {
I915_WRITE(PCH_PP_CONTROL, pp); pp |= PANEL_POWER_RESET; /* restore panel reset bit */
POSTING_READ(PCH_PP_CONTROL); I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL);
return false; }
} }
static void ironlake_edp_panel_off(struct drm_device *dev) static void ironlake_edp_panel_off(struct drm_encoder *encoder)
{ {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp, idle_off_mask = PP_ON | PP_SEQUENCE_MASK | u32 pp, idle_off_mask = PP_ON | PP_SEQUENCE_MASK |
PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK; PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK;
if (!is_edp(intel_dp))
return;
pp = I915_READ(PCH_PP_CONTROL); pp = I915_READ(PCH_PP_CONTROL);
pp &= ~PANEL_UNLOCK_MASK;
pp |= PANEL_UNLOCK_REGS;
if (IS_GEN5(dev)) {
/* ILK workaround: disable reset around power sequence */
pp &= ~PANEL_POWER_RESET;
I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL);
}
/* ILK workaround: disable reset around power sequence */ intel_dp->panel_off_jiffies = jiffies;
pp &= ~PANEL_POWER_RESET;
I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL);
pp &= ~POWER_TARGET_ON; if (IS_GEN5(dev)) {
I915_WRITE(PCH_PP_CONTROL, pp); pp &= ~POWER_TARGET_ON;
POSTING_READ(PCH_PP_CONTROL); I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL);
pp &= ~POWER_TARGET_ON;
I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL);
msleep(intel_dp->panel_power_cycle_delay);
if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000)) if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000))
DRM_ERROR("panel off wait timed out: 0x%08x\n", DRM_ERROR("panel off wait timed out: 0x%08x\n",
I915_READ(PCH_PP_STATUS)); I915_READ(PCH_PP_STATUS));
pp |= PANEL_POWER_RESET; /* restore panel reset bit */ pp |= PANEL_POWER_RESET; /* restore panel reset bit */
I915_WRITE(PCH_PP_CONTROL, pp); I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL); POSTING_READ(PCH_PP_CONTROL);
}
} }
static void ironlake_edp_backlight_on(struct drm_device *dev) static void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
{ {
struct drm_device *dev = intel_dp->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp; u32 pp;
if (!is_edp(intel_dp))
return;
DRM_DEBUG_KMS("\n"); DRM_DEBUG_KMS("\n");
/* /*
* If we enable the backlight right away following a panel power * If we enable the backlight right away following a panel power
...@@ -913,21 +1097,32 @@ static void ironlake_edp_backlight_on(struct drm_device *dev) ...@@ -913,21 +1097,32 @@ static void ironlake_edp_backlight_on(struct drm_device *dev)
* link. So delay a bit to make sure the image is solid before * link. So delay a bit to make sure the image is solid before
* allowing it to appear. * allowing it to appear.
*/ */
msleep(300); msleep(intel_dp->backlight_on_delay);
pp = I915_READ(PCH_PP_CONTROL); pp = I915_READ(PCH_PP_CONTROL);
pp &= ~PANEL_UNLOCK_MASK;
pp |= PANEL_UNLOCK_REGS;
pp |= EDP_BLC_ENABLE; pp |= EDP_BLC_ENABLE;
I915_WRITE(PCH_PP_CONTROL, pp); I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL);
} }
static void ironlake_edp_backlight_off(struct drm_device *dev) static void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
{ {
struct drm_device *dev = intel_dp->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp; u32 pp;
if (!is_edp(intel_dp))
return;
DRM_DEBUG_KMS("\n"); DRM_DEBUG_KMS("\n");
pp = I915_READ(PCH_PP_CONTROL); pp = I915_READ(PCH_PP_CONTROL);
pp &= ~PANEL_UNLOCK_MASK;
pp |= PANEL_UNLOCK_REGS;
pp &= ~EDP_BLC_ENABLE; pp &= ~EDP_BLC_ENABLE;
I915_WRITE(PCH_PP_CONTROL, pp); I915_WRITE(PCH_PP_CONTROL, pp);
POSTING_READ(PCH_PP_CONTROL);
msleep(intel_dp->backlight_off_delay);
} }
static void ironlake_edp_pll_on(struct drm_encoder *encoder) static void ironlake_edp_pll_on(struct drm_encoder *encoder)
...@@ -990,43 +1185,39 @@ static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode) ...@@ -990,43 +1185,39 @@ static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
static void intel_dp_prepare(struct drm_encoder *encoder) static void intel_dp_prepare(struct drm_encoder *encoder)
{ {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct drm_device *dev = encoder->dev;
/* Wake up the sink first */ /* Wake up the sink first */
ironlake_edp_panel_vdd_on(intel_dp);
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
ironlake_edp_panel_vdd_off(intel_dp, false);
if (is_edp(intel_dp)) { /* Make sure the panel is off before trying to
ironlake_edp_backlight_off(dev); * change the mode
ironlake_edp_panel_off(dev); */
if (!is_pch_edp(intel_dp)) ironlake_edp_backlight_off(intel_dp);
ironlake_edp_pll_on(encoder);
else
ironlake_edp_pll_off(encoder);
}
intel_dp_link_down(intel_dp); intel_dp_link_down(intel_dp);
ironlake_edp_panel_off(encoder);
} }
static void intel_dp_commit(struct drm_encoder *encoder) static void intel_dp_commit(struct drm_encoder *encoder)
{ {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
if (is_edp(intel_dp)) ironlake_edp_panel_vdd_on(intel_dp);
ironlake_edp_panel_vdd_on(intel_dp); intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
intel_dp_start_link_train(intel_dp); intel_dp_start_link_train(intel_dp);
ironlake_edp_panel_on(intel_dp);
if (is_edp(intel_dp)) { ironlake_edp_panel_vdd_off(intel_dp, true);
ironlake_edp_panel_on(intel_dp);
ironlake_edp_panel_vdd_off(intel_dp);
}
intel_dp_complete_link_train(intel_dp); intel_dp_complete_link_train(intel_dp);
ironlake_edp_backlight_on(intel_dp);
if (is_edp(intel_dp))
ironlake_edp_backlight_on(dev);
intel_dp->dpms_mode = DRM_MODE_DPMS_ON; intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
if (HAS_PCH_CPT(dev))
intel_cpt_verify_modeset(dev, intel_crtc->pipe);
} }
static void static void
...@@ -1038,28 +1229,27 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) ...@@ -1038,28 +1229,27 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
uint32_t dp_reg = I915_READ(intel_dp->output_reg); uint32_t dp_reg = I915_READ(intel_dp->output_reg);
if (mode != DRM_MODE_DPMS_ON) { if (mode != DRM_MODE_DPMS_ON) {
ironlake_edp_panel_vdd_on(intel_dp);
if (is_edp(intel_dp)) if (is_edp(intel_dp))
ironlake_edp_backlight_off(dev); ironlake_edp_backlight_off(intel_dp);
intel_dp_sink_dpms(intel_dp, mode); intel_dp_sink_dpms(intel_dp, mode);
intel_dp_link_down(intel_dp); intel_dp_link_down(intel_dp);
if (is_edp(intel_dp)) ironlake_edp_panel_off(encoder);
ironlake_edp_panel_off(dev);
if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) if (is_edp(intel_dp) && !is_pch_edp(intel_dp))
ironlake_edp_pll_off(encoder); ironlake_edp_pll_off(encoder);
ironlake_edp_panel_vdd_off(intel_dp, false);
} else { } else {
if (is_edp(intel_dp)) ironlake_edp_panel_vdd_on(intel_dp);
ironlake_edp_panel_vdd_on(intel_dp);
intel_dp_sink_dpms(intel_dp, mode); intel_dp_sink_dpms(intel_dp, mode);
if (!(dp_reg & DP_PORT_EN)) { if (!(dp_reg & DP_PORT_EN)) {
intel_dp_start_link_train(intel_dp); intel_dp_start_link_train(intel_dp);
if (is_edp(intel_dp)) { ironlake_edp_panel_on(intel_dp);
ironlake_edp_panel_on(intel_dp); ironlake_edp_panel_vdd_off(intel_dp, true);
ironlake_edp_panel_vdd_off(intel_dp);
}
intel_dp_complete_link_train(intel_dp); intel_dp_complete_link_train(intel_dp);
} ironlake_edp_backlight_on(intel_dp);
if (is_edp(intel_dp)) } else
ironlake_edp_backlight_on(dev); ironlake_edp_panel_vdd_off(intel_dp, false);
ironlake_edp_backlight_on(intel_dp);
} }
intel_dp->dpms_mode = mode; intel_dp->dpms_mode = mode;
} }
...@@ -1368,7 +1558,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) ...@@ -1368,7 +1558,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
DP_LINK_CONFIGURATION_SIZE); DP_LINK_CONFIGURATION_SIZE);
DP |= DP_PORT_EN; DP |= DP_PORT_EN;
if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
DP &= ~DP_LINK_TRAIN_MASK_CPT; DP &= ~DP_LINK_TRAIN_MASK_CPT;
else else
DP &= ~DP_LINK_TRAIN_MASK; DP &= ~DP_LINK_TRAIN_MASK;
...@@ -1387,7 +1577,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) ...@@ -1387,7 +1577,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
} }
if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
reg = DP | DP_LINK_TRAIN_PAT_1_CPT; reg = DP | DP_LINK_TRAIN_PAT_1_CPT;
else else
reg = DP | DP_LINK_TRAIN_PAT_1; reg = DP | DP_LINK_TRAIN_PAT_1;
...@@ -1462,7 +1652,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) ...@@ -1462,7 +1652,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
} }
if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
reg = DP | DP_LINK_TRAIN_PAT_2_CPT; reg = DP | DP_LINK_TRAIN_PAT_2_CPT;
else else
reg = DP | DP_LINK_TRAIN_PAT_2; reg = DP | DP_LINK_TRAIN_PAT_2;
...@@ -1503,7 +1693,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) ...@@ -1503,7 +1693,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
++tries; ++tries;
} }
if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
reg = DP | DP_LINK_TRAIN_OFF_CPT; reg = DP | DP_LINK_TRAIN_OFF_CPT;
else else
reg = DP | DP_LINK_TRAIN_OFF; reg = DP | DP_LINK_TRAIN_OFF;
...@@ -1533,7 +1723,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) ...@@ -1533,7 +1723,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
udelay(100); udelay(100);
} }
if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) { if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) {
DP &= ~DP_LINK_TRAIN_MASK_CPT; DP &= ~DP_LINK_TRAIN_MASK_CPT;
I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT); I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
} else { } else {
...@@ -1582,6 +1772,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) ...@@ -1582,6 +1772,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
POSTING_READ(intel_dp->output_reg); POSTING_READ(intel_dp->output_reg);
msleep(intel_dp->panel_power_down_delay);
} }
static bool static bool
...@@ -1596,6 +1787,27 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) ...@@ -1596,6 +1787,27 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
return false; return false;
} }
static bool
intel_dp_get_sink_irq(struct intel_dp *intel_dp, u8 *sink_irq_vector)
{
int ret;
ret = intel_dp_aux_native_read_retry(intel_dp,
DP_DEVICE_SERVICE_IRQ_VECTOR,
sink_irq_vector, 1);
if (!ret)
return false;
return true;
}
static void
intel_dp_handle_test_request(struct intel_dp *intel_dp)
{
/* NAK by default */
intel_dp_aux_native_write_1(intel_dp, DP_TEST_RESPONSE, DP_TEST_ACK);
}
/* /*
* According to DP spec * According to DP spec
* 5.1.2: * 5.1.2:
...@@ -1608,6 +1820,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) ...@@ -1608,6 +1820,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
static void static void
intel_dp_check_link_status(struct intel_dp *intel_dp) intel_dp_check_link_status(struct intel_dp *intel_dp)
{ {
u8 sink_irq_vector;
if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON) if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON)
return; return;
...@@ -1626,6 +1840,20 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) ...@@ -1626,6 +1840,20 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
return; return;
} }
/* Try to read the source of the interrupt */
if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
intel_dp_get_sink_irq(intel_dp, &sink_irq_vector)) {
/* Clear interrupt source */
intel_dp_aux_native_write_1(intel_dp,
DP_DEVICE_SERVICE_IRQ_VECTOR,
sink_irq_vector);
if (sink_irq_vector & DP_AUTOMATED_TEST_REQUEST)
intel_dp_handle_test_request(intel_dp);
if (sink_irq_vector & (DP_CP_IRQ | DP_SINK_SPECIFIC_IRQ))
DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
}
if (!intel_channel_eq_ok(intel_dp)) { if (!intel_channel_eq_ok(intel_dp)) {
DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
drm_get_encoder_name(&intel_dp->base.base)); drm_get_encoder_name(&intel_dp->base.base));
...@@ -1687,6 +1915,31 @@ g4x_dp_detect(struct intel_dp *intel_dp) ...@@ -1687,6 +1915,31 @@ g4x_dp_detect(struct intel_dp *intel_dp)
return intel_dp_detect_dpcd(intel_dp); return intel_dp_detect_dpcd(intel_dp);
} }
static struct edid *
intel_dp_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct edid *edid;
ironlake_edp_panel_vdd_on(intel_dp);
edid = drm_get_edid(connector, adapter);
ironlake_edp_panel_vdd_off(intel_dp, false);
return edid;
}
static int
intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter *adapter)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
int ret;
ironlake_edp_panel_vdd_on(intel_dp);
ret = intel_ddc_get_modes(connector, adapter);
ironlake_edp_panel_vdd_off(intel_dp, false);
return ret;
}
/** /**
* Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection. * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
* *
...@@ -1719,7 +1972,7 @@ intel_dp_detect(struct drm_connector *connector, bool force) ...@@ -1719,7 +1972,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
if (intel_dp->force_audio) { if (intel_dp->force_audio) {
intel_dp->has_audio = intel_dp->force_audio > 0; intel_dp->has_audio = intel_dp->force_audio > 0;
} else { } else {
edid = drm_get_edid(connector, &intel_dp->adapter); edid = intel_dp_get_edid(connector, &intel_dp->adapter);
if (edid) { if (edid) {
intel_dp->has_audio = drm_detect_monitor_audio(edid); intel_dp->has_audio = drm_detect_monitor_audio(edid);
connector->display_info.raw_edid = NULL; connector->display_info.raw_edid = NULL;
...@@ -1740,28 +1993,36 @@ static int intel_dp_get_modes(struct drm_connector *connector) ...@@ -1740,28 +1993,36 @@ static int intel_dp_get_modes(struct drm_connector *connector)
/* We should parse the EDID data and find out if it has an audio sink /* We should parse the EDID data and find out if it has an audio sink
*/ */
ret = intel_ddc_get_modes(connector, &intel_dp->adapter); ret = intel_dp_get_edid_modes(connector, &intel_dp->adapter);
if (ret) { if (ret) {
if (is_edp(intel_dp) && !dev_priv->panel_fixed_mode) { if (is_edp(intel_dp) && !intel_dp->panel_fixed_mode) {
struct drm_display_mode *newmode; struct drm_display_mode *newmode;
list_for_each_entry(newmode, &connector->probed_modes, list_for_each_entry(newmode, &connector->probed_modes,
head) { head) {
if (newmode->type & DRM_MODE_TYPE_PREFERRED) { if ((newmode->type & DRM_MODE_TYPE_PREFERRED)) {
dev_priv->panel_fixed_mode = intel_dp->panel_fixed_mode =
drm_mode_duplicate(dev, newmode); drm_mode_duplicate(dev, newmode);
break; break;
} }
} }
} }
return ret; return ret;
} }
/* if eDP has no EDID, try to use fixed panel mode from VBT */ /* if eDP has no EDID, try to use fixed panel mode from VBT */
if (is_edp(intel_dp)) { if (is_edp(intel_dp)) {
if (dev_priv->panel_fixed_mode != NULL) { /* initialize panel mode from VBT if available for eDP */
if (intel_dp->panel_fixed_mode == NULL && dev_priv->lfp_lvds_vbt_mode != NULL) {
intel_dp->panel_fixed_mode =
drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
if (intel_dp->panel_fixed_mode) {
intel_dp->panel_fixed_mode->type |=
DRM_MODE_TYPE_PREFERRED;
}
}
if (intel_dp->panel_fixed_mode) {
struct drm_display_mode *mode; struct drm_display_mode *mode;
mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode); mode = drm_mode_duplicate(dev, intel_dp->panel_fixed_mode);
drm_mode_probed_add(connector, mode); drm_mode_probed_add(connector, mode);
return 1; return 1;
} }
...@@ -1776,7 +2037,7 @@ intel_dp_detect_audio(struct drm_connector *connector) ...@@ -1776,7 +2037,7 @@ intel_dp_detect_audio(struct drm_connector *connector)
struct edid *edid; struct edid *edid;
bool has_audio = false; bool has_audio = false;
edid = drm_get_edid(connector, &intel_dp->adapter); edid = intel_dp_get_edid(connector, &intel_dp->adapter);
if (edid) { if (edid) {
has_audio = drm_detect_monitor_audio(edid); has_audio = drm_detect_monitor_audio(edid);
...@@ -1861,6 +2122,10 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder) ...@@ -1861,6 +2122,10 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
i2c_del_adapter(&intel_dp->adapter); i2c_del_adapter(&intel_dp->adapter);
drm_encoder_cleanup(encoder); drm_encoder_cleanup(encoder);
if (is_edp(intel_dp)) {
cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
ironlake_panel_vdd_off_sync(intel_dp);
}
kfree(intel_dp); kfree(intel_dp);
} }
...@@ -1997,10 +2262,13 @@ intel_dp_init(struct drm_device *dev, int output_reg) ...@@ -1997,10 +2262,13 @@ intel_dp_init(struct drm_device *dev, int output_reg)
else if (output_reg == DP_D || output_reg == PCH_DP_D) else if (output_reg == DP_D || output_reg == PCH_DP_D)
intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
if (is_edp(intel_dp)) if (is_edp(intel_dp)) {
intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
ironlake_panel_vdd_work);
}
intel_encoder->crtc_mask = (1 << 0) | (1 << 1); intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
connector->interlace_allowed = true; connector->interlace_allowed = true;
connector->doublescan_allowed = 0; connector->doublescan_allowed = 0;
...@@ -2036,25 +2304,60 @@ intel_dp_init(struct drm_device *dev, int output_reg) ...@@ -2036,25 +2304,60 @@ intel_dp_init(struct drm_device *dev, int output_reg)
break; break;
} }
intel_dp_i2c_init(intel_dp, intel_connector, name);
/* Cache some DPCD data in the eDP case */ /* Cache some DPCD data in the eDP case */
if (is_edp(intel_dp)) { if (is_edp(intel_dp)) {
bool ret; bool ret;
u32 pp_on, pp_div; struct edp_power_seq cur, vbt;
u32 pp_on, pp_off, pp_div;
pp_on = I915_READ(PCH_PP_ON_DELAYS); pp_on = I915_READ(PCH_PP_ON_DELAYS);
pp_off = I915_READ(PCH_PP_OFF_DELAYS);
pp_div = I915_READ(PCH_PP_DIVISOR); pp_div = I915_READ(PCH_PP_DIVISOR);
/* Get T3 & T12 values (note: VESA not bspec terminology) */ /* Pull timing values out of registers */
dev_priv->panel_t3 = (pp_on & 0x1fff0000) >> 16; cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
dev_priv->panel_t3 /= 10; /* t3 in 100us units */ PANEL_POWER_UP_DELAY_SHIFT;
dev_priv->panel_t12 = pp_div & 0xf;
dev_priv->panel_t12 *= 100; /* t12 in 100ms units */ cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >>
PANEL_LIGHT_ON_DELAY_SHIFT;
cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >>
PANEL_LIGHT_OFF_DELAY_SHIFT;
cur.t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >>
PANEL_POWER_DOWN_DELAY_SHIFT;
cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >>
PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000;
DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12);
vbt = dev_priv->edp.pps;
DRM_DEBUG_KMS("vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
vbt.t1_t3, vbt.t8, vbt.t9, vbt.t10, vbt.t11_t12);
#define get_delay(field) ((max(cur.field, vbt.field) + 9) / 10)
intel_dp->panel_power_up_delay = get_delay(t1_t3);
intel_dp->backlight_on_delay = get_delay(t8);
intel_dp->backlight_off_delay = get_delay(t9);
intel_dp->panel_power_down_delay = get_delay(t10);
intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
intel_dp->panel_power_cycle_delay);
DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
intel_dp->panel_off_jiffies = jiffies - intel_dp->panel_power_down_delay;
ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_panel_vdd_on(intel_dp);
ret = intel_dp_get_dpcd(intel_dp); ret = intel_dp_get_dpcd(intel_dp);
ironlake_edp_panel_vdd_off(intel_dp); ironlake_edp_panel_vdd_off(intel_dp, false);
if (ret) { if (ret) {
if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
dev_priv->no_aux_handshake = dev_priv->no_aux_handshake =
...@@ -2069,18 +2372,11 @@ intel_dp_init(struct drm_device *dev, int output_reg) ...@@ -2069,18 +2372,11 @@ intel_dp_init(struct drm_device *dev, int output_reg)
} }
} }
intel_dp_i2c_init(intel_dp, intel_connector, name);
intel_encoder->hot_plug = intel_dp_hot_plug; intel_encoder->hot_plug = intel_dp_hot_plug;
if (is_edp(intel_dp)) { if (is_edp(intel_dp)) {
/* initialize panel mode from VBT if available for eDP */
if (dev_priv->lfp_lvds_vbt_mode) {
dev_priv->panel_fixed_mode =
drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
if (dev_priv->panel_fixed_mode) {
dev_priv->panel_fixed_mode->type |=
DRM_MODE_TYPE_PREFERRED;
}
}
dev_priv->int_edp_connector = connector; dev_priv->int_edp_connector = connector;
intel_panel_setup_backlight(dev); intel_panel_setup_backlight(dev);
} }
......
...@@ -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