diff options
author | Dave Airlie <airlied@redhat.com> | 2011-10-24 05:48:39 +0100 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-10-24 05:48:39 +0100 |
commit | 9b553f72869584cc14d5724fbbc09f88de0f08de (patch) | |
tree | 923d790483d32dd209bf1bf2cdfc7c7abbb68aa7 /drivers/gpu | |
parent | c5c42360bc1cb14c7da3186683e9525b33b72656 (diff) | |
parent | 82d165557ef094d4b4dfc05871aee618ec7102b0 (diff) |
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
...
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 47 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 31 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_debug.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 30 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_tiling.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 36 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 65 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_bios.h | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_crt.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 409 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 590 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 30 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_i2c.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_panel.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 150 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 21 |
21 files changed, 1130 insertions, 421 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index d76da389f52..2eac955dee1 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -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->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; else dev_priv->num_pipe = 1; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index c96b019a3b7..4c8d681c215 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -79,11 +79,11 @@ MODULE_PARM_DESC(lvds_downclock, "Use panel (LVDS/eDP) downclocking for power savings " "(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_PARM_DESC(lvds_use_ssc, "Use Spread Spectrum Clock with panels [LVDS/eDP] " - "(default: true)"); + "(default: auto from VBT)"); int i915_vbt_sdvo_panel_type __read_mostly = -1; 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) error = i915_gem_init_ringbuffer(dev); mutex_unlock(&dev->struct_mutex); + if (HAS_PCH_SPLIT(dev)) + ironlake_init_pch_refclk(dev); + drm_mode_config_reset(dev); drm_irq_install(dev); @@ -895,3 +898,43 @@ module_exit(i915_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); 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 diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 15c0ca58ad8..06a37f4fd74 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -139,7 +139,6 @@ struct sdvo_device_mapping { u8 slave_addr; u8 dvo_wiring; u8 i2c_pin; - u8 i2c_speed; u8 ddc_pin; }; @@ -349,7 +348,6 @@ typedef struct drm_i915_private { /* LVDS info */ int backlight_level; /* restore backlight to this value */ bool backlight_enabled; - struct drm_display_mode *panel_fixed_mode; struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ @@ -359,6 +357,7 @@ typedef struct drm_i915_private { unsigned int lvds_vbt:1; unsigned int int_crt_support:1; unsigned int lvds_use_ssc:1; + unsigned int display_clock_mode:1; int lvds_ssc_freq; struct { int rate; @@ -674,10 +673,9 @@ typedef struct drm_i915_private { unsigned int lvds_border_bits; /* Panel fitter placement and size for Ironlake+ */ u32 pch_pf_pos, pch_pf_size; - int panel_t3, panel_t12; - struct drm_crtc *plane_to_crtc_mapping[2]; - struct drm_crtc *pipe_to_crtc_mapping[2]; + struct drm_crtc *plane_to_crtc_mapping[3]; + struct drm_crtc *pipe_to_crtc_mapping[3]; wait_queue_head_t pending_flip_queue; bool flip_pending_is_done; @@ -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 void intel_disable_fbc(struct drm_device *dev); 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 gen6_set_rps(struct drm_device *dev, u8 val); 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); ((reg) != FORCEWAKE)) #define __i915_read(x, y) \ -static inline 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; \ -} + u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg); __i915_read(8, b) __i915_read(16, w) @@ -1376,13 +1364,8 @@ __i915_read(64, q) #undef __i915_read #define __i915_write(x, y) \ -static inline 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); \ -} + void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val); + __i915_write(8, b) __i915_write(16, w) __i915_write(32, l) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f0f885f44b8..6651c36b6e8 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -195,6 +195,8 @@ i915_gem_create(struct drm_file *file, u32 handle; size = roundup(size, PAGE_SIZE); + if (size == 0) + return -EINVAL; /* Allocate the new object */ obj = i915_gem_alloc_object(dev, size); @@ -800,11 +802,11 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev, if (IS_ERR(page)) return PTR_ERR(page); - vaddr = kmap_atomic(page, KM_USER0); + vaddr = kmap_atomic(page); ret = __copy_from_user_inatomic(vaddr + page_offset, user_data, page_length); - kunmap_atomic(vaddr, KM_USER0); + kunmap_atomic(vaddr); set_page_dirty(page); mark_page_accessed(page); @@ -1476,7 +1478,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj, 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); return 0; @@ -1498,7 +1500,7 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) 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); if (obj->madv == I915_MADV_DONTNEED) @@ -2191,14 +2193,8 @@ int i915_gpu_idle(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; - bool lists_empty; 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. */ for (i = 0; i < I915_NUM_RINGS; i++) { ret = i915_ring_idle(&dev_priv->ring[i]); diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index ac908757e17..cc93cac242d 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c @@ -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++) { int i; - backing_map = kmap_atomic(obj->pages[page], KM_USER0); + backing_map = kmap_atomic(obj->pages[page]); if (backing_map == NULL) { 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) } } } - kunmap_atomic(backing_map, KM_USER0); + kunmap_atomic(backing_map); backing_map = NULL; } out: if (backing_map != NULL) - kunmap_atomic(backing_map, KM_USER0); + kunmap_atomic(backing_map); iounmap(gtt_mapping); /* give syslog time to catch up */ diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 7a709cd8d54..6042c5e6d27 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -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) { 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, 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, obj->base.size >> PAGE_SHIFT); @@ -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); obj->sg_list = NULL; } + + undo_idling(dev_priv, interruptible); } diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 99c4faa59d8..31d334d9d9d 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -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_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 * same swizzling setup. */ @@ -440,14 +443,9 @@ i915_gem_swizzle_page(struct page *page) void 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 i; - if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17) - return; - if (obj->bit_17 == NULL) return; @@ -464,14 +462,9 @@ i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj) void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj) { - 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 i; - if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17) - return; - if (obj->bit_17 == NULL) { obj->bit_17 = kmalloc(BITS_TO_LONGS(page_count) * sizeof(long), GFP_KERNEL); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 012732b6ec2..9ee2729fe5c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -383,6 +383,7 @@ static void gen6_pm_rps_work(struct work_struct *work) pm_iir = dev_priv->pm_iir; dev_priv->pm_iir = 0; pm_imr = I915_READ(GEN6_PMIMR); + I915_WRITE(GEN6_PMIMR, 0); spin_unlock_irq(&dev_priv->rps_lock); if (!pm_iir) @@ -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 * 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); } @@ -536,8 +536,9 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) unsigned long flags; spin_lock_irqsave(&dev_priv->rps_lock, flags); WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n"); - I915_WRITE(GEN6_PMIMR, 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); queue_work(dev_priv->wq, &dev_priv->rps_work); } @@ -649,8 +650,9 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) unsigned long flags; spin_lock_irqsave(&dev_priv->rps_lock, flags); WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n"); - I915_WRITE(GEN6_PMIMR, 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); queue_work(dev_priv->wq, &dev_priv->rps_work); } @@ -1777,6 +1779,26 @@ static void ironlake_irq_preinstall(struct drm_device *dev) 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) { 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) I915_WRITE(SDEIER, hotplug_mask); POSTING_READ(SDEIER); + ironlake_enable_pch_hotplug(dev); + if (IS_IRONLAKE_M(dev)) { /* Clear & enable PCU event interrupts */ I915_WRITE(DEIIR, DE_PCU_EVENT); @@ -1896,6 +1920,8 @@ static int ivybridge_irq_postinstall(struct drm_device *dev) I915_WRITE(SDEIER, hotplug_mask); POSTING_READ(SDEIER); + ironlake_enable_pch_hotplug(dev); + return 0; } @@ -2020,6 +2046,10 @@ static void ironlake_irq_uninstall(struct drm_device *dev) I915_WRITE(GTIMR, 0xffffffff); I915_WRITE(GTIER, 0x0); 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) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 138eae15bec..5a09416e611 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -242,16 +242,22 @@ #define ASYNC_FLIP (1<<22) #define DISPLAY_PLANE_A (0<<20) #define DISPLAY_PLANE_B (1<<20) -#define GFX_OP_PIPE_CONTROL ((0x3<<29)|(0x3<<27)|(0x2<<24)|2) -#define PIPE_CONTROL_QW_WRITE (1<<14) -#define PIPE_CONTROL_DEPTH_STALL (1<<13) -#define PIPE_CONTROL_WC_FLUSH (1<<12) -#define PIPE_CONTROL_IS_FLUSH (1<<11) /* MBZ on Ironlake */ -#define PIPE_CONTROL_TC_FLUSH (1<<10) /* GM45+ only */ -#define PIPE_CONTROL_ISP_DIS (1<<9) -#define PIPE_CONTROL_NOTIFY (1<<8) +#define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2)) +#define PIPE_CONTROL_CS_STALL (1<<20) +#define PIPE_CONTROL_QW_WRITE (1<<14) +#define PIPE_CONTROL_DEPTH_STALL (1<<13) +#define PIPE_CONTROL_WRITE_FLUSH (1<<12) +#define PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH (1<<12) /* gen6+ */ +#define PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE (1<<11) /* MBZ on Ironlake */ +#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_STALL_EN (1<<1) /* in addr word, Ironlake+ only */ /* @@ -2429,6 +2435,7 @@ #define WM0_PIPE_CURSOR_MASK (0x1f) #define WM0_PIPEB_ILK 0x45104 +#define WM0_PIPEC_IVB 0x45200 #define WM1_LP_ILK 0x45108 #define WM1_LP_SR_EN (1<<31) #define WM1_LP_LATENCY_SHIFT 24 @@ -2567,10 +2574,18 @@ #define _CURBBASE 0x700c4 #define _CURBPOS 0x700c8 +#define _CURBCNTR_IVB 0x71080 +#define _CURBBASE_IVB 0x71084 +#define _CURBPOS_IVB 0x71088 + #define CURCNTR(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR) #define CURBASE(pipe) _PIPE(pipe, _CURABASE, _CURBBASE) #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 */ #define _DSPACNTR 0x70180 #define DISPLAY_PLANE_ENABLE (1<<31) @@ -2916,12 +2931,13 @@ #define SDEIER 0xc400c /* digital port hotplug */ -#define PCH_PORT_HOTPLUG 0xc4030 +#define PCH_PORT_HOTPLUG 0xc4030 /* SHOTPLUG_CTL */ #define PORTD_HOTPLUG_ENABLE (1 << 20) #define PORTD_PULSE_DURATION_2ms (0) #define PORTD_PULSE_DURATION_4_5ms (1 << 18) #define PORTD_PULSE_DURATION_6ms (2 << 18) #define PORTD_PULSE_DURATION_100ms (3 << 18) +#define PORTD_PULSE_DURATION_MASK (3 << 18) #define PORTD_HOTPLUG_NO_DETECT (0) #define PORTD_HOTPLUG_SHORT_DETECT (1 << 16) #define PORTD_HOTPLUG_LONG_DETECT (1 << 17) @@ -2930,6 +2946,7 @@ #define PORTC_PULSE_DURATION_4_5ms (1 << 10) #define PORTC_PULSE_DURATION_6ms (2 << 10) #define PORTC_PULSE_DURATION_100ms (3 << 10) +#define PORTC_PULSE_DURATION_MASK (3 << 10) #define PORTC_HOTPLUG_NO_DETECT (0) #define PORTC_HOTPLUG_SHORT_DETECT (1 << 8) #define PORTC_HOTPLUG_LONG_DETECT (1 << 9) @@ -2938,6 +2955,7 @@ #define PORTB_PULSE_DURATION_4_5ms (1 << 2) #define PORTB_PULSE_DURATION_6ms (2 << 2) #define PORTB_PULSE_DURATION_100ms (3 << 2) +#define PORTB_PULSE_DURATION_MASK (3 << 2) #define PORTB_HOTPLUG_NO_DETECT (0) #define PORTB_HOTPLUG_SHORT_DETECT (1 << 0) #define PORTB_HOTPLUG_LONG_DETECT (1 << 1) @@ -2958,15 +2976,15 @@ #define _PCH_DPLL_A 0xc6014 #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 FP_CB_TUNE (0x3<<22) #define _PCH_FPA1 0xc6044 #define _PCH_FPB0 0xc6048 #define _PCH_FPB1 0xc604c -#define PCH_FP0(pipe) _PIPE(pipe, _PCH_FPA0, _PCH_FPB0) -#define PCH_FP1(pipe) _PIPE(pipe, _PCH_FPA1, _PCH_FPB1) +#define PCH_FP0(pipe) (pipe == 0 ? _PCH_FPA0 : _PCH_FPB0) +#define PCH_FP1(pipe) (pipe == 0 ? _PCH_FPA1 : _PCH_FPB1) #define PCH_DPLL_TEST 0xc606c @@ -3180,6 +3198,7 @@ #define FDI_LINK_TRAIN_NONE_IVB (3<<8) /* both Tx and Rx */ +#define FDI_COMPOSITE_SYNC (1<<11) #define FDI_LINK_TRAIN_AUTO (1<<10) #define FDI_SCRAMBLING_ENABLE (0<<7) #define FDI_SCRAMBLING_DISABLE (1<<7) @@ -3321,15 +3340,35 @@ #define PCH_PP_STATUS 0xc7200 #define PCH_PP_CONTROL 0xc7204 #define PANEL_UNLOCK_REGS (0xabcd << 16) +#define PANEL_UNLOCK_MASK (0xffff << 16) #define EDP_FORCE_VDD (1 << 3) #define EDP_BLC_ENABLE (1 << 2) #define PANEL_POWER_RESET (1 << 1) #define PANEL_POWER_OFF (0 << 0) #define PANEL_POWER_ON (1 << 0) #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 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 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 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_DPB_AUX_CH_CTL 0xe4110 diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 33378da63fd..63880e2e5cf 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1,5 +1,5 @@ /* - * Copyright © 2006 Intel Corporation + * Copyright © 2006 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -309,6 +309,13 @@ parse_general_features(struct drm_i915_private *dev_priv, dev_priv->lvds_use_ssc = general->enable_ssc; dev_priv->lvds_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, p_mapping->dvo_wiring = p_child->dvo_wiring; p_mapping->ddc_pin = p_child->ddc_pin; p_mapping->i2c_pin = p_child->i2c_pin; - p_mapping->i2c_speed = p_child->i2c_speed; 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->slave_addr, p_mapping->dvo_wiring, p_mapping->ddc_pin, - p_mapping->i2c_pin, - p_mapping->i2c_speed); + p_mapping->i2c_pin); } else { DRM_DEBUG_KMS("Maybe one SDVO port is shared by " "two SDVO device.\n"); @@ -610,7 +615,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) /* Default to using SSC */ dev_priv->lvds_use_ssc = 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 */ dev_priv->edp.bpp = 18; @@ -639,7 +644,7 @@ intel_parse_bios(struct drm_device *dev) if (dev_priv->opregion.vbt) { struct vbt_header *vbt = dev_priv->opregion.vbt; 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); bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset); } else diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index c2e38feb789..8af3735e27c 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -1,5 +1,5 @@ /* - * Copyright © 2006 Intel Corporation + * Copyright © 2006 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -120,7 +120,9 @@ struct bdb_general_features { u8 ssc_freq:1; u8 enable_lfp_on_override: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 */ u8 disable_smooth_vision:1; @@ -133,7 +135,10 @@ struct bdb_general_features { /* bits 5 */ u8 int_crt_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)); /* pre-915 */ @@ -197,8 +202,7 @@ struct bdb_general_features { struct child_device_config { u16 handle; u16 device_type; - u8 i2c_speed; - u8 rsvd[9]; + u8 device_id[10]; /* ascii string */ u16 addin_offset; u8 dvo_port; /* See Device_PORT_* above */ u8 i2c_pin; @@ -446,11 +450,11 @@ struct bdb_driver_features { #define EDP_VSWING_1_2V 3 struct edp_power_seq { - u16 t3; - u16 t7; + u16 t1_t3; + u16 t8; u16 t9; u16 t10; - u16 t12; + u16 t11_t12; } __attribute__ ((packed)); struct edp_link_params { diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 451534cb44d..fee0ad02c6d 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -152,17 +152,13 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) adpa |= ADPA_VSYNC_ACTIVE_HIGH; - if (intel_crtc->pipe == 0) { - if (HAS_PCH_CPT(dev)) - adpa |= PORT_TRANS_A_SEL_CPT; - else - adpa |= ADPA_PIPE_A_SELECT; - } else { - if (HAS_PCH_CPT(dev)) - adpa |= PORT_TRANS_B_SEL_CPT; - else - adpa |= ADPA_PIPE_B_SELECT; - } + /* For CPT allow 3 pipe config, for others just use A or B */ + if (HAS_PCH_CPT(dev)) + adpa |= PORT_TRANS_SEL_CPT(intel_crtc->pipe); + else if (intel_crtc->pipe == 0) + adpa |= ADPA_PIPE_A_SELECT; + else + adpa |= ADPA_PIPE_B_SELECT; if (!HAS_PCH_SPLIT(dev)) I915_WRITE(BCLRPAT(intel_crtc->pipe), 0); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8230cf54cc8..981b1f1c04d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -803,6 +803,19 @@ static void assert_pch_pll(struct drm_i915_private *dev_priv, u32 val; 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); val = I915_READ(reg); cur_state = !!(val & DPLL_VCO_ENABLE); @@ -1172,6 +1185,9 @@ static void intel_enable_pch_pll(struct drm_i915_private *dev_priv, int reg; u32 val; + if (pipe > 1) + return; + /* PCH only available on ILK+ */ BUG_ON(dev_priv->info->gen < 5); @@ -1192,6 +1208,9 @@ static void intel_disable_pch_pll(struct drm_i915_private *dev_priv, int reg; u32 val; + if (pipe > 1 |