diff options
Diffstat (limited to 'drivers/gpu/drm/i915')
39 files changed, 2287 insertions, 1413 deletions
diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c index d3e8c540f778..1ca799a1e1fc 100644 --- a/drivers/gpu/drm/i915/dvo_ch7017.c +++ b/drivers/gpu/drm/i915/dvo_ch7017.c @@ -227,7 +227,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo, default: DRM_DEBUG_KMS("ch701x not detected, got %d: from %s " "slave %d.\n", - val, adapter->name,dvo->slave_addr); + val, adapter->name, dvo->slave_addr); goto fail; } diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c index 7eaa94e4ff06..4a036600e806 100644 --- a/drivers/gpu/drm/i915/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c @@ -111,7 +111,7 @@ static char *ch7xxx_get_id(uint8_t vid) /** Reads an 8 bit register */ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) { - struct ch7xxx_priv *ch7xxx= dvo->dev_priv; + struct ch7xxx_priv *ch7xxx = dvo->dev_priv; struct i2c_adapter *adapter = dvo->i2c_bus; u8 out_buf[2]; u8 in_buf[2]; @@ -303,7 +303,7 @@ static void ch7xxx_dump_regs(struct intel_dvo_device *dvo) for (i = 0; i < CH7xxx_NUM_REGS; i++) { uint8_t val; - if ((i % 8) == 0 ) + if ((i % 8) == 0) DRM_LOG_KMS("\n %02X: ", i); ch7xxx_readb(dvo, i, &val); DRM_LOG_KMS("%02X ", val); diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c index a12ed9414cc7..04f2893d5e3c 100644 --- a/drivers/gpu/drm/i915/dvo_ivch.c +++ b/drivers/gpu/drm/i915/dvo_ivch.c @@ -344,8 +344,8 @@ static void ivch_mode_set(struct intel_dvo_device *dvo, (adjusted_mode->hdisplay - 1)) >> 2; y_ratio = (((mode->vdisplay - 1) << 16) / (adjusted_mode->vdisplay - 1)) >> 2; - ivch_write (dvo, VR42, x_ratio); - ivch_write (dvo, VR41, y_ratio); + ivch_write(dvo, VR42, x_ratio); + ivch_write(dvo, VR41, y_ratio); } else { vr01 &= ~VR01_PANEL_FIT_ENABLE; vr40 &= ~VR40_CLOCK_GATING_ENABLE; @@ -410,7 +410,7 @@ static void ivch_destroy(struct intel_dvo_device *dvo) } } -struct intel_dvo_dev_ops ivch_ops= { +struct intel_dvo_dev_ops ivch_ops = { .init = ivch_init, .dpms = ivch_dpms, .mode_valid = ivch_mode_valid, diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c index e4b4091df942..a0b13a6f619d 100644 --- a/drivers/gpu/drm/i915/dvo_sil164.c +++ b/drivers/gpu/drm/i915/dvo_sil164.c @@ -104,7 +104,7 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) { - struct sil164_priv *sil= dvo->dev_priv; + struct sil164_priv *sil = dvo->dev_priv; struct i2c_adapter *adapter = dvo->i2c_bus; uint8_t out_buf[2]; struct i2c_msg msg = { diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c index 8ab2855bb544..aa2cd3ec54aa 100644 --- a/drivers/gpu/drm/i915/dvo_tfp410.c +++ b/drivers/gpu/drm/i915/dvo_tfp410.c @@ -56,7 +56,7 @@ #define TFP410_CTL_2_MDI (1<<0) #define TFP410_CTL_3 0x0A -#define TFP410_CTL_3_DK_MASK (0x7<<5) +#define TFP410_CTL_3_DK_MASK (0x7<<5) #define TFP410_CTL_3_DK (1<<5) #define TFP410_CTL_3_DKEN (1<<4) #define TFP410_CTL_3_CTL_MASK (0x7<<1) @@ -225,12 +225,12 @@ static void tfp410_mode_set(struct intel_dvo_device *dvo, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - /* As long as the basics are set up, since we don't have clock dependencies - * in the mode setup, we can just leave the registers alone and everything - * will work fine. - */ - /* don't do much */ - return; + /* As long as the basics are set up, since we don't have clock dependencies + * in the mode setup, we can just leave the registers alone and everything + * will work fine. + */ + /* don't do much */ + return; } /* set the tfp410 power state */ diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3c395a59da35..8e95d66800b0 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -98,12 +98,12 @@ static const char *get_pin_flag(struct drm_i915_gem_object *obj) static const char *get_tiling_flag(struct drm_i915_gem_object *obj) { - switch (obj->tiling_mode) { - default: - case I915_TILING_NONE: return " "; - case I915_TILING_X: return "X"; - case I915_TILING_Y: return "Y"; - } + switch (obj->tiling_mode) { + default: + case I915_TILING_NONE: return " "; + case I915_TILING_X: return "X"; + case I915_TILING_Y: return "Y"; + } } static const char *cache_level_str(int type) @@ -217,7 +217,7 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) ++mappable_count; \ } \ } \ -} while(0) +} while (0) static int i915_gem_object_info(struct seq_file *m, void* data) { @@ -1293,12 +1293,12 @@ i915_wedged_read(struct file *filp, char buf[80]; int len; - len = snprintf(buf, sizeof (buf), + len = snprintf(buf, sizeof(buf), "wedged : %d\n", atomic_read(&dev_priv->mm.wedged)); - if (len > sizeof (buf)) - len = sizeof (buf); + if (len > sizeof(buf)) + len = sizeof(buf); return simple_read_from_buffer(ubuf, max, ppos, buf, len); } @@ -1314,7 +1314,7 @@ i915_wedged_write(struct file *filp, int val = 1; if (cnt > 0) { - if (cnt > sizeof (buf) - 1) + if (cnt > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, ubuf, cnt)) @@ -1357,11 +1357,11 @@ i915_max_freq_read(struct file *filp, char buf[80]; int len; - len = snprintf(buf, sizeof (buf), + len = snprintf(buf, sizeof(buf), "max freq: %d\n", dev_priv->max_delay * 50); - if (len > sizeof (buf)) - len = sizeof (buf); + if (len > sizeof(buf)) + len = sizeof(buf); return simple_read_from_buffer(ubuf, max, ppos, buf, len); } @@ -1378,7 +1378,7 @@ i915_max_freq_write(struct file *filp, int val = 1; if (cnt > 0) { - if (cnt > sizeof (buf) - 1) + if (cnt > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, ubuf, cnt)) @@ -1432,12 +1432,12 @@ i915_cache_sharing_read(struct file *filp, snpcr = I915_READ(GEN6_MBCUNIT_SNPCR); mutex_unlock(&dev_priv->dev->struct_mutex); - len = snprintf(buf, sizeof (buf), + len = snprintf(buf, sizeof(buf), "%d\n", (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT); - if (len > sizeof (buf)) - len = sizeof (buf); + if (len > sizeof(buf)) + len = sizeof(buf); return simple_read_from_buffer(ubuf, max, ppos, buf, len); } @@ -1455,7 +1455,7 @@ i915_cache_sharing_write(struct file *filp, int val = 1; if (cnt > 0) { - if (cnt > sizeof (buf) - 1) + if (cnt > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, ubuf, cnt)) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 8a3942c4f099..2eac955dee18 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -884,7 +884,7 @@ static int i915_get_bridge_dev(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0)); + dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)); if (!dev_priv->bridge_dev) { DRM_ERROR("bridge device not found\n"); return -1; @@ -1730,10 +1730,10 @@ static DEFINE_SPINLOCK(mchdev_lock); */ unsigned long i915_read_mch_val(void) { - struct drm_i915_private *dev_priv; + struct drm_i915_private *dev_priv; unsigned long chipset_val, graphics_val, ret = 0; - spin_lock(&mchdev_lock); + spin_lock(&mchdev_lock); if (!i915_mch_dev) goto out_unlock; dev_priv = i915_mch_dev; @@ -1744,9 +1744,9 @@ unsigned long i915_read_mch_val(void) ret = chipset_val + graphics_val; out_unlock: - spin_unlock(&mchdev_lock); + spin_unlock(&mchdev_lock); - return ret; + return ret; } EXPORT_SYMBOL_GPL(i915_read_mch_val); @@ -1757,10 +1757,10 @@ EXPORT_SYMBOL_GPL(i915_read_mch_val); */ bool i915_gpu_raise(void) { - struct drm_i915_private *dev_priv; + struct drm_i915_private *dev_priv; bool ret = true; - spin_lock(&mchdev_lock); + spin_lock(&mchdev_lock); if (!i915_mch_dev) { ret = false; goto out_unlock; @@ -1771,9 +1771,9 @@ bool i915_gpu_raise(void) dev_priv->max_delay--; out_unlock: - spin_unlock(&mchdev_lock); + spin_unlock(&mchdev_lock); - return ret; + return ret; } EXPORT_SYMBOL_GPL(i915_gpu_raise); @@ -1785,10 +1785,10 @@ EXPORT_SYMBOL_GPL(i915_gpu_raise); */ bool i915_gpu_lower(void) { - struct drm_i915_private *dev_priv; + struct drm_i915_private *dev_priv; bool ret = true; - spin_lock(&mchdev_lock); + spin_lock(&mchdev_lock); if (!i915_mch_dev) { ret = false; goto out_unlock; @@ -1799,9 +1799,9 @@ bool i915_gpu_lower(void) dev_priv->max_delay++; out_unlock: - spin_unlock(&mchdev_lock); + spin_unlock(&mchdev_lock); - return ret; + return ret; } EXPORT_SYMBOL_GPL(i915_gpu_lower); @@ -1812,10 +1812,10 @@ EXPORT_SYMBOL_GPL(i915_gpu_lower); */ bool i915_gpu_busy(void) { - struct drm_i915_private *dev_priv; + struct drm_i915_private *dev_priv; bool ret = false; - spin_lock(&mchdev_lock); + spin_lock(&mchdev_lock); if (!i915_mch_dev) goto out_unlock; dev_priv = i915_mch_dev; @@ -1823,9 +1823,9 @@ bool i915_gpu_busy(void) ret = dev_priv->busy; out_unlock: - spin_unlock(&mchdev_lock); + spin_unlock(&mchdev_lock); - return ret; + return ret; } EXPORT_SYMBOL_GPL(i915_gpu_busy); @@ -1837,10 +1837,10 @@ EXPORT_SYMBOL_GPL(i915_gpu_busy); */ bool i915_gpu_turbo_disable(void) { - struct drm_i915_private *dev_priv; + struct drm_i915_private *dev_priv; bool ret = true; - spin_lock(&mchdev_lock); + spin_lock(&mchdev_lock); if (!i915_mch_dev) { ret = false; goto out_unlock; @@ -1853,9 +1853,9 @@ bool i915_gpu_turbo_disable(void) ret = false; out_unlock: - spin_unlock(&mchdev_lock); + spin_unlock(&mchdev_lock); - return ret; + return ret; } EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable); @@ -1948,7 +1948,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; - dev_priv->mm.gtt_mapping = + dev_priv->mm.gtt_mapping = io_mapping_create_wc(dev->agp->base, agp_size); if (dev_priv->mm.gtt_mapping == NULL) { ret = -EIO; @@ -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 f07e4252b708..4c8d681c2151 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); @@ -294,7 +294,7 @@ MODULE_DEVICE_TABLE(pci, pciidlist); #define INTEL_PCH_CPT_DEVICE_ID_TYPE 0x1c00 #define INTEL_PCH_PPT_DEVICE_ID_TYPE 0x1e00 -void intel_detect_pch (struct drm_device *dev) +void intel_detect_pch(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct pci_dev *pch; @@ -377,7 +377,7 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) { - if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES ) { + if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) { int loop = 500; u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) { @@ -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); @@ -770,12 +773,12 @@ static int i915_pm_poweroff(struct device *dev) } static const struct dev_pm_ops i915_pm_ops = { - .suspend = i915_pm_suspend, - .resume = i915_pm_resume, - .freeze = i915_pm_freeze, - .thaw = i915_pm_thaw, - .poweroff = i915_pm_poweroff, - .restore = i915_pm_resume, + .suspend = i915_pm_suspend, + .resume = i915_pm_resume, + .freeze = i915_pm_freeze, + .thaw = i915_pm_thaw, + .poweroff = i915_pm_poweroff, + .restore = i915_pm_resume, }; static struct vm_operations_struct i915_gem_vm_ops = { @@ -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 7916bd97d5c1..06a37f4fd74b 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; }; @@ -209,6 +208,8 @@ struct drm_i915_display_funcs { struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb); + void (*write_eld)(struct drm_connector *connector, + struct drm_crtc *crtc); void (*fdi_link_train)(struct drm_crtc *crtc); void (*init_clock_gating)(struct drm_device *dev); void (*init_pch_clock_gating)(struct drm_device *dev); @@ -226,26 +227,26 @@ struct drm_i915_display_funcs { struct intel_device_info { u8 gen; - u8 is_mobile : 1; - u8 is_i85x : 1; - u8 is_i915g : 1; - u8 is_i945gm : 1; - u8 is_g33 : 1; - u8 need_gfx_hws : 1; - u8 is_g4x : 1; - u8 is_pineview : 1; - u8 is_broadwater : 1; - u8 is_crestline : 1; - u8 is_ivybridge : 1; - u8 has_fbc : 1; - u8 has_pipe_cxsr : 1; - u8 has_hotplug : 1; - u8 cursor_needs_physical : 1; - u8 has_overlay : 1; - u8 overlay_needs_physical : 1; - u8 supports_tv : 1; - u8 has_bsd_ring : 1; - u8 has_blt_ring : 1; + u8 is_mobile:1; + u8 is_i85x:1; + u8 is_i915g:1; + u8 is_i945gm:1; + u8 is_g33:1; + u8 need_gfx_hws:1; + u8 is_g4x:1; + u8 is_pineview:1; + u8 is_broadwater:1; + u8 is_crestline:1; + u8 is_ivybridge:1; + u8 has_fbc:1; + u8 has_pipe_cxsr:1; + u8 has_hotplug:1; + u8 cursor_needs_physical:1; + u8 has_overlay:1; + u8 overlay_needs_physical:1; + u8 supports_tv:1; + u8 has_bsd_ring:1; + u8 has_blt_ring:1; }; enum no_fbc_reason { @@ -347,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 */ @@ -357,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; @@ -672,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; @@ -759,19 +759,19 @@ struct drm_i915_gem_object { * (has pending rendering), and is not set if it's on inactive (ready * to be unbound). */ - unsigned int active : 1; + unsigned int active:1; /** * This is set if the object has been written to since last bound * to the GTT */ - unsigned int dirty : 1; + unsigned int dirty:1; /** * This is set if the object has been written to since the last * GPU flush. */ - unsigned int pending_gpu_write : 1; + unsigned int pending_gpu_write:1; /** * Fence register bits (if any) for this object. Will be set @@ -780,18 +780,18 @@ struct drm_i915_gem_object { * * Size: 4 bits for 16 fences + sign (for FENCE_REG_NONE) */ - signed int fence_reg : 5; + signed int fence_reg:5; /** * Advice: are the backing pages purgeable? */ - unsigned int madv : 2; + unsigned int madv:2; /** * Current tiling mode for the object. */ - unsigned int tiling_mode : 2; - unsigned int tiling_changed : 1; + unsigned int tiling_mode:2; + unsigned int tiling_changed:1; /** How many users have pinned this object in GTT space. The following * users can each hold at most one reference: pwrite/pread, pin_ioctl @@ -802,22 +802,22 @@ struct drm_i915_gem_object { * * In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3 * bits with absolutely no headroom. So use 4 bits. */ - unsigned int pin_count : 4; + unsigned int pin_count:4; #define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf /** * Is the object at the current location in the gtt mappable and * fenceable? Used to avoid costly recalculations. */ - unsigned int map_and_fenceable : 1; + unsigned int map_and_fenceable:1; /** * Whether the current gtt mapping needs to be mappable (and isn't just * mappable by accident). Track pin and fault separate for a more * accurate mappable working set. */ - unsigned int fault_mappable : 1; - unsigned int pin_mappable : 1; + unsigned int fault_mappable:1; + unsigned int pin_mappable:1; /* * Is the GPU currently using a fence to access this buffer, @@ -1056,7 +1056,7 @@ i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); void i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); -void intel_enable_asle (struct drm_device *dev); +void intel_enable_asle(struct drm_device *dev); #ifdef CONFIG_DEBUG_FS extern void i915_destroy_error_state(struct drm_device *dev); @@ -1146,7 +1146,7 @@ int i915_gem_dumb_create(struct drm_file *file_priv, int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev, uint32_t handle, uint64_t *offset); int i915_gem_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev, - uint32_t handle); + uint32_t handle); /** * Returns true if seq1 is later than seq2. */ @@ -1301,10 +1301,11 @@ 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); -extern int intel_trans_dp_port_sel (struct drm_crtc *crtc); +extern void intel_detect_pch(struct drm_device *dev); +extern int intel_trans_dp_port_sel(struct drm_crtc *crtc); /* overlay */ #ifdef CONFIG_DEBUG_FS @@ -1354,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) @@ -1374,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 a546a71fb060..6651c36b6e8a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -179,7 +179,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, mutex_unlock(&dev->struct_mutex); args->aper_size = dev_priv->mm.gtt_total; - args->aper_available_size = args->aper_size -pinned; + args->aper_available_size = args->aper_size - pinned; return 0; } @@ -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); @@ -1265,74 +1267,6 @@ out: } /** - * i915_gem_create_mmap_offset - create a fake mmap offset for an object - * @obj: obj in question - * - * GEM memory mapping works by handing back to userspace a fake mmap offset - * it can use in a subsequent mmap(2) call. The DRM core code then looks - * up the object based on the offset and sets up the various memory mapping - * structures. - * - * This routine allocates and attaches a fake offset for @obj. - */ -static int -i915_gem_create_mmap_offset(struct drm_i915_gem_object *obj) -{ - struct drm_device *dev = obj->base.dev; - struct drm_gem_mm *mm = dev->mm_private; - struct drm_map_list *list; - struct drm_local_map *map; - int ret = 0; - - /* Set the object up for mmap'ing */ - list = &obj->base.map_list; - list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL); - if (!list->map) - return -ENOMEM; - - map = list->map; - map->type = _DRM_GEM; - map->size = obj->base.size; - map->handle = obj; - - /* Get a DRM GEM mmap offset allocated... */ - list->file_offset_node = drm_mm_search_free(&mm->offset_manager, - obj->base.size / PAGE_SIZE, - 0, 0); - if (!list->file_offset_node) { - DRM_ERROR("failed to allocate offset for bo %d\n", - obj->base.name); - ret = -ENOSPC; - goto out_free_list; - } - - list->file_offset_node = drm_mm_get_block(list->file_offset_node, - obj->base.size / PAGE_SIZE, - 0); - if (!list->file_offset_node) { - ret = -ENOMEM; - goto out_free_list; - } - - list->hash.key = list->file_offset_node->start; - ret = drm_ht_insert_item(&mm->offset_hash, &list->hash); - if (ret) { - DRM_ERROR("failed to add to map hash\n"); - goto out_free_mm; - } - - return 0; - -out_free_mm: - drm_mm_put_block(list->file_offset_node); -out_free_list: - kfree(list->map); - list->map = NULL; - - return ret; -} - -/** * i915_gem_release_mmap - remove physical page mappings * @obj: obj in question * @@ -1360,19 +1294,6 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj) obj->fault_mappable = false; } -static void -i915_gem_free_mmap_offset(struct drm_i915_gem_object *obj) -{ - struct drm_device *dev = obj->base.dev; - struct drm_gem_mm *mm = dev->mm_private; - struct drm_map_list *list = &obj->base.map_list; - - drm_ht_remove_item(&mm->offset_hash, &list->hash); - drm_mm_put_block(list->file_offset_node); - kfree(list->map); - list->map = NULL; -} - static uint32_t i915_gem_get_gtt_size(struct drm_device *dev, uint32_t size, int tiling_mode) { @@ -1485,7 +1406,7 @@ i915_gem_mmap_gtt(struct drm_file *file, } if (!obj->base.map_list.map) { - ret = i915_gem_create_mmap_offset(obj); + ret = drm_gem_create_mmap_offset(&obj->base); if (ret) goto out; } @@ -1557,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; @@ -1579,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) @@ -1856,7 +1777,7 @@ void i915_gem_reset(struct drm_device *dev) * lost bo to the inactive list. */ while (!list_empty(&dev_priv->mm.flushing_list)) { - obj= list_first_entry(&dev_priv->mm.flushing_list, + obj = list_first_entry(&dev_priv->mm.flushing_list, struct drm_i915_gem_object, mm_list); @@ -1922,7 +1843,7 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring) while (!list_empty(&ring->active_list)) { struct drm_i915_gem_object *obj; - obj= list_first_entry(&ring->active_list, + obj = list_first_entry(&ring->active_list, struct drm_i915_gem_object, ring_list); @@ -2272,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]); @@ -2882,7 +2797,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, fenceable = obj->gtt_space->size == fence_size && - (obj->gtt_space->start & (fence_alignment -1)) == 0; + (obj->gtt_space->start & (fence_alignment - 1)) == 0; mappable = obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end; @@ -3598,7 +3513,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, */ request = kzalloc(sizeof(*request), GFP_KERNEL); if (request) - ret = i915_add_request(obj->ring, NULL,request); + ret = i915_add_request(obj->ring, NULL, request); else ret = -ENOMEM; } @@ -3623,7 +3538,7 @@ int i915_gem_throttle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - return i915_gem_ring_throttle(dev, file_priv); + return i915_gem_ring_throttle(dev, file_priv); } int @@ -3752,7 +3667,7 @@ static void i915_gem_free_object_tail(struct drm_i915_gem_object *obj) trace_i915_gem_object_destroy(obj); if (obj->base.map_list.map) - i915_gem_free_mmap_offset(obj); + drm_gem_free_mmap_offset(&obj->base); drm_gem_object_release(&obj->base); i915_gem_info_remove_obj(dev_priv, obj->base.size); diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index 8da1899bd24f..cc93cac242d6 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c @@ -72,7 +72,7 @@ i915_verify_lists(struct drm_device *dev) break; } else if (!obj->active || (obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0 || - list_empty(&obj->gpu_write_list)){ + list_empty(&obj->gpu_write_list)) { DRM_ERROR("invalid flushing %p (a %d w %x gwl %d)\n", obj, obj->active, @@ -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_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index da05a2692a75..ead5d00f91b0 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -122,7 +122,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, goto found; } list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) { - if (! obj->base.write_domain || obj->pin_count) + if (!obj->base.write_domain || obj->pin_count) continue; if (mark_free(obj, &unwind_list)) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 4934cf84c320..3693e83a97f3 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -784,7 +784,8 @@ i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj, } from->sync_seqno[idx] = seqno; - return intel_ring_sync(to, from, seqno - 1); + + return to->sync_to(to, from, seqno - 1); } static int diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 7a709cd8d543..6042c5e6d278 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 99c4faa59d8f..31d334d9d9da 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 9cbb0cd8f46a..9ee2729fe5c6 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); } @@ -711,7 +713,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv, page_count = src->base.size / PAGE_SIZE; - dst = kmalloc(sizeof(*dst) + page_count * sizeof (u32 *), GFP_ATOMIC); + dst = kmalloc(sizeof(*dst) + page_count * sizeof(u32 *), GFP_ATOMIC); if (dst == NULL) return NULL; @@ -1493,7 +1495,7 @@ static int ironlake_enable_vblank(struct drm_device *dev, int pipe) spin_lock_irqsave(&dev_priv->irq_lock, irqflags); ironlake_enable_display_irq(dev_priv, (pipe == 0) ? - DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); + DE_PIPEA_VBLANK : DE_PIPEB_VBLANK); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); return 0; @@ -1541,7 +1543,7 @@ static void ironlake_disable_vblank(struct drm_device *dev, int pipe) spin_lock_irqsave(&dev_priv->irq_lock, irqflags); ironlake_disable_display_irq(dev_priv, (pipe == 0) ? - DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); + DE_PIPEA_VBLANK : DE_PIPEB_VBLANK); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } @@ -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_mem.c b/drivers/gpu/drm/i915/i915_mem.c index 83b7b81bb2b8..cc8f6d49cf20 100644 --- a/drivers/gpu/drm/i915/i915_mem.c +++ b/drivers/gpu/drm/i915/i915_mem.c @@ -202,7 +202,7 @@ static int init_heap(struct mem_block **heap, int start, int size) blocks->next = blocks->prev = *heap; memset(*heap, 0, sizeof(**heap)); - (*heap)->file_priv = (struct drm_file *) - 1; + (*heap)->file_priv = (struct drm_file *) -1; (*heap)->next = (*heap)->prev = blocks; return 0; } @@ -359,19 +359,19 @@ int i915_mem_init_heap(struct drm_device *dev, void *data, return init_heap(heap, initheap->start, initheap->size); } -int i915_mem_destroy_heap( struct drm_device *dev, void *data, - struct drm_file *file_priv ) +int i915_mem_destroy_heap(struct drm_device *dev, void *data, + struct drm_file *file_priv) { drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_mem_destroy_heap_t *destroyheap = data; struct mem_block **heap; - if ( !dev_priv ) { - DRM_ERROR( "called with no initialization\n" ); + if (!dev_priv) { + DRM_ERROR("called with no initialization\n"); return -EINVAL; } - heap = get_heap( dev_priv, destroyheap->region ); + heap = get_heap(dev_priv, destroyheap->region); if (!heap) { DRM_ERROR("get_heap failed"); return -EFAULT; @@ -382,6 +382,6 @@ int i915_mem_destroy_heap( struct drm_device *dev, void *data, return -EFAULT; } - i915_mem_takedown( heap ); + i915_mem_takedown(heap); return 0; } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 542453f7498c..5a09416e611f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -156,7 +156,7 @@ #define MI_SUSPEND_FLUSH MI_INSTR(0x0b, 0) #define MI_SUSPEND_FLUSH_EN (1<<0) #define MI_REPORT_HEAD MI_INSTR(0x07, 0) -#define MI_OVERLAY_FLIP MI_INSTR(0x11,0) +#define MI_OVERLAY_FLIP MI_INSTR(0x11, 0) #define MI_OVERLAY_CONTINUE (0x0<<21) #define MI_OVERLAY_ON (0x1<<21) #define MI_OVERLAY_OFF (0x2<<21) @@ -194,6 +194,13 @@ #define MI_SEMAPHORE_UPDATE (1<<21) #define MI_SEMAPHORE_COMPARE (1<<20) #define MI_SEMAPHORE_REGISTER (1<<18) +#define MI_SEMAPHORE_SYNC_RV (2<<16) +#define MI_SEMAPHORE_SYNC_RB (0<<16) +#define MI_SEMAPHORE_SYNC_VR (0<<16) +#define MI_SEMAPHORE_SYNC_VB (2<<16) +#define MI_SEMAPHORE_SYNC_BR (2<<16) +#define MI_SEMAPHORE_SYNC_BV (0<<16) +#define MI_SEMAPHORE_SYNC_INVALID (1<<0) /* * 3D instructions used by the kernel */ @@ -235,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 */ /* @@ -296,6 +309,12 @@ #define RING_CTL(base) ((base)+0x3c) #define RING_SYNC_0(base) ((base)+0x40) #define RING_SYNC_1(base) ((base)+0x44) +#define GEN6_RVSYNC (RING_SYNC_0(RENDER_RING_BASE)) +#define GEN6_RBSYNC (RING_SYNC_1(RENDER_RING_BASE)) +#define GEN6_VRSYNC (RING_SYNC_1(GEN6_BSD_RING_BASE)) +#define GEN6_VBSYNC (RING_SYNC_0(GEN6_BSD_RING_BASE)) +#define GEN6_BRSYNC (RING_SYNC_0(BLT_RING_BASE)) +#define GEN6_BVSYNC (RING_SYNC_1(BLT_RING_BASE)) #define RING_MAX_IDLE(base) ((base)+0x54) #define RING_HWS_PGA(base) ((base)+0x80) #define RING_HWS_PGA_GEN6(base) ((base)+0x2080) @@ -470,7 +489,7 @@ /* Enables non-sequential data reads through arbiter */ -#define MI_ARB_DUAL_DATA_PHASE_DISABLE (1 << 9) +#define MI_ARB_DUAL_DATA_PHASE_DISABLE (1 << 9) /* Disable FSB snooping of cacheable write cycles from binner/render * command stream @@ -626,7 +645,7 @@ #define ILK_DISPLAY_CHICKEN1 0x42000 #define ILK_FBCQ_DIS (1<<22) -#define ILK_PABSTRETCH_DIS (1<<21) +#define ILK_PABSTRETCH_DIS (1<<21) /* @@ -2358,7 +2377,7 @@ #define DSPFW1 0x70034 #define DSPFW_SR_SHIFT 23 -#define DSPFW_SR_MASK (0x1ff<<23) +#define DSPFW_SR_MASK (0x1ff<<23) #define DSPFW_CURSORB_SHIFT 16 #define DSPFW_CURSORB_MASK (0x3f<<16) #define DSPFW_PLANEB_SHIFT 8 @@ -2416,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 @@ -2554,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) @@ -2903,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) @@ -2917,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) @@ -2925,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) @@ -2945,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 @@ -3167,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) @@ -3308,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 @@ -3470,4 +3522,29 @@ #define GEN6_PCODE_DATA 0x138128 #define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8 +#define G4X_AUD_VID_DID 0x62020 +#define INTEL_AUDIO_DEVCL 0x808629FB +#define INTEL_AUDIO_DEVBLC 0x80862801 +#define INTEL_AUDIO_DEVCTG 0x80862802 + +#define G4X_AUD_CNTL_ST 0x620B4 +#define G4X_ELDV_DEVCL_DEVBLC (1 << 13) +#define G4X_ELDV_DEVCTG (1 << 14) +#define G4X_ELD_ADDR (0xf << 5) +#define G4X_ELD_ACK (1 << 4) +#define G4X_HDMIW_HDMIEDID 0x6210C + +#define GEN5_HDMIW_HDMIEDID_A 0xE2050 +#define GEN5_AUD_CNTL_ST_A 0xE20B4 +#define GEN5_ELD_BUFFER_SIZE (0x1f << 10) +#define GEN5_ELD_ADDRESS (0x1f << 5) +#define GEN5_ELD_ACK (1 << 4) +#define GEN5_AUD_CNTL_ST2 0xE20C0 +#define GEN5_ELD_VALIDB (1 << 0) +#define GEN5_CP_READYB (1 << 1) + +#define GEN7_HDMIW_HDMIEDID_A 0xE5050 +#define GEN7_AUD_CNTRL_ST_A 0xE50B4 +#define GEN7_AUD_CNTRL_ST2 0xE50C0 + #endif /* _I915_REG_H_ */ diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index f10742359ec9..f8f602d76650 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -60,7 +60,7 @@ static void i915_save_palette(struct drm_device *dev, enum pipe pipe) else array = dev_priv->save_palette_b; - for(i = 0; i < 256; i++) + for (i = 0; i < 256; i++) array[i] = I915_READ(reg + (i << 2)); } @@ -82,7 +82,7 @@ static void i915_restore_palette(struct drm_device *dev, enum pipe pipe) else array = dev_priv->save_palette_b; - for(i = 0; i < 256; i++) + for (i = 0; i < 256; i++) I915_WRITE(reg + (i << 2), array[i]); } @@ -887,10 +887,10 @@ int i915_restore_state(struct drm_device *dev) mutex_lock(&dev->struct_mutex); /* Cache mode state */ - I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); + I915_WRITE(CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); /* Memory arbitration state */ - I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000); + I915_WRITE(MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000); for (i = 0; i < 16; i++) { I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]); diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index d623fefbfaca..dac7bba4d9da 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -385,29 +385,29 @@ TRACE_EVENT(i915_flip_complete, ); TRACE_EVENT(i915_reg_rw, - TP_PROTO(bool write, u32 reg, u64 val, int len), - - TP_ARGS(write, reg, val, len), - - TP_STRUCT__entry( - __field(u64, val) - __field(u32, reg) - __field(u16, write) - __field(u16, len) - ), - - TP_fast_assign( - __entry->val = (u64)val; - __entry->reg = reg; - __entry->write = write; - __entry->len = len; - ), - - TP_printk("%s reg=0x%x, len=%d, val=(0x%x, 0x%x)", - __entry->write ? "write" : "read", - __entry->reg, __entry->len, - (u32)(__entry->val & 0xffffffff), - (u32)(__entry->val >> 32)) + TP_PROTO(bool write, u32 reg, u64 val, int len), + + TP_ARGS(write, reg, val, len), + + TP_STRUCT__entry( + __field(u64, val) + __field(u32, reg) + __field(u16, write) + __field(u16, len) + ), + + TP_fast_assign( + __entry->val = (u64)val; + __entry->reg = reg; + __entry->write = write; + __entry->len = len; + ), + + TP_printk("%s reg=0x%x, len=%d, val=(0x%x, 0x%x)", + __entry->write ? "write" : "read", + __entry->reg, __entry->len, + (u32)(__entry->val & 0xffffffff), + (u32)(__entry->val >> 32)) ); #endif /* _I915_TRACE_H_ */ diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c index 2cb8e0b9f1ee..cb912106d1a2 100644 --- a/drivers/gpu/drm/i915/intel_acpi.c +++ b/drivers/gpu/drm/i915/intel_acpi.c @@ -64,7 +64,7 @@ static int intel_dsm(acpi_handle handle, int func, int arg) case ACPI_TYPE_BUFFER: if (obj->buffer.length == 4) { - result =(obj->buffer.pointer[0] | + result = (obj->buffer.pointer[0] | (obj->buffer.pointer[1] << 8) | (obj->buffer.pointer[2] << 16) | (obj->buffer.pointer[3] << 24)); diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 61abef8a8119..63880e2e5cfd 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); } } @@ -381,7 +388,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, if (p_child->dvo_port != DEVICE_PORT_DVOB && p_child->dvo_port != DEVICE_PORT_DVOC) { /* skip the incorrect SDVO port */ - DRM_DEBUG_KMS("Incorrect SDVO port. Skip it \n"); + DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n"); continue; } DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on" @@ -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"); @@ -564,7 +569,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, count++; } if (!count) { - DRM_DEBUG_KMS("no child dev is parsed from VBT \n"); + DRM_DEBUG_KMS("no child dev is parsed from VBT\n"); return; } dev_priv->child_dev = kzalloc(sizeof(*p_child) * count, GFP_KERNEL); @@ -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 5f8e4edcbbb9..8af3735e27c6 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; @@ -240,7 +244,7 @@ struct bdb_general_definitions { * And the device num is related with the size of general definition * block. It is obtained by using the following formula: * number = (block_size - sizeof(bdb_general_definitions))/ - * sizeof(child_device_config); + * sizeof(child_device_config); */ struct child_device_config devices[0]; } __attribute__((packed)); @@ -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 0979d8877880..fee0ad02c6d0 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -69,7 +69,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode) temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); temp &= ~ADPA_DAC_ENABLE; - switch(mode) { + switch (mode) { case DRM_MODE_DPMS_ON: temp |= ADPA_DAC_ENABLE; break; @@ -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 04411ad2e779..981b1f1c04d8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -31,6 +31,7 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/vgaarb.h> +#include <drm/drm_edid.h> #include "drmP.h" #include "intel_drv.h" #include "i915_drm.h" @@ -42,39 +43,39 @@ #define HAS_eDP (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) -bool intel_pipe_has_type (struct drm_crtc *crtc, int type); +bool intel_pipe_has_type(struct drm_crtc *crtc, int type); static void intel_update_watermarks(struct drm_device *dev); static void intel_increase_pllclock(struct drm_crtc *crtc); static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on); typedef struct { - /* given values */ - int n; - int m1, m2; - int p1, p2; - /* derived values */ - int dot; - int vco; - int m; - int p; + /* given values */ + int n; + int m1, m2; + int p1, p2; + /* derived values */ + int dot; + int vco; + int m; + int p; } intel_clock_t; typedef struct { - int min, max; + int min, max; } intel_range_t; typedef struct { - int dot_limit; - int p2_slow, p2_fast; + int dot_limit; + int p2_slow, p2_fast; } intel_p2_t; #define INTEL_P2_NUM 2 typedef struct intel_limit intel_limit_t; struct intel_limit { - intel_range_t dot, vco, n, m, m1, m2, p, p1; - intel_p2_t p2; - bool (* find_pll)(const intel_limit_t *, struct drm_crtc *, - int, int, intel_clock_t *); + intel_range_t dot, vco, n, m, m1, m2, p, p1; + intel_p2_t p2; + bool (* find_pll)(const intel_limit_t *, struct drm_crtc *, + int, int, intel_clock_t *); }; /* FDI */ @@ -105,56 +106,56 @@ intel_fdi_link_freq(struct drm_device *dev) } static const intel_limit_t intel_limits_i8xx_dvo = { - .dot = { .min = 25000, .max = 350000 }, - .vco = { .min = 930000, .max = 1400000 }, - .n = { .min = 3, .max = 16 }, - .m = { .min = 96, .max = 140 }, - .m1 = { .min = 18, .max = 26 }, - .m2 = { .min = 6, .max = 16 }, - .p = { .min = 4, .max = 128 }, - .p1 = { .min = 2, .max = 33 }, + .dot = { .min = 25000, .max = 350000 }, + .vco = { .min = 930000, .max = 1400000 }, + .n = { .min = 3, .max = 16 }, + .m = { .min = 96, .max = 140 }, + .m1 = { .min = 18, .max = 26 }, + .m2 = { .min = 6, .max = 16 }, + .p = { .min = 4, .max = 128 }, + .p1 = { .min = 2, .max = 33 }, .p2 = { .dot_limit = 165000, .p2_slow = 4, .p2_fast = 2 }, .find_pll = intel_find_best_PLL, }; static const intel_limit_t intel_limits_i8xx_lvds = { - .dot = { .min = 25000, .max = 350000 }, - .vco = { .min = 930000, .max = 1400000 }, - .n = { .min = 3, .max = 16 }, - .m = { .min = 96, .max = 140 }, - .m1 = { .min = 18, .max = 26 }, - .m2 = { .min = 6, .max = 16 }, - .p = { .min = 4, .max = 128 }, - .p1 = { .min = 1, .max = 6 }, + .dot = { .min = 25000, .max = 350000 }, + .vco = { .min = 930000, .max = 1400000 }, + .n = { .min = 3, .max = 16 }, + .m = { .min = 96, .max = 140 }, + .m1 = { .min = 18, .max = 26 }, + .m2 = { .min = 6, .max = 16 }, + .p = { .min = 4, .max = 128 }, + .p1 = { .min = 1, .max = 6 }, .p2 = { .dot_limit = 165000, .p2_slow = 14, .p2_fast = 7 }, .find_pll = intel_find_best_PLL, }; static const intel_limit_t intel_limits_i9xx_sdvo = { - .dot = { .min = 20000, .max = 400000 }, - .vco = { .min = 1400000, .max = 2800000 }, - .n = { .min = 1, .max = 6 }, - .m = { .min = 70, .max = 120 }, - .m1 = { .min = 10, .max = 22 }, - .m2 = { .min = 5, .max = 9 }, - .p = { .min = 5, .max = 80 }, - .p1 = { .min = 1, .max = 8 }, + .dot = { .min = 20000, .max = 400000 }, + .vco = { .min = 1400000, .max = 2800000 }, + .n = { .min = 1, .max = 6 }, + .m = { .min = 70, .max = 120 }, + .m1 = { .min = 10, .max = 22 }, + .m2 = { .min = 5, .max = 9 }, + .p = { .min = 5, .max = 80 }, + .p1 = { .min = 1, .max = 8 }, .p2 = { .dot_limit = 200000, .p2_slow = 10, .p2_fast = 5 }, .find_pll = intel_find_best_PLL, }; static const intel_limit_t intel_limits_i9xx_lvds = { - .dot = { .min = 20000, .max = 400000 }, - .vco = { .min = 1400000, .max = 2800000 }, - .n = { .min = 1, .max = 6 }, - .m = { .min = 70, .max = 120 }, - .m1 = { .min = 10, .max = 22 }, - .m2 = { .min = 5, .max = 9 }, - .p = { .min = 7, .max = 98 }, - .p1 = { .min = 1, .max = 8 }, + .dot = { .min = 20000, .max = 400000 }, + .vco = { .min = 1400000, .max = 2800000 }, + .n = { .min = 1, .max = 6 }, + .m = { .min = 70, .max = 120 }, + .m1 = { .min = 10, .max = 22 }, + .m2 = { .min = 5, .max = 9 }, + .p = { .min = 7, .max = 98 }, + .p1 = { .min = 1, .max = 8 }, .p2 = { .dot_limit = 112000, .p2_slow = 14, .p2_fast = 7 }, .find_pll = intel_find_best_PLL, @@ -222,44 +223,44 @@ static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { }; static const intel_limit_t intel_limits_g4x_display_port = { - .dot = { .min = 161670, .max = 227000 }, - .vco = { .min = 1750000, .max = 3500000}, - .n = { .min = 1, .max = 2 }, - .m = { .min = 97, .max = 108 }, - .m1 = { .min = 0x10, .max = 0x12 }, - .m2 = { .min = 0x05, .max = 0x06 }, - .p = { .min = 10, .max = 20 }, - .p1 = { .min = 1, .max = 2}, - .p2 = { .dot_limit = 0, + .dot = { .min = 161670, .max = 227000 }, + .vco = { .min = 1750000, .max = 3500000}, + .n = { .min = 1, .max = 2 }, + .m = { .min = 97, .max = 108 }, + .m1 = { .min = 0x10, .max = 0x12 }, + .m2 = { .min = 0x05, .max = 0x06 }, + .p = { .min = 10, .max = 20 }, + .p1 = { .min = 1, .max = 2}, + .p2 = { .dot_limit = 0, .p2_slow = 10, .p2_fast = 10 }, - .find_pll = intel_find_pll_g4x_dp, + .find_pll = intel_find_pll_g4x_dp, }; static const intel_limit_t intel_limits_pineview_sdvo = { - .dot = { .min = 20000, .max = 400000}, - .vco = { .min = 1700000, .max = 3500000 }, + .dot = { .min = 20000, .max = 400000}, + .vco = { .min = 1700000, .max = 3500000 }, /* Pineview's Ncounter is a ring counter */ - .n = { .min = 3, .max = 6 }, - .m = { .min = 2, .max = 256 }, + .n = { .min = 3, .max = 6 }, + .m = { .min = 2, .max = 256 }, /* Pineview only has one combined m divider, which we treat as m2. */ - .m1 = { .min = 0, .max = 0 }, - .m2 = { .min = 0, .max = 254 }, - .p = { .min = 5, .max = 80 }, - .p1 = { .min = 1, .max = 8 }, + .m1 = { .min = 0, .max = 0 }, + .m2 = { .min = 0, .max = 254 }, + .p = { .min = 5, .max = 80 }, + .p1 = { .min = 1, .max = 8 }, .p2 = { .dot_limit = 200000, .p2_slow = 10, .p2_fast = 5 }, .find_pll = intel_find_best_PLL, }; static const intel_limit_t intel_limits_pineview_lvds = { - .dot = { .min = 20000, .max = 400000 }, - .vco = { .min = 1700000, .max = 3500000 }, - .n = { .min = 3, .max = 6 }, - .m = { .min = 2, .max = 256 }, - .m1 = { .min = 0, .max = 0 }, - .m2 = { .min = 0, .max = 254 }, - .p = { .min = 7, .max = 112 }, - .p1 = { .min = 1, .max = 8 }, + .dot = { .min = 20000, .max = 400000 }, + .vco = { .min = 1700000, .max = 3500000 }, + .n = { .min = 3, .max = 6 }, + .m = { .min = 2, .max = 256 }, + .m1 = { .min = 0, .max = 0 }, + .m2 = { .min = 0, .max = 254 }, + .p = { .min = 7, .max = 112 }, + .p1 = { .min = 1, .max = 8 }, .p2 = { .dot_limit = 112000, .p2_slow = 14, .p2_fast = 14 }, .find_pll = intel_find_best_PLL, @@ -321,7 +322,7 @@ static const intel_limit_t intel_limits_ironlake_single_lvds_100m = { .m1 = { .min = 12, .max = 22 }, .m2 = { .min = 5, .max = 9 }, .p = { .min = 28, .max = 112 }, - .p1 = { .min = 2,.max = 8 }, + .p1 = { .min = 2, .max = 8 }, .p2 = { .dot_limit = 225000, .p2_slow = 14, .p2_fast = 14 }, .find_pll = intel_g4x_find_best_PLL, @@ -335,24 +336,24 @@ static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = { .m1 = { .min = 12, .max = 22 }, .m2 = { .min = 5, .max = 9 }, .p = { .min = 14, .max = 42 }, - .p1 = { .min = 2,.max = 6 }, + .p1 = { .min = 2, .max = 6 }, .p2 = { .dot_limit = 225000, .p2_slow = 7, .p2_fast = 7 }, .find_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_ironlake_display_port = { - .dot = { .min = 25000, .max = 350000 }, - .vco = { .min = 1760000, .max = 3510000}, - .n = { .min = 1, .max = 2 }, - .m = { .min = 81, .max = 90 }, - .m1 = { .min = 12, .max = 22 }, - .m2 = { .min = 5, .max = 9 }, - .p = { .min = 10, .max = 20 }, - .p1 = { .min = 1, .max = 2}, - .p2 = { .dot_limit = 0, + .dot = { .min = 25000, .max = 350000 }, + .vco = { .min = 1760000, .max = 3510000}, + .n = { .min = 1, .max = 2 }, + .m = { .min = 81, .max = 90 }, + .m1 = { .min = 12, .max = 22 }, + .m2 = { .min = 5, .max = 9 }, + .p = { .min = 10, .max = 20 }, + .p1 = { .min = 1, .max = 2}, + .p2 = { .dot_limit = 0, .p2_slow = 10, .p2_fast = 10 }, - .find_pll = intel_find_pll_ironlake_dp, + .find_pll = intel_find_pll_ironlake_dp, }; static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc, @@ -404,7 +405,7 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) limit = &intel_limits_g4x_hdmi; } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { limit = &intel_limits_g4x_sdvo; - } else if (intel_pipe_has_type (crtc, INTEL_OUTPUT_DISPLAYPORT)) { + } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { limit = &intel_limits_g4x_display_port; } else /* The option is for other outputs */ limit = &intel_limits_i9xx_sdvo; @@ -488,26 +489,26 @@ static bool intel_PLL_is_valid(struct drm_device *dev, const intel_clock_t *clock) { if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) - INTELPllInvalid ("p1 out of range\n"); + INTELPllInvalid("p1 out of range\n"); if (clock->p < limit->p.min || limit->p.max < clock->p) - INTELPllInvalid ("p out of range\n"); + INTELPllInvalid("p out of range\n"); if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2) - INTELPllInvalid ("m2 out of range\n"); + INTELPllInvalid("m2 out of range\n"); if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) - INTELPllInvalid ("m1 out of range\n"); + INTELPllInvalid("m1 out of range\n"); if (clock->m1 <= clock->m2 && !IS_PINEVIEW(dev)) - INTELPllInvalid ("m1 <= m2\n"); + INTELPllInvalid("m1 <= m2\n"); if (clock->m < limit->m.min || limit->m.max < clock->m) - INTELPllInvalid ("m out of range\n"); + INTELPllInvalid("m out of range\n"); if (clock->n < limit->n.min || limit->n.max < clock->n) - INTELPllInvalid ("n out of range\n"); + INTELPllInvalid("n out of range\n"); if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) - INTELPllInvalid ("vco out of range\n"); + INTELPllInvalid("vco out of range\n"); /* XXX: We may need to be checking "Dot clock" depending on the multiplier, * connector, etc., rather than just a single range. */ if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) - INTELPllInvalid ("dot out of range\n"); + INTELPllInvalid("dot out of range\n"); return true; } @@ -542,7 +543,7 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, clock.p2 = limit->p2.p2_fast; } - memset (best_clock, 0, sizeof (*best_clock)); + memset(best_clock, 0, sizeof(*best_clock)); for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { @@ -802,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); @@ -1171,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); @@ -1191,6 +1208,9 @@ static void intel_disable_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); @@ -1256,7 +1276,7 @@ static void intel_disable_transcoder(struct drm_i915_private *dev_priv, I915_WRITE(reg, val); /* wait for PCH transcoder off, transcoder state */ 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); } /** @@ -2085,6 +2105,7 @@ static int ironlake_update_plane(struct drm_crtc *crtc, switch (plane) { case 0: case 1: + case 2: break; default: DRM_ERROR("Can't update plane %d in SAREA\n", plane); @@ -2184,6 +2205,10 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, case 0: case 1: break; + case 2: + if (IS_IVYBRIDGE(dev)) + break; + /* fall through otherwise */ default: DRM_ERROR("no plane for crtc\n"); return -EINVAL; @@ -2440,7 +2465,7 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc) } -static const int snb_b_fdi_train_param [] = { +static const int snb_b_fdi_train_param[] = { FDI_LINK_TRAIN_400MV_0DB_SNB_B, FDI_LINK_TRAIN_400MV_6DB_SNB_B, FDI_LINK_TRAIN_600MV_3_5DB_SNB_B, @@ -2496,7 +2521,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) if (HAS_PCH_CPT(dev)) cpt_phase_pointer_enable(dev, pipe); - for (i = 0; i < 4; i++ ) { + for (i = 0; i < 4; i++) { reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; @@ -2545,7 +2570,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) POSTING_READ(reg); udelay(150); - for (i = 0; i < 4; i++ ) { + for (i = 0; i < 4; i++) { reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; @@ -2600,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_VOL_EMP_MASK; temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; + temp |= FDI_COMPOSITE_SYNC; I915_WRITE(reg, temp | FDI_TX_ENABLE); reg = FDI_RX_CTL(pipe); @@ -2607,6 +2633,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) temp &= ~FDI_LINK_TRAIN_AUTO; temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; + temp |= FDI_COMPOSITE_SYNC; I915_WRITE(reg, temp | FDI_RX_ENABLE); POSTING_READ(reg); @@ -2615,7 +2642,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) if (HAS_PCH_CPT(dev)) cpt_phase_pointer_enable(dev, pipe); - for (i = 0; i < 4; i++ ) { + for (i = 0; i < 4; i++) { reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; @@ -2657,7 +2684,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) POSTING_READ(reg); udelay(150); - for (i = 0; i < 4; i++ ) { + for (i = 0; i < 4; i++) { reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; @@ -2866,7 +2893,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; - u32 reg, temp; + u32 reg, temp, transc_sel; /* For PCH output, training FDI link */ dev_priv->display.fdi_link_train(crtc); @@ -2874,12 +2901,21 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) intel_enable_pch_pll(dev_priv, pipe); 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 */ 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); - else if (pipe == 1 && (temp & TRANSB_DPLL_ENABLE) == 0) + } else if (pipe == 1) { + temp &= ~(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); } @@ -2935,6 +2971,24 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) 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) { struct drm_device *dev = crtc->dev; @@ -3045,13 +3099,13 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) temp = I915_READ(PCH_DPLL_SEL); switch (pipe) { case 0: - temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL); + temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL); break; case 1: temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); break; case 2: - /* FIXME: manage transcoder PLLs? */ + /* C shares PLL A or B */ temp &= ~(TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL); break; default: @@ -3061,7 +3115,8 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) } /* 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 */ reg = FDI_RX_CTL(pipe); @@ -3293,18 +3348,25 @@ static void ironlake_crtc_commit(struct drm_crtc *crtc) ironlake_crtc_enable(crtc); } -void intel_encoder_prepare (struct drm_encoder *encoder) +void intel_encoder_prepare(struct drm_encoder *encoder) { struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; /* lvds has its own version of prepare see intel_lvds_prepare */ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); } -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_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 */ 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) @@ -4478,6 +4540,20 @@ static void sandybridge_update_wm(struct drm_device *dev) 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 * display plane is used. @@ -4584,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) { - 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); } @@ -5107,36 +5185,52 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, 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_mode_config *mode_config = &dev->mode_config; - struct drm_crtc *crtc; struct intel_encoder *encoder; - struct intel_encoder *has_edp_encoder = NULL; u32 temp; 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 */ - list_for_each_entry(crtc, &mode_config->crtc_list, head) { - if (!crtc->enabled) - continue; - - list_for_each_entry(encoder, &mode_config->encoder_list, - base.head) { - if (encoder->base.crtc != crtc) - continue; - - switch (encoder->type) { - case INTEL_OUTPUT_LVDS: - has_lvds = true; - case INTEL_OUTPUT_EDP: - has_edp_encoder = encoder; - break; - } + list_for_each_entry(encoder, &mode_config->encoder_list, + base.head) { + switch (encoder->type) { + case INTEL_OUTPUT_LVDS: + has_panel = true; + has_lvds = true; + break; + case INTEL_OUTPUT_EDP: + has_panel = true; + if (intel_encoder_is_pch_edp(&encoder->base)) + has_pch_edp = true; + else + has_cpu_edp = true; + 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 * enabling. This is only under driver's control after * PCH B stepping, previous chipset stepping should be @@ -5145,43 +5239,102 @@ static void ironlake_update_pch_refclk(struct drm_device *dev) temp = I915_READ(PCH_DREF_CONTROL); /* Always enable nonspread source */ 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); - udelay(200); + if (has_ck505) + temp |= DREF_NONSPREAD_CK505_ENABLE; + else + temp |= DREF_NONSPREAD_SOURCE_ENABLE; - if (has_edp_encoder) { - if (intel_panel_use_ssc(dev_priv)) { - temp |= DREF_SSC1_ENABLE; - I915_WRITE(PCH_DREF_CONTROL, temp); + if (has_panel) { + temp &= ~DREF_SSC_SOURCE_MASK; + temp |= DREF_SSC_SOURCE_ENABLE; - POSTING_READ(PCH_DREF_CONTROL); - udelay(200); + /* SSC must be turned on before enabling the CPU output */ + 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; /* Enable CPU source on CPU attached eDP */ - if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) { - if (intel_panel_use_ssc(dev_priv)) + if (has_cpu_edp) { + if (intel_panel_use_ssc(dev_priv) && can_ssc) { + DRM_DEBUG_KMS("Using SSC on eDP\n"); temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; + } else temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; - } else { - /* Enable SSC on PCH eDP if needed */ - if (intel_panel_use_ssc(dev_priv)) { - DRM_ERROR("enabling SSC on PCH\n"); - temp |= DREF_SUPERSPREAD_SOURCE_ENABLE; - } - } + } else + temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE; + + I915_WRITE(PCH_DREF_CONTROL, temp); + POSTING_READ(PCH_DREF_CONTROL); + 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, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -5241,16 +5394,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, num_connectors++; } - if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { - 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 */ - } + refclk = ironlake_get_refclk(crtc); /* * Returns a set of divisors for the desired target clock with the given @@ -5377,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, &m_n); - ironlake_update_pch_refclk(dev); - fp = clock.n << 16 | clock.m1 << 8 | clock.m2; if (has_reduced_clock) fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 | @@ -5450,39 +5592,32 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, /* Set up the display plane register */ 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); /* PCH eDP needs FDI, but CPU eDP does not */ - if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { - I915_WRITE(PCH_FP0(pipe), fp); - I915_WRITE(PCH_DPLL(pipe), dpll & ~DPLL_VCO_ENABLE); - - POSTING_READ(PCH_DPLL(pipe)); - udelay(150); - } + if (!intel_crtc->no_pll) { + if (!has_edp_encoder || + intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + I915_WRITE(PCH_FP0(pipe), fp); + I915_WRITE(PCH_DPLL(pipe), dpll & ~DPLL_VCO_ENABLE); - /* enable transcoder DPLL */ - if (HAS_PCH_CPT(dev)) { - temp = I915_READ(PCH_DPLL_SEL); - switch (pipe) { - case 0: - temp |= TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL; - break; - case 1: - temp |= TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL; - break; - case 2: - /* FIXME: manage transcoder PLLs? */ - temp |= TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL; - break; - default: - BUG(); + POSTING_READ(PCH_DPLL(pipe)); + udelay(150); + } + } else { + if (dpll == (I915_READ(PCH_DPLL(0)) & 0x7fffffff) && + fp == I915_READ(PCH_FP0(0))) { + intel_crtc->use_pll_a = true; + DRM_DEBUG_KMS("using pipe a dpll\n"); + } else if (dpll == (I915_READ(PCH_DPLL(1)) & 0x7fffffff) && + fp == I915_READ(PCH_FP0(1))) { + intel_crtc->use_pll_a = false; + DRM_DEBUG_KMS("using pipe b dpll\n"); + } else { + DRM_DEBUG_KMS("no matching PLL configuration for pipe 2\n"); + return -EINVAL; } - 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. @@ -5492,17 +5627,13 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, if (is_lvds) { temp = I915_READ(PCH_LVDS); temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; - if (pipe == 1) { - if (HAS_PCH_CPT(dev)) - temp |= PORT_TRANS_B_SEL_CPT; - else - temp |= LVDS_PIPEB_SELECT; - } else { - if (HAS_PCH_CPT(dev)) - temp &= ~PORT_TRANS_SEL_MASK; - else - temp &= ~LVDS_PIPEB_SELECT; - } + if (HAS_PCH_CPT(dev)) + temp |= PORT_TRANS_SEL_CPT(pipe); + else if (pipe == 1) + temp |= LVDS_PIPEB_SELECT; + else + temp &= ~LVDS_PIPEB_SELECT; + /* set the corresponsding LVDS_BORDER bit */ temp |= dev_priv->lvds_border_bits; /* Set the B0-B3 data pairs corresponding to whether we're going to @@ -5552,8 +5683,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(TRANSDPLINK_N1(pipe), 0); } - if (!has_edp_encoder || - intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + if (!intel_crtc->no_pll && + (!has_edp_encoder || + intel_encoder_is_pch_edp(&has_edp_encoder->base))) { I915_WRITE(PCH_DPLL(pipe), dpll); /* Wait for the clocks to stabilize. */ @@ -5569,18 +5701,20 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, } intel_crtc->lowfreq_avail = false; - if (is_lvds && has_reduced_clock && i915_powersave) { - I915_WRITE(PCH_FP1(pipe), fp2); - intel_crtc->lowfreq_avail = true; - if (HAS_PIPE_CXSR(dev)) { - DRM_DEBUG_KMS("enabling CxSR downclocking\n"); - pipeconf |= PIPECONF_CXSR_DOWNCLOCK; - } - } else { - I915_WRITE(PCH_FP1(pipe), fp); - if (HAS_PIPE_CXSR(dev)) { - DRM_DEBUG_KMS("disabling CxSR downclocking\n"); - pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; + if (!intel_crtc->no_pll) { + if (is_lvds && has_reduced_clock && i915_powersave) { + I915_WRITE(PCH_FP1(pipe), fp2); + intel_crtc->lowfreq_avail = true; + if (HAS_PIPE_CXSR(dev)) { + DRM_DEBUG_KMS("enabling CxSR downclocking\n"); + pipeconf |= PIPECONF_CXSR_DOWNCLOCK; + } + } else { + I915_WRITE(PCH_FP1(pipe), fp); + if (HAS_PIPE_CXSR(dev)) { + DRM_DEBUG_KMS("disabling CxSR downclocking\n"); + pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; + } } } @@ -5677,6 +5811,131 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, return ret; } +static void g4x_write_eld(struct drm_connector *connector, + struct drm_crtc *crtc) +{ + struct drm_i915_private *dev_priv = connector->dev->dev_private; + uint8_t *eld = connector->eld; + uint32_t eldv; + uint32_t len; + uint32_t i; + + i = I915_READ(G4X_AUD_VID_DID); + + if (i == INTEL_AUDIO_DEVBLC || i == INTEL_AUDIO_DEVCL) + eldv = G4X_ELDV_DEVCL_DEVBLC; + else + eldv = G4X_ELDV_DEVCTG; + + i = I915_READ(G4X_AUD_CNTL_ST); + i &= ~(eldv | G4X_ELD_ADDR); + len = (i >> 9) & 0x1f; /* ELD buffer size */ + I915_WRITE(G4X_AUD_CNTL_ST, i); + + if (!eld[0]) + return; + + len = min_t(uint8_t, eld[2], len); + DRM_DEBUG_DRIVER("ELD size %d\n", len); + for (i = 0; i < len; i++) + I915_WRITE(G4X_HDMIW_HDMIEDID, *((uint32_t *)eld + i)); + + i = I915_READ(G4X_AUD_CNTL_ST); + i |= eldv; + I915_WRITE(G4X_AUD_CNTL_ST, i); +} + +static void ironlake_write_eld(struct drm_connector *connector, + struct drm_crtc *crtc) +{ + struct drm_i915_private *dev_priv = connector->dev->dev_private; + uint8_t *eld = connector->eld; + uint32_t eldv; + uint32_t i; + int len; + int hdmiw_hdmiedid; + int aud_cntl_st; + int aud_cntrl_st2; + + if (IS_IVYBRIDGE(connector->dev)) { + hdmiw_hdmiedid = GEN7_HDMIW_HDMIEDID_A; + aud_cntl_st = GEN7_AUD_CNTRL_ST_A; + aud_cntrl_st2 = GEN7_AUD_CNTRL_ST2; + } else { + hdmiw_hdmiedid = GEN5_HDMIW_HDMIEDID_A; + aud_cntl_st = GEN5_AUD_CNTL_ST_A; + aud_cntrl_st2 = GEN5_AUD_CNTL_ST2; + } + + i = to_intel_crtc(crtc)->pipe; + hdmiw_hdmiedid += i * 0x100; + aud_cntl_st += i * 0x100; + + DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(i)); + + i = I915_READ(aud_cntl_st); + i = (i >> 29) & 0x3; /* DIP_Port_Select, 0x1 = PortB */ + if (!i) { + DRM_DEBUG_DRIVER("Audio directed to unknown port\n"); + /* operate blindly on all ports */ + eldv = GEN5_ELD_VALIDB; + eldv |= GEN5_ELD_VALIDB << 4; + eldv |= GEN5_ELD_VALIDB << 8; + } else { + DRM_DEBUG_DRIVER("ELD on port %c\n", 'A' + i); + eldv = GEN5_ELD_VALIDB << ((i - 1) * 4); + } + + i = I915_READ(aud_cntrl_st2); + i &= ~eldv; + I915_WRITE(aud_cntrl_st2, i); + + if (!eld[0]) + return; + + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { + DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); + eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ + } + + i = I915_READ(aud_cntl_st); + i &= ~GEN5_ELD_ADDRESS; + I915_WRITE(aud_cntl_st, i); + + len = min_t(uint8_t, eld[2], 21); /* 84 bytes of hw ELD buffer */ + DRM_DEBUG_DRIVER("ELD size %d\n", len); + for (i = 0; i < len; i++) + I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i)); + + i = I915_READ(aud_cntrl_st2); + i |= eldv; + I915_WRITE(aud_cntrl_st2, i); +} + +void intel_write_eld(struct drm_encoder *encoder, + struct drm_display_mode *mode) +{ + struct drm_crtc *crtc = encoder->crtc; + struct drm_connector *connector; + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + connector = drm_select_eld(encoder, mode); + if (!connector) + return; + + DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n", + connector->base.id, + drm_get_connector_name(connector), + connector->encoder->base.id, + drm_get_encoder_name(connector->encoder)); + + connector->eld[6] = drm_av_sync_delay(connector, mode) / 2; + + if (dev_priv->display.write_eld) + dev_priv->display.write_eld(connector, crtc); +} + /** Loads the palette/gamma unit for the CRTC with the prepared values */ void intel_crtc_load_lut(struct drm_crtc *crtc) { @@ -5758,6 +6017,31 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 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... */ static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on) @@ -5805,11 +6089,16 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, if (!visible && !intel_crtc->cursor_visible) return; - I915_WRITE(CURPOS(pipe), pos); - if (IS_845G(dev) || IS_I865G(dev)) - i845_update_cursor(crtc, base); - else - i9xx_update_cursor(crtc, base); + if (IS_IVYBRIDGE(dev)) { + I915_WRITE(CURPOS_IVB(pipe), pos); + ivb_update_cursor(crtc, base); + } else { + 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) intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj); @@ -7071,6 +7360,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) intel_crtc->bpp = 24; /* default for pre-Ironlake */ 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.commit = ironlake_crtc_commit; } else { @@ -7250,6 +7541,9 @@ static void intel_setup_outputs(struct drm_device *dev) /* disable all the possible outputs/crtcs before entering KMS mode */ 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) @@ -7494,6 +7788,10 @@ void gen6_disable_rps(struct drm_device *dev) I915_WRITE(GEN6_RPNSWREQ, 1 << 31); I915_WRITE(GEN6_PMINTRMSK, 0xffffffff); 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); dev_priv->pm_iir = 0; @@ -8154,7 +8452,7 @@ static void intel_init_display(struct drm_device *dev) } /* Returns the core display clock speed */ - if (IS_I945G(dev) || (IS_G33(dev) && ! IS_PINEVIEW_M(dev))) + if (IS_I945G(dev) || (IS_G33(dev) && !IS_PINEVIEW_M(dev))) dev_priv->display.get_display_clock_speed = i945_get_display_clock_speed; else if (IS_I915G(dev)) @@ -8193,6 +8491,7 @@ static void intel_init_display(struct drm_device *dev) } dev_priv->display.fdi_link_train = ironlake_fdi_link_train; dev_priv->display.init_clock_gating = ironlake_init_clock_gating; + dev_priv->display.write_eld = ironlake_write_eld; } else if (IS_GEN6(dev)) { if (SNB_READ_WM0_LATENCY()) { dev_priv->display.update_wm = sandybridge_update_wm; @@ -8203,6 +8502,7 @@ static void intel_init_display(struct drm_device *dev) } dev_priv->display.fdi_link_train = gen6_fdi_link_train; dev_priv->display.init_clock_gating = gen6_init_clock_gating; + dev_priv->display.write_eld = ironlake_write_eld; } else if (IS_IVYBRIDGE(dev)) { /* FIXME: detect B0+ stepping and use auto training */ dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train; @@ -8214,7 +8514,7 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.update_wm = NULL; } dev_priv->display.init_clock_gating = ivybridge_init_clock_gating; - + dev_priv->display.write_eld = ironlake_write_eld; } else dev_priv->display.update_wm = NULL; } else if (IS_PINEVIEW(dev)) { @@ -8225,7 +8525,7 @@ static void intel_init_display(struct drm_device *dev) DRM_INFO("failed to find known CxSR latency " "(found ddr%s fsb freq %d, mem freq %d), " "disabling CxSR\n", - (dev_priv->is_ddr3 == 1) ? "3": "2", + (dev_priv->is_ddr3 == 1) ? "3" : "2", dev_priv->fsb_freq, dev_priv->mem_freq); /* Disable CxSR and never update its watermark again */ pineview_disable_cxsr(dev); @@ -8234,6 +8534,7 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.update_wm = pineview_update_wm; dev_priv->display.init_clock_gating = gen3_init_clock_gating; } else if (IS_G4X(dev)) { + dev_priv->display.write_eld = g4x_write_eld; dev_priv->display.update_wm = g4x_update_wm; dev_priv->display.init_clock_gating = g4x_init_clock_gating; } else if (IS_GEN4(dev)) { @@ -8294,7 +8595,7 @@ static void intel_init_display(struct drm_device *dev) * resume, or other times. This quirk makes sure that's the case for * affected systems. */ -static void quirk_pipea_force (struct drm_device *dev) +static void quirk_pipea_force(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -8322,7 +8623,7 @@ struct intel_quirk intel_quirks[] = { /* HP Compaq 2730p needs pipe A force quirk (LP: #291555) */ { 0x2a42, 0x103c, 0x30eb, quirk_pipea_force }, /* HP Mini needs pipe A force quirk (LP: #322104) */ - { 0x27ae,0x103c, 0x361a, quirk_pipea_force }, + { 0x27ae, 0x103c, 0x361a, quirk_pipea_force }, /* Thinkpad R31 needs pipe A force quirk */ { 0x3577, 0x1014, 0x0505, quirk_pipea_force }, @@ -8488,6 +8789,7 @@ void intel_modeset_cleanup(struct drm_device *dev) * enqueue unpin/hotplug work. */ drm_irq_uninstall(dev); cancel_work_sync(&dev_priv->hotplug_work); + cancel_work_sync(&dev_priv->rps_work); /* flush any delayed tasks or pending work */ flush_scheduled_work(); @@ -8573,7 +8875,7 @@ struct intel_display_error_state { struct intel_display_error_state * intel_display_capture_error_state(struct drm_device *dev) { - drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_private_t *dev_priv = dev->dev_private; struct intel_display_error_state *error; int i; @@ -8589,7 +8891,7 @@ intel_display_capture_error_state(struct drm_device *dev) error->plane[i].control = I915_READ(DSPCNTR(i)); error->plane[i].stride = I915_READ(DSPSTRIDE(i)); error->plane[i].size = I915_READ(DSPSIZE(i)); - error->plane[i].pos= I915_READ(DSPPOS(i)); + error->plane[i].pos = I915_READ(DSPPOS(i)); error->plane[i].addr = I915_READ(DSPADDR(i)); if (INTEL_INFO(dev)->gen >= 4) { error->plane[i].surface = I915_READ(DSPSURF(i)); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 44fef5e1c490..fc1a0832af4f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -36,7 +36,7 @@ #include "i915_drv.h" #include "drm_dp_helper.h" - +#define DP_RECEIVER_CAP_SIZE 0xf #define DP_LINK_STATUS_SIZE 6 #define DP_LINK_CHECK_TIMEOUT (10 * 1000) @@ -53,12 +53,21 @@ struct intel_dp { int dpms_mode; uint8_t link_bw; uint8_t lane_count; - uint8_t dpcd[8]; + uint8_t dpcd[DP_RECEIVER_CAP_SIZE]; struct i2c_adapter adapter; struct i2c_algo_dp_aux_data algo; bool is_pch_edp; uint8_t train_set[4]; 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) 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) { return container_of(encoder, struct intel_dp, base.base); @@ -121,7 +141,7 @@ static void intel_dp_complete_link_train(struct intel_dp *intel_dp); static void intel_dp_link_down(struct intel_dp *intel_dp); void -intel_edp_link_config (struct intel_encoder *intel_encoder, +intel_edp_link_config(struct intel_encoder *intel_encoder, int *lane_num, int *link_bw) { struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base); @@ -175,9 +195,25 @@ intel_dp_link_clock(uint8_t link_bw) 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 -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 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 if (intel_crtc) bpp = intel_crtc->bpp; - return (pixel_clock * bpp + 7) / 8; + return (pixel_clock * bpp + 9) / 10; } static int @@ -200,24 +236,19 @@ intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { 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_lanes = intel_dp_max_lane_count(intel_dp); - if (is_edp(intel_dp) && dev_priv->panel_fixed_mode) { - if (mode->hdisplay > dev_priv->panel_fixed_mode->hdisplay) + if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { + if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay) return MODE_PANEL; - if (mode->vdisplay > dev_priv->panel_fixed_mode->vdisplay) + if (mode->vdisplay > intel_dp->panel_fixed_mode->vdisplay) return MODE_PANEL; } - /* only refuse the mode on non eDP since we have seen some weird eDP panels - which are outside spec tolerances but somehow work by magic */ - 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))) + if (intel_dp_link_required(intel_dp, mode->clock) + > intel_dp_max_data_rate(max_link_clock, max_lanes)) return MODE_CLOCK_HIGH; if (mode->clock < 10000) @@ -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 intel_dp_aux_ch(struct intel_dp *intel_dp, uint8_t *send, int send_bytes, @@ -295,6 +358,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, uint32_t aux_clock_divider; int try, precharge; + intel_dp_check_edp(intel_dp); /* The clock divider is based off the hrawclk, * and would like to run at 2MHz. So, take the * hrawclk value and divide by 2 and use that @@ -302,7 +366,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, * Note that PCH attached eDP panels should use a 125MHz input * clock divider. */ - if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) { + if (is_cpu_edp(intel_dp)) { if (IS_GEN6(dev)) aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */ else @@ -337,7 +401,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, for (i = 0; i < send_bytes; i += 4) I915_WRITE(ch_data + i, pack_aux(send + i, send_bytes - i)); - + /* Send the command and wait for it to complete */ I915_WRITE(ch_ctl, DP_AUX_CH_CTL_SEND_BUSY | @@ -354,7 +418,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, break; udelay(100); } - + /* Clear done status and any errors */ I915_WRITE(ch_ctl, status | @@ -390,7 +454,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); if (recv_bytes > recv_size) recv_bytes = recv_size; - + for (i = 0; i < recv_bytes; i += 4) unpack_aux(I915_READ(ch_data + i), recv + i, recv_bytes - i); @@ -408,6 +472,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp, int msg_bytes; uint8_t ack; + intel_dp_check_edp(intel_dp); if (send_bytes > 16) return -1; msg[0] = AUX_NATIVE_WRITE << 4; @@ -450,6 +515,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, uint8_t ack; int ret; + intel_dp_check_edp(intel_dp); msg[0] = AUX_NATIVE_READ << 4; msg[1] = address >> 8; msg[2] = address & 0xff; @@ -493,6 +559,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, int reply_bytes; int ret; + intel_dp_check_edp(intel_dp); /* Set up the command byte */ if (mode & MODE_I2C_READ) msg[0] = AUX_I2C_READ << 4; @@ -573,24 +640,32 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, 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 intel_dp_i2c_init(struct intel_dp *intel_dp, struct intel_connector *intel_connector, const char *name) { + int ret; + DRM_DEBUG_KMS("i2c_init %s\n", name); intel_dp->algo.running = false; intel_dp->algo.address = 0; intel_dp->algo.aux_ch = intel_dp_i2c_aux_ch; - memset(&intel_dp->adapter, '\0', sizeof (intel_dp->adapter)); + memset(&intel_dp->adapter, '\0', sizeof(intel_dp->adapter)); intel_dp->adapter.owner = THIS_MODULE; intel_dp->adapter.class = I2C_CLASS_DDC; - strncpy (intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1); + strncpy(intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1); intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0'; intel_dp->adapter.algo_data = &intel_dp->algo; 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 @@ -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_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct intel_dp *intel_dp = enc_to_intel_dp(encoder); int lane_count, clock; 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; static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; - if (is_edp(intel_dp) && dev_priv->panel_fixed_mode) { - intel_fixed_panel_mode(dev_priv->panel_fixed_mode, adjusted_mode); + if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { + intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode); intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN, mode, adjusted_mode); /* * the mode->clock is used to calculate the Data&Link M/N * 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 (clock = 0; clock <= max_clock; clock++) { 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) { intel_dp->link_bw = bws[clock]; intel_dp->lane_count = lane_count; @@ -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; } @@ -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 intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_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 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 |= intel_dp->color_range; @@ -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) 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; else intel_dp->DP |= DP_LINK_TRAIN_OFF; @@ -773,8 +845,12 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, intel_dp->DP |= DP_PORT_WIDTH_4; break; } - if (intel_dp->has_audio) + if (intel_dp->has_audio) { + DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n", + pipe_name(intel_crtc->pipe)); intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE; + intel_write_eld(encoder, adjusted_mode); + } memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); intel_dp->link_configuration[0] = intel_dp->link_bw; @@ -794,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)) 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 */ intel_dp->DP |= DP_PLL_ENABLE; if (adjusted_mode->clock < 200000) @@ -804,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) { struct drm_device *dev = intel_dp->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 pp; - /* - * If the panel wasn't on, make sure there's not a currently - * active PP sequence before enabling AUX VDD. - */ - if (!(I915_READ(PCH_PP_STATUS) & PP_ON)) - msleep(dev_priv->panel_t3); + if (!is_edp(intel_dp)) + return; + DRM_DEBUG_KMS("Turn eDP VDD on\n"); + + 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 &= ~PANEL_UNLOCK_MASK; + pp |= PANEL_UNLOCK_REGS; pp |= EDP_FORCE_VDD; I915_WRITE(PCH_PP_CONTROL, pp); 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_i915_private *dev_priv = dev->dev_private; u32 pp; - pp = I915_READ(PCH_PP_CONTROL); - pp &= ~EDP_FORCE_VDD; - I915_WRITE(PCH_PP_CONTROL, pp); - POSTING_READ(PCH_PP_CONTROL); + if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) { + pp = I915_READ(PCH_PP_CONTROL); + pp &= ~PANEL_UNLOCK_MASK; + 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; + } +} + +static void ironlake_panel_vdd_work(struct work_struct *__work) +{ + 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; - /* Make sure sequencer is idle before allowing subsequent activity */ - msleep(dev_priv->panel_t12); + 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 */ -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_i915_private *dev_priv = dev->dev_private; u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE; - if (I915_READ(PCH_PP_STATUS) & PP_ON) - return true; + if (!is_edp(intel_dp)) + return; + if (ironlake_edp_have_panel_power(intel_dp)) + return; + ironlake_wait_panel_off(intel_dp); 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 &= ~PANEL_POWER_RESET; - I915_WRITE(PCH_PP_CONTROL, pp); - POSTING_READ(PCH_PP_CONTROL); - - pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON; + pp |= POWER_TARGET_ON; I915_WRITE(PCH_PP_CONTROL, pp); POSTING_READ(PCH_PP_CONTROL); @@ -864,44 +1032,64 @@ static bool ironlake_edp_panel_on (struct intel_dp *intel_dp) DRM_ERROR("panel on wait timed out: 0x%08x\n", I915_READ(PCH_PP_STATUS)); - pp |= PANEL_POWER_RESET; /* restore panel reset bit */ - I915_WRITE(PCH_PP_CONTROL, pp); - POSTING_READ(PCH_PP_CONTROL); - - return false; + if (IS_GEN5(dev)) { + pp |= PANEL_POWER_RESET; /* restore panel reset bit */ + I915_WRITE(PCH_PP_CONTROL, pp); + POSTING_READ(PCH_PP_CONTROL); + } } -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; u32 pp, idle_off_mask = PP_ON | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK; + if (!is_edp(intel_dp)) + return; 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 &= ~PANEL_POWER_RESET; - I915_WRITE(PCH_PP_CONTROL, pp); - POSTING_READ(PCH_PP_CONTROL); + intel_dp->panel_off_jiffies = jiffies; - pp &= ~POWER_TARGET_ON; - I915_WRITE(PCH_PP_CONTROL, pp); - POSTING_READ(PCH_PP_CONTROL); + if (IS_GEN5(dev)) { + pp &= ~POWER_TARGET_ON; + 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)) - DRM_ERROR("panel off wait timed out: 0x%08x\n", - I915_READ(PCH_PP_STATUS)); + if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000)) + DRM_ERROR("panel off wait timed out: 0x%08x\n", + I915_READ(PCH_PP_STATUS)); - pp |= PANEL_POWER_RESET; /* restore panel reset bit */ - I915_WRITE(PCH_PP_CONTROL, pp); - POSTING_READ(PCH_PP_CONTROL); + pp |= PANEL_POWER_RESET; /* restore panel reset bit */ + I915_WRITE(PCH_PP_CONTROL, pp); + 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; u32 pp; + if (!is_edp(intel_dp)) + return; + DRM_DEBUG_KMS("\n"); /* * If we enable the backlight right away following a panel power @@ -909,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 * allowing it to appear. */ - msleep(300); + msleep(intel_dp->backlight_on_delay); pp = I915_READ(PCH_PP_CONTROL); + pp &= ~PANEL_UNLOCK_MASK; + pp |= PANEL_UNLOCK_REGS; pp |= EDP_BLC_ENABLE; 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; u32 pp; + if (!is_edp(intel_dp)) + return; + DRM_DEBUG_KMS("\n"); pp = I915_READ(PCH_PP_CONTROL); + pp &= ~PANEL_UNLOCK_MASK; + pp |= PANEL_UNLOCK_REGS; pp &= ~EDP_BLC_ENABLE; 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) @@ -986,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) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - struct drm_device *dev = encoder->dev; /* Wake up the sink first */ + ironlake_edp_panel_vdd_on(intel_dp); intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); + ironlake_edp_panel_vdd_off(intel_dp, false); - if (is_edp(intel_dp)) { - ironlake_edp_backlight_off(dev); - ironlake_edp_panel_off(dev); - if (!is_pch_edp(intel_dp)) - ironlake_edp_pll_on(encoder); - else - ironlake_edp_pll_off(encoder); - } + /* Make sure the panel is off before trying to + * change the mode + */ + ironlake_edp_backlight_off(intel_dp); intel_dp_link_down(intel_dp); + ironlake_edp_panel_off(encoder); } static void intel_dp_commit(struct drm_encoder *encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 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); - - if (is_edp(intel_dp)) { - ironlake_edp_panel_on(intel_dp); - ironlake_edp_panel_vdd_off(intel_dp); - } + ironlake_edp_panel_on(intel_dp); + ironlake_edp_panel_vdd_off(intel_dp, true); intel_dp_complete_link_train(intel_dp); - - if (is_edp(intel_dp)) - ironlake_edp_backlight_on(dev); + ironlake_edp_backlight_on(intel_dp); intel_dp->dpms_mode = DRM_MODE_DPMS_ON; + + if (HAS_PCH_CPT(dev)) + intel_cpt_verify_modeset(dev, intel_crtc->pipe); } static void @@ -1034,28 +1229,27 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) uint32_t dp_reg = I915_READ(intel_dp->output_reg); if (mode != DRM_MODE_DPMS_ON) { + ironlake_edp_panel_vdd_on(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_link_down(intel_dp); - if (is_edp(intel_dp)) - ironlake_edp_panel_off(dev); + ironlake_edp_panel_off(encoder); if (is_edp(intel_dp) && !is_pch_edp(intel_dp)) ironlake_edp_pll_off(encoder); + ironlake_edp_panel_vdd_off(intel_dp, false); } 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); if (!(dp_reg & DP_PORT_EN)) { intel_dp_start_link_train(intel_dp); - if (is_edp(intel_dp)) { - ironlake_edp_panel_on(intel_dp); - ironlake_edp_panel_vdd_off(intel_dp); - } + ironlake_edp_panel_on(intel_dp); + ironlake_edp_panel_vdd_off(intel_dp, true); intel_dp_complete_link_train(intel_dp); - } - if (is_edp(intel_dp)) - ironlake_edp_backlight_on(dev); + ironlake_edp_backlight_on(intel_dp); + } else + ironlake_edp_panel_vdd_off(intel_dp, false); + ironlake_edp_backlight_on(intel_dp); } intel_dp->dpms_mode = mode; } @@ -1364,7 +1558,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) DP_LINK_CONFIGURATION_SIZE); 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; else DP &= ~DP_LINK_TRAIN_MASK; @@ -1383,7 +1577,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) 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; else reg = DP | DP_LINK_TRAIN_PAT_1; @@ -1458,7 +1652,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) 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; else reg = DP | DP_LINK_TRAIN_PAT_2; @@ -1499,7 +1693,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) ++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; else reg = DP | DP_LINK_TRAIN_OFF; @@ -1529,7 +1723,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) 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; I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT); } else { @@ -1578,13 +1772,14 @@ intel_dp_link_down(struct intel_dp *intel_dp) I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); POSTING_READ(intel_dp->output_reg); + msleep(intel_dp->panel_power_down_delay); } static bool intel_dp_get_dpcd(struct intel_dp *intel_dp) { if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd, - sizeof (intel_dp->dpcd)) && + sizeof(intel_dp->dpcd)) && (intel_dp->dpcd[DP_DPCD_REV] != 0)) { return true; } @@ -1592,6 +1787,27 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) 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 * 5.1.2: @@ -1604,6 +1820,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) static void intel_dp_check_link_status(struct intel_dp *intel_dp) { + u8 sink_irq_vector; + if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON) return; @@ -1622,6 +1840,20 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) 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)) { DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", drm_get_encoder_name(&intel_dp->base.base)); @@ -1683,6 +1915,31 @@ g4x_dp_detect(struct intel_dp *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. * @@ -1715,7 +1972,7 @@ intel_dp_detect(struct drm_connector *connector, bool force) if (intel_dp->force_audio) { intel_dp->has_audio = intel_dp->force_audio > 0; } else { - edid = drm_get_edid(connector, &intel_dp->adapter); + edid = intel_dp_get_edid(connector, &intel_dp->adapter); if (edid) { intel_dp->has_audio = drm_detect_monitor_audio(edid); connector->display_info.raw_edid = NULL; @@ -1736,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 */ - ret = intel_ddc_get_modes(connector, &intel_dp->adapter); + ret = intel_dp_get_edid_modes(connector, &intel_dp->adapter); 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; list_for_each_entry(newmode, &connector->probed_modes, head) { - if (newmode->type & DRM_MODE_TYPE_PREFERRED) { - dev_priv->panel_fixed_mode = + if ((newmode->type & DRM_MODE_TYPE_PREFERRED)) { + intel_dp->panel_fixed_mode = drm_mode_duplicate(dev, newmode); break; } } } - return ret; } /* if eDP has no EDID, try to use fixed panel mode from VBT */ 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; - 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); return 1; } @@ -1772,7 +2037,7 @@ intel_dp_detect_audio(struct drm_connector *connector) struct edid *edid; bool has_audio = false; - edid = drm_get_edid(connector, &intel_dp->adapter); + edid = intel_dp_get_edid(connector, &intel_dp->adapter); if (edid) { has_audio = drm_detect_monitor_audio(edid); @@ -1839,7 +2104,7 @@ done: } static void -intel_dp_destroy (struct drm_connector *connector) +intel_dp_destroy(struct drm_connector *connector) { struct drm_device *dev = connector->dev; @@ -1857,6 +2122,10 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder) i2c_del_adapter(&intel_dp->adapter); 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); } @@ -1896,7 +2165,7 @@ intel_dp_hot_plug(struct intel_encoder *intel_encoder) /* Return which DP Port should be selected for Transcoder DP control */ int -intel_trans_dp_port_sel (struct drm_crtc *crtc) +intel_trans_dp_port_sel(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_mode_config *mode_config = &dev->mode_config; @@ -1993,10 +2262,13 @@ intel_dp_init(struct drm_device *dev, int output_reg) else if (output_reg == DP_D || output_reg == PCH_DP_D) 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); + 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->doublescan_allowed = 0; @@ -2032,25 +2304,60 @@ intel_dp_init(struct drm_device *dev, int output_reg) break; } - intel_dp_i2c_init(intel_dp, intel_connector, name); - /* Cache some DPCD data in the eDP case */ if (is_edp(intel_dp)) { 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_off = I915_READ(PCH_PP_OFF_DELAYS); pp_div = I915_READ(PCH_PP_DIVISOR); - /* Get T3 & T12 values (note: VESA not bspec terminology) */ - dev_priv->panel_t3 = (pp_on & 0x1fff0000) >> 16; - dev_priv->panel_t3 /= 10; /* t3 in 100us units */ - dev_priv->panel_t12 = pp_div & 0xf; - dev_priv->panel_t12 *= 100; /* t12 in 100ms units */ + /* Pull timing values out of registers */ + cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >> + PANEL_POWER_UP_DELAY_SHIFT; + + 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); 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 (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) dev_priv->no_aux_handshake = @@ -2065,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; 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; intel_panel_setup_backlight(dev); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index fe1099d8817e..bd9a604b73da 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -34,7 +34,7 @@ #define _wait_for(COND, MS, W) ({ \ unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \ int ret__ = 0; \ - while (! (COND)) { \ + while (!(COND)) { \ if (time_after(jiffies, timeout__)) { \ ret__ = -ETIMEDOUT; \ break; \ @@ -49,10 +49,10 @@ #define MSLEEP(x) do { \ if (in_dbg_master()) \ - mdelay(x); \ + mdelay(x); \ else \ msleep(x); \ -} while(0) +} while (0) #define KHz(x) (1000*x) #define MHz(x) KHz(1000*x) @@ -171,6 +171,9 @@ struct intel_crtc { int16_t cursor_width, cursor_height; bool cursor_visible; 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) @@ -184,7 +187,7 @@ struct intel_crtc { #define DIP_VERSION_AVI 0x2 #define DIP_LEN_AVI 13 -#define DIP_TYPE_SPD 0x3 +#define DIP_TYPE_SPD 0x83 #define DIP_VERSION_SPD 0x1 #define DIP_LEN_SPD 25 #define DIP_SPD_UNKNOWN 0 @@ -284,7 +287,7 @@ void intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); extern bool intel_dpd_is_edp(struct drm_device *dev); -extern void intel_edp_link_config (struct intel_encoder *, int *, int *); +extern void intel_edp_link_config(struct intel_encoder *, int *, int *); extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder); /* intel_panel.c */ @@ -304,8 +307,8 @@ extern void intel_panel_destroy_backlight(struct drm_device *dev); extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); extern void intel_crtc_load_lut(struct drm_crtc *crtc); -extern void intel_encoder_prepare (struct drm_encoder *encoder); -extern void intel_encoder_commit (struct drm_encoder *encoder); +extern void intel_encoder_prepare(struct drm_encoder *encoder); +extern void intel_encoder_commit(struct drm_encoder *encoder); extern void intel_encoder_destroy(struct drm_encoder *encoder); static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector) @@ -377,4 +380,8 @@ extern void intel_fb_output_poll_changed(struct drm_device *dev); extern void intel_fb_restore_mode(struct drm_device *dev); extern void intel_init_clock_gating(struct drm_device *dev); +extern void intel_write_eld(struct drm_encoder *encoder, + struct drm_display_mode *mode); +extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe); + #endif /* __INTEL_DRV_H__ */ diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 226ba830f383..d4f5a0b2120d 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -69,8 +69,7 @@ void intel_dip_infoframe_csum(struct dip_infoframe *frame) frame->checksum = 0; frame->ecc = 0; - /* Header isn't part of the checksum */ - for (i = 5; i < frame->len; i++) + for (i = 0; i < frame->len + DIP_HEADER_SIZE; i++) sum += data[i]; frame->checksum = 0x100 - sum; @@ -104,7 +103,7 @@ static u32 intel_infoframe_flags(struct dip_infoframe *frame) flags |= VIDEO_DIP_ENABLE_AVI | VIDEO_DIP_FREQ_VSYNC; break; case DIP_TYPE_SPD: - flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_2VSYNC; + flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_VSYNC; break; default: DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); @@ -165,9 +164,9 @@ static void ironlake_write_infoframe(struct drm_encoder *encoder, 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) { I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); @@ -245,16 +244,17 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, sdvox |= HDMI_MODE_SELECT; if (intel_hdmi->has_audio) { + DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n", + pipe_name(intel_crtc->pipe)); sdvox |= SDVO_AUDIO_ENABLE; sdvox |= SDVO_NULL_PACKETS_DURING_VSYNC; + intel_write_eld(encoder, adjusted_mode); } - if (intel_crtc->pipe == 1) { - if (HAS_PCH_CPT(dev)) - sdvox |= PORT_TRANS_B_SEL_CPT; - else - sdvox |= SDVO_PIPE_B_SELECT; - } + if (HAS_PCH_CPT(dev)) + sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe); + else if (intel_crtc->pipe == 1) + sdvox |= SDVO_PIPE_B_SELECT; I915_WRITE(intel_hdmi->sdvox_reg, sdvox); POSTING_READ(intel_hdmi->sdvox_reg); @@ -486,6 +486,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) struct intel_encoder *intel_encoder; struct intel_connector *intel_connector; struct intel_hdmi *intel_hdmi; + int i; intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL); if (!intel_hdmi) @@ -511,7 +512,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) connector->polled = DRM_CONNECTOR_POLL_HPD; connector->interlace_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. */ if (sdvox_reg == SDVOB) { @@ -538,10 +539,14 @@ void intel_hdmi_init(struct drm_device *dev, int 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; - else + I915_WRITE(VIDEO_DIP_CTL, 0); + } else { 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); diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index d98cee60b602..9ed5380e5a53 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -422,13 +422,7 @@ void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed) { struct intel_gmbus *bus = to_intel_gmbus(adapter); - /* speed: - * 0x0 = 100 KHz - * 0x1 = 50 KHz - * 0x2 = 400 KHz - * 0x3 = 1000 Khz - */ - bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | (speed << 8); + bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | speed; } void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 31da77f5c051..42f165a520de 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -888,9 +888,11 @@ bool intel_lvds_init(struct drm_device *dev) intel_encoder->type = INTEL_OUTPUT_LVDS; intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); - intel_encoder->crtc_mask = (1 << 1); - if (INTEL_INFO(dev)->gen >= 5) - intel_encoder->crtc_mask |= (1 << 0); + if (HAS_PCH_SPLIT(dev)) + intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); + else + intel_encoder->crtc_mask = (1 << 1); + drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); connector->display_info.subpixel_order = SubPixelHorizontalRGB; diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index 3b26a3ba02dd..be2c6fe07d12 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c @@ -26,6 +26,7 @@ #include <linux/slab.h> #include <linux/i2c.h> #include <linux/fb.h> +#include <drm/drm_edid.h> #include "drmP.h" #include "intel_drv.h" #include "i915_drv.h" @@ -74,6 +75,7 @@ int intel_ddc_get_modes(struct drm_connector *connector, if (edid) { drm_mode_connector_update_edid_property(connector, edid); ret = drm_add_edid_modes(connector, edid); + drm_edid_to_eld(connector, edid); connector->display_info.raw_edid = NULL; kfree(edid); } diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index b8e8158bb16e..289140bc83cb 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -51,61 +51,61 @@ #define MBOX_ASLE (1<<2) struct opregion_header { - u8 signature[16]; - u32 size; - u32 opregion_ver; - u8 bios_ver[32]; - u8 vbios_ver[16]; - u8 driver_ver[16]; - u32 mboxes; - u8 reserved[164]; + u8 signature[16]; + u32 size; + u32 opregion_ver; + u8 bios_ver[32]; + u8 vbios_ver[16]; + u8 driver_ver[16]; + u32 mboxes; + u8 reserved[164]; } __attribute__((packed)); /* OpRegion mailbox #1: public ACPI methods */ struct opregion_acpi { - u32 drdy; /* driver readiness */ - u32 csts; /* notification status */ - u32 cevt; /* current event */ - u8 rsvd1[20]; - u32 didl[8]; /* supported display devices ID list */ - u32 cpdl[8]; /* currently presented display list */ - u32 cadl[8]; /* currently active display list */ - u32 nadl[8]; /* next active devices list */ - u32 aslp; /* ASL sleep time-out */ - u32 tidx; /* toggle table index */ - u32 chpd; /* current hotplug enable indicator */ - u32 clid; /* current lid state*/ - u32 cdck; /* current docking state */ - u32 sxsw; /* Sx state resume */ - u32 evts; /* ASL supported events */ - u32 cnot; /* current OS notification */ - u32 nrdy; /* driver status */ - u8 rsvd2[60]; + u32 drdy; /* driver readiness */ + u32 csts; /* notification status */ + u32 cevt; /* current event */ + u8 rsvd1[20]; + u32 didl[8]; /* supported display devices ID list */ + u32 cpdl[8]; /* currently presented display list */ + u32 cadl[8]; /* currently active display list */ + u32 nadl[8]; /* next active devices list */ + u32 aslp; /* ASL sleep time-out */ + u32 tidx; /* toggle table index */ + u32 chpd; /* current hotplug enable indicator */ + u32 clid; /* current lid state*/ + u32 cdck; /* current docking state */ + u32 sxsw; /* Sx state resume */ + u32 evts; /* ASL supported events */ + u32 cnot; /* current OS notification */ + u32 nrdy; /* driver status */ + u8 rsvd2[60]; } __attribute__((packed)); /* OpRegion mailbox #2: SWSCI */ struct opregion_swsci { - u32 scic; /* SWSCI command|status|data */ - u32 parm; /* command parameters */ - u32 dslp; /* driver sleep time-out */ - u8 rsvd[244]; + u32 scic; /* SWSCI command|status|data */ + u32 parm; /* command parameters */ + u32 dslp; /* driver sleep time-out */ + u8 rsvd[244]; } __attribute__((packed)); /* OpRegion mailbox #3: ASLE */ struct opregion_asle { - u32 ardy; /* driver readiness */ - u32 aslc; /* ASLE interrupt command */ - u32 tche; /* technology enabled indicator */ - u32 alsi; /* current ALS illuminance reading */ - u32 bclp; /* backlight brightness to set */ - u32 pfit; /* panel fitting state */ - u32 cblv; /* current brightness level */ - u16 bclm[20]; /* backlight level duty cycle mapping table */ - u32 cpfm; /* current panel fitting mode */ - u32 epfm; /* enabled panel fitting modes */ - u8 plut[74]; /* panel LUT and identifier */ - u32 pfmb; /* PWM freq and min brightness */ - u8 rsvd[102]; + u32 ardy; /* driver readiness */ + u32 aslc; /* ASLE interrupt command */ + u32 tche; /* technology enabled indicator */ + u32 alsi; /* current ALS illuminance reading */ + u32 bclp; /* backlight brightness to set */ + u32 pfit; /* panel fitting state */ + u32 cblv; /* current brightness level */ + u16 bclm[20]; /* backlight level duty cycle mapping table */ + u32 cpfm; /* current panel fitting mode */ + u32 epfm; /* enabled panel fitting modes */ + u8 plut[74]; /* panel LUT and identifier */ + u32 pfmb; /* PWM freq and min brightness */ + u8 rsvd[102]; } __attribute__((packed)); /* ASLE irq request bits */ @@ -361,7 +361,7 @@ static void intel_didl_outputs(struct drm_device *dev) list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) { if (i >= 8) { - dev_printk (KERN_ERR, &dev->pdev->dev, + dev_printk(KERN_ERR, &dev->pdev->dev, "More than 8 outputs detected\n"); return; } @@ -387,7 +387,7 @@ blind_set: list_for_each_entry(connector, &dev->mode_config.connector_list, head) { int output_type = ACPI_OTHER_OUTPUT; if (i >= 8) { - dev_printk (KERN_ERR, &dev->pdev->dev, + dev_printk(KERN_ERR, &dev->pdev->dev, "More than 8 outputs detected\n"); return; } diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index d36038086826..cdf17d4cc1f7 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -117,57 +117,57 @@ /* memory bufferd overlay registers */ struct overlay_registers { - u32 OBUF_0Y; - u32 OBUF_1Y; - u32 OBUF_0U; - u32 OBUF_0V; - u32 OBUF_1U; - u32 OBUF_1V; - u32 OSTRIDE; - u32 YRGB_VPH; - u32 UV_VPH; - u32 HORZ_PH; - u32 INIT_PHS; - u32 DWINPOS; - u32 DWINSZ; - u32 SWIDTH; - u32 SWIDTHSW; - u32 SHEIGHT; - u32 YRGBSCALE; - u32 UVSCALE; - u32 OCLRC0; - u32 OCLRC1; - u32 DCLRKV; - u32 DCLRKM; - u32 SCLRKVH; - u32 SCLRKVL; - u32 SCLRKEN; - u32 OCONFIG; - u32 OCMD; - u32 RESERVED1; /* 0x6C */ - u32 OSTART_0Y; - u32 OSTART_1Y; - u32 OSTART_0U; - u32 OSTART_0V; - u32 OSTART_1U; - u32 OSTART_1V; - u32 OTILEOFF_0Y; - u32 OTILEOFF_1Y; - u32 OTILEOFF_0U; - u32 OTILEOFF_0V; - u32 OTILEOFF_1U; - u32 OTILEOFF_1V; - u32 FASTHSCALE; /* 0xA0 */ - u32 UVSCALEV; /* 0xA4 */ - u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */ - u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */ - u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES]; - u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */ - u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES]; - u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */ - u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES]; - u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */ - u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES]; + u32 OBUF_0Y; + u32 OBUF_1Y; + u32 OBUF_0U; + u32 OBUF_0V; + u32 OBUF_1U; + u32 OBUF_1V; + u32 OSTRIDE; + u32 YRGB_VPH; + u32 UV_VPH; + u32 HORZ_PH; + u32 INIT_PHS; + u32 DWINPOS; + u32 DWINSZ; + u32 SWIDTH; + u32 SWIDTHSW; + u32 SHEIGHT; + u32 YRGBSCALE; + u32 UVSCALE; + u32 OCLRC0; + u32 OCLRC1; + u32 DCLRKV; + u32 DCLRKM; + u32 SCLRKVH; + u32 SCLRKVL; + u32 SCLRKEN; + u32 OCONFIG; + u32 OCMD; + u32 RESERVED1; /* 0x6C */ + u32 OSTART_0Y; + u32 OSTART_1Y; + u32 OSTART_0U; + u32 OSTART_0V; + u32 OSTART_1U; + u32 OSTART_1V; + u32 OTILEOFF_0Y; + u32 OTILEOFF_1Y; + u32 OTILEOFF_0U; + u32 OTILEOFF_0V; + u32 OTILEOFF_1U; + u32 OTILEOFF_1V; + u32 FASTHSCALE; /* 0xA0 */ + u32 UVSCALEV; /* 0xA4 */ + u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */ + u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */ + u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES]; + u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */ + u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES]; + u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */ + u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES]; + u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */ + u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES]; }; struct intel_overlay { @@ -192,7 +192,7 @@ struct intel_overlay { static struct overlay_registers * intel_overlay_map_regs(struct intel_overlay *overlay) { - drm_i915_private_t *dev_priv = overlay->dev->dev_private; + drm_i915_private_t *dev_priv = overlay->dev->dev_private; struct overlay_registers *regs; if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) @@ -264,7 +264,7 @@ i830_activate_pipe_a(struct drm_device *dev) mode = drm_mode_duplicate(dev, &vesa_640x480); drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); - if(!drm_crtc_helper_set_mode(&crtc->base, mode, + if (!drm_crtc_helper_set_mode(&crtc->base, mode, crtc->base.x, crtc->base.y, crtc->base.fb)) return 0; @@ -332,7 +332,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay, bool load_polyphase_filter) { struct drm_device *dev = overlay->dev; - drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_gem_request *request; u32 flip_addr = overlay->flip_addr; u32 tmp; @@ -359,7 +359,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay, } OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); OUT_RING(flip_addr); - ADVANCE_LP_RING(); + ADVANCE_LP_RING(); ret = i915_add_request(LP_RING(dev_priv), NULL, request); if (ret) { @@ -583,7 +583,7 @@ static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width) ret = ((offset + width + mask) >> shift) - (offset >> shift); if (!IS_GEN2(dev)) ret <<= 1; - ret -=1; + ret -= 1; return ret << 2; } @@ -817,7 +817,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, regs->SWIDTHSW = calc_swidthsw(overlay->dev, params->offset_Y, tmp_width); regs->SHEIGHT = params->src_h; - regs->OBUF_0Y = new_bo->gtt_offset + params-> offset_Y; + regs->OBUF_0Y = new_bo->gtt_offset + params->offset_Y; regs->OSTRIDE = params->stride_Y; if (params->format & I915_OVERLAY_YUV_PLANAR) { @@ -917,7 +917,7 @@ static void update_pfit_vscale_ratio(struct intel_overlay *overlay) * line with the intel documentation for the i965 */ if (INTEL_INFO(dev)->gen >= 4) { - /* on i965 use the PGM reg to read out the autoscaler values */ + /* on i965 use the PGM reg to read out the autoscaler values */ ratio = I915_READ(PFIT_PGM_RATIOS) >> PFIT_VERT_SCALE_SHIFT_965; } else { if (pfit_control & VERT_AUTO_SCALE) @@ -1098,7 +1098,7 @@ static int intel_panel_fitter_pipe(struct drm_device *dev) } int intel_overlay_put_image(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file_priv) { struct drm_intel_overlay_put_image *put_image_rec = data; drm_i915_private_t *dev_priv = dev->dev_private; @@ -1301,10 +1301,10 @@ static int check_gamma(struct drm_intel_overlay_attrs *attrs) } int intel_overlay_attrs(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file_priv) { struct drm_intel_overlay_attrs *attrs = data; - drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_private_t *dev_priv = dev->dev_private; struct intel_overlay *overlay; struct overlay_registers *regs; int ret; @@ -1393,7 +1393,7 @@ out_unlock: void intel_setup_overlay(struct drm_device *dev) { - drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_private_t *dev_priv = dev->dev_private; struct intel_overlay *overlay; struct drm_i915_gem_object *reg_bo; struct overlay_registers *regs; @@ -1421,24 +1421,24 @@ void intel_setup_overlay(struct drm_device *dev) ret = i915_gem_attach_phys_object(dev, reg_bo, I915_GEM_PHYS_OVERLAY_REGS, PAGE_SIZE); - if (ret) { - DRM_ERROR("failed to attach phys overlay regs\n"); - goto out_free_bo; - } + if (ret) { + DRM_ERROR("failed to attach phys overlay regs\n"); + goto out_free_bo; + } overlay->flip_addr = reg_bo->phys_obj->handle->busaddr; } else { ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true); if (ret) { - DRM_ERROR("failed to pin overlay register bo\n"); - goto out_free_bo; - } + DRM_ERROR("failed to pin overlay register bo\n"); + goto out_free_bo; + } overlay->flip_addr = reg_bo->gtt_offset; ret = i915_gem_object_set_to_gtt_domain(reg_bo, true); if (ret) { - DRM_ERROR("failed to move overlay register bo into the GTT\n"); - goto out_unpin_bo; - } + DRM_ERROR("failed to move overlay register bo into the GTT\n"); + goto out_unpin_bo; + } } /* init all values */ @@ -1525,7 +1525,7 @@ static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay, struct intel_overlay_error_state * intel_overlay_capture_error_state(struct drm_device *dev) { - drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_private_t *dev_priv = dev->dev_private; struct intel_overlay *overlay = dev_priv->overlay; struct intel_overlay_error_state *error; struct overlay_registers __iomem *regs; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index a9e0c7bcd317..499d4c0dbeeb 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -84,7 +84,7 @@ intel_pch_panel_fitting(struct drm_device *dev, if (scaled_width > scaled_height) { /* pillar */ width = scaled_height / mode->vdisplay; if (width & 1) - width++; + width++; x = (adjusted_mode->hdisplay - width + 1) / 2; y = 0; height = adjusted_mode->vdisplay; @@ -206,7 +206,7 @@ u32 intel_panel_get_backlight(struct drm_device *dev) if (IS_PINEVIEW(dev)) val >>= 1; - if (is_backlight_combination_mode(dev)){ + if (is_backlight_combination_mode(dev)) { u8 lbpc; val &= ~1; @@ -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); } -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; u32 tmp; @@ -236,7 +236,7 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level) if (HAS_PCH_SPLIT(dev)) return intel_pch_panel_set_backlight(dev, level); - if (is_backlight_combination_mode(dev)){ + if (is_backlight_combination_mode(dev)) { u32 max = intel_panel_get_max_backlight(dev); u8 lbpc; @@ -254,16 +254,21 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 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; - if (dev_priv->backlight_enabled) { - dev_priv->backlight_level = intel_panel_get_backlight(dev); - dev_priv->backlight_enabled = false; - } + dev_priv->backlight_level = level; + if (dev_priv->backlight_enabled) + 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) @@ -273,8 +278,8 @@ void intel_panel_enable_backlight(struct drm_device *dev) if (dev_priv->backlight_level == 0) dev_priv->backlight_level = intel_panel_get_max_backlight(dev); - intel_panel_set_backlight(dev, dev_priv->backlight_level); 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) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index c30626ea9f93..ca70e2f10445 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -34,6 +34,16 @@ #include "i915_trace.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) { int space = (ring->head & HEAD_ADDR) - (ring->tail + 8); @@ -123,6 +133,118 @@ render_ring_flush(struct intel_ring_buffer *ring, 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, u32 value) { @@ -206,16 +328,6 @@ static int init_ring_common(struct intel_ring_buffer *ring) 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 init_pipe_control(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)); } - if (INTEL_INFO(dev)->gen >= 6) { - } else if (IS_GEN5(dev)) { + if (INTEL_INFO(dev)->gen >= 5) { ret = init_pipe_control(ring); if (ret) return ret; @@ -315,83 +426,131 @@ static void render_ring_cleanup(struct intel_ring_buffer *ring) } static void -update_semaphore(struct intel_ring_buffer *ring, int i, u32 seqno) +update_mboxes(struct intel_ring_buffer *ring, + u32 seqno, + u32 mmio_offset) { - struct drm_device *dev = ring->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int id; - - /* - * cs -> 1 = vcs, 0 = bcs - * vcs -> 1 = bcs, 0 = cs, - * bcs -> 1 = cs, 0 = vcs. - */ - id = ring - dev_priv->ring; - id += 2 - i; - id %= 3; - - intel_ring_emit(ring, - MI_SEMAPHORE_MBOX | - MI_SEMAPHORE_REGISTER | - MI_SEMAPHORE_UPDATE); + intel_ring_emit(ring, MI_SEMAPHORE_MBOX | + MI_SEMAPHORE_GLOBAL_GTT | + MI_SEMAPHORE_REGISTER | + MI_SEMAPHORE_UPDATE); intel_ring_emit(ring, seqno); - intel_ring_emit(ring, - RING_SYNC_0(dev_priv->ring[id].mmio_base) + 4*i); + intel_ring_emit(ring, mmio_offset); } +/** + * gen6_add_request - Update the semaphore mailbox registers + * + * @ring - ring that is adding a request + * @seqno - return seqno stuck into the ring + * + * Update the mailbox registers in the *other* rings with the current seqno. + * This acts like a signal in the canonical semaphore. + */ static int gen6_add_request(struct intel_ring_buffer *ring, - u32 *result) + u32 *seqno) { - u32 seqno; + u32 mbox1_reg; + u32 mbox2_reg; int ret; ret = intel_ring_begin(ring, 10); if (ret) return ret; - seqno = i915_gem_get_seqno(ring->dev); - update_semaphore(ring, 0, seqno); - update_semaphore(ring, 1, seqno); + mbox1_reg = ring->signal_mbox[0]; + mbox2_reg = ring->signal_mbox[1]; + *seqno = i915_gem_get_seqno(ring->dev); + + update_mboxes(ring, *seqno, mbox1_reg); + update_mboxes(ring, *seqno, mbox2_reg); intel_ring_emit(ring, MI_STORE_DWORD_INDEX); intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - intel_ring_emit(ring, seqno); + intel_ring_emit(ring, *seqno); intel_ring_emit(ring, MI_USER_INTERRUPT); intel_ring_advance(ring); - *result = seqno; return 0; } -int -intel_ring_sync(struct intel_ring_buffer *ring, - struct intel_ring_buffer *to, +/** + * intel_ring_sync - sync the waiter to the signaller on seqno + * + * @waiter - ring that is waiting + * @signaller - ring which has, or will signal + * @seqno - seqno which the waiter will block on + */ +static int +intel_ring_sync(struct intel_ring_buffer *waiter, + struct intel_ring_buffer *signaller, + int ring, u32 seqno) { int ret; + u32 dw1 = MI_SEMAPHORE_MBOX | + MI_SEMAPHORE_COMPARE | + MI_SEMAPHORE_REGISTER; - ret = intel_ring_begin(ring, 4); + ret = intel_ring_begin(waiter, 4); if (ret) return ret; - intel_ring_emit(ring, - MI_SEMAPHORE_MBOX | - MI_SEMAPHORE_REGISTER | - intel_ring_sync_index(ring, to) << 17 | - MI_SEMAPHORE_COMPARE); - intel_ring_emit(ring, seqno); - intel_ring_emit(ring, 0); - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); + intel_ring_emit(waiter, dw1 | signaller->semaphore_register[ring]); + intel_ring_emit(waiter, seqno); + intel_ring_emit(waiter, 0); + intel_ring_emit(waiter, MI_NOOP); + intel_ring_advance(waiter); return 0; } +/* VCS->RCS (RVSYNC) or BCS->RCS (RBSYNC) */ +int +render_ring_sync_to(struct intel_ring_buffer *waiter, + struct intel_ring_buffer *signaller, + u32 seqno) +{ + WARN_ON(signaller->semaphore_register[RCS] == MI_SEMAPHORE_SYNC_INVALID); + return intel_ring_sync(waiter, + signaller, + RCS, + seqno); +} + +/* RCS->VCS (VRSYNC) or BCS->VCS (VBSYNC) */ +int +gen6_bsd_ring_sync_to(struct intel_ring_buffer *waiter, + struct intel_ring_buffer *signaller, + u32 seqno) +{ + WARN_ON(signaller->semaphore_register[VCS] == MI_SEMAPHORE_SYNC_INVALID); + return intel_ring_sync(waiter, + signaller, + VCS, + seqno); +} + +/* RCS->BCS (BRSYNC) or VCS->BCS (BVSYNC) */ +int +gen6_blt_ring_sync_to(struct intel_ring_buffer *waiter, + struct intel_ring_buffer *signaller, + u32 seqno) +{ + WARN_ON(signaller->semaphore_register[BCS] == MI_SEMAPHORE_SYNC_INVALID); + return intel_ring_sync(waiter, + signaller, + BCS, + seqno); +} + + + #define PIPE_CONTROL_FLUSH(ring__, addr__) \ do { \ - intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | \ - PIPE_CONTROL_DEPTH_STALL | 2); \ + intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \ + PIPE_CONTROL_DEPTH_STALL); \ intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \ intel_ring_emit(ring__, 0); \ intel_ring_emit(ring__, 0); \ @@ -419,8 +578,9 @@ pc_render_add_request(struct intel_ring_buffer *ring, if (ret) return ret; - intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | - PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH); + intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | + PIPE_CONTROL_WRITE_FLUSH | + PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT); intel_ring_emit(ring, seqno); intel_ring_emit(ring, 0); @@ -435,8 +595,9 @@ pc_render_add_request(struct intel_ring_buffer *ring, PIPE_CONTROL_FLUSH(ring, scratch_addr); scratch_addr += 128; PIPE_CONTROL_FLUSH(ring, scratch_addr); - intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | - PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH | + intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | + PIPE_CONTROL_WRITE_FLUSH | + PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | PIPE_CONTROL_NOTIFY); intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT); intel_ring_emit(ring, seqno); @@ -1026,7 +1187,12 @@ static const struct intel_ring_buffer render_ring = { .irq_get = render_ring_get_irq, .irq_put = render_ring_put_irq, .dispatch_execbuffer = render_ring_dispatch_execbuffer, - .cleanup = render_ring_cleanup, + .cleanup = render_ring_cleanup, + .sync_to = render_ring_sync_to, + .semaphore_register = {MI_SEMAPHORE_SYNC_INVALID, + MI_SEMAPHORE_SYNC_RV, + MI_SEMAPHORE_SYNC_RB}, + .signal_mbox = {GEN6_VRSYNC, GEN6_BRSYNC}, }; /* ring buffer for bit-stream decoder */ @@ -1050,23 +1216,23 @@ static const struct intel_ring_buffer bsd_ring = { static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring, u32 value) { - drm_i915_private_t *dev_priv = ring->dev->dev_private; + drm_i915_private_t *dev_priv = ring->dev->dev_private; /* Every tail move must follow the sequence below */ - I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, - GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK | - GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE); - I915_WRITE(GEN6_BSD_RNCID, 0x0); - - if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & - GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0, - 50)) - DRM_ERROR("timed out waiting for IDLE Indicator\n"); - - I915_WRITE_TAIL(ring, value); - I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, - GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK | - GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE); + I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, + GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK | + GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE); + I915_WRITE(GEN6_BSD_RNCID, 0x0); + + if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & + GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0, + 50)) + DRM_ERROR("timed out waiting for IDLE Indicator\n"); + + I915_WRITE_TAIL(ring, value); + I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, + GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK | + GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE); } static int gen6_ring_flush(struct intel_ring_buffer *ring, @@ -1094,18 +1260,18 @@ static int gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 len) { - int ret; + int ret; - ret = intel_ring_begin(ring, 2); - if (ret) - return ret; + ret = intel_ring_begin(ring, 2); + if (ret) + return ret; - intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965); - /* bit0-7 is the length on GEN6+ */ - intel_ring_emit(ring, offset); - intel_ring_advance(ring); + intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965); + /* bit0-7 is the length on GEN6+ */ + intel_ring_emit(ring, offset); + intel_ring_advance(ring); - return 0; + return 0; } static bool @@ -1154,6 +1320,11 @@ static const struct intel_ring_buffer gen6_bsd_ring = { .irq_get = gen6_bsd_ring_get_irq, .irq_put = gen6_bsd_ring_put_irq, .dispatch_execbuffer = gen6_ring_dispatch_execbuffer, + .sync_to = gen6_bsd_ring_sync_to, + .semaphore_register = {MI_SEMAPHORE_SYNC_VR, + MI_SEMAPHORE_SYNC_INVALID, + MI_SEMAPHORE_SYNC_VB}, + .signal_mbox = {GEN6_RVSYNC, GEN6_BVSYNC}, }; /* Blitter support (SandyBridge+) */ @@ -1272,19 +1443,24 @@ static void blt_ring_cleanup(struct intel_ring_buffer *ring) } static const struct intel_ring_buffer gen6_blt_ring = { - .name = "blt ring", - .id = RING_BLT, - .mmio_base = BLT_RING_BASE, - .size = 32 * PAGE_SIZE, - .init = blt_ring_init, - .write_tail = ring_write_tail, - .flush = blt_ring_flush, - .add_request = gen6_add_request, - .get_seqno = ring_get_seqno, - .irq_get = blt_ring_get_irq, - .irq_put = blt_ring_put_irq, - .dispatch_execbuffer = gen6_ring_dispatch_execbuffer, - .cleanup = blt_ring_cleanup, + .name = "blt ring", + .id = RING_BLT, + .mmio_base = BLT_RING_BASE, + .size = 32 * PAGE_SIZE, + .init = blt_ring_init, + .write_tail = ring_write_tail, + .flush = blt_ring_flush, + .add_request = gen6_add_request, + .get_seqno = ring_get_seqno, + .irq_get = blt_ring_get_irq, + .irq_put = blt_ring_put_irq, + .dispatch_execbuffer = gen6_ring_dispatch_execbuffer, + .cleanup = blt_ring_cleanup, + .sync_to = gen6_blt_ring_sync_to, + .semaphore_register = {MI_SEMAPHORE_SYNC_BR, + MI_SEMAPHORE_SYNC_BV, + MI_SEMAPHORE_SYNC_INVALID}, + .signal_mbox = {GEN6_RBSYNC, GEN6_VBSYNC}, }; int intel_init_render_ring_buffer(struct drm_device *dev) @@ -1295,6 +1471,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) *ring = render_ring; if (INTEL_INFO(dev)->gen >= 6) { ring->add_request = gen6_add_request; + ring->flush = gen6_render_ring_flush; ring->irq_get = gen6_render_ring_get_irq; ring->irq_put = gen6_render_ring_put_irq; } else if (IS_GEN5(dev)) { diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 39ac2b634ae5..68281c96c558 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -2,10 +2,10 @@ #define _INTEL_RINGBUFFER_H_ enum { - RCS = 0x0, - VCS, - BCS, - I915_NUM_RINGS, + RCS = 0x0, + VCS, + BCS, + I915_NUM_RINGS, }; struct intel_hw_status_page { @@ -75,7 +75,12 @@ struct intel_ring_buffer { int (*dispatch_execbuffer)(struct intel_ring_buffer *ring, u32 offset, u32 length); void (*cleanup)(struct intel_ring_buffer *ring); + int (*sync_to)(struct intel_ring_buffer *ring, + struct intel_ring_buffer *to, + u32 seqno); + u32 semaphore_register[3]; /*our mbox written by others */ + u32 signal_mbox[2]; /* mboxes this ring signals to */ /** * List of objects currently involved in rendering from the * ringbuffer. @@ -180,9 +185,6 @@ static inline void intel_ring_emit(struct intel_ring_buffer *ring, void intel_ring_advance(struct intel_ring_buffer *ring); u32 intel_ring_get_seqno(struct intel_ring_buffer *ring); -int intel_ring_sync(struct intel_ring_buffer *ring, - struct intel_ring_buffer *to, - u32 seqno); int intel_init_render_ring_buffer(struct drm_device *dev); int intel_init_bsd_ring_buffer(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 6348c499616f..6db3b1ccb6eb 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -43,7 +43,7 @@ #define SDVO_TV_MASK (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_SVID0) #define SDVO_OUTPUT_MASK (SDVO_TMDS_MASK | SDVO_RGB_MASK | SDVO_LVDS_MASK |\ - SDVO_TV_MASK) + SDVO_TV_MASK) #define IS_TV(c) (c->output_flag & SDVO_TV_MASK) #define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK) @@ -288,117 +288,117 @@ static const struct _sdvo_cmd_name { u8 cmd; const char *name; } sdvo_cmd_names[] = { - SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_POWER_STATES), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POWER_STATE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODER_POWER_STATE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DISPLAY_POWER_STATE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS), - - /* Add the op code for SDVO enhancements */ - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HPOS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HPOS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HPOS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_VPOS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_VPOS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_VPOS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SATURATION), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SATURATION), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SATURATION), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HUE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HUE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HUE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_CONTRAST), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CONTRAST), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTRAST), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_BRIGHTNESS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_BRIGHTNESS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_BRIGHTNESS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_H), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_H), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_H), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_V), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_V), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_V), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_ADAPTIVE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_ADAPTIVE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_ADAPTIVE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_2D), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_2D), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_2D), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SHARPNESS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SHARPNESS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SHARPNESS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DOT_CRAWL), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DOT_CRAWL), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_CHROMA_FILTER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_CHROMA_FILTER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_CHROMA_FILTER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_LUMA_FILTER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_LUMA_FILTER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_LUMA_FILTER), - - /* HDMI op code */ - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPP_ENCODE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_PIXEL_REPLI), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PIXEL_REPLI), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY_CAP), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_COLORIMETRY), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_AUDIO_STAT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_STAT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INDEX), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_INDEX), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INFO), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_AV_SPLIT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_AV_SPLIT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_TXRATE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_TXRATE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_DATA), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_DATA), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_POWER_STATES), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POWER_STATE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODER_POWER_STATE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DISPLAY_POWER_STATE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS), + + /* Add the op code for SDVO enhancements */ + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HPOS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HPOS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HPOS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_VPOS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_VPOS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_VPOS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SATURATION), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SATURATION), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SATURATION), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HUE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HUE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HUE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_CONTRAST), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CONTRAST), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTRAST), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_BRIGHTNESS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_BRIGHTNESS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_BRIGHTNESS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_H), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_H), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_H), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_V), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_V), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_V), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_ADAPTIVE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_ADAPTIVE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_ADAPTIVE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_2D), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_2D), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_2D), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SHARPNESS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SHARPNESS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SHARPNESS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DOT_CRAWL), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DOT_CRAWL), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_CHROMA_FILTER), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_CHROMA_FILTER), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_CHROMA_FILTER), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_LUMA_FILTER), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_LUMA_FILTER), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_LUMA_FILTER), + + /* HDMI op code */ + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPP_ENCODE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_PIXEL_REPLI), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PIXEL_REPLI), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY_CAP), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_COLORIMETRY), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_AUDIO_STAT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_STAT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INDEX), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_INDEX), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INFO), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_AV_SPLIT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_AV_SPLIT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_TXRATE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_TXRATE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_DATA), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_DATA), }; #define IS_SDVOB(reg) (reg == SDVOB || reg == PCH_SDVOB) @@ -1232,8 +1232,7 @@ static bool intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo) { /* Is there more than one type of output? */ - int caps = intel_sdvo->caps.output_flags & 0xf; - return caps & -caps; + return hweight16(intel_sdvo->caps.output_flags) > 1; } static struct edid * @@ -1254,7 +1253,7 @@ intel_sdvo_get_analog_edid(struct drm_connector *connector) } 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); enum drm_connector_status status; @@ -1349,7 +1348,7 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) if ((intel_sdvo_connector->output_flag & response) == 0) ret = connector_status_disconnected; else if (IS_TMDS(intel_sdvo_connector)) - ret = intel_sdvo_hdmi_sink_detect(connector); + ret = intel_sdvo_tmds_sink_detect(connector); else { struct edid *edid; @@ -1896,7 +1895,7 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, struct intel_sdvo *sdvo, u32 reg) { struct sdvo_device_mapping *mapping; - u8 pin, speed; + u8 pin; if (IS_SDVOB(reg)) mapping = &dev_priv->sdvo_mappings[0]; @@ -1904,18 +1903,16 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, mapping = &dev_priv->sdvo_mappings[1]; pin = GMBUS_PORT_DPB; - speed = GMBUS_RATE_1MHZ >> 8; - if (mapping->initialized) { + if (mapping->initialized) pin = mapping->i2c_pin; - speed = mapping->i2c_speed; - } if (pin < GMBUS_NUM_PORTS) { 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); - } else + } else { sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter; + } } static bool @@ -2206,7 +2203,7 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags) bytes[0], bytes[1]); return false; } - intel_sdvo->base.crtc_mask = (1 << 0) | (1 << 1); + intel_sdvo->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); return true; } @@ -2275,7 +2272,7 @@ static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo, DRM_DEBUG_KMS(#name ": max %d, default %d, current %d\n", \ data_value[0], data_value[1], response); \ } \ -} while(0) +} while (0) static bool intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo, @@ -2442,7 +2439,7 @@ static bool intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo, if (IS_TV(intel_sdvo_connector)) return intel_sdvo_create_enhance_property_tv(intel_sdvo, intel_sdvo_connector, enhancements.reply); - else if(IS_LVDS(intel_sdvo_connector)) + else if (IS_LVDS(intel_sdvo_connector)) return intel_sdvo_create_enhance_property_lvds(intel_sdvo, intel_sdvo_connector, enhancements.reply); else return true; diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 4f4e23bc2d16..4aa6f343e49a 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h @@ -46,63 +46,63 @@ #define SDVO_OUTPUT_LAST (14) struct intel_sdvo_caps { - u8 vendor_id; - u8 device_id; - u8 device_rev_id; - u8 sdvo_version_major; - u8 sdvo_version_minor; - unsigned int sdvo_inputs_mask:2; - unsigned int smooth_scaling:1; - unsigned int sharp_scaling:1; - unsigned int up_scaling:1; - unsigned int down_scaling:1; - unsigned int stall_support:1; - unsigned int pad:1; - u16 output_flags; + u8 vendor_id; + u8 device_id; + u8 device_rev_id; + u8 sdvo_version_major; + u8 sdvo_version_minor; + unsigned int sdvo_inputs_mask:2; + unsigned int smooth_scaling:1; + unsigned int sharp_scaling:1; + unsigned int up_scaling:1; + unsigned int down_scaling:1; + unsigned int stall_support:1; + unsigned int pad:1; + u16 output_flags; } __attribute__((packed)); /** This matches the EDID DTD structure, more or less */ struct intel_sdvo_dtd { - struct { - u16 clock; /**< pixel clock, in 10kHz units */ - u8 h_active; /**< lower 8 bits (pixels) */ - u8 h_blank; /**< lower 8 bits (pixels) */ - u8 h_high; /**< upper 4 bits each h_active, h_blank */ - u8 v_active; /**< lower 8 bits (lines) */ - u8 v_blank; /**< lower 8 bits (lines) */ - u8 v_high; /**< upper 4 bits each v_active, v_blank */ - } part1; - - struct { - u8 h_sync_off; /**< lower 8 bits, from hblank start */ - u8 h_sync_width; /**< lower 8 bits (pixels) */ - /** lower 4 bits each vsync offset, vsync width */ - u8 v_sync_off_width; - /** - * 2 high bits of hsync offset, 2 high bits of hsync width, - * bits 4-5 of vsync offset, and 2 high bits of vsync width. - */ - u8 sync_off_width_high; - u8 dtd_flags; - u8 sdvo_flags; - /** bits 6-7 of vsync offset at bits 6-7 */ - u8 v_sync_off_high; - u8 reserved; - } part2; + struct { + u16 clock; /**< pixel clock, in 10kHz units */ + u8 h_active; /**< lower 8 bits (pixels) */ + u8 h_blank; /**< lower 8 bits (pixels) */ + u8 h_high; /**< upper 4 bits each h_active, h_blank */ + u8 v_active; /**< lower 8 bits (lines) */ + u8 v_blank; /**< lower 8 bits (lines) */ + u8 v_high; /**< upper 4 bits each v_active, v_blank */ + } part1; + + struct { + u8 h_sync_off; /**< lower 8 bits, from hblank start */ + u8 h_sync_width; /**< lower 8 bits (pixels) */ + /** lower 4 bits each vsync offset, vsync width */ + u8 v_sync_off_width; + /** + * 2 high bits of hsync offset, 2 high bits of hsync width, + * bits 4-5 of vsync offset, and 2 high bits of vsync width. + */ + u8 sync_off_width_high; + u8 dtd_flags; + u8 sdvo_flags; + /** bits 6-7 of vsync offset at bits 6-7 */ + u8 v_sync_off_high; + u8 reserved; + } part2; } __attribute__((packed)); struct intel_sdvo_pixel_clock_range { - u16 min; /**< pixel clock, in 10kHz units */ - u16 max; /**< pixel clock, in 10kHz units */ + u16 min; /**< pixel clock, in 10kHz units */ + u16 max; /**< pixel clock, in 10kHz units */ } __attribute__((packed)); struct intel_sdvo_preferred_input_timing_args { - u16 clock; - u16 width; - u16 height; - u8 interlace:1; - u8 scaled:1; - u8 pad:6; + u16 clock; + u16 width; + u16 height; + u8 interlace:1; + u8 scaled:1; + u8 pad:6; } __attribute__((packed)); /* I2C registers for SDVO */ @@ -154,9 +154,9 @@ struct intel_sdvo_preferred_input_timing_args { */ #define SDVO_CMD_GET_TRAINED_INPUTS 0x03 struct intel_sdvo_get_trained_inputs_response { - unsigned int input0_trained:1; - unsigned int input1_trained:1; - unsigned int pad:6; + unsigned int input0_trained:1; + unsigned int input1_trained:1; + unsigned int pad:6; } __attribute__((packed)); /** Returns a struct intel_sdvo_output_flags of active outputs. */ @@ -177,7 +177,7 @@ struct intel_sdvo_get_trained_inputs_response { */ #define SDVO_CMD_GET_IN_OUT_MAP 0x06 struct intel_sdvo_in_out_map { - u16 in0, in1; + u16 in0, in1; }; /** @@ -210,10 +210,10 @@ struct intel_sdvo_in_out_map { #define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE 0x0f struct intel_sdvo_get_interrupt_event_source_response { - u16 interrupt_status; - unsigned int ambient_light_interrupt:1; - unsigned int hdmi_audio_encrypt_change:1; - unsigned int pad:6; + u16 interrupt_status; + unsigned int ambient_light_interrupt:1; + unsigned int hdmi_audio_encrypt_change:1; + unsigned int pad:6; } __attribute__((packed)); /** @@ -225,8 +225,8 @@ struct intel_sdvo_get_interrupt_event_source_response { */ #define SDVO_CMD_SET_TARGET_INPUT 0x10 struct intel_sdvo_set_target_input_args { - unsigned int target_1:1; - unsigned int pad:7; + unsigned int target_1:1; + unsigned int pad:7; } __attribute__((packed)); /** @@ -314,57 +314,57 @@ struct intel_sdvo_set_target_input_args { #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27 /** 6 bytes of bit flags for TV formats shared by all TV format functions */ struct intel_sdvo_tv_format { - unsigned int ntsc_m:1; - unsigned int ntsc_j:1; - unsigned int ntsc_443:1; - unsigned int pal_b:1; - unsigned int pal_d:1; - unsigned int pal_g:1; - unsigned int pal_h:1; - unsigned int pal_i:1; - - unsigned int pal_m:1; - unsigned int pal_n:1; - unsigned int pal_nc:1; - unsigned int pal_60:1; - unsigned int secam_b:1; - unsigned int secam_d:1; - unsigned int secam_g:1; - unsigned int secam_k:1; - - unsigned int secam_k1:1; - unsigned int secam_l:1; - unsigned int secam_60:1; - unsigned int hdtv_std_smpte_240m_1080i_59:1; - unsigned int hdtv_std_smpte_240m_1080i_60:1; - unsigned int hdtv_std_smpte_260m_1080i_59:1; - unsigned int hdtv_std_smpte_260m_1080i_60:1; - unsigned int hdtv_std_smpte_274m_1080i_50:1; - - unsigned int hdtv_std_smpte_274m_1080i_59:1; - unsigned int hdtv_std_smpte_274m_1080i_60:1; - unsigned int hdtv_std_smpte_274m_1080p_23:1; - unsigned int hdtv_std_smpte_274m_1080p_24:1; - unsigned int hdtv_std_smpte_274m_1080p_25:1; - unsigned int hdtv_std_smpte_274m_1080p_29:1; - unsigned int hdtv_std_smpte_274m_1080p_30:1; - unsigned int hdtv_std_smpte_274m_1080p_50:1; - - unsigned int hdtv_std_smpte_274m_1080p_59:1; - unsigned int hdtv_std_smpte_274m_1080p_60:1; - unsigned int hdtv_std_smpte_295m_1080i_50:1; - unsigned int hdtv_std_smpte_295m_1080p_50:1; - unsigned int hdtv_std_smpte_296m_720p_59:1; - unsigned int hdtv_std_smpte_296m_720p_60:1; - unsigned int hdtv_std_smpte_296m_720p_50:1; - unsigned int hdtv_std_smpte_293m_480p_59:1; - - unsigned int hdtv_std_smpte_170m_480i_59:1; - unsigned int hdtv_std_iturbt601_576i_50:1; - unsigned int hdtv_std_iturbt601_576p_50:1; - unsigned int hdtv_std_eia_7702a_480i_60:1; - unsigned int hdtv_std_eia_7702a_480p_60:1; - unsigned int pad:3; + unsigned int ntsc_m:1; + unsigned int ntsc_j:1; + unsigned int ntsc_443:1; + unsigned int pal_b:1; + unsigned int pal_d:1; + unsigned int pal_g:1; + unsigned int pal_h:1; + unsigned int pal_i:1; + + unsigned int pal_m:1; + unsigned int pal_n:1; + unsigned int pal_nc:1; + unsigned int pal_60:1; + unsigned int secam_b:1; + unsigned int secam_d:1; + unsigned int secam_g:1; + unsigned int secam_k:1; + + unsigned int secam_k1:1; + unsigned int secam_l:1; + unsigned int secam_60:1; + unsigned int hdtv_std_smpte_240m_1080i_59:1; + unsigned int hdtv_std_smpte_240m_1080i_60:1; + unsigned int hdtv_std_smpte_260m_1080i_59:1; + unsigned int hdtv_std_smpte_260m_1080i_60:1; + unsigned int hdtv_std_smpte_274m_1080i_50:1; + + unsigned int hdtv_std_smpte_274m_1080i_59:1; + unsigned int hdtv_std_smpte_274m_1080i_60:1; + unsigned int hdtv_std_smpte_274m_1080p_23:1; + unsigned int hdtv_std_smpte_274m_1080p_24:1; + unsigned int hdtv_std_smpte_274m_1080p_25:1; + unsigned int hdtv_std_smpte_274m_1080p_29:1; + unsigned int hdtv_std_smpte_274m_1080p_30:1; + unsigned int hdtv_std_smpte_274m_1080p_50:1; + + unsigned int hdtv_std_smpte_274m_1080p_59:1; + unsigned int hdtv_std_smpte_274m_1080p_60:1; + unsigned int hdtv_std_smpte_295m_1080i_50:1; + unsigned int hdtv_std_smpte_295m_1080p_50:1; + unsigned int hdtv_std_smpte_296m_720p_59:1; + unsigned int hdtv_std_smpte_296m_720p_60:1; + unsigned int hdtv_std_smpte_296m_720p_50:1; + unsigned int hdtv_std_smpte_293m_480p_59:1; + + unsigned int hdtv_std_smpte_170m_480i_59:1; + unsigned int hdtv_std_iturbt601_576i_50:1; + unsigned int hdtv_std_iturbt601_576p_50:1; + unsigned int hdtv_std_eia_7702a_480i_60:1; + unsigned int hdtv_std_eia_7702a_480p_60:1; + unsigned int pad:3; } __attribute__((packed)); #define SDVO_CMD_GET_TV_FORMAT 0x28 @@ -374,53 +374,53 @@ struct intel_sdvo_tv_format { /** Returns the resolutiosn that can be used with the given TV format */ #define SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT 0x83 struct intel_sdvo_sdtv_resolution_request { - unsigned int ntsc_m:1; - unsigned int ntsc_j:1; - unsigned int ntsc_443:1; - unsigned int pal_b:1; - unsigned int pal_d:1; - unsigned int pal_g:1; - unsigned int pal_h:1; - unsigned int pal_i:1; - - unsigned int pal_m:1; - unsigned int pal_n:1; - unsigned int pal_nc:1; - unsigned int pal_60:1; - unsigned int secam_b:1; - unsigned int secam_d:1; - unsigned int secam_g:1; - unsigned int secam_k:1; - - unsigned int secam_k1:1; - unsigned int secam_l:1; - unsigned int secam_60:1; - unsigned int pad:5; + unsigned int ntsc_m:1; + unsigned int ntsc_j:1; + unsigned int ntsc_443:1; + unsigned int pal_b:1; + unsigned int pal_d:1; + unsigned int pal_g:1; + unsigned int pal_h:1; + unsigned int pal_i:1; + + unsigned int pal_m:1; + unsigned int pal_n:1; + unsigned int pal_nc:1; + unsigned int pal_60:1; + unsigned int secam_b:1; + unsigned int secam_d:1; + unsigned int secam_g:1; + unsigned int secam_k:1; + + unsigned int secam_k1:1; + unsigned int secam_l:1; + unsigned int secam_60:1; + unsigned int pad:5; } __attribute__((packed)); struct intel_sdvo_sdtv_resolution_reply { - unsigned int res_320x200:1; - unsigned int res_320x240:1; - unsigned int res_400x300:1; - unsigned int res_640x350:1; - unsigned int res_640x400:1; - unsigned int res_640x480:1; - unsigned int res_704x480:1; - unsigned int res_704x576:1; - - unsigned int res_720x350:1; - unsigned int res_720x400:1; - unsigned int res_720x480:1; - unsigned int res_720x540:1; - unsigned int res_720x576:1; - unsigned int res_768x576:1; - unsigned int res_800x600:1; - unsigned int res_832x624:1; - - unsigned int res_920x766:1; - unsigned int res_1024x768:1; - unsigned int res_1280x1024:1; - unsigned int pad:5; + unsigned int res_320x200:1; + unsigned int res_320x240:1; + unsigned int res_400x300:1; + unsigned int res_640x350:1; + unsigned int res_640x400:1; + unsigned int res_640x480:1; + unsigned int res_704x480:1; + unsigned int res_704x576:1; + + unsigned int res_720x350:1; + unsigned int res_720x400:1; + unsigned int res_720x480:1; + unsigned int res_720x540:1; + unsigned int res_720x576:1; + unsigned int res_768x576:1; + unsigned int res_800x600:1; + unsigned int res_832x624:1; + + unsigned int res_920x766:1; + unsigned int res_1024x768:1; + unsigned int res_1280x1024:1; + unsigned int pad:5; } __attribute__((packed)); /* Get supported resolution with squire pixel aspect ratio that can be @@ -428,90 +428,90 @@ struct intel_sdvo_sdtv_resolution_reply { #define SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT 0x85 struct intel_sdvo_hdtv_resolution_request { - unsigned int hdtv_std_smpte_240m_1080i_59:1; - unsigned int hdtv_std_smpte_240m_1080i_60:1; - unsigned int hdtv_std_smpte_260m_1080i_59:1; - unsigned int hdtv_std_smpte_260m_1080i_60:1; - unsigned int hdtv_std_smpte_274m_1080i_50:1; - unsigned int hdtv_std_smpte_274m_1080i_59:1; - unsigned int hdtv_std_smpte_274m_1080i_60:1; - unsigned int hdtv_std_smpte_274m_1080p_23:1; - - unsigned int hdtv_std_smpte_274m_1080p_24:1; - unsigned int hdtv_std_smpte_274m_1080p_25:1; - unsigned int hdtv_std_smpte_274m_1080p_29:1; - unsigned int hdtv_std_smpte_274m_1080p_30:1; - unsigned int hdtv_std_smpte_274m_1080p_50:1; - unsigned int hdtv_std_smpte_274m_1080p_59:1; - unsigned int hdtv_std_smpte_274m_1080p_60:1; - unsigned int hdtv_std_smpte_295m_1080i_50:1; - - unsigned int hdtv_std_smpte_295m_1080p_50:1; - unsigned int hdtv_std_smpte_296m_720p_59:1; - unsigned int hdtv_std_smpte_296m_720p_60:1; - unsigned int hdtv_std_smpte_296m_720p_50:1; - unsigned int hdtv_std_smpte_293m_480p_59:1; - unsigned int hdtv_std_smpte_170m_480i_59:1; - unsigned int hdtv_std_iturbt601_576i_50:1; - unsigned int hdtv_std_iturbt601_576p_50:1; - - unsigned int hdtv_std_eia_7702a_480i_60:1; - unsigned int hdtv_std_eia_7702a_480p_60:1; - unsigned int pad:6; + unsigned int hdtv_std_smpte_240m_1080i_59:1; + unsigned int hdtv_std_smpte_240m_1080i_60:1; + unsigned int hdtv_std_smpte_260m_1080i_59:1; + unsigned int hdtv_std_smpte_260m_1080i_60:1; + unsigned int hdtv_std_smpte_274m_1080i_50:1; + unsigned int hdtv_std_smpte_274m_1080i_59:1; + unsigned int hdtv_std_smpte_274m_1080i_60:1; + unsigned int hdtv_std_smpte_274m_1080p_23:1; + + unsigned int hdtv_std_smpte_274m_1080p_24:1; + unsigned int hdtv_std_smpte_274m_1080p_25:1; + unsigned int hdtv_std_smpte_274m_1080p_29:1; + unsigned int hdtv_std_smpte_274m_1080p_30:1; + unsigned int hdtv_std_smpte_274m_1080p_50:1; + unsigned int hdtv_std_smpte_274m_1080p_59:1; + unsigned int hdtv_std_smpte_274m_1080p_60:1; + unsigned int hdtv_std_smpte_295m_1080i_50:1; + + unsigned int hdtv_std_smpte_295m_1080p_50:1; + unsigned int hdtv_std_smpte_296m_720p_59:1; + unsigned int hdtv_std_smpte_296m_720p_60:1; + unsigned int hdtv_std_smpte_296m_720p_50:1; + unsigned int hdtv_std_smpte_293m_480p_59:1; + unsigned int hdtv_std_smpte_170m_480i_59:1; + unsigned int hdtv_std_iturbt601_576i_50:1; + unsigned int hdtv_std_iturbt601_576p_50:1; + + unsigned int hdtv_std_eia_7702a_480i_60:1; + unsigned int hdtv_std_eia_7702a_480p_60:1; + unsigned int pad:6; } __attribute__((packed)); struct intel_sdvo_hdtv_resolution_reply { - unsigned int res_640x480:1; - unsigned int res_800x600:1; - unsigned int res_1024x768:1; - unsigned int res_1280x960:1; - unsigned int res_1400x1050:1; - unsigned int res_1600x1200:1; - unsigned int res_1920x1440:1; - unsigned int res_2048x1536:1; - - unsigned int res_2560x1920:1; - unsigned int res_3200x2400:1; - unsigned int res_3840x2880:1; - unsigned int pad1:5; - - unsigned int res_848x480:1; - unsigned int res_1064x600:1; - unsigned int res_1280x720:1; - unsigned int res_1360x768:1; - unsigned int res_1704x960:1; - unsigned int res_1864x1050:1; - unsigned int res_1920x1080:1; - unsigned int res_2128x1200:1; - - unsigned int res_2560x1400:1; - unsigned int res_2728x1536:1; - unsigned int res_3408x1920:1; - unsigned int res_4264x2400:1; - unsigned int res_5120x2880:1; - unsigned int pad2:3; - - unsigned int res_768x480:1; - unsigned int res_960x600:1; - unsigned int res_1152x720:1; - unsigned int res_1124x768:1; - unsigned int res_1536x960:1; - unsigned int res_1680x1050:1; - unsigned int res_1728x1080:1; - unsigned int res_1920x1200:1; - - unsigned int res_2304x1440:1; - unsigned int res_2456x1536:1; - unsigned int res_3072x1920:1; - unsigned int res_3840x2400:1; - unsigned int res_4608x2880:1; - unsigned int pad3:3; - - unsigned int res_1280x1024:1; - unsigned int pad4:7; - - unsigned int res_1280x768:1; - unsigned int pad5:7; + unsigned int res_640x480:1; + unsigned int res_800x600:1; + unsigned int res_1024x768:1; + unsigned int res_1280x960:1; + unsigned int res_1400x1050:1; + unsigned int res_1600x1200:1; + unsigned int res_1920x1440:1; + unsigned int res_2048x1536:1; + + unsigned int res_2560x1920:1; + unsigned int res_3200x2400:1; + unsigned int res_3840x2880:1; + unsigned int pad1:5; + + unsigned int res_848x480:1; + unsigned int res_1064x600:1; + unsigned int res_1280x720:1; + unsigned int res_1360x768:1; + unsigned int res_1704x960:1; + unsigned int res_1864x1050:1; + unsigned int res_1920x1080:1; + unsigned int res_2128x1200:1; + + unsigned int res_2560x1400:1; + unsigned int res_2728x1536:1; + unsigned int res_3408x1920:1; + unsigned int res_4264x2400:1; + unsigned int res_5120x2880:1; + unsigned int pad2:3; + + unsigned int res_768x480:1; + unsigned int res_960x600:1; + unsigned int res_1152x720:1; + unsigned int res_1124x768:1; + unsigned int res_1536x960:1; + unsigned int res_1680x1050:1; + unsigned int res_1728x1080:1; + unsigned int res_1920x1200:1; + + unsigned int res_2304x1440:1; + unsigned int res_2456x1536:1; + unsigned int res_3072x1920:1; + unsigned int res_3840x2400:1; + unsigned int res_4608x2880:1; + unsigned int pad3:3; + + unsigned int res_1280x1024:1; + unsigned int pad4:7; + + unsigned int res_1280x768:1; + unsigned int pad5:7; } __attribute__((packed)); /* Get supported power state returns info for encoder and monitor, rely on @@ -539,25 +539,25 @@ struct intel_sdvo_hdtv_resolution_reply { * The high fields are bits 8:9 of the 10-bit values. */ struct sdvo_panel_power_sequencing { - u8 t0; - u8 t1; - u8 t2; - u8 t3; - u8 t4; - - unsigned int t0_high:2; - unsigned int t1_high:2; - unsigned int t2_high:2; - unsigned int t3_high:2; - - unsigned int t4_high:2; - unsigned int pad:6; + u8 t0; + u8 t1; + u8 t2; + u8 t3; + u8 t4; + + unsigned int t0_high:2; + unsigned int t1_high:2; + unsigned int t2_high:2; + unsigned int t3_high:2; + + unsigned int t4_high:2; + unsigned int pad:6; } __attribute__((packed)); #define SDVO_CMD_GET_MAX_BACKLIGHT_LEVEL 0x30 struct sdvo_max_backlight_reply { - u8 max_value; - u8 default_value; + u8 max_value; + u8 default_value; } __attribute__((packed)); #define SDVO_CMD_GET_BACKLIGHT_LEVEL 0x31 @@ -565,16 +565,16 @@ struct sdvo_max_backlight_reply { #define SDVO_CMD_GET_AMBIENT_LIGHT 0x33 struct sdvo_get_ambient_light_reply { - u16 trip_low; - u16 trip_high; - u16 value; + u16 trip_low; + u16 trip_high; + u16 value; } __attribute__((packed)); #define SDVO_CMD_SET_AMBIENT_LIGHT 0x34 struct sdvo_set_ambient_light_reply { - u16 trip_low; - u16 trip_high; - unsigned int enable:1; - unsigned int pad:7; + u16 trip_low; + u16 trip_high; + unsigned int enable:1; + unsigned int pad:7; } __attribute__((packed)); /* Set display power state */ @@ -586,23 +586,23 @@ struct sdvo_set_ambient_light_reply { #define SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS 0x84 struct intel_sdvo_enhancements_reply { - unsigned int flicker_filter:1; - unsigned int flicker_filter_adaptive:1; - unsigned int flicker_filter_2d:1; - unsigned int saturation:1; - unsigned int hue:1; - unsigned int brightness:1; - unsigned int contrast:1; - unsigned int overscan_h:1; - - unsigned int overscan_v:1; - unsigned int hpos:1; - unsigned int vpos:1; - unsigned int sharpness:1; - unsigned int dot_crawl:1; - unsigned int dither:1; - unsigned int tv_chroma_filter:1; - unsigned int tv_luma_filter:1; + unsigned int flicker_filter:1; + unsigned int flicker_filter_adaptive:1; + unsigned int flicker_filter_2d:1; + unsigned int saturation:1; + unsigned int hue:1; + unsigned int brightness:1; + unsigned int contrast:1; + unsigned int overscan_h:1; + + unsigned int overscan_v:1; + unsigned int hpos:1; + unsigned int vpos:1; + unsigned int sharpness:1; + unsigned int dot_crawl:1; + unsigned int dither:1; + unsigned int tv_chroma_filter:1; + unsigned int tv_luma_filter:1; } __attribute__((packed)); /* Picture enhancement limits below are dependent on the current TV format, @@ -623,8 +623,8 @@ struct intel_sdvo_enhancements_reply { #define SDVO_CMD_GET_MAX_TV_CHROMA_FILTER 0x74 #define SDVO_CMD_GET_MAX_TV_LUMA_FILTER 0x77 struct intel_sdvo_enhancement_limits_reply { - u16 max_value; - u16 default_value; + u16 max_value; + u16 default_value; } __attribute__((packed)); #define SDVO_CMD_GET_LVDS_PANEL_INFORMATION 0x7f @@ -665,8 +665,8 @@ struct intel_sdvo_enhancement_limits_reply { #define SDVO_CMD_GET_TV_LUMA_FILTER 0x78 #define SDVO_CMD_SET_TV_LUMA_FILTER 0x79 struct intel_sdvo_enhancements_arg { - u16 value; -}__attribute__((packed)); + u16 value; +} __attribute__((packed)); #define SDVO_CMD_GET_DOT_CRAWL 0x70 #define SDVO_CMD_SET_DOT_CRAWL 0x71 @@ -717,7 +717,7 @@ struct intel_sdvo_enhancements_arg { #define SDVO_CMD_GET_AUDIO_TX_INFO 0x9c #define SDVO_NEED_TO_STALL (1 << 7) -struct intel_sdvo_encode{ - u8 dvi_rev; - u8 hdmi_rev; +struct intel_sdvo_encode { + u8 dvi_rev; + u8 hdmi_rev; } __attribute__ ((packed)); diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 210d570fd516..f3c6a9a8b081 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -194,10 +194,10 @@ static const u32 filter_table[] = { * * if (f >= 1) { * exp = 0x7; - * mant = 1 << 8; + * mant = 1 << 8; * } else { * for (exp = 0; exp < 3 && f < 0.5; exp++) - * f *= 2.0; + * f *= 2.0; * mant = (f * (1 << 9) + 0.5); * if (mant >= (1 << 9)) * mant = (1 << 9) - 1; @@ -430,7 +430,7 @@ static const struct tv_mode tv_modes[] = { .vsync_start_f1 = 6, .vsync_start_f2 = 7, .vsync_len = 6, - .veq_ena = true, .veq_start_f1 = 0, + .veq_ena = true, .veq_start_f1 = 0, .veq_start_f2 = 1, .veq_len = 18, .vi_end_f1 = 20, .vi_end_f2 = 21, @@ -472,7 +472,7 @@ static const struct tv_mode tv_modes[] = { .vsync_start_f1 = 6, .vsync_start_f2 = 7, .vsync_len = 6, - .veq_ena = true, .veq_start_f1 = 0, + .veq_ena = true, .veq_start_f1 = 0, .veq_start_f2 = 1, .veq_len = 18, .vi_end_f1 = 20, .vi_end_f2 = 21, @@ -515,7 +515,7 @@ static const struct tv_mode tv_modes[] = { .vsync_start_f1 = 6, .vsync_start_f2 = 7, .vsync_len = 6, - .veq_ena = true, .veq_start_f1 = 0, + .veq_ena = true, .veq_start_f1 = 0, .veq_start_f2 = 1, .veq_len = 18, .vi_end_f1 = 20, .vi_end_f2 = 21, @@ -558,7 +558,7 @@ static const struct tv_mode tv_modes[] = { .vsync_start_f1 = 6, .vsync_start_f2 = 7, .vsync_len = 6, - .veq_ena = true, .veq_start_f1 = 0, + .veq_ena = true, .veq_start_f1 = 0, .veq_start_f2 = 1, .veq_len = 18, .vi_end_f1 = 20, .vi_end_f2 = 21, @@ -602,14 +602,14 @@ static const struct tv_mode tv_modes[] = { .vsync_start_f1 = 6, .vsync_start_f2 = 7, .vsync_len = 6, - .veq_ena = true, .veq_start_f1 = 0, + .veq_ena = true, .veq_start_f1 = 0, .veq_start_f2 = 1, .veq_len = 18, .vi_end_f1 = 24, .vi_end_f2 = 25, .nbr_end = 286, .burst_ena = true, - .hburst_start = 73, .hburst_len = 34, + .hburst_start = 73, .hburst_len = 34, .vburst_start_f1 = 8, .vburst_end_f1 = 285, .vburst_start_f2 = 8, .vburst_end_f2 = 286, .vburst_start_f3 = 9, .vburst_end_f3 = 286, @@ -646,7 +646,7 @@ static const struct tv_mode tv_modes[] = { .vsync_start_f1 = 5, .vsync_start_f2 = 6, .vsync_len = 5, - .veq_ena = true, .veq_start_f1 = 0, + .veq_ena = true, .veq_start_f1 = 0, .veq_start_f2 = 1, .veq_len = 15, .vi_end_f1 = 24, .vi_end_f2 = 25, @@ -675,7 +675,7 @@ static const struct tv_mode tv_modes[] = { }, { .name = "480p@59.94Hz", - .clock = 107520, + .clock = 107520, .refresh = 59940, .oversample = TV_OVERSAMPLE_4X, .component_only = 1, @@ -683,7 +683,7 @@ static const struct tv_mode tv_modes[] = { .hsync_end = 64, .hblank_end = 122, .hblank_start = 842, .htotal = 857, - .progressive = true,.trilevel_sync = false, + .progressive = true, .trilevel_sync = false, .vsync_start_f1 = 12, .vsync_start_f2 = 12, .vsync_len = 12, @@ -699,7 +699,7 @@ static const struct tv_mode tv_modes[] = { }, { .name = "480p@60Hz", - .clock = 107520, + .clock = 107520, .refresh = 60000, .oversample = TV_OVERSAMPLE_4X, .component_only = 1, @@ -707,7 +707,7 @@ static const struct tv_mode tv_modes[] = { .hsync_end = 64, .hblank_end = 122, .hblank_start = 842, .htotal = 856, - .progressive = true,.trilevel_sync = false, + .progressive = true, .trilevel_sync = false, .vsync_start_f1 = 12, .vsync_start_f2 = 12, .vsync_len = 12, @@ -723,7 +723,7 @@ static const struct tv_mode tv_modes[] = { }, { .name = "576p", - .clock = 107520, + .clock = 107520, .refresh = 50000, .oversample = TV_OVERSAMPLE_4X, .component_only = 1, @@ -755,7 +755,7 @@ static const struct tv_mode tv_modes[] = { .hsync_end = 80, .hblank_end = 300, .hblank_start = 1580, .htotal = 1649, - .progressive = true, .trilevel_sync = true, + .progressive = true, .trilevel_sync = true, .vsync_start_f1 = 10, .vsync_start_f2 = 10, .vsync_len = 10, @@ -779,7 +779,7 @@ static const struct tv_mode tv_modes[] = { .hsync_end = 80, .hblank_end = 300, .hblank_start = 1580, .htotal = 1651, - .progressive = true, .trilevel_sync = true, + .progressive = true, .trilevel_sync = true, .vsync_start_f1 = 10, .vsync_start_f2 = 10, .vsync_len = 10, @@ -803,7 +803,7 @@ static const struct tv_mode tv_modes[] = { .hsync_end = 80, .hblank_end = 300, .hblank_start = 1580, .htotal = 1979, - .progressive = true, .trilevel_sync = true, + .progressive = true, .trilevel_sync = true, .vsync_start_f1 = 10, .vsync_start_f2 = 10, .vsync_len = 10, @@ -828,12 +828,12 @@ static const struct tv_mode tv_modes[] = { .hsync_end = 88, .hblank_end = 235, .hblank_start = 2155, .htotal = 2639, - .progressive = false, .trilevel_sync = true, + .progressive = false, .trilevel_sync = true, .vsync_start_f1 = 4, .vsync_start_f2 = 5, .vsync_len = 10, - .veq_ena = true, .veq_start_f1 = 4, + .veq_ena = true, .veq_start_f1 = 4, .veq_start_f2 = 4, .veq_len = 10, @@ -854,12 +854,12 @@ static const struct tv_mode tv_modes[] = { .hsync_end = 88, .hblank_end = 235, .hblank_start = 2155, .htotal = 2199, - .progressive = false, .trilevel_sync = true, + .progressive = false, .trilevel_sync = true, .vsync_start_f1 = 4, .vsync_start_f2 = 5, .vsync_len = 10, - .veq_ena = true, .veq_start_f1 = 4, + .veq_ena = true, .veq_start_f1 = 4, .veq_start_f2 = 4, .veq_len = 10, @@ -880,16 +880,16 @@ static const struct tv_mode tv_modes[] = { .hsync_end = 88, .hblank_end = 235, .hblank_start = 2155, .htotal = 2201, - .progressive = false, .trilevel_sync = true, + .progressive = false, .trilevel_sync = true, .vsync_start_f1 = 4, .vsync_start_f2 = 5, .vsync_len = 10, .veq_ena = true, .veq_start_f1 = 4, - .veq_start_f2 = 4, .veq_len = 10, + .veq_start_f2 = 4, .veq_len = 10, - .vi_end_f1 = 21, .vi_end_f2 = 22, + .vi_end_f1 = 21, .vi_end_f2 = 22, .nbr_end = 539, .burst_ena = false, @@ -916,7 +916,7 @@ intel_tv_dpms(struct drm_encoder *encoder, int mode) struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - switch(mode) { + switch (mode) { case DRM_MODE_DPMS_ON: I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE); break; @@ -933,7 +933,7 @@ intel_tv_mode_lookup(const char *tv_format) { int i; - for (i = 0; i < sizeof(tv_modes) / sizeof (tv_modes[0]); i++) { + for (i = 0; i < sizeof(tv_modes) / sizeof(tv_modes[0]); i++) { const struct tv_mode *tv_mode = &tv_modes[i]; if (!strcmp(tv_format, tv_mode->name)) @@ -1128,7 +1128,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, if (color_conversion) { I915_WRITE(TV_CSC_Y, (color_conversion->ry << 16) | color_conversion->gy); - I915_WRITE(TV_CSC_Y2,(color_conversion->by << 16) | + I915_WRITE(TV_CSC_Y2, (color_conversion->by << 16) | color_conversion->ay); I915_WRITE(TV_CSC_U, (color_conversion->ru << 16) | color_conversion->gu); @@ -1232,7 +1232,7 @@ static const struct drm_display_mode reported_modes[] = { * \return false if TV is disconnected. */ static int -intel_tv_detect_type (struct intel_tv *intel_tv, +intel_tv_detect_type(struct intel_tv *intel_tv, struct drm_connector *connector) { struct drm_encoder *encoder = &intel_tv->base.base; @@ -1486,7 +1486,7 @@ intel_tv_get_modes(struct drm_connector *connector) } static void -intel_tv_destroy (struct drm_connector *connector) +intel_tv_destroy(struct drm_connector *connector) { drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); |