diff options
author | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
commit | 62b8c978ee6b8d135d9e7953221de58000dba986 (patch) | |
tree | 683b04b2e627f6710c22c151b23c8cc9a165315e /drivers/gpu/drm/i915 | |
parent | 78fd82238d0e5716578c326404184a27ba67fd6e (diff) | |
download | linux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz |
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'drivers/gpu/drm/i915')
50 files changed, 3420 insertions, 11268 deletions
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig deleted file mode 100644 index 6199d0b..0000000 --- a/drivers/gpu/drm/i915/Kconfig +++ /dev/null @@ -1,67 +0,0 @@ -config DRM_I915 - tristate "Intel 8xx/9xx/G3x/G4x/HD Graphics" - depends on DRM - depends on AGP - depends on AGP_INTEL - # we need shmfs for the swappable backing store, and in particular - # the shmem_readpage() which depends upon tmpfs - select SHMEM - select TMPFS - select DRM_KMS_HELPER - # i915 depends on ACPI_VIDEO when ACPI is enabled - # but for select to work, need to select ACPI_VIDEO's dependencies, ick - select BACKLIGHT_LCD_SUPPORT if ACPI - select BACKLIGHT_CLASS_DEVICE if ACPI - select VIDEO_OUTPUT_CONTROL if ACPI - select INPUT if ACPI - select ACPI_VIDEO if ACPI - select ACPI_BUTTON if ACPI - help - Choose this option if you have a system that has "Intel Graphics - Media Accelerator" or "HD Graphics" integrated graphics, - including 830M, 845G, 852GM, 855GM, 865G, 915G, 945G, 965G, - G35, G41, G43, G45 chipsets and Celeron, Pentium, Core i3, - Core i5, Core i7 as well as Atom CPUs with integrated graphics. - If M is selected, the module will be called i915. AGP support - is required for this driver to work. This driver is used by - the Intel driver in X.org 6.8 and XFree86 4.4 and above. It - replaces the older i830 module that supported a subset of the - hardware in older X.org releases. - - Note that the older i810/i815 chipsets require the use of the - i810 driver instead, and the Atom z5xx series has an entirely - different implementation. - -config DRM_I915_KMS - bool "Enable modesetting on intel by default" - depends on DRM_I915 - help - Choose this option if you want kernel modesetting enabled by default, - and you have a new enough userspace to support this. Running old - userspaces with this enabled will cause pain. Note that this causes - the driver to bind to PCI devices, which precludes loading things - like intelfb. - -config DRM_I915_FBDEV - bool "Enable legacy fbdev support for the modesettting intel driver" - depends on DRM_I915 - select DRM_KMS_FB_HELPER - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - default y - help - Choose this option if you have a need for the legacy fbdev - support. Note that this support also provide the linux console - support on top of the intel modesetting driver. - -config DRM_I915_PRELIMINARY_HW_SUPPORT - bool "Enable preliminary support for prerelease Intel hardware by default" - depends on DRM_I915 - help - Choose this option if you have prerelease Intel hardware and want the - i915 driver to support it by default. You can enable such support at - runtime with the module option i915.preliminary_hw_support=1; this - option changes the default for that module option. - - If in doubt, say "N". diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 41838ea..b8449a8 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -21,9 +21,6 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \ intel_display.o \ intel_crt.o \ intel_lvds.o \ - intel_dsi.o \ - intel_dsi_cmd.o \ - intel_dsi_pll.o \ intel_bios.o \ intel_ddi.o \ intel_dp.o \ @@ -33,6 +30,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \ intel_panel.o \ intel_pm.o \ intel_i2c.o \ + intel_fb.o \ intel_tv.o \ intel_dvo.o \ intel_ringbuffer.o \ @@ -53,8 +51,6 @@ i915-$(CONFIG_COMPAT) += i915_ioc32.o i915-$(CONFIG_ACPI) += intel_acpi.o -i915-$(CONFIG_DRM_I915_FBDEV) += intel_fbdev.o - obj-$(CONFIG_DRM_I915) += i915.o CFLAGS_i915_trace_points.o := -I$(src) diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h index 3121633..33a62ad 100644 --- a/drivers/gpu/drm/i915/dvo.h +++ b/drivers/gpu/drm/i915/dvo.h @@ -77,6 +77,17 @@ struct intel_dvo_dev_ops { struct drm_display_mode *mode); /* + * Callback to adjust the mode to be set in the CRTC. + * + * This allows an output to adjust the clock or even the entire set of + * timings, which is used for panels with fixed timings or for + * buses with clock limitations. + */ + bool (*mode_fixup)(struct intel_dvo_device *dvo, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); + + /* * Callback for preparing mode changes on an output */ void (*prepare)(struct intel_dvo_device *dvo); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6ed45a9..a6f4cb5 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -27,8 +27,6 @@ */ #include <linux/seq_file.h> -#include <linux/circ_buf.h> -#include <linux/ctype.h> #include <linux/debugfs.h> #include <linux/slab.h> #include <linux/export.h> @@ -40,6 +38,9 @@ #include <drm/i915_drm.h> #include "i915_drv.h" +#define DRM_I915_RING_DEBUG 1 + + #if defined(CONFIG_DEBUG_FS) enum { @@ -53,32 +54,6 @@ static const char *yesno(int v) return v ? "yes" : "no"; } -/* As the drm_debugfs_init() routines are called before dev->dev_private is - * allocated we need to hook into the minor for release. */ -static int -drm_add_fake_info_node(struct drm_minor *minor, - struct dentry *ent, - const void *key) -{ - struct drm_info_node *node; - - node = kmalloc(sizeof(*node), GFP_KERNEL); - if (node == NULL) { - debugfs_remove(ent); - return -ENOMEM; - } - - node->minor = minor; - node->dent = ent; - node->info_ent = (void *) key; - - mutex_lock(&minor->debugfs_lock); - list_add(&node->list, &minor->debugfs_list); - mutex_unlock(&minor->debugfs_lock); - - return 0; -} - static int i915_capabilities(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; @@ -170,13 +145,6 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) seq_printf(m, " (%s)", obj->ring->name); } -static void describe_ctx(struct seq_file *m, struct i915_hw_context *ctx) -{ - seq_putc(m, ctx->is_initialized ? 'I' : 'i'); - seq_putc(m, ctx->remap_slice ? 'R' : 'r'); - seq_putc(m, ' '); -} - static int i915_gem_object_list_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; @@ -586,53 +554,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) if (ret) return ret; - if (INTEL_INFO(dev)->gen >= 8) { - int i; - seq_printf(m, "Master Interrupt Control:\t%08x\n", - I915_READ(GEN8_MASTER_IRQ)); - - for (i = 0; i < 4; i++) { - seq_printf(m, "GT Interrupt IMR %d:\t%08x\n", - i, I915_READ(GEN8_GT_IMR(i))); - seq_printf(m, "GT Interrupt IIR %d:\t%08x\n", - i, I915_READ(GEN8_GT_IIR(i))); - seq_printf(m, "GT Interrupt IER %d:\t%08x\n", - i, I915_READ(GEN8_GT_IER(i))); - } - - for_each_pipe(i) { - seq_printf(m, "Pipe %c IMR:\t%08x\n", - pipe_name(i), - I915_READ(GEN8_DE_PIPE_IMR(i))); - seq_printf(m, "Pipe %c IIR:\t%08x\n", - pipe_name(i), - I915_READ(GEN8_DE_PIPE_IIR(i))); - seq_printf(m, "Pipe %c IER:\t%08x\n", - pipe_name(i), - I915_READ(GEN8_DE_PIPE_IER(i))); - } - - seq_printf(m, "Display Engine port interrupt mask:\t%08x\n", - I915_READ(GEN8_DE_PORT_IMR)); - seq_printf(m, "Display Engine port interrupt identity:\t%08x\n", - I915_READ(GEN8_DE_PORT_IIR)); - seq_printf(m, "Display Engine port interrupt enable:\t%08x\n", - I915_READ(GEN8_DE_PORT_IER)); - - seq_printf(m, "Display Engine misc interrupt mask:\t%08x\n", - I915_READ(GEN8_DE_MISC_IMR)); - seq_printf(m, "Display Engine misc interrupt identity:\t%08x\n", - I915_READ(GEN8_DE_MISC_IIR)); - seq_printf(m, "Display Engine misc interrupt enable:\t%08x\n", - I915_READ(GEN8_DE_MISC_IER)); - - seq_printf(m, "PCU interrupt mask:\t%08x\n", - I915_READ(GEN8_PCU_IMR)); - seq_printf(m, "PCU interrupt identity:\t%08x\n", - I915_READ(GEN8_PCU_IIR)); - seq_printf(m, "PCU interrupt enable:\t%08x\n", - I915_READ(GEN8_PCU_IER)); - } else if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev)) { seq_printf(m, "Display IER:\t%08x\n", I915_READ(VLV_IER)); seq_printf(m, "Display IIR:\t%08x\n", @@ -704,7 +626,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) seq_printf(m, "Interrupts received: %d\n", atomic_read(&dev_priv->irq_received)); for_each_ring(ring, dev_priv, i) { - if (INTEL_INFO(dev)->gen >= 6) { + if (IS_GEN6(dev) || IS_GEN7(dev)) { seq_printf(m, "Graphics Interrupt mask (%s): %08x\n", ring->name, I915_READ_IMR(ring)); @@ -921,8 +843,6 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) drm_i915_private_t *dev_priv = dev->dev_private; int ret; - flush_delayed_work(&dev_priv->rps.delayed_resume_work); - if (IS_GEN5(dev)) { u16 rgvswctl = I915_READ16(MEMSWCTL); u16 rgvstat = I915_READ16(MEMSTAT_ILK); @@ -1401,8 +1321,6 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) return 0; } - flush_delayed_work(&dev_priv->rps.delayed_resume_work); - ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock); if (ret) return ret; @@ -1477,12 +1395,12 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - struct intel_fbdev *ifbdev = NULL; + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_fbdev *ifbdev; struct intel_framebuffer *fb; + int ret; -#ifdef CONFIG_DRM_I915_FBDEV - struct drm_i915_private *dev_priv = dev->dev_private; - int ret = mutex_lock_interruptible(&dev->mode_config.mutex); + ret = mutex_lock_interruptible(&dev->mode_config.mutex); if (ret) return ret; @@ -1498,11 +1416,10 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) describe_obj(m, fb->obj); seq_putc(m, '\n'); mutex_unlock(&dev->mode_config.mutex); -#endif mutex_lock(&dev->mode_config.fb_lock); list_for_each_entry(fb, &dev->mode_config.fb_list, base.head) { - if (ifbdev && &fb->base == ifbdev->helper.fb) + if (&fb->base == ifbdev->helper.fb) continue; seq_printf(m, "user size: %d x %d, depth %d, %d bpp, refcount %d, obj ", @@ -1525,7 +1442,6 @@ static int i915_context_status(struct seq_file *m, void *unused) struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; struct intel_ring_buffer *ring; - struct i915_hw_context *ctx; int ret, i; ret = mutex_lock_interruptible(&dev->mode_config.mutex); @@ -1544,15 +1460,12 @@ static int i915_context_status(struct seq_file *m, void *unused) seq_putc(m, '\n'); } - list_for_each_entry(ctx, &dev_priv->context_list, link) { - seq_puts(m, "HW context "); - describe_ctx(m, ctx); - for_each_ring(ring, dev_priv, i) - if (ring->default_context == ctx) - seq_printf(m, "(default context %s) ", ring->name); - - describe_obj(m, ctx->obj); - seq_putc(m, '\n'); + for_each_ring(ring, dev_priv, i) { + if (ring->default_context) { + seq_printf(m, "HW default context %s ring ", ring->name); + describe_obj(m, ring->default_context->obj); + seq_putc(m, '\n'); + } } mutex_unlock(&dev->mode_config.mutex); @@ -1623,7 +1536,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data) I915_READ16(C0DRB3)); seq_printf(m, "C1DRB3 = 0x%04x\n", I915_READ16(C1DRB3)); - } else if (INTEL_INFO(dev)->gen >= 6) { + } else if (IS_GEN6(dev) || IS_GEN7(dev)) { seq_printf(m, "MAD_DIMM_C0 = 0x%08x\n", I915_READ(MAD_DIMM_C0)); seq_printf(m, "MAD_DIMM_C1 = 0x%08x\n", @@ -1632,12 +1545,8 @@ static int i915_swizzle_info(struct seq_file *m, void *data) I915_READ(MAD_DIMM_C2)); seq_printf(m, "TILECTL = 0x%08x\n", I915_READ(TILECTL)); - if (IS_GEN8(dev)) - seq_printf(m, "GAMTARBMODE = 0x%08x\n", - I915_READ(GAMTARBMODE)); - else - seq_printf(m, "ARB_MODE = 0x%08x\n", - I915_READ(ARB_MODE)); + seq_printf(m, "ARB_MODE = 0x%08x\n", + I915_READ(ARB_MODE)); seq_printf(m, "DISP_ARB_CTL = 0x%08x\n", I915_READ(DISP_ARB_CTL)); } @@ -1646,37 +1555,18 @@ static int i915_swizzle_info(struct seq_file *m, void *data) return 0; } -static void gen8_ppgtt_info(struct seq_file *m, struct drm_device *dev) +static int i915_ppgtt_info(struct seq_file *m, void *data) { + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_ring_buffer *ring; - struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; - int unused, i; - - if (!ppgtt) - return; - - seq_printf(m, "Page directories: %d\n", ppgtt->num_pd_pages); - seq_printf(m, "Page tables: %d\n", ppgtt->num_pt_pages); - for_each_ring(ring, dev_priv, unused) { - seq_printf(m, "%s\n", ring->name); - for (i = 0; i < 4; i++) { - u32 offset = 0x270 + i * 8; - u64 pdp = I915_READ(ring->mmio_base + offset + 4); - pdp <<= 32; - pdp |= I915_READ(ring->mmio_base + offset); - for (i = 0; i < 4; i++) - seq_printf(m, "\tPDP%d 0x%016llx\n", i, pdp); - } - } -} + int i, ret; -static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_ring_buffer *ring; - int i; + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; if (INTEL_INFO(dev)->gen == 6) seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(GFX_MODE)); @@ -1695,22 +1585,6 @@ static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev) seq_printf(m, "pd gtt offset: 0x%08x\n", ppgtt->pd_offset); } seq_printf(m, "ECOCHK: 0x%08x\n", I915_READ(GAM_ECOCHK)); -} - -static int i915_ppgtt_info(struct seq_file *m, void *data) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - - int ret = mutex_lock_interruptible(&dev->struct_mutex); - if (ret) - return ret; - - if (INTEL_INFO(dev)->gen >= 8) - gen8_ppgtt_info(m, dev); - else if (INTEL_INFO(dev)->gen >= 6) - gen6_ppgtt_info(m, dev); - mutex_unlock(&dev->struct_mutex); return 0; @@ -1736,27 +1610,27 @@ static int i915_dpio_info(struct seq_file *m, void *data) seq_printf(m, "DPIO_CTL: 0x%08x\n", I915_READ(DPIO_CTL)); seq_printf(m, "DPIO_DIV_A: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_DIV_A)); + vlv_dpio_read(dev_priv, _DPIO_DIV_A)); seq_printf(m, "DPIO_DIV_B: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_DIV_B)); + vlv_dpio_read(dev_priv, _DPIO_DIV_B)); seq_printf(m, "DPIO_REFSFR_A: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_REFSFR_A)); + vlv_dpio_read(dev_priv, _DPIO_REFSFR_A)); seq_printf(m, "DPIO_REFSFR_B: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_REFSFR_B)); + vlv_dpio_read(dev_priv, _DPIO_REFSFR_B)); seq_printf(m, "DPIO_CORE_CLK_A: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_CORE_CLK_A)); + vlv_dpio_read(dev_priv, _DPIO_CORE_CLK_A)); seq_printf(m, "DPIO_CORE_CLK_B: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_CORE_CLK_B)); + vlv_dpio_read(dev_priv, _DPIO_CORE_CLK_B)); seq_printf(m, "DPIO_LPF_COEFF_A: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_LPF_COEFF_A)); + vlv_dpio_read(dev_priv, _DPIO_LPF_COEFF_A)); seq_printf(m, "DPIO_LPF_COEFF_B: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, _DPIO_LPF_COEFF_B)); + vlv_dpio_read(dev_priv, _DPIO_LPF_COEFF_B)); seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n", - vlv_dpio_read(dev_priv, PIPE_A, DPIO_FASTCLK_DISABLE)); + vlv_dpio_read(dev_priv, DPIO_FASTCLK_DISABLE)); mutex_unlock(&dev_priv->dpio_lock); @@ -1781,815 +1655,176 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) struct drm_info_node *node = m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 psrperf = 0; - bool enabled = false; - - seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support)); - seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok)); - - enabled = HAS_PSR(dev) && - I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE; - seq_printf(m, "Enabled: %s\n", yesno(enabled)); - - if (HAS_PSR(dev)) - psrperf = I915_READ(EDP_PSR_PERF_CNT(dev)) & - EDP_PSR_PERF_CNT_MASK; - seq_printf(m, "Performance_Counter: %u\n", psrperf); - - return 0; -} - -static int i915_energy_uJ(struct seq_file *m, void *data) -{ - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - u64 power; - u32 units; - - if (INTEL_INFO(dev)->gen < 6) - return -ENODEV; - - rdmsrl(MSR_RAPL_POWER_UNIT, power); - power = (power & 0x1f00) >> 8; - units = 1000000 / (1 << power); /* convert to uJ */ - power = I915_READ(MCH_SECP_NRG_STTS); - power *= units; - - seq_printf(m, "%llu", (long long unsigned)power); - - return 0; -} - -static int i915_pc8_status(struct seq_file *m, void *unused) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = dev->dev_private; + u32 psrstat, psrperf; if (!IS_HASWELL(dev)) { - seq_puts(m, "not supported\n"); - return 0; - } - - mutex_lock(&dev_priv->pc8.lock); - seq_printf(m, "Requirements met: %s\n", - yesno(dev_priv->pc8.requirements_met)); - seq_printf(m, "GPU idle: %s\n", yesno(dev_priv->pc8.gpu_idle)); - seq_printf(m, "Disable count: %d\n", dev_priv->pc8.disable_count); - seq_printf(m, "IRQs disabled: %s\n", - yesno(dev_priv->pc8.irqs_disabled)); - seq_printf(m, "Enabled: %s\n", yesno(dev_priv->pc8.enabled)); - mutex_unlock(&dev_priv->pc8.lock); - - return 0; -} - -struct pipe_crc_info { - const char *name; - struct drm_device *dev; - enum pipe pipe; -}; - -static int i915_pipe_crc_open(struct inode *inode, struct file *filep) -{ - struct pipe_crc_info *info = inode->i_private; - struct drm_i915_private *dev_priv = info->dev->dev_private; - struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; - - spin_lock_irq(&pipe_crc->lock); - - if (pipe_crc->opened) { - spin_unlock_irq(&pipe_crc->lock); - return -EBUSY; /* already open */ - } - - pipe_crc->opened = true; - filep->private_data = inode->i_private; - - spin_unlock_irq(&pipe_crc->lock); - - return 0; -} - -static int i915_pipe_crc_release(struct inode *inode, struct file *filep) -{ - struct pipe_crc_info *info = inode->i_private; - struct drm_i915_private *dev_priv = info->dev->dev_private; - struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; - - spin_lock_irq(&pipe_crc->lock); - pipe_crc->opened = false; - spin_unlock_irq(&pipe_crc->lock); - - return 0; -} - -/* (6 fields, 8 chars each, space separated (5) + '\n') */ -#define PIPE_CRC_LINE_LEN (6 * 8 + 5 + 1) -/* account for \'0' */ -#define PIPE_CRC_BUFFER_LEN (PIPE_CRC_LINE_LEN + 1) - -static int pipe_crc_data_count(struct intel_pipe_crc *pipe_crc) -{ - assert_spin_locked(&pipe_crc->lock); - return CIRC_CNT(pipe_crc->head, pipe_crc->tail, - INTEL_PIPE_CRC_ENTRIES_NR); -} - -static ssize_t -i915_pipe_crc_read(struct file *filep, char __user *user_buf, size_t count, - loff_t *pos) -{ - struct pipe_crc_info *info = filep->private_data; - struct drm_device *dev = info->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; - char buf[PIPE_CRC_BUFFER_LEN]; - int head, tail, n_entries, n; - ssize_t bytes_read; - - /* - * Don't allow user space to provide buffers not big enough to hold - * a line of data. - */ - if (count < PIPE_CRC_LINE_LEN) - return -EINVAL; - - if (pipe_crc->source == INTEL_PIPE_CRC_SOURCE_NONE) - return 0; - - /* nothing to read */ - spin_lock_irq(&pipe_crc->lock); - while (pipe_crc_data_count(pipe_crc) == 0) { - int ret; - - if (filep->f_flags & O_NONBLOCK) { - spin_unlock_irq(&pipe_crc->lock); - return -EAGAIN; - } - - ret = wait_event_interruptible_lock_irq(pipe_crc->wq, - pipe_crc_data_count(pipe_crc), pipe_crc->lock); - if (ret) { - spin_unlock_irq(&pipe_crc->lock); - return ret; - } - } - - /* We now have one or more entries to read */ - head = pipe_crc->head; - tail = pipe_crc->tail; - n_entries = min((size_t)CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR), - count / PIPE_CRC_LINE_LEN); - spin_unlock_irq(&pipe_crc->lock); - - bytes_read = 0; - n = 0; - do { - struct intel_pipe_crc_entry *entry = &pipe_crc->entries[tail]; - int ret; - - bytes_read += snprintf(buf, PIPE_CRC_BUFFER_LEN, - "%8u %8x %8x %8x %8x %8x\n", - entry->frame, entry->crc[0], - entry->crc[1], entry->crc[2], - entry->crc[3], entry->crc[4]); - - ret = copy_to_user(user_buf + n * PIPE_CRC_LINE_LEN, - buf, PIPE_CRC_LINE_LEN); - if (ret == PIPE_CRC_LINE_LEN) - return -EFAULT; - - BUILD_BUG_ON_NOT_POWER_OF_2(INTEL_PIPE_CRC_ENTRIES_NR); - tail = (tail + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); - n++; - } while (--n_entries); - - spin_lock_irq(&pipe_crc->lock); - pipe_crc->tail = tail; - spin_unlock_irq(&pipe_crc->lock); - - return bytes_read; -} - -static const struct file_operations i915_pipe_crc_fops = { - .owner = THIS_MODULE, - .open = i915_pipe_crc_open, - .read = i915_pipe_crc_read, - .release = i915_pipe_crc_release, -}; - -static struct pipe_crc_info i915_pipe_crc_data[I915_MAX_PIPES] = { - { - .name = "i915_pipe_A_crc", - .pipe = PIPE_A, - }, - { - .name = "i915_pipe_B_crc", - .pipe = PIPE_B, - }, - { - .name = "i915_pipe_C_crc", - .pipe = PIPE_C, - }, -}; - -static int i915_pipe_crc_create(struct dentry *root, struct drm_minor *minor, - enum pipe pipe) -{ - struct drm_device *dev = minor->dev; - struct dentry *ent; - struct pipe_crc_info *info = &i915_pipe_crc_data[pipe]; - - info->dev = dev; - ent = debugfs_create_file(info->name, S_IRUGO, root, info, - &i915_pipe_crc_fops); - if (IS_ERR(ent)) - return PTR_ERR(ent); - - return drm_add_fake_info_node(minor, ent, info); -} - -static const char * const pipe_crc_sources[] = { - "none", - "plane1", - "plane2", - "pf", - "pipe", - "TV", - "DP-B", - "DP-C", - "DP-D", - "auto", -}; - -static const char *pipe_crc_source_name(enum intel_pipe_crc_source source) -{ - BUILD_BUG_ON(ARRAY_SIZE(pipe_crc_sources) != INTEL_PIPE_CRC_SOURCE_MAX); - return pipe_crc_sources[source]; -} - -static int display_crc_ctl_show(struct seq_file *m, void *data) -{ - struct drm_device *dev = m->private; - struct drm_i915_private *dev_priv = dev->dev_private; - int i; - - for (i = 0; i < I915_MAX_PIPES; i++) - seq_printf(m, "%c %s\n", pipe_name(i), - pipe_crc_source_name(dev_priv->pipe_crc[i].source)); - - return 0; -} - -static int display_crc_ctl_open(struct inode *inode, struct file *file) -{ - struct drm_device *dev = inode->i_private; - - return single_open(file, display_crc_ctl_show, dev); -} - -static int i8xx_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, - uint32_t *val) -{ - if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) - *source = INTEL_PIPE_CRC_SOURCE_PIPE; - - switch (*source) { - case INTEL_PIPE_CRC_SOURCE_PIPE: - *val = PIPE_CRC_ENABLE | PIPE_CRC_INCLUDE_BORDER_I8XX; - break; - case INTEL_PIPE_CRC_SOURCE_NONE: - *val = 0; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int i9xx_pipe_crc_auto_source(struct drm_device *dev, enum pipe pipe, - enum intel_pipe_crc_source *source) -{ - struct intel_encoder *encoder; - struct intel_crtc *crtc; - struct intel_digital_port *dig_port; - int ret = 0; - - *source = INTEL_PIPE_CRC_SOURCE_PIPE; - - mutex_lock(&dev->mode_config.mutex); - list_for_each_entry(encoder, &dev->mode_config.encoder_list, - base.head) { - if (!encoder->base.crtc) - continue; - - crtc = to_intel_crtc(encoder->base.crtc); - - if (crtc->pipe != pipe) - continue; - - switch (encoder->type) { - case INTEL_OUTPUT_TVOUT: - *source = INTEL_PIPE_CRC_SOURCE_TV; + seq_puts(m, "PSR not supported on this platform\n"); + } else if (IS_HASWELL(dev) && I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE) { + seq_puts(m, "PSR enabled\n"); + } else { + seq_puts(m, "PSR disabled: "); + switch (dev_priv->no_psr_reason) { + case PSR_NO_SOURCE: + seq_puts(m, "not supported on this platform"); break; - case INTEL_OUTPUT_DISPLAYPORT: - case INTEL_OUTPUT_EDP: - dig_port = enc_to_dig_port(&encoder->base); - switch (dig_port->port) { - case PORT_B: - *source = INTEL_PIPE_CRC_SOURCE_DP_B; - break; - case PORT_C: - *source = INTEL_PIPE_CRC_SOURCE_DP_C; - break; - case PORT_D: - *source = INTEL_PIPE_CRC_SOURCE_DP_D; - break; - default: - WARN(1, "nonexisting DP port %c\n", - port_name(dig_port->port)); - break; - } + case PSR_NO_SINK: + seq_puts(m, "not supported by panel"); + break; + case PSR_MODULE_PARAM: + seq_puts(m, "disabled by flag"); + break; + case PSR_CRTC_NOT_ACTIVE: + seq_puts(m, "crtc not active"); + break; + case PSR_PWR_WELL_ENABLED: + seq_puts(m, "power well enabled"); break; + case PSR_NOT_TILED: + seq_puts(m, "not tiled"); + break; + case PSR_SPRITE_ENABLED: + seq_puts(m, "sprite enabled"); + break; + case PSR_S3D_ENABLED: + seq_puts(m, "stereo 3d enabled"); + break; + case PSR_INTERLACED_ENABLED: + seq_puts(m, "interlaced enabled"); + break; + case PSR_HSW_NOT_DDIA: + seq_puts(m, "HSW ties PSR to DDI A (eDP)"); + break; + default: + seq_puts(m, "unknown reason"); } + seq_puts(m, "\n"); + return 0; } - mutex_unlock(&dev->mode_config.mutex); - return ret; -} - -static int vlv_pipe_crc_ctl_reg(struct drm_device *dev, - enum pipe pipe, - enum intel_pipe_crc_source *source, - uint32_t *val) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - bool need_stable_symbols = false; + psrstat = I915_READ(EDP_PSR_STATUS_CTL); - if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) { - int ret = i9xx_pipe_crc_auto_source(dev, pipe, source); - if (ret) - return ret; - } - - switch (*source) { - case INTEL_PIPE_CRC_SOURCE_PIPE: - *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_VLV; - break; - case INTEL_PIPE_CRC_SOURCE_DP_B: - *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_B_VLV; - need_stable_symbols = true; - break; - case INTEL_PIPE_CRC_SOURCE_DP_C: - *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_C_VLV; - need_stable_symbols = true; - break; - case INTEL_PIPE_CRC_SOURCE_NONE: - *val = 0; + seq_puts(m, "PSR Current State: "); + switch (psrstat & EDP_PSR_STATUS_STATE_MASK) { + case EDP_PSR_STATUS_STATE_IDLE: + seq_puts(m, "Reset state\n"); break; - default: - return -EINVAL; - } - - /* - * When the pipe CRC tap point is after the transcoders we need - * to tweak symbol-level features to produce a deterministic series of - * symbols for a given frame. We need to reset those features only once - * a frame (instead of every nth symbol): - * - DC-balance: used to ensure a better clock recovery from the data - * link (SDVO) - * - DisplayPort scrambling: used for EMI reduction - */ - if (need_stable_symbols) { - uint32_t tmp = I915_READ(PORT_DFT2_G4X); - - WARN_ON(!IS_G4X(dev)); - - tmp |= DC_BALANCE_RESET_VLV; - if (pipe == PIPE_A) - tmp |= PIPE_A_SCRAMBLE_RESET; - else - tmp |= PIPE_B_SCRAMBLE_RESET; - - I915_WRITE(PORT_DFT2_G4X, tmp); - } - - return 0; -} - -static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev, - enum pipe pipe, - enum intel_pipe_crc_source *source, - uint32_t *val) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - bool need_stable_symbols = false; - - if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) { - int ret = i9xx_pipe_crc_auto_source(dev, pipe, source); - if (ret) - return ret; - } - - switch (*source) { - case INTEL_PIPE_CRC_SOURCE_PIPE: - *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_I9XX; + case EDP_PSR_STATUS_STATE_SRDONACK: + seq_puts(m, "Wait for TG/Stream to send on frame of data after SRD conditions are met\n"); break; - case INTEL_PIPE_CRC_SOURCE_TV: - if (!SUPPORTS_TV(dev)) - return -EINVAL; - *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_TV_PRE; + case EDP_PSR_STATUS_STATE_SRDENT: + seq_puts(m, "SRD entry\n"); break; - case INTEL_PIPE_CRC_SOURCE_DP_B: - if (!IS_G4X(dev)) - return -EINVAL; - *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_B_G4X; - need_stable_symbols = true; + case EDP_PSR_STATUS_STATE_BUFOFF: + seq_puts(m, "Wait for buffer turn off\n"); break; - case INTEL_PIPE_CRC_SOURCE_DP_C: - if (!IS_G4X(dev)) - return -EINVAL; - *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_C_G4X; - need_stable_symbols = true; + case EDP_PSR_STATUS_STATE_BUFON: + seq_puts(m, "Wait for buffer turn on\n"); break; - case INTEL_PIPE_CRC_SOURCE_DP_D: - if (!IS_G4X(dev)) - return -EINVAL; - *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_D_G4X; - need_stable_symbols = true; + case EDP_PSR_STATUS_STATE_AUXACK: + seq_puts(m, "Wait for AUX to acknowledge on SRD exit\n"); break; - case INTEL_PIPE_CRC_SOURCE_NONE: - *val = 0; + case EDP_PSR_STATUS_STATE_SRDOFFACK: + seq_puts(m, "Wait for TG/Stream to acknowledge the SRD VDM exit\n"); break; default: - return -EINVAL; - } - - /* - * When the pipe CRC tap point is after the transcoders we need - * to tweak symbol-level features to produce a deterministic series of - * symbols for a given frame. We need to reset those features only once - * a frame (instead of every nth symbol): - * - DC-balance: used to ensure a better clock recovery from the data - * link (SDVO) - * - DisplayPort scrambling: used for EMI reduction - */ - if (need_stable_symbols) { - uint32_t tmp = I915_READ(PORT_DFT2_G4X); - - WARN_ON(!IS_G4X(dev)); - - I915_WRITE(PORT_DFT_I9XX, - I915_READ(PORT_DFT_I9XX) | DC_BALANCE_RESET); - - if (pipe == PIPE_A) - tmp |= PIPE_A_SCRAMBLE_RESET; - else - tmp |= PIPE_B_SCRAMBLE_RESET; - - I915_WRITE(PORT_DFT2_G4X, tmp); - } - - return 0; -} - -static void vlv_undo_pipe_scramble_reset(struct drm_device *dev, - enum pipe pipe) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t tmp = I915_READ(PORT_DFT2_G4X); - - if (pipe == PIPE_A) - tmp &= ~PIPE_A_SCRAMBLE_RESET; - else - tmp &= ~PIPE_B_SCRAMBLE_RESET; - if (!(tmp & PIPE_SCRAMBLE_RESET_MASK)) - tmp &= ~DC_BALANCE_RESET_VLV; - I915_WRITE(PORT_DFT2_G4X, tmp); - -} - -static void g4x_undo_pipe_scramble_reset(struct drm_device *dev, - enum pipe pipe) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t tmp = I915_READ(PORT_DFT2_G4X); - - if (pipe == PIPE_A) - tmp &= ~PIPE_A_SCRAMBLE_RESET; - else - tmp &= ~PIPE_B_SCRAMBLE_RESET; - I915_WRITE(PORT_DFT2_G4X, tmp); - - if (!(tmp & PIPE_SCRAMBLE_RESET_MASK)) { - I915_WRITE(PORT_DFT_I9XX, - I915_READ(PORT_DFT_I9XX) & ~DC_BALANCE_RESET); - } -} - -static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, - uint32_t *val) -{ - if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) - *source = INTEL_PIPE_CRC_SOURCE_PIPE; - - switch (*source) { - case INTEL_PIPE_CRC_SOURCE_PLANE1: - *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PRIMARY_ILK; - break; - case INTEL_PIPE_CRC_SOURCE_PLANE2: - *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_ILK; - break; - case INTEL_PIPE_CRC_SOURCE_PIPE: - *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_ILK; - break; - case INTEL_PIPE_CRC_SOURCE_NONE: - *val = 0; + seq_puts(m, "Unknown\n"); break; - default: - return -EINVAL; } - return 0; -} - -static int ivb_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, - uint32_t *val) -{ - if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) - *source = INTEL_PIPE_CRC_SOURCE_PF; - - switch (*source) { - case INTEL_PIPE_CRC_SOURCE_PLANE1: - *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PRIMARY_IVB; - break; - case INTEL_PIPE_CRC_SOURCE_PLANE2: - *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB; + seq_puts(m, "Link Status: "); + switch (psrstat & EDP_PSR_STATUS_LINK_MASK) { + case EDP_PSR_STATUS_LINK_FULL_OFF: + seq_puts(m, "Link is fully off\n"); break; - case INTEL_PIPE_CRC_SOURCE_PF: - *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB; + case EDP_PSR_STATUS_LINK_FULL_ON: + seq_puts(m, "Link is fully on\n"); break; - case INTEL_PIPE_CRC_SOURCE_NONE: - *val = 0; + case EDP_PSR_STATUS_LINK_STANDBY: + seq_puts(m, "Link is in standby\n"); break; default: - return -EINVAL; + seq_puts(m, "Unknown\n"); + break; } - return 0; -} - -static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, - enum intel_pipe_crc_source source) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; - u32 val; - int ret; - - if (pipe_crc->source == source) - return 0; - - /* forbid changing the source without going back to 'none' */ - if (pipe_crc->source && source) - return -EINVAL; + seq_printf(m, "PSR Entry Count: %u\n", + psrstat >> EDP_PSR_STATUS_COUNT_SHIFT & + EDP_PSR_STATUS_COUNT_MASK); - if (IS_GEN2(dev)) - ret = i8xx_pipe_crc_ctl_reg(&source, &val); - else if (INTEL_INFO(dev)->gen < 5) - ret = i9xx_pipe_crc_ctl_reg(dev, pipe, &source, &val); - else if (IS_VALLEYVIEW(dev)) - ret = vlv_pipe_crc_ctl_reg(dev,pipe, &source, &val); - else if (IS_GEN5(dev) || IS_GEN6(dev)) - ret = ilk_pipe_crc_ctl_reg(&source, &val); - else - ret = ivb_pipe_crc_ctl_reg(&source, &val); + seq_printf(m, "Max Sleep Timer Counter: %u\n", + psrstat >> EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT & + EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK); - if (ret != 0) - return ret; - - /* none -> real source transition */ - if (source) { - DRM_DEBUG_DRIVER("collecting CRCs for pipe %c, %s\n", - pipe_name(pipe), pipe_crc_source_name(source)); - - pipe_crc->entries = kzalloc(sizeof(*pipe_crc->entries) * - INTEL_PIPE_CRC_ENTRIES_NR, - GFP_KERNEL); - if (!pipe_crc->entries) - return -ENOMEM; - - spin_lock_irq(&pipe_crc->lock); - pipe_crc->head = 0; - pipe_crc->tail = 0; - spin_unlock_irq(&pipe_crc->lock); - } + seq_printf(m, "Had AUX error: %s\n", + yesno(psrstat & EDP_PSR_STATUS_AUX_ERROR)); - pipe_crc->source = source; + seq_printf(m, "Sending AUX: %s\n", + yesno(psrstat & EDP_PSR_STATUS_AUX_SENDING)); - I915_WRITE(PIPE_CRC_CTL(pipe), val); - POSTING_READ(PIPE_CRC_CTL(pipe)); + seq_printf(m, "Sending Idle: %s\n", + yesno(psrstat & EDP_PSR_STATUS_SENDING_IDLE)); - /* real source -> none transition */ - if (source == INTEL_PIPE_CRC_SOURCE_NONE) { - struct intel_pipe_crc_entry *entries; + seq_printf(m, "Sending TP2 TP3: %s\n", + yesno(psrstat & EDP_PSR_STATUS_SENDING_TP2_TP3)); - DRM_DEBUG_DRIVER("stopping CRCs for pipe %c\n", - pipe_name(pipe)); + seq_printf(m, "Sending TP1: %s\n", + yesno(psrstat & EDP_PSR_STATUS_SENDING_TP1)); - intel_wait_for_vblank(dev, pipe); + seq_printf(m, "Idle Count: %u\n", + psrstat & EDP_PSR_STATUS_IDLE_MASK); - spin_lock_irq(&pipe_crc->lock); - entries = pipe_crc->entries; - pipe_crc->entries = NULL; - spin_unlock_irq(&pipe_crc->lock); - - kfree(entries); - - if (IS_G4X(dev)) - g4x_undo_pipe_scramble_reset(dev, pipe); - else if (IS_VALLEYVIEW(dev)) - vlv_undo_pipe_scramble_reset(dev, pipe); - } + psrperf = (I915_READ(EDP_PSR_PERF_CNT)) & EDP_PSR_PERF_CNT_MASK; + seq_printf(m, "Performance Counter: %u\n", psrperf); return 0; } -/* - * Parse pipe CRC command strings: - * command: wsp* object wsp+ name wsp+ source wsp* - * object: 'pipe' - * name: (A | B | C) - * source: (none | plane1 | plane2 | pf) - * wsp: (#0x20 | #0x9 | #0xA)+ - * - * eg.: - * "pipe A plane1" -> Start CRC computations on plane1 of pipe A - * "pipe A none" -> Stop CRC - */ -static int display_crc_ctl_tokenize(char *buf, char *words[], int max_words) -{ - int n_words = 0; - - while (*buf) { - char *end; - - /* skip leading white space */ - buf = skip_spaces(buf); - if (!*buf) - break; /* end of buffer */ - - /* find end of word */ - for (end = buf; *end && !isspace(*end); end++) - ; - - if (n_words == max_words) { - DRM_DEBUG_DRIVER("too many words, allowed <= %d\n", - max_words); - return -EINVAL; /* ran out of words[] before bytes */ - } - - if (*end) - *end++ = '\0'; - words[n_words++] = buf; - buf = end; - } - - return n_words; -} - -enum intel_pipe_crc_object { - PIPE_CRC_OBJECT_PIPE, -}; - -static const char * const pipe_crc_objects[] = { - "pipe", -}; - -static int -display_crc_ctl_parse_object(const char *buf, enum intel_pipe_crc_object *o) +static int i915_energy_uJ(struct seq_file *m, void *data) { - int i; - - for (i = 0; i < ARRAY_SIZE(pipe_crc_objects); i++) - if (!strcmp(buf, pipe_crc_objects[i])) { - *o = i; - return 0; - } - - return -EINVAL; -} + struct drm_info_node *node = m->private; + struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u64 power; + u32 units; -static int display_crc_ctl_parse_pipe(const char *buf, enum pipe *pipe) -{ - const char name = buf[0]; + if (INTEL_INFO(dev)->gen < 6) + return -ENODEV; - if (name < 'A' || name >= pipe_name(I915_MAX_PIPES)) - return -EINVAL; + rdmsrl(MSR_RAPL_POWER_UNIT, power); + power = (power & 0x1f00) >> 8; + units = 1000000 / (1 << power); /* convert to uJ */ + power = I915_READ(MCH_SECP_NRG_STTS); + power *= units; - *pipe = name - 'A'; + seq_printf(m, "%llu", (long long unsigned)power); return 0; } -static int -display_crc_ctl_parse_source(const char *buf, enum intel_pipe_crc_source *s) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(pipe_crc_sources); i++) - if (!strcmp(buf, pipe_crc_sources[i])) { - *s = i; - return 0; - } - - return -EINVAL; -} - -static int display_crc_ctl_parse(struct drm_device *dev, char *buf, size_t len) -{ -#define N_WORDS 3 - int n_words; - char *words[N_WORDS]; - enum pipe pipe; - enum intel_pipe_crc_object object; - enum intel_pipe_crc_source source; - - n_words = display_crc_ctl_tokenize(buf, words, N_WORDS); - if (n_words != N_WORDS) { - DRM_DEBUG_DRIVER("tokenize failed, a command is %d words\n", - N_WORDS); - return -EINVAL; - } - - if (display_crc_ctl_parse_object(words[0], &object) < 0) { - DRM_DEBUG_DRIVER("unknown object %s\n", words[0]); - return -EINVAL; - } - - if (display_crc_ctl_parse_pipe(words[1], &pipe) < 0) { - DRM_DEBUG_DRIVER("unknown pipe %s\n", words[1]); - return -EINVAL; - } - - if (display_crc_ctl_parse_source(words[2], &source) < 0) { - DRM_DEBUG_DRIVER("unknown source %s\n", words[2]); - return -EINVAL; - } - - return pipe_crc_set_source(dev, pipe, source); -} - -static ssize_t display_crc_ctl_write(struct file *file, const char __user *ubuf, - size_t len, loff_t *offp) +static int i915_pc8_status(struct seq_file *m, void *unused) { - struct seq_file *m = file->private_data; - struct drm_device *dev = m->private; - char *tmpbuf; - int ret; + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = dev->dev_private; - if (len == 0) + if (!IS_HASWELL(dev)) { + seq_puts(m, "not supported\n"); return 0; - - if (len > PAGE_SIZE - 1) { - DRM_DEBUG_DRIVER("expected <%lu bytes into pipe crc control\n", - PAGE_SIZE); - return -E2BIG; - } - - tmpbuf = kmalloc(len + 1, GFP_KERNEL); - if (!tmpbuf) - return -ENOMEM; - - if (copy_from_user(tmpbuf, ubuf, len)) { - ret = -EFAULT; - goto out; } - tmpbuf[len] = '\0'; - ret = display_crc_ctl_parse(dev, tmpbuf, len); - -out: - kfree(tmpbuf); - if (ret < 0) - return ret; + mutex_lock(&dev_priv->pc8.lock); + seq_printf(m, "Requirements met: %s\n", + yesno(dev_priv->pc8.requirements_met)); + seq_printf(m, "GPU idle: %s\n", yesno(dev_priv->pc8.gpu_idle)); + seq_printf(m, "Disable count: %d\n", dev_priv->pc8.disable_count); + seq_printf(m, "IRQs disabled: %s\n", + yesno(dev_priv->pc8.irqs_disabled)); + seq_printf(m, "Enabled: %s\n", yesno(dev_priv->pc8.enabled)); + mutex_unlock(&dev_priv->pc8.lock); - *offp += len; - return len; + return 0; } -static const struct file_operations i915_display_crc_ctl_fops = { - .owner = THIS_MODULE, - .open = display_crc_ctl_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = display_crc_ctl_write -}; - static int i915_wedged_get(void *data, u64 *val) { @@ -2650,72 +1885,6 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_ring_stop_fops, i915_ring_stop_get, i915_ring_stop_set, "0x%08llx\n"); -static int -i915_ring_missed_irq_get(void *data, u64 *val) -{ - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = dev->dev_private; - - *val = dev_priv->gpu_error.missed_irq_rings; - return 0; -} - -static int -i915_ring_missed_irq_set(void *data, u64 val) -{ - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = dev->dev_private; - int ret; - - /* Lock against concurrent debugfs callers */ - ret = mutex_lock_interruptible(&dev->struct_mutex); - if (ret) - return ret; - dev_priv->gpu_error.missed_irq_rings = val; - mutex_unlock(&dev->struct_mutex); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(i915_ring_missed_irq_fops, - i915_ring_missed_irq_get, i915_ring_missed_irq_set, - "0x%08llx\n"); - -static int -i915_ring_test_irq_get(void *data, u64 *val) -{ - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = dev->dev_private; - - *val = dev_priv->gpu_error.test_irq_rings; - - return 0; -} - -static int -i915_ring_test_irq_set(void *data, u64 val) -{ - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = dev->dev_private; - int ret; - - DRM_DEBUG_DRIVER("Masking interrupts on rings 0x%08llx\n", val); - - /* Lock against concurrent debugfs callers */ - ret = mutex_lock_interruptible(&dev->struct_mutex); - if (ret) - return ret; - - dev_priv->gpu_error.test_irq_rings = val; - mutex_unlock(&dev->struct_mutex); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(i915_ring_test_irq_fops, - i915_ring_test_irq_get, i915_ring_test_irq_set, - "0x%08llx\n"); - #define DROP_UNBOUND 0x1 #define DROP_BOUND 0x2 #define DROP_RETIRE 0x4 @@ -2803,8 +1972,6 @@ i915_max_freq_get(void *data, u64 *val) if (!(IS_GEN6(dev) || IS_GEN7(dev))) return -ENODEV; - flush_delayed_work(&dev_priv->rps.delayed_resume_work); - ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock); if (ret) return ret; @@ -2829,8 +1996,6 @@ i915_max_freq_set(void *data, u64 val) if (!(IS_GEN6(dev) || IS_GEN7(dev))) return -ENODEV; - flush_delayed_work(&dev_priv->rps.delayed_resume_work); - DRM_DEBUG_DRIVER("Manually setting max freq to %llu\n", val); ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock); @@ -2869,8 +2034,6 @@ i915_min_freq_get(void *data, u64 *val) if (!(IS_GEN6(dev) || IS_GEN7(dev))) return -ENODEV; - flush_delayed_work(&dev_priv->rps.delayed_resume_work); - ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock); if (ret) return ret; @@ -2895,8 +2058,6 @@ i915_min_freq_set(void *data, u64 val) if (!(IS_GEN6(dev) || IS_GEN7(dev))) return -ENODEV; - flush_delayed_work(&dev_priv->rps.delayed_resume_work); - DRM_DEBUG_DRIVER("Manually setting min freq to %llu\n", val); ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock); @@ -2975,6 +2136,32 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_cache_sharing_fops, i915_cache_sharing_get, i915_cache_sharing_set, "%llu\n"); +/* As the drm_debugfs_init() routines are called before dev->dev_private is + * allocated we need to hook into the minor for release. */ +static int +drm_add_fake_info_node(struct drm_minor *minor, + struct dentry *ent, + const void *key) +{ + struct drm_info_node *node; + + node = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL); + if (node == NULL) { + debugfs_remove(ent); + return -ENOMEM; + } + + node->minor = minor; + node->dent = ent; + node->info_ent = (void *) key; + + mutex_lock(&minor->debugfs_lock); + list_add(&node->list, &minor->debugfs_list); + mutex_unlock(&minor->debugfs_lock); + + return 0; +} + static int i915_forcewake_open(struct inode *inode, struct file *file) { struct drm_device *dev = inode->i_private; @@ -3040,7 +2227,7 @@ static int i915_debugfs_create(struct dentry *root, return drm_add_fake_info_node(minor, ent, fops); } -static const struct drm_info_list i915_debugfs_list[] = { +static struct drm_info_list i915_debugfs_list[] = { {"i915_capabilities", i915_capabilities, 0}, {"i915_gem_objects", i915_gem_object_info, 0}, {"i915_gem_gtt", i915_gem_gtt_info, 0}, @@ -3082,7 +2269,7 @@ static const struct drm_info_list i915_debugfs_list[] = { }; #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) -static const struct i915_debugfs_files { +static struct i915_debugfs_files { const char *name; const struct file_operations *fops; } i915_debugfs_files[] = { @@ -3091,28 +2278,11 @@ static const struct i915_debugfs_files { {"i915_min_freq", &i915_min_freq_fops}, {"i915_cache_sharing", &i915_cache_sharing_fops}, {"i915_ring_stop", &i915_ring_stop_fops}, - {"i915_ring_missed_irq", &i915_ring_missed_irq_fops}, - {"i915_ring_test_irq", &i915_ring_test_irq_fops}, {"i915_gem_drop_caches", &i915_drop_caches_fops}, {"i915_error_state", &i915_error_state_fops}, {"i915_next_seqno", &i915_next_seqno_fops}, - {"i915_display_crc_ctl", &i915_display_crc_ctl_fops}, }; -void intel_display_crc_init(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - int i; - - for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) { - struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[i]; - - pipe_crc->opened = false; - spin_lock_init(&pipe_crc->lock); - init_waitqueue_head(&pipe_crc->wq); - } -} - int i915_debugfs_init(struct drm_minor *minor) { int ret, i; @@ -3121,12 +2291,6 @@ int i915_debugfs_init(struct drm_minor *minor) if (ret) return ret; - for (i = 0; i < ARRAY_SIZE(i915_pipe_crc_data); i++) { - ret = i915_pipe_crc_create(minor->debugfs_root, minor, i); - if (ret) - return ret; - } - for (i = 0; i < ARRAY_SIZE(i915_debugfs_files); i++) { ret = i915_debugfs_create(minor->debugfs_root, minor, i915_debugfs_files[i].name, @@ -3146,17 +2310,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor) drm_debugfs_remove_files(i915_debugfs_list, I915_DEBUGFS_ENTRIES, minor); - drm_debugfs_remove_files((struct drm_info_list *) &i915_forcewake_fops, 1, minor); - - for (i = 0; i < ARRAY_SIZE(i915_pipe_crc_data); i++) { - struct drm_info_list *info_list = - (struct drm_info_list *)&i915_pipe_crc_data[i]; - - drm_debugfs_remove_files(info_list, 1, minor); - } - for (i = 0; i < ARRAY_SIZE(i915_debugfs_files); i++) { struct drm_info_list *info_list = (struct drm_info_list *) i915_debugfs_files[i].fops; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 0cab2d0..d5c784d 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -52,7 +52,7 @@ intel_ring_emit(LP_RING(dev_priv), x) #define ADVANCE_LP_RING() \ - __intel_ring_advance(LP_RING(dev_priv)) + intel_ring_advance(LP_RING(dev_priv)) /** * Lock test for when it's just for synchronization of ring access. @@ -641,7 +641,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, if (batch->num_cliprects) { cliprects = kcalloc(batch->num_cliprects, - sizeof(*cliprects), + sizeof(struct drm_clip_rect), GFP_KERNEL); if (cliprects == NULL) return -ENOMEM; @@ -703,7 +703,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, if (cmdbuf->num_cliprects) { cliprects = kcalloc(cmdbuf->num_cliprects, - sizeof(*cliprects), GFP_KERNEL); + sizeof(struct drm_clip_rect), GFP_KERNEL); if (cliprects == NULL) { ret = -ENOMEM; goto fail_batch_free; @@ -931,7 +931,7 @@ static int i915_getparam(struct drm_device *dev, void *data, value = READ_BREADCRUMB(dev_priv); break; case I915_PARAM_CHIPSET_ID: - value = dev->pdev->device; + value = dev->pci_device; break; case I915_PARAM_HAS_GEM: value = 1; @@ -1311,15 +1311,13 @@ static int i915_load_modeset_init(struct drm_device *dev) if (ret) goto cleanup_gem_stolen; - intel_power_domains_init_hw(dev); - /* Important: The output setup functions called by modeset_init need * working irqs for e.g. gmbus and dp aux transfers. */ intel_modeset_init(dev); ret = i915_gem_init(dev); if (ret) - goto cleanup_power; + goto cleanup_irq; INIT_WORK(&dev_priv->console_resume_work, intel_console_resume); @@ -1327,11 +1325,9 @@ static int i915_load_modeset_init(struct drm_device *dev) /* Always safe in the mode setting case. */ /* FIXME: do pre/post-mode set stuff in core KMS code */ - dev->vblank_disable_allowed = true; - if (INTEL_INFO(dev)->num_pipes == 0) { - intel_display_power_put(dev, POWER_DOMAIN_VGA); + dev->vblank_disable_allowed = 1; + if (INTEL_INFO(dev)->num_pipes == 0) return 0; - } ret = intel_fbdev_init(dev); if (ret) @@ -1366,8 +1362,7 @@ cleanup_gem: mutex_unlock(&dev->struct_mutex); i915_gem_cleanup_aliasing_ppgtt(dev); drm_mm_takedown(&dev_priv->gtt.base.mm); -cleanup_power: - intel_display_power_put(dev, POWER_DOMAIN_VGA); +cleanup_irq: drm_irq_uninstall(dev); cleanup_gem_stolen: i915_gem_cleanup_stolen(dev); @@ -1403,7 +1398,6 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master) master->driver_priv = NULL; } -#ifdef CONFIG_DRM_I915_FBDEV static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv) { struct apertures_struct *ap; @@ -1424,11 +1418,6 @@ static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv) kfree(ap); } -#else -static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv) -{ -} -#endif static void i915_dump_device_info(struct drm_i915_private *dev_priv) { @@ -1470,13 +1459,17 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) info = (struct intel_device_info *) flags; /* Refuse to load on gen6+ without kms enabled. */ - if (info->gen >= 6 && !drm_core_check_feature(dev, DRIVER_MODESET)) { - DRM_INFO("Your hardware requires kernel modesetting (KMS)\n"); - DRM_INFO("See CONFIG_DRM_I915_KMS, nomodeset, and i915.modeset parameters\n"); + if (info->gen >= 6 && !drm_core_check_feature(dev, DRIVER_MODESET)) return -ENODEV; - } - dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); + /* i915 has 4 more counters */ + dev->counters += 4; + dev->types[6] = _DRM_STAT_IRQ; + dev->types[7] = _DRM_STAT_PRIMARY; + dev->types[8] = _DRM_STAT_SECONDARY; + dev->types[9] = _DRM_STAT_DMA; + + dev_priv = kzalloc(sizeof(drm_i915_private_t), GFP_KERNEL); if (dev_priv == NULL) return -ENOMEM; @@ -1501,8 +1494,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */ INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work); - intel_display_crc_init(dev); - i915_dump_device_info(dev_priv); /* Not all pre-production machines fall into this category, only the @@ -1540,14 +1531,19 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_uncore_early_sanitize(dev); - /* This must be called before any calls to HAS_PCH_* */ - intel_detect_pch(dev); - - intel_uncore_init(dev); + if (IS_HASWELL(dev) && (I915_READ(HSW_EDRAM_PRESENT) == 1)) { + /* The docs do not explain exactly how the calculation can be + * made. It is somewhat guessable, but for now, it's always + * 128MB. + * NB: We can't write IDICR yet because we do not have gt funcs + * set up */ + dev_priv->ellc_size = 128; + DRM_INFO("Found %zuMB of eLLC\n", dev_priv->ellc_size); + } ret = i915_gem_gtt_init(dev); if (ret) - goto out_regs; + goto put_bridge; if (drm_core_check_feature(dev, DRIVER_MODESET)) i915_kick_out_firmware_fb(dev_priv); @@ -1576,7 +1572,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) aperture_size); if (dev_priv->gtt.mappable == NULL) { ret = -EIO; - goto out_gtt; + goto out_rmmap; } dev_priv->gtt.mtrr = arch_phys_wc_add(dev_priv->gtt.mappable_base, @@ -1602,9 +1598,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto out_mtrrfree; } + /* This must be called before any calls to HAS_PCH_* */ + intel_detect_pch(dev); + intel_irq_init(dev); intel_pm_init(dev); intel_uncore_sanitize(dev); + intel_uncore_init(dev); /* Try to make sure MCHBAR is enabled before poking at it */ intel_setup_mchbar(dev); @@ -1640,13 +1640,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) } if (HAS_POWER_WELL(dev)) - intel_power_domains_init(dev); + i915_init_power_well(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) { ret = i915_load_modeset_init(dev); if (ret < 0) { DRM_ERROR("failed to init modeset\n"); - goto out_power_well; + goto out_gem_unload; } } else { /* Start out suspended in ums mode. */ @@ -1666,10 +1666,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) return 0; -out_power_well: - if (HAS_POWER_WELL(dev)) - intel_power_domains_remove(dev); - drm_vblank_cleanup(dev); out_gem_unload: if (dev_priv->mm.inactive_shrinker.scan_objects) unregister_shrinker(&dev_priv->mm.inactive_shrinker); @@ -1683,18 +1679,12 @@ out_gem_unload: out_mtrrfree: arch_phys_wc_del(dev_priv->gtt.mtrr); io_mapping_free(dev_priv->gtt.mappable); -out_gtt: - list_del(&dev_priv->gtt.base.global_link); - drm_mm_takedown(&dev_priv->gtt.base.mm); dev_priv->gtt.base.cleanup(&dev_priv->gtt.base); -out_regs: - intel_uncore_fini(dev); +out_rmmap: pci_iounmap(dev->pdev, dev_priv->regs); put_bridge: pci_dev_put(dev_priv->bridge_dev); free_priv: - if (dev_priv->slab) - kmem_cache_destroy(dev_priv->slab); kfree(dev_priv); return ret; } @@ -1710,8 +1700,8 @@ int i915_driver_unload(struct drm_device *dev) /* The i915.ko module is still not prepared to be loaded when * the power well is not enabled, so just enable it in case * we're going to unload/reload. */ - intel_display_set_init_power(dev, true); - intel_power_domains_remove(dev); + intel_set_power_well(dev, true); + i915_remove_power_well(dev); } i915_teardown_sysfs(dev); @@ -1719,9 +1709,15 @@ int i915_driver_unload(struct drm_device *dev) if (dev_priv->mm.inactive_shrinker.scan_objects) unregister_shrinker(&dev_priv->mm.inactive_shrinker); - ret = i915_gem_suspend(dev); + mutex_lock(&dev->struct_mutex); + ret = i915_gpu_idle(dev); if (ret) DRM_ERROR("failed to idle hardware: %d\n", ret); + i915_gem_retire_requests(dev); + mutex_unlock(&dev->struct_mutex); + + /* Cancel the retire work handler, which should be idle now. */ + cancel_delayed_work_sync(&dev_priv->mm.retire_work); io_mapping_free(dev_priv->gtt.mappable); arch_phys_wc_del(dev_priv->gtt.mtrr); @@ -1778,8 +1774,8 @@ int i915_driver_unload(struct drm_device *dev) list_del(&dev_priv->gtt.base.global_link); WARN_ON(!list_empty(&dev_priv->vm_list)); drm_mm_takedown(&dev_priv->gtt.base.mm); - - drm_vblank_cleanup(dev); + if (dev_priv->regs != NULL) + pci_iounmap(dev->pdev, dev_priv->regs); intel_teardown_gmbus(dev); intel_teardown_mchbar(dev); @@ -1789,10 +1785,6 @@ int i915_driver_unload(struct drm_device *dev) dev_priv->gtt.base.cleanup(&dev_priv->gtt.base); - intel_uncore_fini(dev); - if (dev_priv->regs != NULL) - pci_iounmap(dev->pdev, dev_priv->regs); - if (dev_priv->slab) kmem_cache_destroy(dev_priv->slab); @@ -1804,11 +1796,19 @@ int i915_driver_unload(struct drm_device *dev) int i915_driver_open(struct drm_device *dev, struct drm_file *file) { - int ret; + struct drm_i915_file_private *file_priv; - ret = i915_gem_open(dev, file); - if (ret) - return ret; + DRM_DEBUG_DRIVER("\n"); + file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); + if (!file_priv) + return -ENOMEM; + + file->driver_priv = file_priv; + + spin_lock_init(&file_priv->mm.lock); + INIT_LIST_HEAD(&file_priv->mm.request_list); + + idr_init(&file_priv->context_idr); return 0; } @@ -1836,7 +1836,7 @@ void i915_driver_lastclose(struct drm_device * dev) return; if (drm_core_check_feature(dev, DRIVER_MODESET)) { - intel_fbdev_restore_mode(dev); + intel_fb_restore_mode(dev); vga_switcheroo_process_delayed_switch(); return; } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2e367a1..2ad2788 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -160,58 +160,49 @@ extern int intel_agp_enabled; static const struct intel_device_info intel_i830_info = { .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2, .has_overlay = 1, .overlay_needs_physical = 1, - .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_845g_info = { .gen = 2, .num_pipes = 1, .has_overlay = 1, .overlay_needs_physical = 1, - .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i85x_info = { .gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, - .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i865g_info = { .gen = 2, .num_pipes = 1, .has_overlay = 1, .overlay_needs_physical = 1, - .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i915g_info = { .gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, .num_pipes = 2, .has_overlay = 1, .overlay_needs_physical = 1, - .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i915gm_info = { .gen = 3, .is_mobile = 1, .num_pipes = 2, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, .supports_tv = 1, - .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i945g_info = { .gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, .num_pipes = 2, .has_overlay = 1, .overlay_needs_physical = 1, - .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i945gm_info = { .gen = 3, .is_i945gm = 1, .is_mobile = 1, .num_pipes = 2, .has_hotplug = 1, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, .supports_tv = 1, - .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i965g_info = { .gen = 4, .is_broadwater = 1, .num_pipes = 2, .has_hotplug = 1, .has_overlay = 1, - .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i965gm_info = { @@ -219,20 +210,18 @@ static const struct intel_device_info intel_i965gm_info = { .is_mobile = 1, .has_fbc = 1, .has_hotplug = 1, .has_overlay = 1, .supports_tv = 1, - .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_g33_info = { .gen = 3, .is_g33 = 1, .num_pipes = 2, .need_gfx_hws = 1, .has_hotplug = 1, .has_overlay = 1, - .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_g45_info = { .gen = 4, .is_g4x = 1, .need_gfx_hws = 1, .num_pipes = 2, .has_pipe_cxsr = 1, .has_hotplug = 1, - .ring_mask = RENDER_RING | BSD_RING, + .has_bsd_ring = 1, }; static const struct intel_device_info intel_gm45_info = { @@ -240,7 +229,7 @@ static const struct intel_device_info intel_gm45_info = { .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_pipe_cxsr = 1, .has_hotplug = 1, .supports_tv = 1, - .ring_mask = RENDER_RING | BSD_RING, + .has_bsd_ring = 1, }; static const struct intel_device_info intel_pineview_info = { @@ -252,36 +241,42 @@ static const struct intel_device_info intel_pineview_info = { static const struct intel_device_info intel_ironlake_d_info = { .gen = 5, .num_pipes = 2, .need_gfx_hws = 1, .has_hotplug = 1, - .ring_mask = RENDER_RING | BSD_RING, + .has_bsd_ring = 1, }; static const struct intel_device_info intel_ironlake_m_info = { .gen = 5, .is_mobile = 1, .num_pipes = 2, .need_gfx_hws = 1, .has_hotplug = 1, .has_fbc = 1, - .ring_mask = RENDER_RING | BSD_RING, + .has_bsd_ring = 1, }; static const struct intel_device_info intel_sandybridge_d_info = { .gen = 6, .num_pipes = 2, .need_gfx_hws = 1, .has_hotplug = 1, - .ring_mask = RENDER_RING | BSD_RING | BLT_RING, + .has_bsd_ring = 1, + .has_blt_ring = 1, .has_llc = 1, + .has_force_wake = 1, }; static const struct intel_device_info intel_sandybridge_m_info = { .gen = 6, .is_mobile = 1, .num_pipes = 2, .need_gfx_hws = 1, .has_hotplug = 1, .has_fbc = 1, - .ring_mask = RENDER_RING | BSD_RING | BLT_RING, + .has_bsd_ring = 1, + .has_blt_ring = 1, .has_llc = 1, + .has_force_wake = 1, }; #define GEN7_FEATURES \ .gen = 7, .num_pipes = 3, \ .need_gfx_hws = 1, .has_hotplug = 1, \ - .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ - .has_llc = 1 + .has_bsd_ring = 1, \ + .has_blt_ring = 1, \ + .has_llc = 1, \ + .has_force_wake = 1 static const struct intel_device_info intel_ivybridge_d_info = { GEN7_FEATURES, @@ -323,7 +318,7 @@ static const struct intel_device_info intel_haswell_d_info = { .is_haswell = 1, .has_ddi = 1, .has_fpga_dbg = 1, - .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, + .has_vebox_ring = 1, }; static const struct intel_device_info intel_haswell_m_info = { @@ -333,25 +328,7 @@ static const struct intel_device_info intel_haswell_m_info = { .has_ddi = 1, .has_fpga_dbg = 1, .has_fbc = 1, - .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, -}; - -static const struct intel_device_info intel_broadwell_d_info = { - .is_preliminary = 1, - .gen = 8, .num_pipes = 3, - .need_gfx_hws = 1, .has_hotplug = 1, - .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, - .has_llc = 1, - .has_ddi = 1, -}; - -static const struct intel_device_info intel_broadwell_m_info = { - .is_preliminary = 1, - .gen = 8, .is_mobile = 1, .num_pipes = 3, - .need_gfx_hws = 1, .has_hotplug = 1, - .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, - .has_llc = 1, - .has_ddi = 1, + .has_vebox_ring = 1, }; /* @@ -385,9 +362,7 @@ static const struct intel_device_info intel_broadwell_m_info = { INTEL_HSW_D_IDS(&intel_haswell_d_info), \ INTEL_HSW_M_IDS(&intel_haswell_m_info), \ INTEL_VLV_M_IDS(&intel_valleyview_m_info), \ - INTEL_VLV_D_IDS(&intel_valleyview_d_info), \ - INTEL_BDW_M_IDS(&intel_broadwell_m_info), \ - INTEL_BDW_D_IDS(&intel_broadwell_d_info) + INTEL_VLV_D_IDS(&intel_valleyview_d_info) static const struct pci_device_id pciidlist[] = { /* aka */ INTEL_PCI_IDS, @@ -441,19 +416,13 @@ void intel_detect_pch(struct drm_device *dev) } else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) { /* PantherPoint is CPT compatible */ dev_priv->pch_type = PCH_CPT; - DRM_DEBUG_KMS("Found PantherPoint PCH\n"); + DRM_DEBUG_KMS("Found PatherPoint PCH\n"); WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev))); } else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_LPT; DRM_DEBUG_KMS("Found LynxPoint PCH\n"); WARN_ON(!IS_HASWELL(dev)); WARN_ON(IS_ULT(dev)); - } else if (IS_BROADWELL(dev)) { - dev_priv->pch_type = PCH_LPT; - dev_priv->pch_id = - INTEL_PCH_LPT_LP_DEVICE_ID_TYPE; - DRM_DEBUG_KMS("This is Broadwell, assuming " - "LynxPoint LP PCH\n"); } else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_LPT; DRM_DEBUG_KMS("Found LynxPoint LP PCH\n"); @@ -478,12 +447,6 @@ bool i915_semaphore_is_enabled(struct drm_device *dev) if (INTEL_INFO(dev)->gen < 6) return 0; - /* Until we get further testing... */ - if (IS_GEN8(dev)) { - WARN_ON(!i915_preliminary_hw_support); - return 0; - } - if (i915_semaphores >= 0) return i915_semaphores; @@ -509,7 +472,7 @@ static int i915_drm_freeze(struct drm_device *dev) /* We do a lot of poking in a lot of registers, make sure they work * properly. */ hsw_disable_package_c8(dev_priv); - intel_display_set_init_power(dev, true); + intel_set_power_well(dev, true); drm_kms_helper_poll_disable(dev); @@ -519,7 +482,9 @@ static int i915_drm_freeze(struct drm_device *dev) if (drm_core_check_feature(dev, DRIVER_MODESET)) { int error; - error = i915_gem_suspend(dev); + mutex_lock(&dev->struct_mutex); + error = i915_gem_idle(dev); + mutex_unlock(&dev->struct_mutex); if (error) { dev_err(&dev->pdev->dev, "GEM idle failed, resume might fail\n"); @@ -534,10 +499,8 @@ static int i915_drm_freeze(struct drm_device *dev) * Disable CRTCs directly since we want to preserve sw state * for _thaw. */ - mutex_lock(&dev->mode_config.mutex); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) dev_priv->display.crtc_disable(crtc); - mutex_unlock(&dev->mode_config.mutex); intel_modeset_suspend_hw(dev); } @@ -615,24 +578,11 @@ static void intel_resume_hotplug(struct drm_device *dev) drm_helper_hpd_irq_event(dev); } -static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) +static int __i915_drm_thaw(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int error = 0; - intel_uncore_early_sanitize(dev); - - intel_uncore_sanitize(dev); - - if (drm_core_check_feature(dev, DRIVER_MODESET) && - restore_gtt_mappings) { - mutex_lock(&dev->struct_mutex); - i915_gem_restore_gtt_mappings(dev); - mutex_unlock(&dev->struct_mutex); - } - - intel_power_domains_init_hw(dev); - i915_restore_state(dev); intel_opregion_setup(dev); @@ -692,10 +642,20 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) static int i915_drm_thaw(struct drm_device *dev) { - if (drm_core_check_feature(dev, DRIVER_MODESET)) + int error = 0; + + intel_uncore_sanitize(dev); + + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + mutex_lock(&dev->struct_mutex); + i915_gem_restore_gtt_mappings(dev); + mutex_unlock(&dev->struct_mutex); + } else if (drm_core_check_feature(dev, DRIVER_MODESET)) i915_check_and_clear_faults(dev); - return __i915_drm_thaw(dev, true); + __i915_drm_thaw(dev); + + return error; } int i915_resume(struct drm_device *dev) @@ -711,12 +671,20 @@ int i915_resume(struct drm_device *dev) pci_set_master(dev->pdev); + intel_uncore_sanitize(dev); + /* * Platforms with opregion should have sane BIOS, older ones (gen3 and - * earlier) need to restore the GTT mappings since the BIOS might clear - * all our scratch PTEs. + * earlier) need this since the BIOS might clear all our scratch PTEs. */ - ret = __i915_drm_thaw(dev, !dev_priv->opregion.header); + if (drm_core_check_feature(dev, DRIVER_MODESET) && + !dev_priv->opregion.header) { + mutex_lock(&dev->struct_mutex); + i915_gem_restore_gtt_mappings(dev); + mutex_unlock(&dev->struct_mutex); + } + + ret = __i915_drm_thaw(dev); if (ret) return ret; @@ -754,19 +722,24 @@ int i915_reset(struct drm_device *dev) simulated = dev_priv->gpu_error.stop_rings != 0; - ret = intel_gpu_reset(dev); - - /* Also reset the gpu hangman. */ - if (simulated) { - DRM_INFO("Simulated gpu hang, resetting stop_rings\n"); - dev_priv->gpu_error.stop_rings = 0; - if (ret == -ENODEV) { - DRM_ERROR("Reset not implemented, but ignoring " - "error for simulated gpu hangs\n"); - ret = 0; - } + if (!simulated && get_seconds() - dev_priv->gpu_error.last_reset < 5) { + DRM_ERROR("GPU hanging too fast, declaring wedged!\n"); + ret = -ENODEV; + } else { + ret = intel_gpu_reset(dev); + + /* Also reset the gpu hangman. */ + if (simulated) { + DRM_INFO("Simulated gpu hang, resetting stop_rings\n"); + dev_priv->gpu_error.stop_rings = 0; + if (ret == -ENODEV) { + DRM_ERROR("Reset not implemented, but ignoring " + "error for simulated gpu hangs\n"); + ret = 0; + } + } else + dev_priv->gpu_error.last_reset = get_seconds(); } - if (ret) { DRM_ERROR("Failed to reset chip.\n"); mutex_unlock(&dev->struct_mutex); @@ -789,18 +762,31 @@ int i915_reset(struct drm_device *dev) */ if (drm_core_check_feature(dev, DRIVER_MODESET) || !dev_priv->ums.mm_suspended) { - bool hw_contexts_disabled = dev_priv->hw_contexts_disabled; + struct intel_ring_buffer *ring; + int i; + dev_priv->ums.mm_suspended = 0; - ret = i915_gem_init_hw(dev); - if (!hw_contexts_disabled && dev_priv->hw_contexts_disabled) - DRM_ERROR("HW contexts didn't survive reset\n"); - mutex_unlock(&dev->struct_mutex); - if (ret) { - DRM_ERROR("Failed hw init on reset %d\n", ret); - return ret; + i915_gem_init_swizzling(dev); + + for_each_ring(ring, dev_priv, i) + ring->init(ring); + + i915_gem_context_init(dev); + if (dev_priv->mm.aliasing_ppgtt) { + ret = dev_priv->mm.aliasing_ppgtt->enable(dev); + if (ret) + i915_gem_cleanup_aliasing_ppgtt(dev); } + /* + * It would make sense to re-init all the other hw state, at + * least the rps/rc6/emon init done within modeset_init_hw. For + * some unknown reason, this blows up my ilk, so don't. + */ + + mutex_unlock(&dev->struct_mutex); + drm_irq_uninstall(dev); drm_irq_install(dev); intel_hpd_init(dev); @@ -816,12 +802,6 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct intel_device_info *intel_info = (struct intel_device_info *) ent->driver_data; - if (IS_PRELIMINARY_HW(intel_info) && !i915_preliminary_hw_support) { - DRM_INFO("This hardware requires preliminary hardware support.\n" - "See CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT, and/or modparam preliminary_hw_support\n"); - return -ENODEV; - } - /* Only bind to function 0 of the device. Early generations * used function 1 as a placeholder for multi-head. This causes * us confusion instead, especially on the systems where both @@ -969,6 +949,7 @@ static struct drm_driver driver = { .debugfs_init = i915_debugfs_init, .debugfs_cleanup = i915_debugfs_cleanup, #endif + .gem_init_object = i915_gem_init_object, .gem_free_object = i915_gem_free_object, .gem_vm_ops = &i915_gem_vm_ops, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ccdbecc..ab0f2c0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -54,7 +54,6 @@ #define DRIVER_DATE "20080730" enum pipe { - INVALID_PIPE = -1, PIPE_A = 0, PIPE_B, PIPE_C, @@ -99,29 +98,13 @@ enum intel_display_power_domain { POWER_DOMAIN_TRANSCODER_A, POWER_DOMAIN_TRANSCODER_B, POWER_DOMAIN_TRANSCODER_C, - POWER_DOMAIN_TRANSCODER_EDP, - POWER_DOMAIN_VGA, - POWER_DOMAIN_INIT, - - POWER_DOMAIN_NUM, + POWER_DOMAIN_TRANSCODER_EDP = POWER_DOMAIN_TRANSCODER_A + 0xF, }; -#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1) - #define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A) #define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \ ((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER) -#define POWER_DOMAIN_TRANSCODER(tran) \ - ((tran) == TRANSCODER_EDP ? POWER_DOMAIN_TRANSCODER_EDP : \ - (tran) + POWER_DOMAIN_TRANSCODER_A) - -#define HSW_ALWAYS_ON_POWER_DOMAINS ( \ - BIT(POWER_DOMAIN_PIPE_A) | \ - BIT(POWER_DOMAIN_TRANSCODER_EDP)) -#define BDW_ALWAYS_ON_POWER_DOMAINS ( \ - BIT(POWER_DOMAIN_PIPE_A) | \ - BIT(POWER_DOMAIN_TRANSCODER_EDP) | \ - BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER)) +#define POWER_DOMAIN_TRANSCODER(tran) ((tran) + POWER_DOMAIN_TRANSCODER_A) enum hpd_pin { HPD_NONE = 0, @@ -242,12 +225,9 @@ struct intel_opregion { struct opregion_header __iomem *header; struct opregion_acpi __iomem *acpi; struct opregion_swsci __iomem *swsci; - u32 swsci_gbda_sub_functions; - u32 swsci_sbcb_sub_functions; struct opregion_asle __iomem *asle; void __iomem *vbt; u32 __iomem *lid_state; - struct work_struct asle_work; }; #define OPREGION_SIZE (8*1024) @@ -305,7 +285,6 @@ struct drm_i915_error_state { u32 cpu_ring_tail[I915_NUM_RINGS]; u32 error; /* gen6+ */ u32 err_int; /* gen7 */ - u32 bbstate[I915_NUM_RINGS]; u32 instpm[I915_NUM_RINGS]; u32 instps[I915_NUM_RINGS]; u32 extra_instdone[I915_NUM_INSTDONE_REG]; @@ -342,13 +321,11 @@ struct drm_i915_error_state { u32 dirty:1; u32 purgeable:1; s32 ring:4; - u32 cache_level:3; + u32 cache_level:2; } **active_bo, **pinned_bo; u32 *active_bo_count, *pinned_bo_count; struct intel_overlay_error_state *overlay; struct intel_display_error_state *display; - int hangcheck_score[I915_NUM_RINGS]; - enum intel_ring_hangcheck_action hangcheck_action[I915_NUM_RINGS]; }; struct intel_crtc_config; @@ -380,7 +357,7 @@ struct drm_i915_display_funcs { int target, int refclk, struct dpll *match_clock, struct dpll *best_clock); - void (*update_wm)(struct drm_crtc *crtc); + void (*update_wm)(struct drm_device *dev); void (*update_sprite_wm)(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t sprite_width, int pixel_size, @@ -390,6 +367,7 @@ struct drm_i915_display_funcs { * fills out the pipe-config with the hw state. */ bool (*get_pipe_config)(struct intel_crtc *, struct intel_crtc_config *); + void (*get_clock)(struct intel_crtc *, struct intel_crtc_config *); int (*crtc_mode_set)(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb); @@ -397,8 +375,7 @@ struct drm_i915_display_funcs { void (*crtc_disable)(struct drm_crtc *crtc); void (*off)(struct drm_crtc *crtc); void (*write_eld)(struct drm_connector *connector, - struct drm_crtc *crtc, - struct drm_display_mode *mode); + struct drm_crtc *crtc); void (*fdi_link_train)(struct drm_crtc *crtc); void (*init_clock_gating)(struct drm_device *dev); int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc, @@ -418,20 +395,6 @@ struct drm_i915_display_funcs { struct intel_uncore_funcs { void (*force_wake_get)(struct drm_i915_private *dev_priv); void (*force_wake_put)(struct drm_i915_private *dev_priv); - - uint8_t (*mmio_readb)(struct drm_i915_private *dev_priv, off_t offset, bool trace); - uint16_t (*mmio_readw)(struct drm_i915_private *dev_priv, off_t offset, bool trace); - uint32_t (*mmio_readl)(struct drm_i915_private *dev_priv, off_t offset, bool trace); - uint64_t (*mmio_readq)(struct drm_i915_private *dev_priv, off_t offset, bool trace); - - void (*mmio_writeb)(struct drm_i915_private *dev_priv, off_t offset, - uint8_t val, bool trace); - void (*mmio_writew)(struct drm_i915_private *dev_priv, off_t offset, - uint16_t val, bool trace); - void (*mmio_writel)(struct drm_i915_private *dev_priv, off_t offset, - uint32_t val, bool trace); - void (*mmio_writeq)(struct drm_i915_private *dev_priv, off_t offset, - uint64_t val, bool trace); }; struct intel_uncore { @@ -441,8 +404,6 @@ struct intel_uncore { unsigned fifo_count; unsigned forcewake_count; - - struct delayed_work force_wake_work; }; #define DEV_INFO_FOR_EACH_FLAG(func, sep) \ @@ -459,7 +420,7 @@ struct intel_uncore { func(is_ivybridge) sep \ func(is_valleyview) sep \ func(is_haswell) sep \ - func(is_preliminary) sep \ + func(has_force_wake) sep \ func(has_fbc) sep \ func(has_pipe_cxsr) sep \ func(has_hotplug) sep \ @@ -467,6 +428,9 @@ struct intel_uncore { func(has_overlay) sep \ func(overlay_needs_physical) sep \ func(supports_tv) sep \ + func(has_bsd_ring) sep \ + func(has_blt_ring) sep \ + func(has_vebox_ring) sep \ func(has_llc) sep \ func(has_ddi) sep \ func(has_fpga_dbg) @@ -478,7 +442,6 @@ struct intel_device_info { u32 display_mmio_offset; u8 num_pipes:3; u8 gen; - u8 ring_mask; /* Rings supported by the HW */ DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG, SEP_SEMICOLON); }; @@ -579,21 +542,10 @@ struct i915_gtt { struct i915_hw_ppgtt { struct i915_address_space base; unsigned num_pd_entries; - union { - struct page **pt_pages; - struct page *gen8_pt_pages; - }; - struct page *pd_pages; - int num_pd_pages; - int num_pt_pages; - union { - uint32_t pd_offset; - dma_addr_t pd_dma_addr[4]; - }; - union { - dma_addr_t *pt_dma_addr; - dma_addr_t *gen8_pt_dma_addr[4]; - }; + struct page **pt_pages; + uint32_t pd_offset; + dma_addr_t *pt_dma_addr; + int (*enable)(struct drm_device *dev); }; @@ -618,13 +570,6 @@ struct i915_vma { /** This vma's place in the batchbuffer or on the eviction list */ struct list_head exec_list; - /** - * Used for performing relocations during execbuffer insertion. - */ - struct hlist_node exec_node; - unsigned long exec_handle; - struct drm_i915_gem_exec_object2 *exec_entry; - }; struct i915_ctx_hang_stats { @@ -633,12 +578,6 @@ struct i915_ctx_hang_stats { /* This context had batch active when hang was declared */ unsigned batch_active; - - /* Time when this context was last blamed for a GPU reset */ - unsigned long guilty_ts; - - /* This context is banned to submit more work */ - bool banned; }; /* This must match up with the value previously used for execbuf2.rsvd1. */ @@ -647,13 +586,10 @@ struct i915_hw_context { struct kref ref; int id; bool is_initialized; - uint8_t remap_slice; struct drm_i915_file_private *file_priv; struct intel_ring_buffer *ring; struct drm_i915_gem_object *obj; struct i915_ctx_hang_stats hang_stats; - - struct list_head link; }; struct i915_fbc { @@ -687,9 +623,17 @@ struct i915_fbc { } no_fbc_reason; }; -struct i915_psr { - bool sink_support; - bool source_ok; +enum no_psr_reason { + PSR_NO_SOURCE, /* Not supported on platform */ + PSR_NO_SINK, /* Not supported by panel */ + PSR_MODULE_PARAM, + PSR_CRTC_NOT_ACTIVE, + PSR_PWR_WELL_ENABLED, + PSR_NOT_TILED, + PSR_SPRITE_ENABLED, + PSR_S3D_ENABLED, + PSR_INTERLACED_ENABLED, + PSR_HSW_NOT_DDIA, }; enum intel_pch { @@ -760,9 +704,6 @@ struct i915_suspend_saved_registers { u32 saveBLC_HIST_CTL; u32 saveBLC_PWM_CTL; u32 saveBLC_PWM_CTL2; - u32 saveBLC_HIST_CTL_B; - u32 saveBLC_PWM_CTL_B; - u32 saveBLC_PWM_CTL2_B; u32 saveBLC_CPU_PWM_CTL; u32 saveBLC_CPU_PWM_CTL2; u32 saveFPB0; @@ -882,20 +823,17 @@ struct intel_gen6_power_mgmt { struct work_struct work; u32 pm_iir; + /* On vlv we need to manually drop to Vmin with a delayed work. */ + struct delayed_work vlv_work; + /* The below variables an all the rps hw state are protected by * dev->struct mutext. */ u8 cur_delay; u8 min_delay; u8 max_delay; u8 rpe_delay; - u8 rp1_delay; - u8 rp0_delay; u8 hw_max; - int last_adj; - enum { LOW_POWER, BETWEEN, HIGH_POWER } power; - - bool enabled; struct delayed_work delayed_resume_work; /* @@ -932,21 +870,11 @@ struct intel_ilk_power_mgmt { /* Power well structure for haswell */ struct i915_power_well { + struct drm_device *device; + spinlock_t lock; /* power well enable/disable usage count */ int count; -}; - -#define I915_MAX_POWER_WELLS 1 - -struct i915_power_domains { - /* - * Power wells needed for initialization at driver init and suspend - * time are on. They are kept on until after the first modeset. - */ - bool init_power_on; - - struct mutex lock; - struct i915_power_well power_wells[I915_MAX_POWER_WELLS]; + int i915_request; }; struct i915_dri1_state { @@ -974,11 +902,9 @@ struct i915_ums_state { int mm_suspended; }; -#define MAX_L3_SLICES 2 struct intel_l3_parity { - u32 *remap_info[MAX_L3_SLICES]; + u32 *remap_info; struct work_struct error_work; - int which_slice; }; struct i915_gem_mm { @@ -1016,15 +942,6 @@ struct i915_gem_mm { struct delayed_work retire_work; /** - * When we detect an idle GPU, we want to turn on - * powersaving features. So once we see that there - * are no more requests outstanding and no more - * arrive within a small period of time, we fire - * off the idle_work. - */ - struct delayed_work idle_work; - - /** * Are we in a non-interruptible section of code like * modesetting? */ @@ -1062,9 +979,6 @@ struct i915_gpu_error { /* For hangcheck timer */ #define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */ #define DRM_I915_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD) - /* Hang gpu twice in this window and your context gets banned */ -#define DRM_I915_CTX_BAN_PERIOD DIV_ROUND_UP(8*DRM_I915_HANGCHECK_PERIOD, 1000) - struct timer_list hangcheck_timer; /* For reset and error_state handling. */ @@ -1073,8 +987,7 @@ struct i915_gpu_error { struct drm_i915_error_state *first_error; struct work_struct work; - - unsigned long missed_irq_rings; + unsigned long last_reset; /** * State variable and reset counter controlling the reset flow @@ -1114,9 +1027,6 @@ struct i915_gpu_error { /* For gpu hang simulation. */ unsigned int stop_rings; - - /* For missed irq/seqno simulation. */ - unsigned int test_irq_rings; }; enum modeset_restore { @@ -1125,14 +1035,6 @@ enum modeset_restore { MODESET_SUSPENDED, }; -struct ddi_vbt_port_info { - uint8_t hdmi_level_shift; - - uint8_t supports_dvi:1; - uint8_t supports_hdmi:1; - uint8_t supports_dp:1; -}; - struct intel_vbt_data { struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ @@ -1158,17 +1060,10 @@ struct intel_vbt_data { int edp_bpp; struct edp_power_seq edp_pps; - /* MIPI DSI */ - struct { - u16 panel_id; - } dsi; - int crt_ddc_pin; int child_dev_num; - union child_device_config *child_dev; - - struct ddi_vbt_port_info ddi_port_info[I915_MAX_PORTS]; + struct child_device_config *child_dev; }; enum intel_ddb_partitioning { @@ -1184,15 +1079,6 @@ struct intel_wm_level { uint32_t fbc_val; }; -struct hsw_wm_values { - uint32_t wm_pipe[3]; - uint32_t wm_lp[3]; - uint32_t wm_lp_spr[3]; - uint32_t wm_linetime[3]; - bool enable_fbc_wm; - enum intel_ddb_partitioning partitioning; -}; - /* * This struct tracks the state needed for the Package C8+ feature. * @@ -1262,36 +1148,6 @@ struct i915_package_c8 { } regsave; }; -enum intel_pipe_crc_source { - INTEL_PIPE_CRC_SOURCE_NONE, - INTEL_PIPE_CRC_SOURCE_PLANE1, - INTEL_PIPE_CRC_SOURCE_PLANE2, - INTEL_PIPE_CRC_SOURCE_PF, - INTEL_PIPE_CRC_SOURCE_PIPE, - /* TV/DP on pre-gen5/vlv can't use the pipe source. */ - INTEL_PIPE_CRC_SOURCE_TV, - INTEL_PIPE_CRC_SOURCE_DP_B, - INTEL_PIPE_CRC_SOURCE_DP_C, - INTEL_PIPE_CRC_SOURCE_DP_D, - INTEL_PIPE_CRC_SOURCE_AUTO, - INTEL_PIPE_CRC_SOURCE_MAX, -}; - -struct intel_pipe_crc_entry { - uint32_t frame; - uint32_t crc[5]; -}; - -#define INTEL_PIPE_CRC_ENTRIES_NR 128 -struct intel_pipe_crc { - spinlock_t lock; - bool opened; /* exclusive access to the result file */ - struct intel_pipe_crc_entry *entries; - enum intel_pipe_crc_source source; - int head, tail; - wait_queue_head_t wq; -}; - typedef struct drm_i915_private { struct drm_device *dev; struct kmem_cache *slab; @@ -1337,10 +1193,7 @@ typedef struct drm_i915_private { struct mutex dpio_lock; /** Cached value of IMR to avoid reads in updating the bitfield */ - union { - u32 irq_mask; - u32 de_irq_mask[I915_MAX_PIPES]; - }; + u32 irq_mask; u32 gt_irq_mask; u32 pm_irq_mask; @@ -1419,10 +1272,6 @@ typedef struct drm_i915_private { struct drm_crtc *pipe_to_crtc_mapping[3]; wait_queue_head_t pending_flip_queue; -#ifdef CONFIG_DEBUG_FS - struct intel_pipe_crc pipe_crc[I915_MAX_PIPES]; -#endif - int num_shared_dpll; struct intel_shared_dpll shared_dplls[I915_NUM_PLLS]; struct intel_ddi_plls ddi_plls; @@ -1448,18 +1297,17 @@ typedef struct drm_i915_private { * mchdev_lock in intel_pm.c */ struct intel_ilk_power_mgmt ips; - struct i915_power_domains power_domains; + /* Haswell power well */ + struct i915_power_well power_well; - struct i915_psr psr; + enum no_psr_reason no_psr_reason; struct i915_gpu_error gpu_error; struct drm_i915_gem_object *vlv_pctx; -#ifdef CONFIG_DRM_I915_FBDEV /* list of fbdev register on this device */ struct intel_fbdev *fbdev; -#endif /* * The console may be contended at resume, but we don't @@ -1472,7 +1320,6 @@ typedef struct drm_i915_private { bool hw_contexts_disabled; uint32_t hw_context_size; - struct list_head context_list; u32 fdi_rx_config; @@ -1490,9 +1337,6 @@ typedef struct drm_i915_private { uint16_t spr_latency[5]; /* cursor */ uint16_t cur_latency[5]; - - /* current hardware state */ - struct hsw_wm_values hw; } wm; struct i915_package_c8 pc8; @@ -1556,6 +1400,8 @@ struct drm_i915_gem_object { struct list_head ring_list; /** Used in execbuf to temporarily hold a ref */ struct list_head obj_exec_link; + /** This object's place in the batchbuffer or on the eviction list */ + struct list_head exec_list; /** * This is set if the object is on the active lists (has pending @@ -1641,6 +1487,13 @@ struct drm_i915_gem_object { void *dma_buf_vmapping; int vmapping_count; + /** + * Used for performing relocations during execbuffer insertion. + */ + struct hlist_node exec_node; + unsigned long exec_handle; + struct drm_i915_gem_exec_object2 *exec_entry; + struct intel_ring_buffer *ring; /** Breadcrumb of last rendering to the buffer. */ @@ -1652,14 +1505,11 @@ struct drm_i915_gem_object { /** Current tiling stride for the object, if it's tiled. */ uint32_t stride; - /** References from framebuffers, locks out tiling changes. */ - unsigned long framebuffer_references; - /** Record of address bit 17 of each page at last unbind. */ unsigned long *bit_17; /** User space pin count and filp owning the pin */ - unsigned long user_pin_count; + uint32_t user_pin_count; struct drm_file *pin_filp; /** for phy allocated objects */ @@ -1710,56 +1560,48 @@ struct drm_i915_gem_request { }; struct drm_i915_file_private { - struct drm_i915_private *dev_priv; - struct { spinlock_t lock; struct list_head request_list; - struct delayed_work idle_work; } mm; struct idr context_idr; struct i915_ctx_hang_stats hang_stats; - atomic_t rps_wait_boost; }; #define INTEL_INFO(dev) (to_i915(dev)->info) -#define IS_I830(dev) ((dev)->pdev->device == 0x3577) -#define IS_845G(dev) ((dev)->pdev->device == 0x2562) +#define IS_I830(dev) ((dev)->pci_device == 0x3577) +#define IS_845G(dev) ((dev)->pci_device == 0x2562) #define IS_I85X(dev) (INTEL_INFO(dev)->is_i85x) -#define IS_I865G(dev) ((dev)->pdev->device == 0x2572) +#define IS_I865G(dev) ((dev)->pci_device == 0x2572) #define IS_I915G(dev) (INTEL_INFO(dev)->is_i915g) -#define IS_I915GM(dev) ((dev)->pdev->device == 0x2592) -#define IS_I945G(dev) ((dev)->pdev->device == 0x2772) +#define IS_I915GM(dev) ((dev)->pci_device == 0x2592) +#define IS_I945G(dev) ((dev)->pci_device == 0x2772) #define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm) #define IS_BROADWATER(dev) (INTEL_INFO(dev)->is_broadwater) #define IS_CRESTLINE(dev) (INTEL_INFO(dev)->is_crestline) -#define IS_GM45(dev) ((dev)->pdev->device == 0x2A42) +#define IS_GM45(dev) ((dev)->pci_device == 0x2A42) #define IS_G4X(dev) (INTEL_INFO(dev)->is_g4x) -#define IS_PINEVIEW_G(dev) ((dev)->pdev->device == 0xa001) -#define IS_PINEVIEW_M(dev) ((dev)->pdev->device == 0xa011) +#define IS_PINEVIEW_G(dev) ((dev)->pci_device == 0xa001) +#define IS_PINEVIEW_M(dev) ((dev)->pci_device == 0xa011) #define IS_PINEVIEW(dev) (INTEL_INFO(dev)->is_pineview) #define IS_G33(dev) (INTEL_INFO(dev)->is_g33) -#define IS_IRONLAKE_M(dev) ((dev)->pdev->device == 0x0046) +#define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046) #define IS_IVYBRIDGE(dev) (INTEL_INFO(dev)->is_ivybridge) -#define IS_IVB_GT1(dev) ((dev)->pdev->device == 0x0156 || \ - (dev)->pdev->device == 0x0152 || \ - (dev)->pdev->device == 0x015a) -#define IS_SNB_GT1(dev) ((dev)->pdev->device == 0x0102 || \ - (dev)->pdev->device == 0x0106 || \ - (dev)->pdev->device == 0x010A) +#define IS_IVB_GT1(dev) ((dev)->pci_device == 0x0156 || \ + (dev)->pci_device == 0x0152 || \ + (dev)->pci_device == 0x015a) +#define IS_SNB_GT1(dev) ((dev)->pci_device == 0x0102 || \ + (dev)->pci_device == 0x0106 || \ + (dev)->pci_device == 0x010A) #define IS_VALLEYVIEW(dev) (INTEL_INFO(dev)->is_valleyview) #define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell) -#define IS_BROADWELL(dev) (INTEL_INFO(dev)->gen == 8) #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) #define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \ - ((dev)->pdev->device & 0xFF00) == 0x0C00) + ((dev)->pci_device & 0xFF00) == 0x0C00) #define IS_ULT(dev) (IS_HASWELL(dev) && \ - ((dev)->pdev->device & 0xFF00) == 0x0A00) -#define IS_HSW_GT3(dev) (IS_HASWELL(dev) && \ - ((dev)->pdev->device & 0x00F0) == 0x0020) -#define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) + ((dev)->pci_device & 0xFF00) == 0x0A00) /* * The genX designation typically refers to the render engine, so render @@ -1773,15 +1615,10 @@ struct drm_i915_file_private { #define IS_GEN5(dev) (INTEL_INFO(dev)->gen == 5) #define IS_GEN6(dev) (INTEL_INFO(dev)->gen == 6) #define IS_GEN7(dev) (INTEL_INFO(dev)->gen == 7) -#define IS_GEN8(dev) (INTEL_INFO(dev)->gen == 8) - -#define RENDER_RING (1<<RCS) -#define BSD_RING (1<<VCS) -#define BLT_RING (1<<BCS) -#define VEBOX_RING (1<<VECS) -#define HAS_BSD(dev) (INTEL_INFO(dev)->ring_mask & BSD_RING) -#define HAS_BLT(dev) (INTEL_INFO(dev)->ring_mask & BLT_RING) -#define HAS_VEBOX(dev) (INTEL_INFO(dev)->ring_mask & VEBOX_RING) + +#define HAS_BSD(dev) (INTEL_INFO(dev)->has_bsd_ring) +#define HAS_BLT(dev) (INTEL_INFO(dev)->has_blt_ring) +#define HAS_VEBOX(dev) (INTEL_INFO(dev)->has_vebox_ring) #define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) #define HAS_WT(dev) (IS_HASWELL(dev) && to_i915(dev)->ellc_size) #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) @@ -1803,6 +1640,7 @@ struct drm_i915_file_private { #define SUPPORTS_DIGITAL_OUTPUTS(dev) (!IS_GEN2(dev) && !IS_PINEVIEW(dev)) #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_GEN5(dev)) #define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_GEN5(dev)) +#define SUPPORTS_EDP(dev) (IS_IRONLAKE_M(dev)) #define SUPPORTS_TV(dev) (INTEL_INFO(dev)->supports_tv) #define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug) @@ -1810,13 +1648,11 @@ struct drm_i915_file_private { #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) #define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) -#define HAS_IPS(dev) (IS_ULT(dev) || IS_BROADWELL(dev)) +#define HAS_IPS(dev) (IS_ULT(dev)) #define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi) -#define HAS_POWER_WELL(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev)) +#define HAS_POWER_WELL(dev) (IS_HASWELL(dev)) #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) -#define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev)) -#define HAS_PC8(dev) (IS_HASWELL(dev)) /* XXX HSW:ULX */ #define INTEL_PCH_DEVICE_ID_MASK 0xff00 #define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00 @@ -1832,14 +1668,35 @@ struct drm_i915_file_private { #define HAS_PCH_NOP(dev) (INTEL_PCH_TYPE(dev) == PCH_NOP) #define HAS_PCH_SPLIT(dev) (INTEL_PCH_TYPE(dev) != PCH_NONE) -/* DPF == dynamic parity feature */ -#define HAS_L3_DPF(dev) (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) -#define NUM_L3_SLICES(dev) (IS_HSW_GT3(dev) ? 2 : HAS_L3_DPF(dev)) +#define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake) + +#define HAS_L3_GPU_CACHE(dev) (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) #define GT_FREQUENCY_MULTIPLIER 50 #include "i915_trace.h" +/** + * RC6 is a special power stage which allows the GPU to enter an very + * low-voltage mode when idle, using down to 0V while at this stage. This + * stage is entered automatically when the GPU is idle when RC6 support is + * enabled, and as soon as new workload arises GPU wakes up automatically as well. + * + * There are different RC6 modes available in Intel GPU, which differentiate + * among each other with the latency required to enter and leave RC6 and + * voltage consumed by the GPU in different states. + * + * The combination of the following flags define which states GPU is allowed + * to enter, while RC6 is the normal RC6 state, RC6p is the deep RC6, and + * RC6pp is deepest RC6. Their support by hardware varies according to the + * GPU, BIOS, chipset and platform. RC6 is usually the safest one and the one + * which brings the most power savings; deeper states save more power, but + * require higher latency to switch to and wake up. + */ +#define INTEL_RC6_ENABLE (1<<0) +#define INTEL_RC6p_ENABLE (1<<1) +#define INTEL_RC6pp_ENABLE (1<<2) + extern const struct drm_ioctl_desc i915_ioctls[]; extern int i915_max_ioctl; extern unsigned int i915_fbpercrtc __always_unused; @@ -1910,13 +1767,12 @@ extern void intel_uncore_early_sanitize(struct drm_device *dev); extern void intel_uncore_init(struct drm_device *dev); extern void intel_uncore_clear_errors(struct drm_device *dev); extern void intel_uncore_check_errors(struct drm_device *dev); -extern void intel_uncore_fini(struct drm_device *dev); void -i915_enable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask); +i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); void -i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask); +i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); /* i915_gem.c */ int i915_gem_init_ioctl(struct drm_device *dev, void *data, @@ -1968,11 +1824,14 @@ int i915_gem_wait_ioctl(struct drm_device *dev, void *data, void i915_gem_load(struct drm_device *dev); void *i915_gem_object_alloc(struct drm_device *dev); void i915_gem_object_free(struct drm_i915_gem_object *obj); +int i915_gem_init_object(struct drm_gem_object *obj); void i915_gem_object_init(struct drm_i915_gem_object *obj, const struct drm_i915_gem_object_ops *ops); struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, size_t size); void i915_gem_free_object(struct drm_gem_object *obj); +struct i915_vma *i915_gem_vma_create(struct drm_i915_gem_object *obj, + struct i915_address_space *vm); void i915_gem_vma_destroy(struct i915_vma *vma); int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj, @@ -2011,8 +1870,9 @@ static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) int __must_check i915_mutex_lock_interruptible(struct drm_device *dev); int i915_gem_object_sync(struct drm_i915_gem_object *obj, struct intel_ring_buffer *to); -void i915_vma_move_to_active(struct i915_vma *vma, - struct intel_ring_buffer *ring); +void i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *ring); + int i915_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev, struct drm_mode_create_dumb *args); @@ -2053,7 +1913,7 @@ i915_gem_object_unpin_fence(struct drm_i915_gem_object *obj) } } -bool i915_gem_retire_requests(struct drm_device *dev); +void i915_gem_retire_requests(struct drm_device *dev); void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring); int __must_check i915_gem_check_wedge(struct i915_gpu_error *error, bool interruptible); @@ -2073,11 +1933,11 @@ bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force); int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj); int __must_check i915_gem_init(struct drm_device *dev); int __must_check i915_gem_init_hw(struct drm_device *dev); -int i915_gem_l3_remap(struct intel_ring_buffer *ring, int slice); +void i915_gem_l3_remap(struct drm_device *dev); void i915_gem_init_swizzling(struct drm_device *dev); void i915_gem_cleanup_ringbuffer(struct drm_device *dev); int __must_check i915_gpu_idle(struct drm_device *dev); -int __must_check i915_gem_suspend(struct drm_device *dev); +int __must_check i915_gem_idle(struct drm_device *dev); int __i915_add_request(struct intel_ring_buffer *ring, struct drm_file *file, struct drm_i915_gem_object *batch_obj, @@ -2104,7 +1964,6 @@ int i915_gem_attach_phys_object(struct drm_device *dev, void i915_gem_detach_phys_object(struct drm_device *dev, struct drm_i915_gem_object *obj); void i915_gem_free_all_phys_object(struct drm_device *dev); -int i915_gem_open(struct drm_device *dev, struct drm_file *file); void i915_gem_release(struct drm_device *dev, struct drm_file *file); uint32_t @@ -2136,9 +1995,6 @@ struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj, struct i915_vma * i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj, struct i915_address_space *vm); - -struct i915_vma *i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj); - /* Some GGTT VM helpers */ #define obj_to_ggtt(obj) \ (&((struct drm_i915_private *)(obj)->base.dev->dev_private)->gtt.base) @@ -2175,6 +2031,7 @@ i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj, return i915_gem_object_pin(obj, obj_to_ggtt(obj), alignment, map_and_fenceable, nonblocking); } +#undef obj_to_ggtt /* i915_gem_context.c */ void i915_gem_context_init(struct drm_device *dev); @@ -2237,7 +2094,6 @@ int __must_check i915_gem_evict_something(struct drm_device *dev, unsigned cache_level, bool mappable, bool nonblock); -int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle); int i915_gem_evict_everything(struct drm_device *dev); /* i915_gem_stolen.c */ @@ -2277,11 +2133,6 @@ int i915_verify_lists(struct drm_device *dev); /* i915_debugfs.c */ int i915_debugfs_init(struct drm_minor *minor); void i915_debugfs_cleanup(struct drm_minor *minor); -#ifdef CONFIG_DEBUG_FS -void intel_display_crc_init(struct drm_device *dev); -#else -static inline void intel_display_crc_init(struct drm_device *dev) {} -#endif /* i915_gpu_error.c */ __printf(2, 3) @@ -2335,30 +2186,15 @@ static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter) extern void intel_i2c_reset(struct drm_device *dev); /* intel_opregion.c */ -struct intel_encoder; extern int intel_opregion_setup(struct drm_device *dev); #ifdef CONFIG_ACPI extern void intel_opregion_init(struct drm_device *dev); extern void intel_opregion_fini(struct drm_device *dev); extern void intel_opregion_asle_intr(struct drm_device *dev); -extern int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder, - bool enable); -extern int intel_opregion_notify_adapter(struct drm_device *dev, - pci_power_t state); #else static inline void intel_opregion_init(struct drm_device *dev) { return; } static inline void intel_opregion_fini(struct drm_device *dev) { return; } static inline void intel_opregion_asle_intr(struct drm_device *dev) { return; } -static inline int -intel_opregion_notify_encoder(struct intel_encoder *intel_encoder, bool enable) -{ - return 0; -} -static inline int -intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state) -{ - return 0; -} #endif /* intel_acpi.c */ @@ -2420,16 +2256,8 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val) u32 vlv_punit_read(struct drm_i915_private *dev_priv, u8 addr); void vlv_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val); u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr); -u32 vlv_gpio_nc_read(struct drm_i915_private *dev_priv, u32 reg); -void vlv_gpio_nc_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); -u32 vlv_cck_read(struct drm_i915_private *dev_priv, u32 reg); -void vlv_cck_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); -u32 vlv_ccu_read(struct drm_i915_private *dev_priv, u32 reg); -void vlv_ccu_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); -u32 vlv_gps_core_read(struct drm_i915_private *dev_priv, u32 reg); -void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); -u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg); -void vlv_dpio_write(struct drm_i915_private *dev_priv, enum pipe pipe, int reg, u32 val); +u32 vlv_dpio_read(struct drm_i915_private *dev_priv, int reg); +void vlv_dpio_write(struct drm_i915_private *dev_priv, int reg, u32 val); u32 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg, enum intel_sbi_destination destination); void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value, @@ -2438,21 +2266,37 @@ void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value, int vlv_gpu_freq(int ddr_freq, int val); int vlv_freq_opcode(int ddr_freq, int val); -#define I915_READ8(reg) dev_priv->uncore.funcs.mmio_readb(dev_priv, (reg), true) -#define I915_WRITE8(reg, val) dev_priv->uncore.funcs.mmio_writeb(dev_priv, (reg), (val), true) - -#define I915_READ16(reg) dev_priv->uncore.funcs.mmio_readw(dev_priv, (reg), true) -#define I915_WRITE16(reg, val) dev_priv->uncore.funcs.mmio_writew(dev_priv, (reg), (val), true) -#define I915_READ16_NOTRACE(reg) dev_priv->uncore.funcs.mmio_readw(dev_priv, (reg), false) -#define I915_WRITE16_NOTRACE(reg, val) dev_priv->uncore.funcs.mmio_writew(dev_priv, (reg), (val), false) - -#define I915_READ(reg) dev_priv->uncore.funcs.mmio_readl(dev_priv, (reg), true) -#define I915_WRITE(reg, val) dev_priv->uncore.funcs.mmio_writel(dev_priv, (reg), (val), true) -#define I915_READ_NOTRACE(reg) dev_priv->uncore.funcs.mmio_readl(dev_priv, (reg), false) -#define I915_WRITE_NOTRACE(reg, val) dev_priv->uncore.funcs.mmio_writel(dev_priv, (reg), (val), false) - -#define I915_WRITE64(reg, val) dev_priv->uncore.funcs.mmio_writeq(dev_priv, (reg), (val), true) -#define I915_READ64(reg) dev_priv->uncore.funcs.mmio_readq(dev_priv, (reg), true) +#define __i915_read(x) \ + u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg, bool trace); +__i915_read(8) +__i915_read(16) +__i915_read(32) +__i915_read(64) +#undef __i915_read + +#define __i915_write(x) \ + void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val, bool trace); +__i915_write(8) +__i915_write(16) +__i915_write(32) +__i915_write(64) +#undef __i915_write + +#define I915_READ8(reg) i915_read8(dev_priv, (reg), true) +#define I915_WRITE8(reg, val) i915_write8(dev_priv, (reg), (val), true) + +#define I915_READ16(reg) i915_read16(dev_priv, (reg), true) +#define I915_WRITE16(reg, val) i915_write16(dev_priv, (reg), (val), true) +#define I915_READ16_NOTRACE(reg) i915_read16(dev_priv, (reg), false) +#define I915_WRITE16_NOTRACE(reg, val) i915_write16(dev_priv, (reg), (val), false) + +#define I915_READ(reg) i915_read32(dev_priv, (reg), true) +#define I915_WRITE(reg, val) i915_write32(dev_priv, (reg), (val), true) +#define I915_READ_NOTRACE(reg) i915_read32(dev_priv, (reg), false) +#define I915_WRITE_NOTRACE(reg, val) i915_write32(dev_priv, (reg), (val), false) + +#define I915_WRITE64(reg, val) i915_write64(dev_priv, (reg), (val), true) +#define I915_READ64(reg) i915_read64(dev_priv, (reg), true) #define POSTING_READ(reg) (void)I915_READ_NOTRACE(reg) #define POSTING_READ16(reg) (void)I915_READ16_NOTRACE(reg) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 621c7c6..cdfb9da 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -41,9 +41,6 @@ static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *o static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj, bool force); static __must_check int -i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, - bool readonly); -static __must_check int i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, struct i915_address_space *vm, unsigned alignment, @@ -64,8 +61,8 @@ static unsigned long i915_gem_inactive_count(struct shrinker *shrinker, struct shrink_control *sc); static unsigned long i915_gem_inactive_scan(struct shrinker *shrinker, struct shrink_control *sc); -static unsigned long i915_gem_purge(struct drm_i915_private *dev_priv, long target); -static unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv); +static long i915_gem_purge(struct drm_i915_private *dev_priv, long target); +static long i915_gem_shrink_all(struct drm_i915_private *dev_priv); static void i915_gem_object_truncate(struct drm_i915_gem_object *obj); static bool cpu_cache_is_coherent(struct drm_device *dev, @@ -261,7 +258,7 @@ i915_gem_dumb_create(struct drm_file *file, struct drm_mode_create_dumb *args) { /* have to work out size/pitch and return them */ - args->pitch = ALIGN(args->width * DIV_ROUND_UP(args->bpp, 8), 64); + args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64); args->size = args->pitch * args->height; return i915_gem_create(file, dev, args->size, &args->handle); @@ -435,9 +432,11 @@ i915_gem_shmem_pread(struct drm_device *dev, * optimizes for the case when the gpu will dirty the data * anyway again before the next pread happens. */ needs_clflush = !cpu_cache_is_coherent(dev, obj->cache_level); - ret = i915_gem_object_wait_rendering(obj, true); - if (ret) - return ret; + if (i915_gem_obj_bound_any(obj)) { + ret = i915_gem_object_set_to_gtt_domain(obj, false); + if (ret) + return ret; + } } ret = i915_gem_object_get_pages(obj); @@ -749,9 +748,11 @@ i915_gem_shmem_pwrite(struct drm_device *dev, * optimizes for the case when the gpu will use the data * right away and we therefore have to clflush anyway. */ needs_clflush_after = cpu_write_needs_clflush(obj); - ret = i915_gem_object_wait_rendering(obj, false); - if (ret) - return ret; + if (i915_gem_obj_bound_any(obj)) { + ret = i915_gem_object_set_to_gtt_domain(obj, true); + if (ret) + return ret; + } } /* Same trick applies to invalidate partially written cachelines read * before writing. */ @@ -965,31 +966,12 @@ i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno) BUG_ON(!mutex_is_locked(&ring->dev->struct_mutex)); ret = 0; - if (seqno == ring->outstanding_lazy_seqno) + if (seqno == ring->outstanding_lazy_request) ret = i915_add_request(ring, NULL); return ret; } -static void fake_irq(unsigned long data) -{ - wake_up_process((struct task_struct *)data); -} - -static bool missed_irq(struct drm_i915_private *dev_priv, - struct intel_ring_buffer *ring) -{ - return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings); -} - -static bool can_wait_boost(struct drm_i915_file_private *file_priv) -{ - if (file_priv == NULL) - return true; - - return !atomic_xchg(&file_priv->rps_wait_boost, true); -} - /** * __wait_seqno - wait until execution of seqno has finished * @ring: the ring expected to report seqno @@ -1010,14 +992,13 @@ static bool can_wait_boost(struct drm_i915_file_private *file_priv) */ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, unsigned reset_counter, - bool interruptible, - struct timespec *timeout, - struct drm_i915_file_private *file_priv) + bool interruptible, struct timespec *timeout) { drm_i915_private_t *dev_priv = ring->dev->dev_private; - struct timespec before, now; - DEFINE_WAIT(wait); - long timeout_jiffies; + struct timespec before, now, wait_time={1,0}; + unsigned long timeout_jiffies; + long end; + bool wait_forever = true; int ret; WARN(dev_priv->pc8.irqs_disabled, "IRQs disabled\n"); @@ -1025,79 +1006,51 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, if (i915_seqno_passed(ring->get_seqno(ring, true), seqno)) return 0; - timeout_jiffies = timeout ? timespec_to_jiffies_timeout(timeout) : 1; + trace_i915_gem_request_wait_begin(ring, seqno); - if (dev_priv->info->gen >= 6 && can_wait_boost(file_priv)) { - gen6_rps_boost(dev_priv); - if (file_priv) - mod_delayed_work(dev_priv->wq, - &file_priv->mm.idle_work, - msecs_to_jiffies(100)); + if (timeout != NULL) { + wait_time = *timeout; + wait_forever = false; } - if (!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(ring)) && - WARN_ON(!ring->irq_get(ring))) + timeout_jiffies = timespec_to_jiffies_timeout(&wait_time); + + if (WARN_ON(!ring->irq_get(ring))) return -ENODEV; - /* Record current time in case interrupted by signal, or wedged */ - trace_i915_gem_request_wait_begin(ring, seqno); + /* Record current time in case interrupted by signal, or wedged * */ getrawmonotonic(&before); - for (;;) { - struct timer_list timer; - unsigned long expire; - prepare_to_wait(&ring->irq_queue, &wait, - interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); +#define EXIT_COND \ + (i915_seqno_passed(ring->get_seqno(ring, false), seqno) || \ + i915_reset_in_progress(&dev_priv->gpu_error) || \ + reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter)) + do { + if (interruptible) + end = wait_event_interruptible_timeout(ring->irq_queue, + EXIT_COND, + timeout_jiffies); + else + end = wait_event_timeout(ring->irq_queue, EXIT_COND, + timeout_jiffies); /* We need to check whether any gpu reset happened in between * the caller grabbing the seqno and now ... */ - if (reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter)) { - /* ... but upgrade the -EAGAIN to an -EIO if the gpu - * is truely gone. */ - ret = i915_gem_check_wedge(&dev_priv->gpu_error, interruptible); - if (ret == 0) - ret = -EAGAIN; - break; - } - - if (i915_seqno_passed(ring->get_seqno(ring, false), seqno)) { - ret = 0; - break; - } + if (reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter)) + end = -EAGAIN; - if (interruptible && signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - - if (timeout_jiffies <= 0) { - ret = -ETIME; - break; - } - - timer.function = NULL; - if (timeout || missed_irq(dev_priv, ring)) { - setup_timer_on_stack(&timer, fake_irq, (unsigned long)current); - expire = jiffies + (missed_irq(dev_priv, ring) ? 1: timeout_jiffies); - mod_timer(&timer, expire); - } - - io_schedule(); - - if (timeout) - timeout_jiffies = expire - jiffies; + /* ... but upgrade the -EGAIN to an -EIO if the gpu is truely + * gone. */ + ret = i915_gem_check_wedge(&dev_priv->gpu_error, interruptible); + if (ret) + end = ret; + } while (end == 0 && wait_forever); - if (timer.function) { - del_singleshot_timer_sync(&timer); - destroy_timer_on_stack(&timer); - } - } getrawmonotonic(&now); - trace_i915_gem_request_wait_end(ring, seqno); ring->irq_put(ring); - - finish_wait(&ring->irq_queue, &wait); + trace_i915_gem_request_wait_end(ring, seqno); +#undef EXIT_COND if (timeout) { struct timespec sleep_time = timespec_sub(now, before); @@ -1106,7 +1059,17 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, set_normalized_timespec(timeout, 0, 0); } - return ret; + switch (end) { + case -EIO: + case -EAGAIN: /* Wedged */ + case -ERESTARTSYS: /* Signal */ + return (int)end; + case 0: /* Timeout */ + return -ETIME; + default: /* Completed */ + WARN_ON(end < 0); /* We're not aware of other errors */ + return 0; + } } /** @@ -1134,7 +1097,7 @@ i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno) return __wait_seqno(ring, seqno, atomic_read(&dev_priv->gpu_error.reset_counter), - interruptible, NULL, NULL); + interruptible, NULL); } static int @@ -1184,7 +1147,6 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, */ static __must_check int i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj, - struct drm_file *file, bool readonly) { struct drm_device *dev = obj->base.dev; @@ -1211,7 +1173,7 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj, reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); mutex_unlock(&dev->struct_mutex); - ret = __wait_seqno(ring, seqno, reset_counter, true, NULL, file->driver_priv); + ret = __wait_seqno(ring, seqno, reset_counter, true, NULL); mutex_lock(&dev->struct_mutex); if (ret) return ret; @@ -1260,7 +1222,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, * We will repeat the flush holding the lock in the normal manner * to catch cases where we are gazumped. */ - ret = i915_gem_object_wait_rendering__nonblocking(obj, file, !write_domain); + ret = i915_gem_object_wait_rendering__nonblocking(obj, !write_domain); if (ret) goto unref; @@ -1728,13 +1690,13 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj) return 0; } -static unsigned long +static long __i915_gem_shrink(struct drm_i915_private *dev_priv, long target, bool purgeable_only) { struct list_head still_bound_list; struct drm_i915_gem_object *obj, *next; - unsigned long count = 0; + long count = 0; list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list, @@ -1800,13 +1762,13 @@ __i915_gem_shrink(struct drm_i915_private *dev_priv, long target, return count; } -static unsigned long +static long i915_gem_purge(struct drm_i915_private *dev_priv, long target) { return __i915_gem_shrink(dev_priv, target, true); } -static unsigned long +static long i915_gem_shrink_all(struct drm_i915_private *dev_priv) { struct drm_i915_gem_object *obj, *next; @@ -1816,8 +1778,9 @@ i915_gem_shrink_all(struct drm_i915_private *dev_priv) list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list, global_list) { - if (i915_gem_object_put_pages(obj) == 0) + if (obj->pages_pin_count == 0) freed += obj->base.size >> PAGE_SHIFT; + i915_gem_object_put_pages(obj); } return freed; } @@ -1902,9 +1865,6 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) sg->length += PAGE_SIZE; } last_pfn = page_to_pfn(page); - - /* Check that the i965g/gm workaround works. */ - WARN_ON((gfp & __GFP_DMA32) && (last_pfn >= 0x00100000UL)); } #ifdef CONFIG_SWIOTLB if (!swiotlb_nr_tbl()) @@ -1958,7 +1918,7 @@ i915_gem_object_get_pages(struct drm_i915_gem_object *obj) return 0; } -static void +void i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, struct intel_ring_buffer *ring) { @@ -1997,13 +1957,6 @@ i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, } } -void i915_vma_move_to_active(struct i915_vma *vma, - struct intel_ring_buffer *ring) -{ - list_move_tail(&vma->mm_list, &vma->vm->active_list); - return i915_gem_object_move_to_active(vma->obj, ring); -} - static void i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj) { @@ -2125,10 +2078,11 @@ int __i915_add_request(struct intel_ring_buffer *ring, if (ret) return ret; - request = ring->preallocated_lazy_request; - if (WARN_ON(request == NULL)) + request = kmalloc(sizeof(*request), GFP_KERNEL); + if (request == NULL) return -ENOMEM; + /* Record the position of the start of the request so that * should we detect the updated seqno part-way through the * GPU processing the request, we never over-estimate the @@ -2137,13 +2091,17 @@ int __i915_add_request(struct intel_ring_buffer *ring, request_ring_position = intel_ring_get_tail(ring); ret = ring->add_request(ring); - if (ret) + if (ret) { + kfree(request); return ret; + } request->seqno = intel_ring_get_seqno(ring); request->ring = ring; request->head = request_start; request->tail = request_ring_position; + request->ctx = ring->last_context; + request->batch_obj = obj; /* Whilst this request exists, batch_obj will be on the * active_list, and so will hold the active reference. Only when this @@ -2151,12 +2109,7 @@ int __i915_add_request(struct intel_ring_buffer *ring, * inactive_list and lose its active reference. Hence we do not need * to explicitly hold another reference here. */ - request->batch_obj = obj; - /* Hold a reference to the current context so that we can inspect - * it later in case a hangcheck error event fires. - */ - request->ctx = ring->last_context; if (request->ctx) i915_gem_context_reference(request->ctx); @@ -2176,14 +2129,12 @@ int __i915_add_request(struct intel_ring_buffer *ring, } trace_i915_gem_request_add(ring, request->seqno); - ring->outstanding_lazy_seqno = 0; - ring->preallocated_lazy_request = NULL; + ring->outstanding_lazy_request = 0; if (!dev_priv->ums.mm_suspended) { i915_queue_hangcheck(ring->dev); if (was_empty) { - cancel_delayed_work_sync(&dev_priv->mm.idle_work); queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, round_jiffies_up_relative(HZ)); @@ -2205,8 +2156,10 @@ i915_gem_request_remove_from_client(struct drm_i915_gem_request *request) return; spin_lock(&file_priv->mm.lock); - list_del(&request->client_list); - request->file_priv = NULL; + if (request->file_priv) { + list_del(&request->client_list); + request->file_priv = NULL; + } spin_unlock(&file_priv->mm.lock); } @@ -2271,21 +2224,6 @@ static bool i915_request_guilty(struct drm_i915_gem_request *request, return false; } -static bool i915_context_is_banned(const struct i915_ctx_hang_stats *hs) -{ - const unsigned long elapsed = get_seconds() - hs->guilty_ts; - - if (hs->banned) - return true; - - if (elapsed <= DRM_I915_CTX_BAN_PERIOD) { - DRM_ERROR("context hanging too fast, declaring banned!\n"); - return true; - } - - return false; -} - static void i915_set_reset_status(struct intel_ring_buffer *ring, struct drm_i915_gem_request *request, u32 acthd) @@ -2322,13 +2260,10 @@ static void i915_set_reset_status(struct intel_ring_buffer *ring, hs = &request->file_priv->hang_stats; if (hs) { - if (guilty) { - hs->banned = i915_context_is_banned(hs); + if (guilty) hs->batch_active++; - hs->guilty_ts = get_seconds(); - } else { + else hs->batch_pending++; - } } } @@ -2406,8 +2341,6 @@ void i915_gem_reset(struct drm_device *dev) for_each_ring(ring, dev_priv, i) i915_gem_reset_ring_lists(dev_priv, ring); - i915_gem_cleanup_ringbuffer(dev); - i915_gem_restore_fences(dev); } @@ -2472,53 +2405,57 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring) WARN_ON(i915_verify_lists(ring->dev)); } -bool +void i915_gem_retire_requests(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; struct intel_ring_buffer *ring; - bool idle = true; int i; - for_each_ring(ring, dev_priv, i) { + for_each_ring(ring, dev_priv, i) i915_gem_retire_requests_ring(ring); - idle &= list_empty(&ring->request_list); - } - - if (idle) - mod_delayed_work(dev_priv->wq, - &dev_priv->mm.idle_work, - msecs_to_jiffies(100)); - - return idle; } static void i915_gem_retire_work_handler(struct work_struct *work) { - struct drm_i915_private *dev_priv = - container_of(work, typeof(*dev_priv), mm.retire_work.work); - struct drm_device *dev = dev_priv->dev; + drm_i915_private_t *dev_priv; + struct drm_device *dev; + struct intel_ring_buffer *ring; bool idle; + int i; + + dev_priv = container_of(work, drm_i915_private_t, + mm.retire_work.work); + dev = dev_priv->dev; /* Come back later if the device is busy... */ - idle = false; - if (mutex_trylock(&dev->struct_mutex)) { - idle = i915_gem_retire_requests(dev); - mutex_unlock(&dev->struct_mutex); - } - if (!idle) + if (!mutex_trylock(&dev->struct_mutex)) { queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, round_jiffies_up_relative(HZ)); -} + return; + } -static void -i915_gem_idle_work_handler(struct work_struct *work) -{ - struct drm_i915_private *dev_priv = - container_of(work, typeof(*dev_priv), mm.idle_work.work); + i915_gem_retire_requests(dev); + + /* Send a periodic flush down the ring so we don't hold onto GEM + * objects indefinitely. + */ + idle = true; + for_each_ring(ring, dev_priv, i) { + if (ring->gpu_caches_dirty) + i915_add_request(ring, NULL); + + idle &= list_empty(&ring->request_list); + } + + if (!dev_priv->ums.mm_suspended && !idle) + queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, + round_jiffies_up_relative(HZ)); + if (idle) + intel_mark_idle(dev); - intel_mark_idle(dev_priv->dev); + mutex_unlock(&dev->struct_mutex); } /** @@ -2616,7 +2553,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); mutex_unlock(&dev->struct_mutex); - ret = __wait_seqno(ring, seqno, reset_counter, true, timeout, file->driver_priv); + ret = __wait_seqno(ring, seqno, reset_counter, true, timeout); if (timeout) args->timeout_ns = timespec_to_ns(timeout); return ret; @@ -2663,7 +2600,6 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj, if (ret) return ret; - trace_i915_gem_ring_sync_to(from, to, seqno); ret = to->sync_to(to, from, seqno); if (!ret) /* We use last_read_seqno because sync_to() @@ -2705,17 +2641,11 @@ int i915_vma_unbind(struct i915_vma *vma) drm_i915_private_t *dev_priv = obj->base.dev->dev_private; int ret; - /* For now we only ever use 1 vma per object */ - WARN_ON(!list_is_singular(&obj->vma_list)); - if (list_empty(&vma->vma_link)) return 0; - if (!drm_mm_node_allocated(&vma->node)) { - i915_gem_vma_destroy(vma); - - return 0; - } + if (!drm_mm_node_allocated(&vma->node)) + goto destroy; if (obj->pin_count) return -EBUSY; @@ -2755,10 +2685,13 @@ int i915_vma_unbind(struct i915_vma *vma) drm_mm_remove_node(&vma->node); +destroy: i915_gem_vma_destroy(vma); /* Since the unbound list is global, only move to that list if - * no more VMAs exist. */ + * no more VMAs exist. + * NB: Until we have real VMAs there will only ever be one */ + WARN_ON(!list_empty(&obj->vma_list)); if (list_empty(&obj->vma_list)) list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list); @@ -2954,7 +2887,6 @@ static void i915_gem_write_fence(struct drm_device *dev, int reg, obj->stride, obj->tiling_mode); switch (INTEL_INFO(dev)->gen) { - case 8: case 7: case 6: case 5: @@ -3457,7 +3389,8 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) /* And bump the LRU for this access */ if (i915_gem_object_is_inactive(obj)) { - struct i915_vma *vma = i915_gem_obj_to_ggtt(obj); + struct i915_vma *vma = i915_gem_obj_to_vma(obj, + &dev_priv->gtt.base); if (vma) list_move_tail(&vma->mm_list, &dev_priv->gtt.base.inactive_list); @@ -3828,7 +3761,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) if (seqno == 0) return 0; - ret = __wait_seqno(ring, seqno, reset_counter, true, NULL, NULL); + ret = __wait_seqno(ring, seqno, reset_counter, true, NULL); if (ret == 0) queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); @@ -3932,11 +3865,6 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, goto out; } - if (obj->user_pin_count == ULONG_MAX) { - ret = -EBUSY; - goto out; - } - if (obj->user_pin_count == 0) { ret = i915_gem_obj_ggtt_pin(obj, args->alignment, true, false); if (ret) @@ -4087,6 +4015,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj, { INIT_LIST_HEAD(&obj->global_list); INIT_LIST_HEAD(&obj->ring_list); + INIT_LIST_HEAD(&obj->exec_list); INIT_LIST_HEAD(&obj->obj_exec_link); INIT_LIST_HEAD(&obj->vma_list); @@ -4158,6 +4087,13 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, return obj; } +int i915_gem_init_object(struct drm_gem_object *obj) +{ + BUG(); + + return 0; +} + void i915_gem_free_object(struct drm_gem_object *gem_obj) { struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); @@ -4211,20 +4147,9 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) i915_gem_object_free(obj); } -struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj, +struct i915_vma *i915_gem_vma_create(struct drm_i915_gem_object *obj, struct i915_address_space *vm) { - struct i915_vma *vma; - list_for_each_entry(vma, &obj->vma_list, vma_link) - if (vma->vm == vm) - return vma; - - return NULL; -} - -static struct i915_vma *__i915_gem_vma_create(struct drm_i915_gem_object *obj, - struct i915_address_space *vm) -{ struct i915_vma *vma = kzalloc(sizeof(*vma), GFP_KERNEL); if (vma == NULL) return ERR_PTR(-ENOMEM); @@ -4244,103 +4169,76 @@ static struct i915_vma *__i915_gem_vma_create(struct drm_i915_gem_object *obj, return vma; } -struct i915_vma * -i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj, - struct i915_address_space *vm) -{ - struct i915_vma *vma; - - vma = i915_gem_obj_to_vma(obj, vm); - if (!vma) - vma = __i915_gem_vma_create(obj, vm); - - return vma; -} - void i915_gem_vma_destroy(struct i915_vma *vma) { WARN_ON(vma->node.allocated); - - /* Keep the vma as a placeholder in the execbuffer reservation lists */ - if (!list_empty(&vma->exec_list)) - return; - list_del(&vma->vma_link); - kfree(vma); } int -i915_gem_suspend(struct drm_device *dev) +i915_gem_idle(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; - int ret = 0; + int ret; - mutex_lock(&dev->struct_mutex); - if (dev_priv->ums.mm_suspended) - goto err; + if (dev_priv->ums.mm_suspended) { + mutex_unlock(&dev->struct_mutex); + return 0; + } ret = i915_gpu_idle(dev); - if (ret) - goto err; - + if (ret) { + mutex_unlock(&dev->struct_mutex); + return ret; + } i915_gem_retire_requests(dev); /* Under UMS, be paranoid and evict. */ if (!drm_core_check_feature(dev, DRIVER_MODESET)) i915_gem_evict_everything(dev); + del_timer_sync(&dev_priv->gpu_error.hangcheck_timer); + i915_kernel_lost_context(dev); i915_gem_cleanup_ringbuffer(dev); - /* Hack! Don't let anybody do execbuf while we don't control the chip. - * We need to replace this with a semaphore, or something. - * And not confound ums.mm_suspended! - */ - dev_priv->ums.mm_suspended = !drm_core_check_feature(dev, - DRIVER_MODESET); - mutex_unlock(&dev->struct_mutex); - - del_timer_sync(&dev_priv->gpu_error.hangcheck_timer); + /* Cancel the retire work handler, which should be idle now. */ cancel_delayed_work_sync(&dev_priv->mm.retire_work); - cancel_delayed_work_sync(&dev_priv->mm.idle_work); return 0; - -err: - mutex_unlock(&dev->struct_mutex); - return ret; } -int i915_gem_l3_remap(struct intel_ring_buffer *ring, int slice) +void i915_gem_l3_remap(struct drm_device *dev) { - struct drm_device *dev = ring->dev; drm_i915_private_t *dev_priv = dev->dev_private; - u32 reg_base = GEN7_L3LOG_BASE + (slice * 0x200); - u32 *remap_info = dev_priv->l3_parity.remap_info[slice]; - int i, ret; + u32 misccpctl; + int i; - if (!HAS_L3_DPF(dev) || !remap_info) - return 0; + if (!HAS_L3_GPU_CACHE(dev)) + return; - ret = intel_ring_begin(ring, GEN7_L3LOG_SIZE / 4 * 3); - if (ret) - return ret; + if (!dev_priv->l3_parity.remap_info) + return; + + misccpctl = I915_READ(GEN7_MISCCPCTL); + I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); + POSTING_READ(GEN7_MISCCPCTL); - /* - * Note: We do not worry about the concurrent register cacheline hang - * here because no other code should access these registers other than - * at initialization time. - */ for (i = 0; i < GEN7_L3LOG_SIZE; i += 4) { - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit(ring, reg_base + i); - intel_ring_emit(ring, remap_info[i/4]); + u32 remap = I915_READ(GEN7_L3LOG_BASE + i); + if (remap && remap != dev_priv->l3_parity.remap_info[i/4]) + DRM_DEBUG("0x%x was already programmed to %x\n", + GEN7_L3LOG_BASE + i, remap); + if (remap && !dev_priv->l3_parity.remap_info[i/4]) + DRM_DEBUG_DRIVER("Clearing remapped register\n"); + I915_WRITE(GEN7_L3LOG_BASE + i, dev_priv->l3_parity.remap_info[i/4]); } - intel_ring_advance(ring); + /* Make sure all the writes land before disabling dop clock gating */ + POSTING_READ(GEN7_L3LOG_BASE); - return ret; + I915_WRITE(GEN7_MISCCPCTL, misccpctl); } void i915_gem_init_swizzling(struct drm_device *dev) @@ -4362,8 +4260,6 @@ void i915_gem_init_swizzling(struct drm_device *dev) I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_SNB)); else if (IS_GEN7(dev)) I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB)); - else if (IS_GEN8(dev)) - I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_BDW)); else BUG(); } @@ -4434,7 +4330,7 @@ int i915_gem_init_hw(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; - int ret, i; + int ret; if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt()) return -EIO; @@ -4442,25 +4338,20 @@ i915_gem_init_hw(struct drm_device *dev) if (dev_priv->ellc_size) I915_WRITE(HSW_IDICR, I915_READ(HSW_IDICR) | IDIHASHMSK(0xf)); - if (IS_HASWELL(dev)) - I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev) ? - LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED); - if (HAS_PCH_NOP(dev)) { u32 temp = I915_READ(GEN7_MSG_CTL); temp &= ~(WAIT_FOR_PCH_FLR_ACK | WAIT_FOR_PCH_RESET_ACK); I915_WRITE(GEN7_MSG_CTL, temp); } + i915_gem_l3_remap(dev); + i915_gem_init_swizzling(dev); ret = i915_gem_init_rings(dev); if (ret) return ret; - for (i = 0; i < NUM_L3_SLICES(dev); i++) - i915_gem_l3_remap(&dev_priv->ring[RCS], i); - /* * XXX: There was some w/a described somewhere suggesting loading * contexts before PPGTT. @@ -4563,12 +4454,26 @@ int i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { + struct drm_i915_private *dev_priv = dev->dev_private; + int ret; + if (drm_core_check_feature(dev, DRIVER_MODESET)) return 0; drm_irq_uninstall(dev); - return i915_gem_suspend(dev); + mutex_lock(&dev->struct_mutex); + ret = i915_gem_idle(dev); + + /* Hack! Don't let anybody do execbuf while we don't control the chip. + * We need to replace this with a semaphore, or something. + * And not confound ums.mm_suspended! + */ + if (ret != 0) + dev_priv->ums.mm_suspended = 1; + mutex_unlock(&dev->struct_mutex); + + return ret; } void @@ -4579,9 +4484,11 @@ i915_gem_lastclose(struct drm_device *dev) if (drm_core_check_feature(dev, DRIVER_MODESET)) return; - ret = i915_gem_suspend(dev); + mutex_lock(&dev->struct_mutex); + ret = i915_gem_idle(dev); if (ret) DRM_ERROR("failed to idle hardware: %d\n", ret); + mutex_unlock(&dev->struct_mutex); } static void @@ -4616,7 +4523,6 @@ i915_gem_load(struct drm_device *dev) INIT_LIST_HEAD(&dev_priv->vm_list); i915_init_vm(dev_priv, &dev_priv->gtt.base); - INIT_LIST_HEAD(&dev_priv->context_list); INIT_LIST_HEAD(&dev_priv->mm.unbound_list); INIT_LIST_HEAD(&dev_priv->mm.bound_list); INIT_LIST_HEAD(&dev_priv->mm.fence_list); @@ -4626,8 +4532,6 @@ i915_gem_load(struct drm_device *dev) INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list); INIT_DELAYED_WORK(&dev_priv->mm.retire_work, i915_gem_retire_work_handler); - INIT_DELAYED_WORK(&dev_priv->mm.idle_work, - i915_gem_idle_work_handler); init_waitqueue_head(&dev_priv->gpu_error.reset_queue); /* On GEN3 we really need to make sure the ARB C3 LP bit is set */ @@ -4678,7 +4582,7 @@ static int i915_gem_init_phys_object(struct drm_device *dev, if (dev_priv->mm.phys_objs[id - 1] || !size) return 0; - phys_obj = kzalloc(sizeof(*phys_obj), GFP_KERNEL); + phys_obj = kzalloc(sizeof(struct drm_i915_gem_phys_object), GFP_KERNEL); if (!phys_obj) return -ENOMEM; @@ -4852,8 +4756,6 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; - cancel_delayed_work_sync(&file_priv->mm.idle_work); - /* Clean up our request list when the client is going away, so that * later retire_requests won't dereference our soon-to-be-gone * file_priv. @@ -4871,38 +4773,6 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file) spin_unlock(&file_priv->mm.lock); } -static void -i915_gem_file_idle_work_handler(struct work_struct *work) -{ - struct drm_i915_file_private *file_priv = - container_of(work, typeof(*file_priv), mm.idle_work.work); - - atomic_set(&file_priv->rps_wait_boost, false); -} - -int i915_gem_open(struct drm_device *dev, struct drm_file *file) -{ - struct drm_i915_file_private *file_priv; - - DRM_DEBUG_DRIVER("\n"); - - file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); - if (!file_priv) - return -ENOMEM; - - file->driver_priv = file_priv; - file_priv->dev_priv = dev->dev_private; - - spin_lock_init(&file_priv->mm.lock); - INIT_LIST_HEAD(&file_priv->mm.request_list); - INIT_DELAYED_WORK(&file_priv->mm.idle_work, - i915_gem_file_idle_work_handler); - - idr_init(&file_priv->context_idr); - - return 0; -} - static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task) { if (!mutex_is_locked(mutex)) @@ -4953,7 +4823,6 @@ i915_gem_inactive_count(struct shrinker *shrinker, struct shrink_control *sc) if (unlock) mutex_unlock(&dev->struct_mutex); - return count; } @@ -4990,10 +4859,11 @@ bool i915_gem_obj_bound(struct drm_i915_gem_object *o, bool i915_gem_obj_bound_any(struct drm_i915_gem_object *o) { - struct i915_vma *vma; + struct drm_i915_private *dev_priv = o->base.dev->dev_private; + struct i915_address_space *vm; - list_for_each_entry(vma, &o->vma_list, vma_link) - if (drm_mm_node_allocated(&vma->node)) + list_for_each_entry(vm, &dev_priv->vm_list, global_link) + if (i915_gem_obj_bound(o, vm)) return true; return false; @@ -5025,6 +4895,7 @@ i915_gem_inactive_scan(struct shrinker *shrinker, struct shrink_control *sc) struct drm_i915_private, mm.inactive_shrinker); struct drm_device *dev = dev_priv->dev; + int nr_to_scan = sc->nr_to_scan; unsigned long freed; bool unlock = true; @@ -5038,30 +4909,38 @@ i915_gem_inactive_scan(struct shrinker *shrinker, struct shrink_control *sc) unlock = false; } - freed = i915_gem_purge(dev_priv, sc->nr_to_scan); - if (freed < sc->nr_to_scan) - freed += __i915_gem_shrink(dev_priv, - sc->nr_to_scan - freed, - false); - if (freed < sc->nr_to_scan) + freed = i915_gem_purge(dev_priv, nr_to_scan); + if (freed < nr_to_scan) + freed += __i915_gem_shrink(dev_priv, nr_to_scan, + false); + if (freed < nr_to_scan) freed += i915_gem_shrink_all(dev_priv); if (unlock) mutex_unlock(&dev->struct_mutex); - return freed; } -struct i915_vma *i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj) +struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj, + struct i915_address_space *vm) { struct i915_vma *vma; + list_for_each_entry(vma, &obj->vma_list, vma_link) + if (vma->vm == vm) + return vma; - if (WARN_ON(list_empty(&obj->vma_list))) - return NULL; + return NULL; +} - vma = list_first_entry(&obj->vma_list, typeof(*vma), vma_link); - if (WARN_ON(vma->vm != obj_to_ggtt(obj))) - return NULL; +struct i915_vma * +i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj, + struct i915_address_space *vm) +{ + struct i915_vma *vma; + + vma = i915_gem_obj_to_vma(obj, vm); + if (!vma) + vma = i915_gem_vma_create(obj, vm); return vma; } diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 72a3df3..403309c 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -73,7 +73,7 @@ * * There are two confusing terms used above: * The "current context" means the context which is currently running on the - * GPU. The GPU has loaded its state already and has stored away the gtt + * GPU. The GPU has loaded it's state already and has stored away the gtt * offset of the BO. The GPU is not actively referencing the data at this * offset, but it will on the next context switch. The only way to avoid this * is to do a GPU reset. @@ -117,9 +117,6 @@ static int get_context_size(struct drm_device *dev) else ret = GEN7_CXT_TOTAL_SIZE(reg) * 64; break; - case 8: - ret = GEN8_CXT_TOTAL_SIZE; - break; default: BUG(); } @@ -132,7 +129,6 @@ void i915_gem_context_free(struct kref *ctx_ref) struct i915_hw_context *ctx = container_of(ctx_ref, typeof(*ctx), ref); - list_del(&ctx->link); drm_gem_object_unreference(&ctx->obj->base); kfree(ctx); } @@ -151,7 +147,6 @@ create_hw_context(struct drm_device *dev, kref_init(&ctx->ref); ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); - INIT_LIST_HEAD(&ctx->link); if (ctx->obj == NULL) { kfree(ctx); DRM_DEBUG_DRIVER("Context object allocated failed\n"); @@ -171,7 +166,6 @@ create_hw_context(struct drm_device *dev, * assertion in the context switch code. */ ctx->ring = &dev_priv->ring[RCS]; - list_add_tail(&ctx->link, &dev_priv->context_list); /* Default context will never have a file_priv */ if (file_priv == NULL) @@ -184,10 +178,6 @@ create_hw_context(struct drm_device *dev, ctx->file_priv = file_priv; ctx->id = ret; - /* NB: Mark all slices as needing a remap so that when the context first - * loads it will restore whatever remap state already exists. If there - * is no remap info, it will be a NOP. */ - ctx->remap_slice = (1 << NUM_L3_SLICES(dev)) - 1; return ctx; @@ -223,6 +213,7 @@ static int create_default_context(struct drm_i915_private *dev_priv) * may not be available. To avoid this we always pin the * default context. */ + dev_priv->ring[RCS].default_context = ctx; ret = i915_gem_obj_ggtt_pin(ctx->obj, CONTEXT_ALIGN, false, false); if (ret) { DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret); @@ -235,8 +226,6 @@ static int create_default_context(struct drm_i915_private *dev_priv) goto err_unpin; } - dev_priv->ring[RCS].default_context = ctx; - DRM_DEBUG_DRIVER("Default HW context loaded\n"); return 0; @@ -292,24 +281,16 @@ void i915_gem_context_fini(struct drm_device *dev) * other code, leading to spurious errors. */ intel_gpu_reset(dev); + i915_gem_object_unpin(dctx->obj); + /* When default context is created and switched to, base object refcount * will be 2 (+1 from object creation and +1 from do_switch()). * i915_gem_context_fini() will be called after gpu_idle() has switched * to default context. So we need to unreference the base object once * to offset the do_switch part, so that i915_gem_context_unreference() * can then free the base object correctly. */ - WARN_ON(!dev_priv->ring[RCS].last_context); - if (dev_priv->ring[RCS].last_context == dctx) { - /* Fake switch to NULL context */ - WARN_ON(dctx->obj->active); - i915_gem_object_unpin(dctx->obj); - i915_gem_context_unreference(dctx); - } - - i915_gem_object_unpin(dctx->obj); + drm_gem_object_unreference(&dctx->obj->base); i915_gem_context_unreference(dctx); - dev_priv->ring[RCS].default_context = NULL; - dev_priv->ring[RCS].last_context = NULL; } static int context_idr_cleanup(int id, void *p, void *data) @@ -412,11 +393,11 @@ static int do_switch(struct i915_hw_context *to) struct intel_ring_buffer *ring = to->ring; struct i915_hw_context *from = ring->last_context; u32 hw_flags = 0; - int ret, i; + int ret; BUG_ON(from != NULL && from->obj != NULL && from->obj->pin_count == 0); - if (from == to && !to->remap_slice) + if (from == to) return 0; ret = i915_gem_obj_ggtt_pin(to->obj, CONTEXT_ALIGN, false, false); @@ -439,6 +420,8 @@ static int do_switch(struct i915_hw_context *to) if (!to->is_initialized || is_default_context(to)) hw_flags |= MI_RESTORE_INHIBIT; + else if (WARN_ON_ONCE(from == to)) /* not yet expected */ + hw_flags |= MI_FORCE_RESTORE; ret = mi_set_context(ring, to, hw_flags); if (ret) { @@ -446,18 +429,6 @@ static int do_switch(struct i915_hw_context *to) return ret; } - for (i = 0; i < MAX_L3_SLICES; i++) { - if (!(to->remap_slice & (1<<i))) - continue; - - ret = i915_gem_l3_remap(ring, i); - /* If it failed, try again next round */ - if (ret) - DRM_DEBUG_DRIVER("L3 remapping failed\n"); - else - to->remap_slice &= ~(1<<i); - } - /* The backing object for the context is done after switching to the * *next* context. Therefore we cannot retire the previous context until * the next context has already started running. In fact, the below code @@ -465,8 +436,11 @@ static int do_switch(struct i915_hw_context *to) * MI_SET_CONTEXT instead of when the next seqno has completed. */ if (from != NULL) { + struct drm_i915_private *dev_priv = from->obj->base.dev->dev_private; + struct i915_address_space *ggtt = &dev_priv->gtt.base; from->obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION; - i915_vma_move_to_active(i915_gem_obj_to_ggtt(from->obj), ring); + list_move_tail(&i915_gem_obj_to_vma(from->obj, ggtt)->mm_list, &ggtt->active_list); + i915_gem_object_move_to_active(from->obj, ring); /* As long as MI_SET_CONTEXT is serializing, ie. it flushes the * whole damn pipeline, we don't need to explicitly mark the * object dirty. The only exception is that the context must be @@ -477,7 +451,17 @@ static int do_switch(struct i915_hw_context *to) from->obj->dirty = 1; BUG_ON(from->obj->ring != ring); - /* obj is kept alive until the next request by its active ref */ + ret = i915_add_request(ring, NULL); + if (ret) { + /* Too late, we've already scheduled a context switch. + * Try to undo the change so that the hw state is + * consistent with out tracking. In case of emergency, + * scream. + */ + WARN_ON(mi_set_context(ring, from, MI_RESTORE_INHIBIT)); + return ret; + } + i915_gem_object_unpin(from->obj); i915_gem_context_unreference(from); } diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index 9bb533e..7d5752f 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -125,15 +125,13 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf) ret = i915_gem_object_get_pages(obj); if (ret) - goto err; - - i915_gem_object_pin_pages(obj); + goto error; ret = -ENOMEM; pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages)); if (pages == NULL) - goto err_unpin; + goto error; i = 0; for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) @@ -143,16 +141,15 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf) drm_free_large(pages); if (!obj->dma_buf_vmapping) - goto err_unpin; + goto error; obj->vmapping_count = 1; + i915_gem_object_pin_pages(obj); out_unlock: mutex_unlock(&dev->struct_mutex); return obj->dma_buf_vmapping; -err_unpin: - i915_gem_object_unpin_pages(obj); -err: +error: mutex_unlock(&dev->struct_mutex); return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index b737653..91b7001 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -37,9 +37,6 @@ mark_free(struct i915_vma *vma, struct list_head *unwind) if (vma->obj->pin_count) return false; - if (WARN_ON(!list_empty(&vma->exec_list))) - return false; - list_add(&vma->exec_list, unwind); return drm_mm_scan_add_block(&vma->node); } @@ -116,7 +113,7 @@ none: } /* We expect the caller to unpin, evict all and try again, or give up. - * So calling i915_gem_evict_vm() is unnecessary. + * So calling i915_gem_evict_everything() is unnecessary. */ return -ENOSPC; @@ -155,48 +152,12 @@ found: return ret; } -/** - * i915_gem_evict_vm - Try to free up VM space - * - * @vm: Address space to evict from - * @do_idle: Boolean directing whether to idle first. - * - * VM eviction is about freeing up virtual address space. If one wants fine - * grained eviction, they should see evict something for more details. In terms - * of freeing up actual system memory, this function may not accomplish the - * desired result. An object may be shared in multiple address space, and this - * function will not assert those objects be freed. - * - * Using do_idle will result in a more complete eviction because it retires, and - * inactivates current BOs. - */ -int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle) -{ - struct i915_vma *vma, *next; - int ret; - - trace_i915_gem_evict_vm(vm); - - if (do_idle) { - ret = i915_gpu_idle(vm->dev); - if (ret) - return ret; - - i915_gem_retire_requests(vm->dev); - } - - list_for_each_entry_safe(vma, next, &vm->inactive_list, mm_list) - if (vma->obj->pin_count == 0) - WARN_ON(i915_vma_unbind(vma)); - - return 0; -} - int i915_gem_evict_everything(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; struct i915_address_space *vm; + struct i915_vma *vma, *next; bool lists_empty = true; int ret; @@ -223,8 +184,11 @@ i915_gem_evict_everything(struct drm_device *dev) i915_gem_retire_requests(dev); /* Having flushed everything, unbind() should never raise an error */ - list_for_each_entry(vm, &dev_priv->vm_list, global_link) - WARN_ON(i915_gem_evict_vm(vm, false)); + list_for_each_entry(vm, &dev_priv->vm_list, global_link) { + list_for_each_entry_safe(vma, next, &vm->inactive_list, mm_list) + if (vma->obj->pin_count == 0) + WARN_ON(i915_vma_unbind(vma)); + } return 0; } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index b7e787f..bf34577 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -33,38 +33,35 @@ #include "intel_drv.h" #include <linux/dma_remapping.h> -#define __EXEC_OBJECT_HAS_PIN (1<<31) -#define __EXEC_OBJECT_HAS_FENCE (1<<30) - -struct eb_vmas { - struct list_head vmas; +struct eb_objects { + struct list_head objects; int and; union { - struct i915_vma *lut[0]; + struct drm_i915_gem_object *lut[0]; struct hlist_head buckets[0]; }; }; -static struct eb_vmas * -eb_create(struct drm_i915_gem_execbuffer2 *args, struct i915_address_space *vm) +static struct eb_objects * +eb_create(struct drm_i915_gem_execbuffer2 *args) { - struct eb_vmas *eb = NULL; + struct eb_objects *eb = NULL; if (args->flags & I915_EXEC_HANDLE_LUT) { - unsigned size = args->buffer_count; - size *= sizeof(struct i915_vma *); - size += sizeof(struct eb_vmas); + int size = args->buffer_count; + size *= sizeof(struct drm_i915_gem_object *); + size += sizeof(struct eb_objects); eb = kmalloc(size, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); } if (eb == NULL) { - unsigned size = args->buffer_count; - unsigned count = PAGE_SIZE / sizeof(struct hlist_head) / 2; + int size = args->buffer_count; + int count = PAGE_SIZE / sizeof(struct hlist_head) / 2; BUILD_BUG_ON_NOT_POWER_OF_2(PAGE_SIZE / sizeof(struct hlist_head)); while (count > 2*size) count >>= 1; eb = kzalloc(count*sizeof(struct hlist_head) + - sizeof(struct eb_vmas), + sizeof(struct eb_objects), GFP_TEMPORARY); if (eb == NULL) return eb; @@ -73,102 +70,64 @@ eb_create(struct drm_i915_gem_execbuffer2 *args, struct i915_address_space *vm) } else eb->and = -args->buffer_count; - INIT_LIST_HEAD(&eb->vmas); + INIT_LIST_HEAD(&eb->objects); return eb; } static void -eb_reset(struct eb_vmas *eb) +eb_reset(struct eb_objects *eb) { if (eb->and >= 0) memset(eb->buckets, 0, (eb->and+1)*sizeof(struct hlist_head)); } static int -eb_lookup_vmas(struct eb_vmas *eb, - struct drm_i915_gem_exec_object2 *exec, - const struct drm_i915_gem_execbuffer2 *args, - struct i915_address_space *vm, - struct drm_file *file) +eb_lookup_objects(struct eb_objects *eb, + struct drm_i915_gem_exec_object2 *exec, + const struct drm_i915_gem_execbuffer2 *args, + struct drm_file *file) { - struct drm_i915_gem_object *obj; - struct list_head objects; - int i, ret = 0; + int i; - INIT_LIST_HEAD(&objects); spin_lock(&file->table_lock); - /* Grab a reference to the object and release the lock so we can lookup - * or create the VMA without using GFP_ATOMIC */ for (i = 0; i < args->buffer_count; i++) { + struct drm_i915_gem_object *obj; + obj = to_intel_bo(idr_find(&file->object_idr, exec[i].handle)); if (obj == NULL) { spin_unlock(&file->table_lock); DRM_DEBUG("Invalid object handle %d at index %d\n", exec[i].handle, i); - ret = -ENOENT; - goto out; + return -ENOENT; } - if (!list_empty(&obj->obj_exec_link)) { + if (!list_empty(&obj->exec_list)) { spin_unlock(&file->table_lock); DRM_DEBUG("Object %p [handle %d, index %d] appears more than once in object list\n", obj, exec[i].handle, i); - ret = -EINVAL; - goto out; + return -EINVAL; } drm_gem_object_reference(&obj->base); - list_add_tail(&obj->obj_exec_link, &objects); - } - spin_unlock(&file->table_lock); - - i = 0; - list_for_each_entry(obj, &objects, obj_exec_link) { - struct i915_vma *vma; + list_add_tail(&obj->exec_list, &eb->objects); - /* - * NOTE: We can leak any vmas created here when something fails - * later on. But that's no issue since vma_unbind can deal with - * vmas which are not actually bound. And since only - * lookup_or_create exists as an interface to get at the vma - * from the (obj, vm) we don't run the risk of creating - * duplicated vmas for the same vm. - */ - vma = i915_gem_obj_lookup_or_create_vma(obj, vm); - if (IS_ERR(vma)) { - DRM_DEBUG("Failed to lookup VMA\n"); - ret = PTR_ERR(vma); - goto out; - } - - list_add_tail(&vma->exec_list, &eb->vmas); - - vma->exec_entry = &exec[i]; + obj->exec_entry = &exec[i]; if (eb->and < 0) { - eb->lut[i] = vma; + eb->lut[i] = obj; } else { uint32_t handle = args->flags & I915_EXEC_HANDLE_LUT ? i : exec[i].handle; - vma->exec_handle = handle; - hlist_add_head(&vma->exec_node, + obj->exec_handle = handle; + hlist_add_head(&obj->exec_node, &eb->buckets[handle & eb->and]); } - ++i; } + spin_unlock(&file->table_lock); - -out: - while (!list_empty(&objects)) { - obj = list_first_entry(&objects, - struct drm_i915_gem_object, - obj_exec_link); - list_del_init(&obj->obj_exec_link); - if (ret) - drm_gem_object_unreference(&obj->base); - } - return ret; + return 0; } -static struct i915_vma *eb_get_vma(struct eb_vmas *eb, unsigned long handle) +static struct drm_i915_gem_object * +eb_get_object(struct eb_objects *eb, unsigned long handle) { if (eb->and < 0) { if (handle >= -eb->and) @@ -180,55 +139,34 @@ static struct i915_vma *eb_get_vma(struct eb_vmas *eb, unsigned long handle) head = &eb->buckets[handle & eb->and]; hlist_for_each(node, head) { - struct i915_vma *vma; + struct drm_i915_gem_object *obj; - vma = hlist_entry(node, struct i915_vma, exec_node); - if (vma->exec_handle == handle) - return vma; + obj = hlist_entry(node, struct drm_i915_gem_object, exec_node); + if (obj->exec_handle == handle) + return obj; } return NULL; } } static void -i915_gem_execbuffer_unreserve_vma(struct i915_vma *vma) +eb_destroy(struct eb_objects *eb) { - struct drm_i915_gem_exec_object2 *entry; - struct drm_i915_gem_object *obj = vma->obj; - - if (!drm_mm_node_allocated(&vma->node)) - return; - - entry = vma->exec_entry; - - if (entry->flags & __EXEC_OBJECT_HAS_FENCE) - i915_gem_object_unpin_fence(obj); - - if (entry->flags & __EXEC_OBJECT_HAS_PIN) - i915_gem_object_unpin(obj); - - entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | __EXEC_OBJECT_HAS_PIN); -} - -static void eb_destroy(struct eb_vmas *eb) -{ - while (!list_empty(&eb->vmas)) { - struct i915_vma *vma; + while (!list_empty(&eb->objects)) { + struct drm_i915_gem_object *obj; - vma = list_first_entry(&eb->vmas, - struct i915_vma, + obj = list_first_entry(&eb->objects, + struct drm_i915_gem_object, exec_list); - list_del_init(&vma->exec_list); - i915_gem_execbuffer_unreserve_vma(vma); - drm_gem_object_unreference(&vma->obj->base); + list_del_init(&obj->exec_list); + drm_gem_object_unreference(&obj->base); } kfree(eb); } static inline int use_cpu_reloc(struct drm_i915_gem_object *obj) { - return (HAS_LLC(obj->base.dev) || - obj->base.write_domain == I915_GEM_DOMAIN_CPU || + return (obj->base.write_domain == I915_GEM_DOMAIN_CPU || !obj->map_and_fenceable || obj->cache_level != I915_CACHE_NONE); } @@ -237,31 +175,17 @@ static int relocate_entry_cpu(struct drm_i915_gem_object *obj, struct drm_i915_gem_relocation_entry *reloc) { - struct drm_device *dev = obj->base.dev; uint32_t page_offset = offset_in_page(reloc->offset); char *vaddr; int ret = -EINVAL; - ret = i915_gem_object_set_to_cpu_domain(obj, true); + ret = i915_gem_object_set_to_cpu_domain(obj, 1); if (ret) return ret; vaddr = kmap_atomic(i915_gem_object_get_page(obj, reloc->offset >> PAGE_SHIFT)); *(uint32_t *)(vaddr + page_offset) = reloc->delta; - - if (INTEL_INFO(dev)->gen >= 8) { - page_offset = offset_in_page(page_offset + sizeof(uint32_t)); - - if (page_offset == 0) { - kunmap_atomic(vaddr); - vaddr = kmap_atomic(i915_gem_object_get_page(obj, - (reloc->offset + sizeof(uint32_t)) >> PAGE_SHIFT)); - } - - *(uint32_t *)(vaddr + page_offset) = 0; - } - kunmap_atomic(vaddr); return 0; @@ -292,21 +216,6 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj, reloc_entry = (uint32_t __iomem *) (reloc_page + offset_in_page(reloc->offset)); iowrite32(reloc->delta, reloc_entry); - - if (INTEL_INFO(dev)->gen >= 8) { - reloc_entry += 1; - - if (offset_in_page(reloc->offset + sizeof(uint32_t)) == 0) { - io_mapping_unmap_atomic(reloc_page); - reloc_page = io_mapping_map_atomic_wc( - dev_priv->gtt.mappable, - reloc->offset + sizeof(uint32_t)); - reloc_entry = reloc_page; - } - - iowrite32(0, reloc_entry); - } - io_mapping_unmap_atomic(reloc_page); return 0; @@ -314,24 +223,22 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj, static int i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, - struct eb_vmas *eb, + struct eb_objects *eb, struct drm_i915_gem_relocation_entry *reloc, struct i915_address_space *vm) { struct drm_device *dev = obj->base.dev; struct drm_gem_object *target_obj; struct drm_i915_gem_object *target_i915_obj; - struct i915_vma *target_vma; uint32_t target_offset; int ret = -EINVAL; /* we've already hold a reference to all valid objects */ - target_vma = eb_get_vma(eb, reloc->target_handle); - if (unlikely(target_vma == NULL)) + target_obj = &eb_get_object(eb, reloc->target_handle)->base; + if (unlikely(target_obj == NULL)) return -ENOENT; - target_i915_obj = target_vma->obj; - target_obj = &target_vma->obj->base; + target_i915_obj = to_intel_bo(target_obj); target_offset = i915_gem_obj_ggtt_offset(target_i915_obj); /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and @@ -377,8 +284,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, return 0; /* Check that the relocation address is valid... */ - if (unlikely(reloc->offset > - obj->base.size - (INTEL_INFO(dev)->gen >= 8 ? 8 : 4))) { + if (unlikely(reloc->offset > obj->base.size - 4)) { DRM_DEBUG("Relocation beyond object bounds: " "obj %p target %d offset %d size %d.\n", obj, reloc->target_handle, @@ -414,13 +320,14 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, } static int -i915_gem_execbuffer_relocate_vma(struct i915_vma *vma, - struct eb_vmas *eb) +i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj, + struct eb_objects *eb, + struct i915_address_space *vm) { #define N_RELOC(x) ((x) / sizeof(struct drm_i915_gem_relocation_entry)) struct drm_i915_gem_relocation_entry stack_reloc[N_RELOC(512)]; struct drm_i915_gem_relocation_entry __user *user_relocs; - struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; + struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; int remain, ret; user_relocs = to_user_ptr(entry->relocs_ptr); @@ -439,8 +346,8 @@ i915_gem_execbuffer_relocate_vma(struct i915_vma *vma, do { u64 offset = r->presumed_offset; - ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, r, - vma->vm); + ret = i915_gem_execbuffer_relocate_entry(obj, eb, r, + vm); if (ret) return ret; @@ -461,16 +368,17 @@ i915_gem_execbuffer_relocate_vma(struct i915_vma *vma, } static int -i915_gem_execbuffer_relocate_vma_slow(struct i915_vma *vma, - struct eb_vmas *eb, - struct drm_i915_gem_relocation_entry *relocs) +i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj, + struct eb_objects *eb, + struct drm_i915_gem_relocation_entry *relocs, + struct i915_address_space *vm) { - const struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; + const struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; int i, ret; for (i = 0; i < entry->relocation_count; i++) { - ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, &relocs[i], - vma->vm); + ret = i915_gem_execbuffer_relocate_entry(obj, eb, &relocs[i], + vm); if (ret) return ret; } @@ -479,10 +387,10 @@ i915_gem_execbuffer_relocate_vma_slow(struct i915_vma *vma, } static int -i915_gem_execbuffer_relocate(struct eb_vmas *eb, +i915_gem_execbuffer_relocate(struct eb_objects *eb, struct i915_address_space *vm) { - struct i915_vma *vma; + struct drm_i915_gem_object *obj; int ret = 0; /* This is the fast path and we cannot handle a pagefault whilst @@ -493,8 +401,8 @@ i915_gem_execbuffer_relocate(struct eb_vmas *eb, * lockdep complains vehemently. */ pagefault_disable(); - list_for_each_entry(vma, &eb->vmas, exec_list) { - ret = i915_gem_execbuffer_relocate_vma(vma, eb); + list_for_each_entry(obj, &eb->objects, exec_list) { + ret = i915_gem_execbuffer_relocate_object(obj, eb, vm); if (ret) break; } @@ -503,33 +411,35 @@ i915_gem_execbuffer_relocate(struct eb_vmas *eb, return ret; } +#define __EXEC_OBJECT_HAS_PIN (1<<31) +#define __EXEC_OBJECT_HAS_FENCE (1<<30) + static int -need_reloc_mappable(struct i915_vma *vma) +need_reloc_mappable(struct drm_i915_gem_object *obj) { - struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; - return entry->relocation_count && !use_cpu_reloc(vma->obj) && - i915_is_ggtt(vma->vm); + struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; + return entry->relocation_count && !use_cpu_reloc(obj); } static int -i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, - struct intel_ring_buffer *ring, - bool *need_reloc) +i915_gem_execbuffer_reserve_object(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *ring, + struct i915_address_space *vm, + bool *need_reloc) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; - struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; + struct drm_i915_private *dev_priv = obj->base.dev->dev_private; + struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; bool need_fence, need_mappable; - struct drm_i915_gem_object *obj = vma->obj; int ret; need_fence = has_fenced_gpu_access && entry->flags & EXEC_OBJECT_NEEDS_FENCE && obj->tiling_mode != I915_TILING_NONE; - need_mappable = need_fence || need_reloc_mappable(vma); + need_mappable = need_fence || need_reloc_mappable(obj); - ret = i915_gem_object_pin(obj, vma->vm, entry->alignment, need_mappable, + ret = i915_gem_object_pin(obj, vm, entry->alignment, need_mappable, false); if (ret) return ret; @@ -557,8 +467,8 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, obj->has_aliasing_ppgtt_mapping = 1; } - if (entry->offset != vma->node.start) { - entry->offset = vma->node.start; + if (entry->offset != i915_gem_obj_offset(obj, vm)) { + entry->offset = i915_gem_obj_offset(obj, vm); *need_reloc = true; } @@ -574,48 +484,62 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, return 0; } +static void +i915_gem_execbuffer_unreserve_object(struct drm_i915_gem_object *obj) +{ + struct drm_i915_gem_exec_object2 *entry; + + if (!i915_gem_obj_bound_any(obj)) + return; + + entry = obj->exec_entry; + + if (entry->flags & __EXEC_OBJECT_HAS_FENCE) + i915_gem_object_unpin_fence(obj); + + if (entry->flags & __EXEC_OBJECT_HAS_PIN) + i915_gem_object_unpin(obj); + + entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | __EXEC_OBJECT_HAS_PIN); +} + static int i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, - struct list_head *vmas, + struct list_head *objects, + struct i915_address_space *vm, bool *need_relocs) { struct drm_i915_gem_object *obj; - struct i915_vma *vma; - struct i915_address_space *vm; - struct list_head ordered_vmas; + struct list_head ordered_objects; bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; int retry; - if (list_empty(vmas)) - return 0; - - vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm; - - INIT_LIST_HEAD(&ordered_vmas); - while (!list_empty(vmas)) { + INIT_LIST_HEAD(&ordered_objects); + while (!list_empty(objects)) { struct drm_i915_gem_exec_object2 *entry; bool need_fence, need_mappable; - vma = list_first_entry(vmas, struct i915_vma, exec_list); - obj = vma->obj; - entry = vma->exec_entry; + obj = list_first_entry(objects, + struct drm_i915_gem_object, + exec_list); + entry = obj->exec_entry; need_fence = has_fenced_gpu_access && entry->flags & EXEC_OBJECT_NEEDS_FENCE && obj->tiling_mode != I915_TILING_NONE; - need_mappable = need_fence || need_reloc_mappable(vma); + need_mappable = need_fence || need_reloc_mappable(obj); if (need_mappable) - list_move(&vma->exec_list, &ordered_vmas); + list_move(&obj->exec_list, &ordered_objects); else - list_move_tail(&vma->exec_list, &ordered_vmas); + list_move_tail(&obj->exec_list, &ordered_objects); obj->base.pending_read_domains = I915_GEM_GPU_DOMAINS & ~I915_GEM_DOMAIN_COMMAND; obj->base.pending_write_domain = 0; obj->pending_fenced_gpu_access = false; } - list_splice(&ordered_vmas, vmas); + list_splice(&ordered_objects, objects); /* Attempt to pin all of the buffers into the GTT. * This is done in 3 phases: @@ -634,53 +558,52 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, int ret = 0; /* Unbind any ill-fitting objects or pin. */ - list_for_each_entry(vma, vmas, exec_list) { - struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; + list_for_each_entry(obj, objects, exec_list) { + struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; bool need_fence, need_mappable; + u32 obj_offset; - obj = vma->obj; - - if (!drm_mm_node_allocated(&vma->node)) + if (!i915_gem_obj_bound(obj, vm)) continue; + obj_offset = i915_gem_obj_offset(obj, vm); need_fence = has_fenced_gpu_access && entry->flags & EXEC_OBJECT_NEEDS_FENCE && obj->tiling_mode != I915_TILING_NONE; - need_mappable = need_fence || need_reloc_mappable(vma); + need_mappable = need_fence || need_reloc_mappable(obj); WARN_ON((need_mappable || need_fence) && - !i915_is_ggtt(vma->vm)); + !i915_is_ggtt(vm)); if ((entry->alignment && - vma->node.start & (entry->alignment - 1)) || + obj_offset & (entry->alignment - 1)) || (need_mappable && !obj->map_and_fenceable)) - ret = i915_vma_unbind(vma); + ret = i915_vma_unbind(i915_gem_obj_to_vma(obj, vm)); else - ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs); + ret = i915_gem_execbuffer_reserve_object(obj, ring, vm, need_relocs); if (ret) goto err; } /* Bind fresh objects */ - list_for_each_entry(vma, vmas, exec_list) { - if (drm_mm_node_allocated(&vma->node)) + list_for_each_entry(obj, objects, exec_list) { + if (i915_gem_obj_bound(obj, vm)) continue; - ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs); + ret = i915_gem_execbuffer_reserve_object(obj, ring, vm, need_relocs); if (ret) goto err; } -err: +err: /* Decrement pin count for bound objects */ + list_for_each_entry(obj, objects, exec_list) + i915_gem_execbuffer_unreserve_object(obj); + if (ret != -ENOSPC || retry++) return ret; - /* Decrement pin count for bound objects */ - list_for_each_entry(vma, vmas, exec_list) - i915_gem_execbuffer_unreserve_vma(vma); - - ret = i915_gem_evict_vm(vm, true); + ret = i915_gem_evict_everything(ring->dev); if (ret) return ret; } while (1); @@ -691,28 +614,24 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, struct drm_i915_gem_execbuffer2 *args, struct drm_file *file, struct intel_ring_buffer *ring, - struct eb_vmas *eb, - struct drm_i915_gem_exec_object2 *exec) + struct eb_objects *eb, + struct drm_i915_gem_exec_object2 *exec, + struct i915_address_space *vm) { struct drm_i915_gem_relocation_entry *reloc; - struct i915_address_space *vm; - struct i915_vma *vma; + struct drm_i915_gem_object *obj; bool need_relocs; int *reloc_offset; int i, total, ret; - unsigned count = args->buffer_count; - - if (WARN_ON(list_empty(&eb->vmas))) - return 0; - - vm = list_first_entry(&eb->vmas, struct i915_vma, exec_list)->vm; + int count = args->buffer_count; /* We may process another execbuffer during the unlock... */ - while (!list_empty(&eb->vmas)) { - vma = list_first_entry(&eb->vmas, struct i915_vma, exec_list); - list_del_init(&vma->exec_list); - i915_gem_execbuffer_unreserve_vma(vma); - drm_gem_object_unreference(&vma->obj->base); + while (!list_empty(&eb->objects)) { + obj = list_first_entry(&eb->objects, + struct drm_i915_gem_object, + exec_list); + list_del_init(&obj->exec_list); + drm_gem_object_unreference(&obj->base); } mutex_unlock(&dev->struct_mutex); @@ -776,19 +695,20 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, /* reacquire the objects */ eb_reset(eb); - ret = eb_lookup_vmas(eb, exec, args, vm, file); + ret = eb_lookup_objects(eb, exec, args, file); if (ret) goto err; need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0; - ret = i915_gem_execbuffer_reserve(ring, &eb->vmas, &need_relocs); + ret = i915_gem_execbuffer_reserve(ring, &eb->objects, vm, &need_relocs); if (ret) goto err; - list_for_each_entry(vma, &eb->vmas, exec_list) { - int offset = vma->exec_entry - exec; - ret = i915_gem_execbuffer_relocate_vma_slow(vma, eb, - reloc + reloc_offset[offset]); + list_for_each_entry(obj, &eb->objects, exec_list) { + int offset = obj->exec_entry - exec; + ret = i915_gem_execbuffer_relocate_object_slow(obj, eb, + reloc + reloc_offset[offset], + vm); if (ret) goto err; } @@ -807,15 +727,14 @@ err: static int i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring, - struct list_head *vmas) + struct list_head *objects) { - struct i915_vma *vma; + struct drm_i915_gem_object *obj; uint32_t flush_domains = 0; bool flush_chipset = false; int ret; - list_for_each_entry(vma, vmas, exec_list) { - struct drm_i915_gem_object *obj = vma->obj; + list_for_each_entry(obj, objects, exec_list) { ret = i915_gem_object_sync(obj, ring); if (ret) return ret; @@ -852,8 +771,8 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec, int count) { int i; - unsigned relocs_total = 0; - unsigned relocs_max = UINT_MAX / sizeof(struct drm_i915_gem_relocation_entry); + int relocs_total = 0; + int relocs_max = INT_MAX / sizeof(struct drm_i915_gem_relocation_entry); for (i = 0; i < count; i++) { char __user *ptr = to_user_ptr(exec[i].relocs_ptr); @@ -890,13 +809,13 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec, } static void -i915_gem_execbuffer_move_to_active(struct list_head *vmas, +i915_gem_execbuffer_move_to_active(struct list_head *objects, + struct i915_address_space *vm, struct intel_ring_buffer *ring) { - struct i915_vma *vma; + struct drm_i915_gem_object *obj; - list_for_each_entry(vma, vmas, exec_list) { - struct drm_i915_gem_object *obj = vma->obj; + list_for_each_entry(obj, objects, exec_list) { u32 old_read = obj->base.read_domains; u32 old_write = obj->base.write_domain; @@ -906,7 +825,9 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas, obj->base.read_domains = obj->base.pending_read_domains; obj->fenced_gpu_access = obj->pending_fenced_gpu_access; - i915_vma_move_to_active(vma, ring); + /* FIXME: This lookup gets fixed later <-- danvet */ + list_move_tail(&i915_gem_obj_to_vma(obj, vm)->mm_list, &vm->active_list); + i915_gem_object_move_to_active(obj, ring); if (obj->base.write_domain) { obj->dirty = 1; obj->last_write_seqno = intel_ring_get_seqno(ring); @@ -964,11 +885,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, struct i915_address_space *vm) { drm_i915_private_t *dev_priv = dev->dev_private; - struct eb_vmas *eb; + struct eb_objects *eb; struct drm_i915_gem_object *batch_obj; struct drm_clip_rect *cliprects = NULL; struct intel_ring_buffer *ring; - struct i915_ctx_hang_stats *hs; u32 ctx_id = i915_execbuffer2_get_context_id(*args); u32 exec_start, exec_len; u32 mask, flags; @@ -1080,8 +1000,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, return -EINVAL; } - cliprects = kcalloc(args->num_cliprects, - sizeof(*cliprects), + cliprects = kmalloc(args->num_cliprects * sizeof(*cliprects), GFP_KERNEL); if (cliprects == NULL) { ret = -ENOMEM; @@ -1106,7 +1025,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, goto pre_mutex_err; } - eb = eb_create(args, vm); + eb = eb_create(args); if (eb == NULL) { mutex_unlock(&dev->struct_mutex); ret = -ENOMEM; @@ -1114,16 +1033,18 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, } /* Look up object handles */ - ret = eb_lookup_vmas(eb, exec, args, vm, file); + ret = eb_lookup_objects(eb, exec, args, file); if (ret) goto err; /* take note of the batch buffer before we might reorder the lists */ - batch_obj = list_entry(eb->vmas.prev, struct i915_vma, exec_list)->obj; + batch_obj = list_entry(eb->objects.prev, + struct drm_i915_gem_object, + exec_list); /* Move the objects en-masse into the GTT, evicting if necessary. */ need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0; - ret = i915_gem_execbuffer_reserve(ring, &eb->vmas, &need_relocs); + ret = i915_gem_execbuffer_reserve(ring, &eb->objects, vm, &need_relocs); if (ret) goto err; @@ -1133,7 +1054,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, if (ret) { if (ret == -EFAULT) { ret = i915_gem_execbuffer_relocate_slow(dev, args, file, ring, - eb, exec); + eb, exec, vm); BUG_ON(!mutex_is_locked(&dev->struct_mutex)); } if (ret) @@ -1150,25 +1071,15 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, /* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure * batch" bit. Hence we need to pin secure batches into the global gtt. - * hsw should have this fixed, but bdw mucks it up again. */ + * hsw should have this fixed, but let's be paranoid and do it + * unconditionally for now. */ if (flags & I915_DISPATCH_SECURE && !batch_obj->has_global_gtt_mapping) i915_gem_gtt_bind_object(batch_obj, batch_obj->cache_level); - ret = i915_gem_execbuffer_move_to_gpu(ring, &eb->vmas); + ret = i915_gem_execbuffer_move_to_gpu(ring, &eb->objects); if (ret) goto err; - hs = i915_gem_context_get_hang_stats(dev, file, ctx_id); - if (IS_ERR(hs)) { - ret = PTR_ERR(hs); - goto err; - } - - if (hs->banned) { - ret = -EIO; - goto err; - } - ret = i915_switch_context(ring, file, ctx_id); if (ret) goto err; @@ -1220,7 +1131,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags); - i915_gem_execbuffer_move_to_active(&eb->vmas, ring); + i915_gem_execbuffer_move_to_active(&eb->objects, vm, ring); i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj); err: diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 38cb8d4..1f7b4ca 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -30,8 +30,6 @@ #define GEN6_PPGTT_PD_ENTRIES 512 #define I915_PPGTT_PT_ENTRIES (PAGE_SIZE / sizeof(gen6_gtt_pte_t)) -typedef uint64_t gen8_gtt_pte_t; -typedef gen8_gtt_pte_t gen8_ppgtt_pde_t; /* PPGTT stuff */ #define GEN6_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0xff0)) @@ -57,44 +55,7 @@ typedef gen8_gtt_pte_t gen8_ppgtt_pde_t; #define HSW_WB_LLC_AGE3 HSW_CACHEABILITY_CONTROL(0x2) #define HSW_WB_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x3) #define HSW_WB_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0xb) -#define HSW_WB_ELLC_LLC_AGE3 HSW_CACHEABILITY_CONTROL(0x8) #define HSW_WT_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x6) -#define HSW_WT_ELLC_LLC_AGE3 HSW_CACHEABILITY_CONTROL(0x7) - -#define GEN8_PTES_PER_PAGE (PAGE_SIZE / sizeof(gen8_gtt_pte_t)) -#define GEN8_PDES_PER_PAGE (PAGE_SIZE / sizeof(gen8_ppgtt_pde_t)) -#define GEN8_LEGACY_PDPS 4 - -#define PPAT_UNCACHED_INDEX (_PAGE_PWT | _PAGE_PCD) -#define PPAT_CACHED_PDE_INDEX 0 /* WB LLC */ -#define PPAT_CACHED_INDEX _PAGE_PAT /* WB LLCeLLC */ -#define PPAT_DISPLAY_ELLC_INDEX _PAGE_PCD /* WT eLLC */ - -static inline gen8_gtt_pte_t gen8_pte_encode(dma_addr_t addr, - enum i915_cache_level level, - bool valid) -{ - gen8_gtt_pte_t pte = valid ? _PAGE_PRESENT | _PAGE_RW : 0; - pte |= addr; - if (level != I915_CACHE_NONE) - pte |= PPAT_CACHED_INDEX; - else - pte |= PPAT_UNCACHED_INDEX; - return pte; -} - -static inline gen8_ppgtt_pde_t gen8_pde_encode(struct drm_device *dev, - dma_addr_t addr, - enum i915_cache_level level) -{ - gen8_ppgtt_pde_t pde = _PAGE_PRESENT | _PAGE_RW; - pde |= addr; - if (level != I915_CACHE_NONE) - pde |= PPAT_CACHED_PDE_INDEX; - else - pde |= PPAT_UNCACHED_INDEX; - return pde; -} static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr, enum i915_cache_level level, @@ -187,267 +148,16 @@ static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr, case I915_CACHE_NONE: break; case I915_CACHE_WT: - pte |= HSW_WT_ELLC_LLC_AGE3; + pte |= HSW_WT_ELLC_LLC_AGE0; break; default: - pte |= HSW_WB_ELLC_LLC_AGE3; + pte |= HSW_WB_ELLC_LLC_AGE0; break; } return pte; } -/* Broadwell Page Directory Pointer Descriptors */ -static int gen8_write_pdp(struct intel_ring_buffer *ring, unsigned entry, - uint64_t val) -{ - int ret; - - BUG_ON(entry >= 4); - - ret = intel_ring_begin(ring, 6); - if (ret) - return ret; - - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit(ring, GEN8_RING_PDP_UDW(ring, entry)); - intel_ring_emit(ring, (u32)(val >> 32)); - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit(ring, GEN8_RING_PDP_LDW(ring, entry)); - intel_ring_emit(ring, (u32)(val)); - intel_ring_advance(ring); - - return 0; -} - -static int gen8_ppgtt_enable(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_ring_buffer *ring; - struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; - int i, j, ret; - - /* bit of a hack to find the actual last used pd */ - int used_pd = ppgtt->num_pd_entries / GEN8_PDES_PER_PAGE; - - for_each_ring(ring, dev_priv, j) { - I915_WRITE(RING_MODE_GEN7(ring), - _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); - } - - for (i = used_pd - 1; i >= 0; i--) { - dma_addr_t addr = ppgtt->pd_dma_addr[i]; - for_each_ring(ring, dev_priv, j) { - ret = gen8_write_pdp(ring, i, addr); - if (ret) - return ret; - } - } - return 0; -} - -static void gen8_ppgtt_clear_range(struct i915_address_space *vm, - unsigned first_entry, - unsigned num_entries, - bool use_scratch) -{ - struct i915_hw_ppgtt *ppgtt = - container_of(vm, struct i915_hw_ppgtt, base); - gen8_gtt_pte_t *pt_vaddr, scratch_pte; - unsigned act_pt = first_entry / GEN8_PTES_PER_PAGE; - unsigned first_pte = first_entry % GEN8_PTES_PER_PAGE; - unsigned last_pte, i; - - scratch_pte = gen8_pte_encode(ppgtt->base.scratch.addr, - I915_CACHE_LLC, use_scratch); - - while (num_entries) { - struct page *page_table = &ppgtt->gen8_pt_pages[act_pt]; - - last_pte = first_pte + num_entries; - if (last_pte > GEN8_PTES_PER_PAGE) - last_pte = GEN8_PTES_PER_PAGE; - - pt_vaddr = kmap_atomic(page_table); - - for (i = first_pte; i < last_pte; i++) - pt_vaddr[i] = scratch_pte; - - kunmap_atomic(pt_vaddr); - - num_entries -= last_pte - first_pte; - first_pte = 0; - act_pt++; - } -} - -static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, - struct sg_table *pages, - unsigned first_entry, - enum i915_cache_level cache_level) -{ - struct i915_hw_ppgtt *ppgtt = - container_of(vm, struct i915_hw_ppgtt, base); - gen8_gtt_pte_t *pt_vaddr; - unsigned act_pt = first_entry / GEN8_PTES_PER_PAGE; - unsigned act_pte = first_entry % GEN8_PTES_PER_PAGE; - struct sg_page_iter sg_iter; - - pt_vaddr = kmap_atomic(&ppgtt->gen8_pt_pages[act_pt]); - for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) { - dma_addr_t page_addr; - - page_addr = sg_dma_address(sg_iter.sg) + - (sg_iter.sg_pgoffset << PAGE_SHIFT); - pt_vaddr[act_pte] = gen8_pte_encode(page_addr, cache_level, - true); - if (++act_pte == GEN8_PTES_PER_PAGE) { - kunmap_atomic(pt_vaddr); - act_pt++; - pt_vaddr = kmap_atomic(&ppgtt->gen8_pt_pages[act_pt]); - act_pte = 0; - - } - } - kunmap_atomic(pt_vaddr); -} - -static void gen8_ppgtt_cleanup(struct i915_address_space *vm) -{ - struct i915_hw_ppgtt *ppgtt = - container_of(vm, struct i915_hw_ppgtt, base); - int i, j; - - for (i = 0; i < ppgtt->num_pd_pages ; i++) { - if (ppgtt->pd_dma_addr[i]) { - pci_unmap_page(ppgtt->base.dev->pdev, - ppgtt->pd_dma_addr[i], - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - - for (j = 0; j < GEN8_PDES_PER_PAGE; j++) { - dma_addr_t addr = ppgtt->gen8_pt_dma_addr[i][j]; - if (addr) - pci_unmap_page(ppgtt->base.dev->pdev, - addr, - PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - - } - } - kfree(ppgtt->gen8_pt_dma_addr[i]); - } - - __free_pages(ppgtt->gen8_pt_pages, ppgtt->num_pt_pages << PAGE_SHIFT); - __free_pages(ppgtt->pd_pages, ppgtt->num_pd_pages << PAGE_SHIFT); -} - -/** - * GEN8 legacy ppgtt programming is accomplished through 4 PDP registers with a - * net effect resembling a 2-level page table in normal x86 terms. Each PDP - * represents 1GB of memory - * 4 * 512 * 512 * 4096 = 4GB legacy 32b address space. - * - * TODO: Do something with the size parameter - **/ -static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size) -{ - struct page *pt_pages; - int i, j, ret = -ENOMEM; - const int max_pdp = DIV_ROUND_UP(size, 1 << 30); - const int num_pt_pages = GEN8_PDES_PER_PAGE * max_pdp; - - if (size % (1<<30)) - DRM_INFO("Pages will be wasted unless GTT size (%llu) is divisible by 1GB\n", size); - - /* FIXME: split allocation into smaller pieces. For now we only ever do - * this once, but with full PPGTT, the multiple contiguous allocations - * will be bad. - */ - ppgtt->pd_pages = alloc_pages(GFP_KERNEL, get_order(max_pdp << PAGE_SHIFT)); - if (!ppgtt->pd_pages) - return -ENOMEM; - - pt_pages = alloc_pages(GFP_KERNEL, get_order(num_pt_pages << PAGE_SHIFT)); - if (!pt_pages) { - __free_pages(ppgtt->pd_pages, get_order(max_pdp << PAGE_SHIFT)); - return -ENOMEM; - } - - ppgtt->gen8_pt_pages = pt_pages; - ppgtt->num_pd_pages = 1 << get_order(max_pdp << PAGE_SHIFT); - ppgtt->num_pt_pages = 1 << get_order(num_pt_pages << PAGE_SHIFT); - ppgtt->num_pd_entries = max_pdp * GEN8_PDES_PER_PAGE; - ppgtt->enable = gen8_ppgtt_enable; - ppgtt->base.clear_range = gen8_ppgtt_clear_range; - ppgtt->base.insert_entries = gen8_ppgtt_insert_entries; - ppgtt->base.cleanup = gen8_ppgtt_cleanup; - - BUG_ON(ppgtt->num_pd_pages > GEN8_LEGACY_PDPS); - - /* - * - Create a mapping for the page directories. - * - For each page directory: - * allocate space for page table mappings. - * map each page table - */ - for (i = 0; i < max_pdp; i++) { - dma_addr_t temp; - temp = pci_map_page(ppgtt->base.dev->pdev, - &ppgtt->pd_pages[i], 0, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(ppgtt->base.dev->pdev, temp)) - goto err_out; - - ppgtt->pd_dma_addr[i] = temp; - - ppgtt->gen8_pt_dma_addr[i] = kmalloc(sizeof(dma_addr_t) * GEN8_PDES_PER_PAGE, GFP_KERNEL); - if (!ppgtt->gen8_pt_dma_addr[i]) - goto err_out; - - for (j = 0; j < GEN8_PDES_PER_PAGE; j++) { - struct page *p = &pt_pages[i * GEN8_PDES_PER_PAGE + j]; - temp = pci_map_page(ppgtt->base.dev->pdev, - p, 0, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(ppgtt->base.dev->pdev, temp)) - goto err_out; - - ppgtt->gen8_pt_dma_addr[i][j] = temp; - } - } - - /* For now, the PPGTT helper functions all require that the PDEs are - * plugged in correctly. So we do that now/here. For aliasing PPGTT, we - * will never need to touch the PDEs again */ - for (i = 0; i < max_pdp; i++) { - gen8_ppgtt_pde_t *pd_vaddr; - pd_vaddr = kmap_atomic(&ppgtt->pd_pages[i]); - for (j = 0; j < GEN8_PDES_PER_PAGE; j++) { - dma_addr_t addr = ppgtt->gen8_pt_dma_addr[i][j]; - pd_vaddr[j] = gen8_pde_encode(ppgtt->base.dev, addr, - I915_CACHE_LLC); - } - kunmap_atomic(pd_vaddr); - } - - ppgtt->base.clear_range(&ppgtt->base, 0, - ppgtt->num_pd_entries * GEN8_PTES_PER_PAGE, - true); - - DRM_DEBUG_DRIVER("Allocated %d pages for page directories (%d wasted)\n", - ppgtt->num_pd_pages, ppgtt->num_pd_pages - max_pdp); - DRM_DEBUG_DRIVER("Allocated %d pages for page tables (%lld wasted)\n", - ppgtt->num_pt_pages, - (ppgtt->num_pt_pages - num_pt_pages) + - size % (1<<30)); - return 0; - -err_out: - ppgtt->base.cleanup(&ppgtt->base); - return ret; -} - static void gen6_write_pdes(struct i915_hw_ppgtt *ppgtt) { struct drm_i915_private *dev_priv = ppgtt->base.dev->dev_private; @@ -632,7 +342,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ppgtt->base.insert_entries = gen6_ppgtt_insert_entries; ppgtt->base.cleanup = gen6_ppgtt_cleanup; ppgtt->base.scratch = dev_priv->gtt.base.scratch; - ppgtt->pt_pages = kcalloc(ppgtt->num_pd_entries, sizeof(struct page *), + ppgtt->pt_pages = kzalloc(sizeof(struct page *)*ppgtt->num_pd_entries, GFP_KERNEL); if (!ppgtt->pt_pages) return -ENOMEM; @@ -643,7 +353,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) goto err_pt_alloc; } - ppgtt->pt_dma_addr = kcalloc(ppgtt->num_pd_entries, sizeof(dma_addr_t), + ppgtt->pt_dma_addr = kzalloc(sizeof(dma_addr_t) *ppgtt->num_pd_entries, GFP_KERNEL); if (!ppgtt->pt_dma_addr) goto err_pt_alloc; @@ -700,8 +410,6 @@ static int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) if (INTEL_INFO(dev)->gen < 8) ret = gen6_ppgtt_init(ppgtt); - else if (IS_GEN8(dev)) - ret = gen8_ppgtt_init(ppgtt, dev_priv->gtt.base.total); else BUG(); @@ -865,57 +573,6 @@ int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) return 0; } -static inline void gen8_set_pte(void __iomem *addr, gen8_gtt_pte_t pte) -{ -#ifdef writeq - writeq(pte, addr); -#else - iowrite32((u32)pte, addr); - iowrite32(pte >> 32, addr + 4); -#endif -} - -static void gen8_ggtt_insert_entries(struct i915_address_space *vm, - struct sg_table *st, - unsigned int first_entry, - enum i915_cache_level level) -{ - struct drm_i915_private *dev_priv = vm->dev->dev_private; - gen8_gtt_pte_t __iomem *gtt_entries = - (gen8_gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry; - int i = 0; - struct sg_page_iter sg_iter; - dma_addr_t addr; - - for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) { - addr = sg_dma_address(sg_iter.sg) + - (sg_iter.sg_pgoffset << PAGE_SHIFT); - gen8_set_pte(>t_entries[i], - gen8_pte_encode(addr, level, true)); - i++; - } - - /* - * XXX: This serves as a posting read to make sure that the PTE has - * actually been updated. There is some concern that even though - * registers and PTEs are within the same BAR that they are potentially - * of NUMA access patterns. Therefore, even with the way we assume - * hardware should work, we must keep this posting read for paranoia. - */ - if (i != 0) - WARN_ON(readq(>t_entries[i-1]) - != gen8_pte_encode(addr, level, true)); - -#if 0 /* TODO: Still needed on GEN8? */ - /* This next bit makes the above posting read even more important. We - * want to flush the TLBs only after we're certain all the PTE updates - * have finished. - */ - I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); - POSTING_READ(GFX_FLSH_CNTL_GEN6); -#endif -} - /* * Binds an object into the global gtt with the specified cache level. The object * will be accessible to the GPU via commands whose operands reference offsets @@ -958,30 +615,6 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, POSTING_READ(GFX_FLSH_CNTL_GEN6); } -static void gen8_ggtt_clear_range(struct i915_address_space *vm, - unsigned int first_entry, - unsigned int num_entries, - bool use_scratch) -{ - struct drm_i915_private *dev_priv = vm->dev->dev_private; - gen8_gtt_pte_t scratch_pte, __iomem *gtt_base = - (gen8_gtt_pte_t __iomem *) dev_priv->gtt.gsm + first_entry; - const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry; - int i; - - if (WARN(num_entries > max_entries, - "First entry = %d; Num entries = %d (max=%d)\n", - first_entry, num_entries, max_entries)) - num_entries = max_entries; - - scratch_pte = gen8_pte_encode(vm->scratch.addr, - I915_CACHE_LLC, - use_scratch); - for (i = 0; i < num_entries; i++) - gen8_set_pte(>t_base[i], scratch_pte); - readl(gtt_base); -} - static void gen6_ggtt_clear_range(struct i915_address_space *vm, unsigned int first_entry, unsigned int num_entries, @@ -1005,6 +638,7 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, readl(gtt_base); } + static void i915_ggtt_insert_entries(struct i915_address_space *vm, struct sg_table *st, unsigned int pg_start, @@ -1086,7 +720,6 @@ static void i915_gtt_color_adjust(struct drm_mm_node *node, *end -= 4096; } } - void i915_gem_setup_global_gtt(struct drm_device *dev, unsigned long start, unsigned long mappable_end, @@ -1184,8 +817,7 @@ void i915_gem_init_global_gtt(struct drm_device *dev) DRM_ERROR("Aliased PPGTT setup failed %d\n", ret); drm_mm_takedown(&dev_priv->gtt.base.mm); - if (INTEL_INFO(dev)->gen < 8) - gtt_size += GEN6_PPGTT_PD_ENTRIES*PAGE_SIZE; + gtt_size += GEN6_PPGTT_PD_ENTRIES * PAGE_SIZE; } i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size); } @@ -1235,15 +867,6 @@ static inline unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl) return snb_gmch_ctl << 20; } -static inline unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl) -{ - bdw_gmch_ctl >>= BDW_GMCH_GGMS_SHIFT; - bdw_gmch_ctl &= BDW_GMCH_GGMS_MASK; - if (bdw_gmch_ctl) - bdw_gmch_ctl = 1 << bdw_gmch_ctl; - return bdw_gmch_ctl << 20; -} - static inline size_t gen6_get_stolen_size(u16 snb_gmch_ctl) { snb_gmch_ctl >>= SNB_GMCH_GMS_SHIFT; @@ -1251,108 +874,6 @@ static inline size_t gen6_get_stolen_size(u16 snb_gmch_ctl) return snb_gmch_ctl << 25; /* 32 MB units */ } -static inline size_t gen8_get_stolen_size(u16 bdw_gmch_ctl) -{ - bdw_gmch_ctl >>= BDW_GMCH_GMS_SHIFT; - bdw_gmch_ctl &= BDW_GMCH_GMS_MASK; - return bdw_gmch_ctl << 25; /* 32 MB units */ -} - -static int ggtt_probe_common(struct drm_device *dev, - size_t gtt_size) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - phys_addr_t gtt_bus_addr; - int ret; - - /* For Modern GENs the PTEs and register space are split in the BAR */ - gtt_bus_addr = pci_resource_start(dev->pdev, 0) + - (pci_resource_len(dev->pdev, 0) / 2); - - dev_priv->gtt.gsm = ioremap_wc(gtt_bus_addr, gtt_size); - if (!dev_priv->gtt.gsm) { - DRM_ERROR("Failed to map the gtt page table\n"); - return -ENOMEM; - } - - ret = setup_scratch_page(dev); - if (ret) { - DRM_ERROR("Scratch setup failed\n"); - /* iounmap will also get called at remove, but meh */ - iounmap(dev_priv->gtt.gsm); - } - - return ret; -} - -/* The GGTT and PPGTT need a private PPAT setup in order to handle cacheability - * bits. When using advanced contexts each context stores its own PAT, but - * writing this data shouldn't be harmful even in those cases. */ -static void gen8_setup_private_ppat(struct drm_i915_private *dev_priv) -{ -#define GEN8_PPAT_UC (0<<0) -#define GEN8_PPAT_WC (1<<0) -#define GEN8_PPAT_WT (2<<0) -#define GEN8_PPAT_WB (3<<0) -#define GEN8_PPAT_ELLC_OVERRIDE (0<<2) -/* FIXME(BDW): Bspec is completely confused about cache control bits. */ -#define GEN8_PPAT_LLC (1<<2) -#define GEN8_PPAT_LLCELLC (2<<2) -#define GEN8_PPAT_LLCeLLC (3<<2) -#define GEN8_PPAT_AGE(x) (x<<4) -#define GEN8_PPAT(i, x) ((uint64_t) (x) << ((i) * 8)) - uint64_t pat; - - pat = GEN8_PPAT(0, GEN8_PPAT_WB | GEN8_PPAT_LLC) | /* for normal objects, no eLLC */ - GEN8_PPAT(1, GEN8_PPAT_WC | GEN8_PPAT_LLCELLC) | /* for something pointing to ptes? */ - GEN8_PPAT(2, GEN8_PPAT_WT | GEN8_PPAT_LLCELLC) | /* for scanout with eLLC */ - GEN8_PPAT(3, GEN8_PPAT_UC) | /* Uncached objects, mostly for scanout */ - GEN8_PPAT(4, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0)) | - GEN8_PPAT(5, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1)) | - GEN8_PPAT(6, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)) | - GEN8_PPAT(7, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3)); - - /* XXX: spec defines this as 2 distinct registers. It's unclear if a 64b - * write would work. */ - I915_WRITE(GEN8_PRIVATE_PAT, pat); - I915_WRITE(GEN8_PRIVATE_PAT + 4, pat >> 32); -} - -static int gen8_gmch_probe(struct drm_device *dev, - size_t *gtt_total, - size_t *stolen, - phys_addr_t *mappable_base, - unsigned long *mappable_end) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - unsigned int gtt_size; - u16 snb_gmch_ctl; - int ret; - - /* TODO: We're not aware of mappable constraints on gen8 yet */ - *mappable_base = pci_resource_start(dev->pdev, 2); - *mappable_end = pci_resource_len(dev->pdev, 2); - - if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(39))) - pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(39)); - - pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); - - *stolen = gen8_get_stolen_size(snb_gmch_ctl); - - gtt_size = gen8_get_total_gtt_size(snb_gmch_ctl); - *gtt_total = (gtt_size / sizeof(gen8_gtt_pte_t)) << PAGE_SHIFT; - - gen8_setup_private_ppat(dev_priv); - - ret = ggtt_probe_common(dev, gtt_size); - - dev_priv->gtt.base.clear_range = gen8_ggtt_clear_range; - dev_priv->gtt.base.insert_entries = gen8_ggtt_insert_entries; - - return ret; -} - static int gen6_gmch_probe(struct drm_device *dev, size_t *gtt_total, size_t *stolen, @@ -1360,6 +881,7 @@ static int gen6_gmch_probe(struct drm_device *dev, unsigned long *mappable_end) { struct drm_i915_private *dev_priv = dev->dev_private; + phys_addr_t gtt_bus_addr; unsigned int gtt_size; u16 snb_gmch_ctl; int ret; @@ -1379,13 +901,24 @@ static int gen6_gmch_probe(struct drm_device *dev, if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(40))) pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(40)); pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); + gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl); *stolen = gen6_get_stolen_size(snb_gmch_ctl); - - gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl); *gtt_total = (gtt_size / sizeof(gen6_gtt_pte_t)) << PAGE_SHIFT; - ret = ggtt_probe_common(dev, gtt_size); + /* For Modern GENs the PTEs and register space are split in the BAR */ + gtt_bus_addr = pci_resource_start(dev->pdev, 0) + + (pci_resource_len(dev->pdev, 0) / 2); + + dev_priv->gtt.gsm = ioremap_wc(gtt_bus_addr, gtt_size); + if (!dev_priv->gtt.gsm) { + DRM_ERROR("Failed to map the gtt page table\n"); + return -ENOMEM; + } + + ret = setup_scratch_page(dev); + if (ret) + DRM_ERROR("Scratch setup failed\n"); dev_priv->gtt.base.clear_range = gen6_ggtt_clear_range; dev_priv->gtt.base.insert_entries = gen6_ggtt_insert_entries; @@ -1439,7 +972,7 @@ int i915_gem_gtt_init(struct drm_device *dev) if (INTEL_INFO(dev)->gen <= 5) { gtt->gtt_probe = i915_gmch_probe; gtt->base.cleanup = i915_gmch_remove; - } else if (INTEL_INFO(dev)->gen < 8) { + } else { gtt->gtt_probe = gen6_gmch_probe; gtt->base.cleanup = gen6_gmch_remove; if (IS_HASWELL(dev) && dev_priv->ellc_size) @@ -1452,9 +985,6 @@ int i915_gem_gtt_init(struct drm_device *dev) gtt->base.pte_encode = ivb_pte_encode; else gtt->base.pte_encode = snb_pte_encode; - } else { - dev_priv->gtt.gtt_probe = gen8_gmch_probe; - dev_priv->gtt.base.cleanup = gen6_gmch_remove; } ret = gtt->gtt_probe(dev, >t->base.total, >t->stolen_size, diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index d284d89..e15a1d9 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -395,7 +395,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, if (gtt_offset == I915_GTT_OFFSET_NONE) return obj; - vma = i915_gem_obj_lookup_or_create_vma(obj, ggtt); + vma = i915_gem_vma_create(obj, ggtt); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto err_out; diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index b139053..032e9ef 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -308,7 +308,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, return -EINVAL; } - if (obj->pin_count || obj->framebuffer_references) { + if (obj->pin_count) { drm_gem_object_unreference_unlocked(&obj->base); return -EBUSY; } @@ -393,7 +393,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, /* Try to preallocate memory required to save swizzling on put-pages */ if (i915_gem_object_needs_bit17_swizzle(obj)) { if (obj->bit_17 == NULL) { - obj->bit_17 = kcalloc(BITS_TO_LONGS(obj->base.size >> PAGE_SHIFT), + obj->bit_17 = kmalloc(BITS_TO_LONGS(obj->base.size >> PAGE_SHIFT) * sizeof(long), GFP_KERNEL); } } else { @@ -504,8 +504,8 @@ i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj) int i; if (obj->bit_17 == NULL) { - obj->bit_17 = kcalloc(BITS_TO_LONGS(page_count), - sizeof(long), GFP_KERNEL); + obj->bit_17 = kmalloc(BITS_TO_LONGS(page_count) * + sizeof(long), GFP_KERNEL); if (obj->bit_17 == NULL) { DRM_ERROR("Failed to allocate memory for bit 17 " "record\n"); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 79dcb8f..dae364f 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -215,24 +215,6 @@ static void print_error_buffers(struct drm_i915_error_state_buf *m, } } -static const char *hangcheck_action_to_str(enum intel_ring_hangcheck_action a) -{ - switch (a) { - case HANGCHECK_IDLE: - return "idle"; - case HANGCHECK_WAIT: - return "wait"; - case HANGCHECK_ACTIVE: - return "active"; - case HANGCHECK_KICK: - return "kick"; - case HANGCHECK_HUNG: - return "hung"; - } - - return "unknown"; -} - static void i915_ring_error_state(struct drm_i915_error_state_buf *m, struct drm_device *dev, struct drm_i915_error_state *error, @@ -249,8 +231,7 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m, err_printf(m, " INSTDONE: 0x%08x\n", error->instdone[ring]); if (ring == RCS && INTEL_INFO(dev)->gen >= 4) err_printf(m, " BBADDR: 0x%08llx\n", error->bbaddr); - if (INTEL_INFO(dev)->gen >= 4) - err_printf(m, " BB_STATE: 0x%08x\n", error->bbstate[ring]); + if (INTEL_INFO(dev)->gen >= 4) err_printf(m, " INSTPS: 0x%08x\n", error->instps[ring]); err_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]); @@ -274,9 +255,6 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m, err_printf(m, " waiting: %s\n", yesno(error->waiting[ring])); err_printf(m, " ring->head: 0x%08x\n", error->cpu_ring_head[ring]); err_printf(m, " ring->tail: 0x%08x\n", error->cpu_ring_tail[ring]); - err_printf(m, " hangcheck: %s [%d]\n", - hangcheck_action_to_str(error->hangcheck_action[ring]), - error->hangcheck_score[ring]); } void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) @@ -305,14 +283,13 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, err_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec, error->time.tv_usec); err_printf(m, "Kernel: " UTS_RELEASE "\n"); - err_printf(m, "PCI ID: 0x%04x\n", dev->pdev->device); + err_printf(m, "PCI ID: 0x%04x\n", dev->pci_device); err_printf(m, "EIR: 0x%08x\n", error->eir); err_printf(m, "IER: 0x%08x\n", error->ier); err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake); err_printf(m, "DERRMR: 0x%08x\n", error->derrmr); err_printf(m, "CCID: 0x%08x\n", error->ccid); - err_printf(m, "Missed interrupts: 0x%08lx\n", dev_priv->gpu_error.missed_irq_rings); for (i = 0; i < dev_priv->num_fence_regs; i++) err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); @@ -624,7 +601,6 @@ static void i915_gem_record_fences(struct drm_device *dev, /* Fences */ switch (INTEL_INFO(dev)->gen) { - case 8: case 7: case 6: for (i = 0; i < dev_priv->num_fence_regs; i++) @@ -727,7 +703,6 @@ static void i915_record_ring_state(struct drm_device *dev, error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base)); if (ring->id == RCS) error->bbaddr = I915_READ64(BB_ADDR); - error->bbstate[ring->id] = I915_READ(RING_BBSTATE(ring->mmio_base)); } else { error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX); error->ipeir[ring->id] = I915_READ(IPEIR); @@ -745,9 +720,6 @@ static void i915_record_ring_state(struct drm_device *dev, error->cpu_ring_head[ring->id] = ring->head; error->cpu_ring_tail[ring->id] = ring->tail; - - error->hangcheck_score[ring->id] = ring->hangcheck.score; - error->hangcheck_action[ring->id] = ring->hangcheck.action; } @@ -797,7 +769,7 @@ static void i915_gem_record_rings(struct drm_device *dev, error->ring[i].num_requests = count; error->ring[i].requests = - kcalloc(count, sizeof(*error->ring[i].requests), + kmalloc(count*sizeof(struct drm_i915_error_request), GFP_ATOMIC); if (error->ring[i].requests == NULL) { error->ring[i].num_requests = 0; @@ -839,7 +811,7 @@ static void i915_gem_capture_vm(struct drm_i915_private *dev_priv, error->pinned_bo_count[ndx] = i - error->active_bo_count[ndx]; if (i) { - active_bo = kcalloc(i, sizeof(*active_bo), GFP_ATOMIC); + active_bo = kmalloc(sizeof(*active_bo)*i, GFP_ATOMIC); if (active_bo) pinned_bo = active_bo + error->active_bo_count[ndx]; } @@ -913,12 +885,8 @@ void i915_capture_error_state(struct drm_device *dev) return; } - DRM_INFO("GPU crash dump saved to /sys/class/drm/card%d/error\n", - dev->primary->index); - DRM_INFO("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n"); - DRM_INFO("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n"); - DRM_INFO("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n"); - DRM_INFO("The gpu crash dump is required to analyze gpu hangs, so please always attach it.\n"); + DRM_INFO("capturing error event; look for more information in " + "/sys/class/drm/card%d/error\n", dev->primary->index); kref_init(&error->ref); error->eir = I915_READ(EIR); @@ -1020,7 +988,6 @@ const char *i915_cache_level_str(int type) case I915_CACHE_NONE: return " uncached"; case I915_CACHE_LLC: return " snooped or LLC"; case I915_CACHE_L3_LLC: return " L3+LLC"; - case I915_CACHE_WT: return " WT"; default: return ""; } } @@ -1045,7 +1012,6 @@ void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone) default: WARN_ONCE(1, "Unsupported platform\n"); case 7: - case 8: instdone[0] = I915_READ(GEN7_INSTDONE_1); instdone[1] = I915_READ(GEN7_SC_INSTDONE); instdone[2] = I915_READ(GEN7_SAMPLER_INSTDONE); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5d1dedc..4b91228 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -30,7 +30,6 @@ #include <linux/sysrq.h> #include <linux/slab.h> -#include <linux/circ_buf.h> #include <drm/drmP.h> #include <drm/i915_drm.h> #include "i915_drv.h" @@ -270,21 +269,6 @@ static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev, } } -static void broadwell_set_fifo_underrun_reporting(struct drm_device *dev, - enum pipe pipe, bool enable) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - assert_spin_locked(&dev_priv->irq_lock); - - if (enable) - dev_priv->de_irq_mask[pipe] &= ~GEN8_PIPE_FIFO_UNDERRUN; - else - dev_priv->de_irq_mask[pipe] |= GEN8_PIPE_FIFO_UNDERRUN; - I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]); - POSTING_READ(GEN8_DE_PIPE_IMR(pipe)); -} - /** * ibx_display_interrupt_update - update SDEIMR * @dev_priv: driver private @@ -397,8 +381,6 @@ bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, ironlake_set_fifo_underrun_reporting(dev, pipe, enable); else if (IS_GEN7(dev)) ivybridge_set_fifo_underrun_reporting(dev, pipe, enable); - else if (IS_GEN8(dev)) - broadwell_set_fifo_underrun_reporting(dev, pipe, enable); done: spin_unlock_irqrestore(&dev_priv->irq_lock, flags); @@ -459,7 +441,7 @@ done: void -i915_enable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask) +i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) { u32 reg = PIPESTAT(pipe); u32 pipestat = I915_READ(reg) & 0x7fff0000; @@ -476,7 +458,7 @@ i915_enable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask) } void -i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask) +i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) { u32 reg = PIPESTAT(pipe); u32 pipestat = I915_READ(reg) & 0x7fff0000; @@ -504,10 +486,9 @@ static void i915_enable_asle_pipestat(struct drm_device *dev) spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_ENABLE); + i915_enable_pipestat(dev_priv, 1, PIPE_LEGACY_BLC_EVENT_ENABLE); if (INTEL_INFO(dev)->gen >= 4) - i915_enable_pipestat(dev_priv, PIPE_A, - PIPE_LEGACY_BLC_EVENT_ENABLE); + i915_enable_pipestat(dev_priv, 0, PIPE_LEGACY_BLC_EVENT_ENABLE); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } @@ -537,12 +518,6 @@ i915_pipe_enabled(struct drm_device *dev, int pipe) } } -static u32 i8xx_get_vblank_counter(struct drm_device *dev, int pipe) -{ - /* Gen2 doesn't have a hardware frame counter */ - return 0; -} - /* Called from drm generic code, passed a 'crtc', which * we use as a pipe index */ @@ -551,7 +526,7 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long high_frame; unsigned long low_frame; - u32 high1, high2, low, pixel, vbl_start; + u32 high1, high2, low; if (!i915_pipe_enabled(dev, pipe)) { DRM_DEBUG_DRIVER("trying to get vblank count for disabled " @@ -559,24 +534,6 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) return 0; } - if (drm_core_check_feature(dev, DRIVER_MODESET)) { - struct intel_crtc *intel_crtc = - to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); - const struct drm_display_mode *mode = - &intel_crtc->config.adjusted_mode; - - vbl_start = mode->crtc_vblank_start * mode->crtc_htotal; - } else { - enum transcoder cpu_transcoder = - intel_pipe_to_cpu_transcoder(dev_priv, pipe); - u32 htotal; - - htotal = ((I915_READ(HTOTAL(cpu_transcoder)) >> 16) & 0x1fff) + 1; - vbl_start = (I915_READ(VBLANK(cpu_transcoder)) & 0x1fff) + 1; - - vbl_start *= htotal; - } - high_frame = PIPEFRAME(pipe); low_frame = PIPEFRAMEPIXEL(pipe); @@ -587,20 +544,13 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) */ do { high1 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK; - low = I915_READ(low_frame); + low = I915_READ(low_frame) & PIPE_FRAME_LOW_MASK; high2 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK; } while (high1 != high2); high1 >>= PIPE_FRAME_HIGH_SHIFT; - pixel = low & PIPE_PIXEL_MASK; low >>= PIPE_FRAME_LOW_SHIFT; - - /* - * The frame counter increments at beginning of active. - * Cook up a vblank counter by also checking the pixel - * counter against vblank start. - */ - return ((high1 << 8) | low) + (pixel >= vbl_start); + return (high1 << 8) | low; } static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) @@ -617,163 +567,66 @@ static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) return I915_READ(reg); } -/* raw reads, only for fast reads of display block, no need for forcewake etc. */ -#define __raw_i915_read32(dev_priv__, reg__) readl((dev_priv__)->regs + (reg__)) -#define __raw_i915_read16(dev_priv__, reg__) readw((dev_priv__)->regs + (reg__)) - -static bool intel_pipe_in_vblank_locked(struct drm_device *dev, enum pipe pipe) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t status; - int reg; - - if (IS_VALLEYVIEW(dev)) { - status = pipe == PIPE_A ? - I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT : - I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; - - reg = VLV_ISR; - } else if (IS_GEN2(dev)) { - status = pipe == PIPE_A ? - I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT : - I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; - - reg = ISR; - } else if (INTEL_INFO(dev)->gen < 5) { - status = pipe == PIPE_A ? - I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT : - I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; - - reg = ISR; - } else if (INTEL_INFO(dev)->gen < 7) { - status = pipe == PIPE_A ? - DE_PIPEA_VBLANK : - DE_PIPEB_VBLANK; - - reg = DEISR; - } else { - switch (pipe) { - default: - case PIPE_A: - status = DE_PIPEA_VBLANK_IVB; - break; - case PIPE_B: - status = DE_PIPEB_VBLANK_IVB; - break; - case PIPE_C: - status = DE_PIPEC_VBLANK_IVB; - break; - } - - reg = DEISR; - } - - if (IS_GEN2(dev)) - return __raw_i915_read16(dev_priv, reg) & status; - else - return __raw_i915_read32(dev_priv, reg) & status; -} - static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, - int *vpos, int *hpos, ktime_t *stime, ktime_t *etime) + int *vpos, int *hpos) { - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - const struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode; - int position; + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + u32 vbl = 0, position = 0; int vbl_start, vbl_end, htotal, vtotal; bool in_vbl = true; int ret = 0; - unsigned long irqflags; + enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, + pipe); - if (!intel_crtc->active) { + if (!i915_pipe_enabled(dev, pipe)) { DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled " "pipe %c\n", pipe_name(pipe)); return 0; } - htotal = mode->crtc_htotal; - vtotal = mode->crtc_vtotal; - vbl_start = mode->crtc_vblank_start; - vbl_end = mode->crtc_vblank_end; - - ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE; + /* Get vtotal. */ + vtotal = 1 + ((I915_READ(VTOTAL(cpu_transcoder)) >> 16) & 0x1fff); - /* - * Lock uncore.lock, as we will do multiple timing critical raw - * register reads, potentially with preemption disabled, so the - * following code must not block on uncore.lock. - */ - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - - /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ - - /* Get optional system timestamp before query. */ - if (stime) - *stime = ktime_get(); - - if (IS_GEN2(dev) || IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { + if (INTEL_INFO(dev)->gen >= 4) { /* No obvious pixelcount register. Only query vertical * scanout position from Display scan line register. */ - if (IS_GEN2(dev)) - position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN2; - else - position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3; + position = I915_READ(PIPEDSL(pipe)); - /* - * The scanline counter increments at the leading edge - * of hsync, ie. it completely misses the active portion - * of the line. Fix up the counter at both edges of vblank - * to get a more accurate picture whether we're in vblank - * or not. + /* Decode into vertical scanout position. Don't have + * horizontal scanout position. */ - in_vbl = intel_pipe_in_vblank_locked(dev, pipe); - if ((in_vbl && position == vbl_start - 1) || - (!in_vbl && position == vbl_end - 1)) - position = (position + 1) % vtotal; + *vpos = position & 0x1fff; + *hpos = 0; } else { /* Have access to pixelcount since start of frame. * We can split this into vertical and horizontal * scanout position. */ - position = (__raw_i915_read32(dev_priv, PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; + position = (I915_READ(PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; - /* convert to pixel counts */ - vbl_start *= htotal; - vbl_end *= htotal; - vtotal *= htotal; + htotal = 1 + ((I915_READ(HTOTAL(cpu_transcoder)) >> 16) & 0x1fff); + *vpos = position / htotal; + *hpos = position - (*vpos * htotal); } - /* Get optional system timestamp after query. */ - if (etime) - *etime = ktime_get(); + /* Query vblank area. */ + vbl = I915_READ(VBLANK(cpu_transcoder)); - /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ + /* Test position against vblank region. */ + vbl_start = vbl & 0x1fff; + vbl_end = (vbl >> 16) & 0x1fff; - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + if ((*vpos < vbl_start) || (*vpos > vbl_end)) + in_vbl = false; - in_vbl = position >= vbl_start && position < vbl_end; + /* Inside "upper part" of vblank area? Apply corrective offset: */ + if (in_vbl && (*vpos >= vbl_start)) + *vpos = *vpos - vtotal; - /* - * While in vblank, position will be negative - * counting up towards 0 at vbl_end. And outside - * vblank, position will be positive counting - * up since vbl_end. - */ - if (position >= vbl_start) - position -= vbl_end; - else - position += vtotal - vbl_end; - - if (IS_GEN2(dev) || IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { - *vpos = position; - *hpos = 0; - } else { - *vpos = position / htotal; - *hpos = position - (*vpos * htotal); - } + /* Readouts valid? */ + if (vbl > 0) + ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE; /* In vblank? */ if (in_vbl) @@ -812,8 +665,7 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe, crtc); } -static bool intel_hpd_irq_event(struct drm_device *dev, - struct drm_connector *connector) +static int intel_hpd_irq_event(struct drm_device *dev, struct drm_connector *connector) { enum drm_connector_status old_status; @@ -821,16 +673,11 @@ static bool intel_hpd_irq_event(struct drm_device *dev, old_status = connector->status; connector->status = connector->funcs->detect(connector, false); - if (old_status == connector->status) - return false; - - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n", + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", connector->base.id, drm_get_connector_name(connector), - drm_get_connector_status_name(old_status), - drm_get_connector_status_name(connector->status)); - - return true; + old_status, connector->status); + return (old_status != connector->status); } /* @@ -954,7 +801,7 @@ static void notify_ring(struct drm_device *dev, if (ring->obj == NULL) return; - trace_i915_gem_request_complete(ring); + trace_i915_gem_request_complete(ring, ring->get_seqno(ring, false)); wake_up_all(&ring->irq_queue); i915_queue_hangcheck(dev); @@ -965,7 +812,7 @@ static void gen6_pm_rps_work(struct work_struct *work) drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, rps.work); u32 pm_iir; - int new_delay, adj; + u8 new_delay; spin_lock_irq(&dev_priv->irq_lock); pm_iir = dev_priv->rps.pm_iir; @@ -982,49 +829,40 @@ static void gen6_pm_rps_work(struct work_struct *work) mutex_lock(&dev_priv->rps.hw_lock); - adj = dev_priv->rps.last_adj; if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) { - if (adj > 0) - adj *= 2; - else - adj = 1; - new_delay = dev_priv->rps.cur_delay + adj; + new_delay = dev_priv->rps.cur_delay + 1; /* * For better performance, jump directly * to RPe if we're below it. */ - if (new_delay < dev_priv->rps.rpe_delay) - new_delay = dev_priv->rps.rpe_delay; - } else if (pm_iir & GEN6_PM_RP_DOWN_TIMEOUT) { - if (dev_priv->rps.cur_delay > dev_priv->rps.rpe_delay) + if (IS_VALLEYVIEW(dev_priv->dev) && + dev_priv->rps.cur_delay < dev_priv->rps.rpe_delay) new_delay = dev_priv->rps.rpe_delay; - else - new_delay = dev_priv->rps.min_delay; - adj = 0; - } else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) { - if (adj < 0) - adj *= 2; - else - adj = -1; - new_delay = dev_priv->rps.cur_delay + adj; - } else { /* unknown event */ - new_delay = dev_priv->rps.cur_delay; - } + } else + new_delay = dev_priv->rps.cur_delay - 1; /* sysfs frequency interfaces may have snuck in while servicing the * interrupt */ - if (new_delay < (int)dev_priv->rps.min_delay) - new_delay = dev_priv->rps.min_delay; - if (new_delay > (int)dev_priv->rps.max_delay) - new_delay = dev_priv->rps.max_delay; - dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_delay; - - if (IS_VALLEYVIEW(dev_priv->dev)) - valleyview_set_rps(dev_priv->dev, new_delay); - else - gen6_set_rps(dev_priv->dev, new_delay); + if (new_delay >= dev_priv->rps.min_delay && + new_delay <= dev_priv->rps.max_delay) { + if (IS_VALLEYVIEW(dev_priv->dev)) + valleyview_set_rps(dev_priv->dev, new_delay); + else + gen6_set_rps(dev_priv->dev, new_delay); + } + + if (IS_VALLEYVIEW(dev_priv->dev)) { + /* + * On VLV, when we enter RC6 we may not be at the minimum + * voltage level, so arm a timer to check. It should only + * fire when there's activity or once after we've entered + * RC6, and then won't be re-armed until the next RPS interrupt. + */ + mod_delayed_work(dev_priv->wq, &dev_priv->rps.vlv_work, + msecs_to_jiffies(100)); + } mutex_unlock(&dev_priv->rps.hw_lock); } @@ -1044,10 +882,9 @@ static void ivybridge_parity_work(struct work_struct *work) drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, l3_parity.error_work); u32 error_status, row, bank, subbank; - char *parity_event[6]; + char *parity_event[5]; uint32_t misccpctl; unsigned long flags; - uint8_t slice = 0; /* We must turn off DOP level clock gating to access the L3 registers. * In order to prevent a get/put style interface, acquire struct mutex @@ -1055,81 +892,55 @@ static void ivybridge_parity_work(struct work_struct *work) */ mutex_lock(&dev_priv->dev->struct_mutex); - /* If we've screwed up tracking, just let the interrupt fire again */ - if (WARN_ON(!dev_priv->l3_parity.which_slice)) - goto out; - misccpctl = I915_READ(GEN7_MISCCPCTL); I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); POSTING_READ(GEN7_MISCCPCTL); - while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) { - u32 reg; - - slice--; - if (WARN_ON_ONCE(slice >= NUM_L3_SLICES(dev_priv->dev))) - break; - - dev_priv->l3_parity.which_slice &= ~(1<<slice); - - reg = GEN7_L3CDERRST1 + (slice * 0x200); - - error_status = I915_READ(reg); - row = GEN7_PARITY_ERROR_ROW(error_status); - bank = GEN7_PARITY_ERROR_BANK(error_status); - subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); + error_status = I915_READ(GEN7_L3CDERRST1); + row = GEN7_PARITY_ERROR_ROW(error_status); + bank = GEN7_PARITY_ERROR_BANK(error_status); + subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); - I915_WRITE(reg, GEN7_PARITY_ERROR_VALID | GEN7_L3CDERRST1_ENABLE); - POSTING_READ(reg); - - parity_event[0] = I915_L3_PARITY_UEVENT "=1"; - parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); - parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); - parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); - parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice); - parity_event[5] = NULL; - - kobject_uevent_env(&dev_priv->dev->primary->kdev->kobj, - KOBJ_CHANGE, parity_event); - - DRM_DEBUG("Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n", - slice, row, bank, subbank); - - kfree(parity_event[4]); - kfree(parity_event[3]); - kfree(parity_event[2]); - kfree(parity_event[1]); - } + I915_WRITE(GEN7_L3CDERRST1, GEN7_PARITY_ERROR_VALID | + GEN7_L3CDERRST1_ENABLE); + POSTING_READ(GEN7_L3CDERRST1); I915_WRITE(GEN7_MISCCPCTL, misccpctl); -out: - WARN_ON(dev_priv->l3_parity.which_slice); spin_lock_irqsave(&dev_priv->irq_lock, flags); - ilk_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv->dev)); + ilk_enable_gt_irq(dev_priv, GT_RENDER_L3_PARITY_ERROR_INTERRUPT); spin_unlock_irqrestore(&dev_priv->irq_lock, flags); mutex_unlock(&dev_priv->dev->struct_mutex); + + parity_event[0] = I915_L3_PARITY_UEVENT "=1"; + parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); + parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); + parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); + parity_event[4] = NULL; + + kobject_uevent_env(&dev_priv->dev->primary->kdev.kobj, + KOBJ_CHANGE, parity_event); + + DRM_DEBUG("Parity error: Row = %d, Bank = %d, Sub bank = %d.\n", + row, bank, subbank); + + kfree(parity_event[3]); + kfree(parity_event[2]); + kfree(parity_event[1]); } -static void ivybridge_parity_error_irq_handler(struct drm_device *dev, u32 iir) +static void ivybridge_parity_error_irq_handler(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - if (!HAS_L3_DPF(dev)) + if (!HAS_L3_GPU_CACHE(dev)) return; spin_lock(&dev_priv->irq_lock); - ilk_disable_gt_irq(dev_priv, GT_PARITY_ERROR(dev)); + ilk_disable_gt_irq(dev_priv, GT_RENDER_L3_PARITY_ERROR_INTERRUPT); spin_unlock(&dev_priv->irq_lock); - iir &= GT_PARITY_ERROR(dev); - if (iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1) - dev_priv->l3_parity.which_slice |= 1 << 1; - - if (iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT) - dev_priv->l3_parity.which_slice |= 1 << 0; - queue_work(dev_priv->wq, &dev_priv->l3_parity.error_work); } @@ -1164,58 +975,8 @@ static void snb_gt_irq_handler(struct drm_device *dev, i915_handle_error(dev, false); } - if (gt_iir & GT_PARITY_ERROR(dev)) - ivybridge_parity_error_irq_handler(dev, gt_iir); -} - -static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, - struct drm_i915_private *dev_priv, - u32 master_ctl) -{ - u32 rcs, bcs, vcs; - uint32_t tmp = 0; - irqreturn_t ret = IRQ_NONE; - - if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { - tmp = I915_READ(GEN8_GT_IIR(0)); - if (tmp) { - ret = IRQ_HANDLED; - rcs = tmp >> GEN8_RCS_IRQ_SHIFT; - bcs = tmp >> GEN8_BCS_IRQ_SHIFT; - if (rcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, &dev_priv->ring[RCS]); - if (bcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, &dev_priv->ring[BCS]); - I915_WRITE(GEN8_GT_IIR(0), tmp); - } else - DRM_ERROR("The master control interrupt lied (GT0)!\n"); - } - - if (master_ctl & GEN8_GT_VCS1_IRQ) { - tmp = I915_READ(GEN8_GT_IIR(1)); - if (tmp) { - ret = IRQ_HANDLED; - vcs = tmp >> GEN8_VCS1_IRQ_SHIFT; - if (vcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, &dev_priv->ring[VCS]); - I915_WRITE(GEN8_GT_IIR(1), tmp); - } else - DRM_ERROR("The master control interrupt lied (GT1)!\n"); - } - - if (master_ctl & GEN8_GT_VECS_IRQ) { - tmp = I915_READ(GEN8_GT_IIR(3)); - if (tmp) { - ret = IRQ_HANDLED; - vcs = tmp >> GEN8_VECS_IRQ_SHIFT; - if (vcs & GT_RENDER_USER_INTERRUPT) - notify_ring(dev, &dev_priv->ring[VECS]); - I915_WRITE(GEN8_GT_IIR(3), tmp); - } else - DRM_ERROR("The master control interrupt lied (GT3)!\n"); - } - - return ret; + if (gt_iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT) + ivybridge_parity_error_irq_handler(dev); } #define HPD_STORM_DETECT_PERIOD 1000 @@ -1289,102 +1050,6 @@ static void dp_aux_irq_handler(struct drm_device *dev) wake_up_all(&dev_priv->gmbus_wait_queue); } -#if defined(CONFIG_DEBUG_FS) -static void display_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe, - uint32_t crc0, uint32_t crc1, - uint32_t crc2, uint32_t crc3, - uint32_t crc4) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; - struct intel_pipe_crc_entry *entry; - int head, tail; - - spin_lock(&pipe_crc->lock); - - if (!pipe_crc->entries) { - spin_unlock(&pipe_crc->lock); - DRM_ERROR("spurious interrupt\n"); - return; - } - - head = pipe_crc->head; - tail = pipe_crc->tail; - - if (CIRC_SPACE(head, tail, INTEL_PIPE_CRC_ENTRIES_NR) < 1) { - spin_unlock(&pipe_crc->lock); - DRM_ERROR("CRC buffer overflowing\n"); - return; - } - - entry = &pipe_crc->entries[head]; - - entry->frame = dev->driver->get_vblank_counter(dev, pipe); - entry->crc[0] = crc0; - entry->crc[1] = crc1; - entry->crc[2] = crc2; - entry->crc[3] = crc3; - entry->crc[4] = crc4; - - head = (head + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); - pipe_crc->head = head; - - spin_unlock(&pipe_crc->lock); - - wake_up_interruptible(&pipe_crc->wq); -} -#else -static inline void -display_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe, - uint32_t crc0, uint32_t crc1, - uint32_t crc2, uint32_t crc3, - uint32_t crc4) {} -#endif - - -static void hsw_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - display_pipe_crc_irq_handler(dev, pipe, - I915_READ(PIPE_CRC_RES_1_IVB(pipe)), - 0, 0, 0, 0); -} - -static void ivb_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - display_pipe_crc_irq_handler(dev, pipe, - I915_READ(PIPE_CRC_RES_1_IVB(pipe)), - I915_READ(PIPE_CRC_RES_2_IVB(pipe)), - I915_READ(PIPE_CRC_RES_3_IVB(pipe)), - I915_READ(PIPE_CRC_RES_4_IVB(pipe)), - I915_READ(PIPE_CRC_RES_5_IVB(pipe))); -} - -static void i9xx_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t res1, res2; - - if (INTEL_INFO(dev)->gen >= 3) - res1 = I915_READ(PIPE_CRC_RES_RES1_I915(pipe)); - else - res1 = 0; - - if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) - res2 = I915_READ(PIPE_CRC_RES_RES2_G4X(pipe)); - else - res2 = 0; - - display_pipe_crc_irq_handler(dev, pipe, - I915_READ(PIPE_CRC_RES_RED(pipe)), - I915_READ(PIPE_CRC_RES_GREEN(pipe)), - I915_READ(PIPE_CRC_RES_BLUE(pipe)), - res1, res2); -} - /* The RPS events need forcewake, so we add them to a work queue and mask their * IMR bits until the work is done. Other interrupts can be processed without * the work queue. */ @@ -1452,16 +1117,13 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); for_each_pipe(pipe) { - if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) + if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) drm_handle_vblank(dev, pipe); if (pipe_stats[pipe] & PLANE_FLIPDONE_INT_STATUS_VLV) { intel_prepare_page_flip(dev, pipe); intel_finish_page_flip(dev, pipe); } - - if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) - i9xx_pipe_crc_irq_handler(dev, pipe); } /* Consume port. Then clear IIR or we'll miss events */ @@ -1550,26 +1212,21 @@ static void ivb_err_int_handler(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 err_int = I915_READ(GEN7_ERR_INT); - enum pipe pipe; if (err_int & ERR_INT_POISON) DRM_ERROR("Poison interrupt\n"); - for_each_pipe(pipe) { - if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) { - if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, - false)) - DRM_DEBUG_DRIVER("Pipe %c FIFO underrun\n", - pipe_name(pipe)); - } + if (err_int & ERR_INT_FIFO_UNDERRUN_A) + if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, false)) + DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n"); - if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) { - if (IS_IVYBRIDGE(dev)) - ivb_pipe_crc_irq_handler(dev, pipe); - else - hsw_pipe_crc_irq_handler(dev, pipe); - } - } + if (err_int & ERR_INT_FIFO_UNDERRUN_B) + if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, false)) + DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n"); + + if (err_int & ERR_INT_FIFO_UNDERRUN_C) + if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_C, false)) + DRM_DEBUG_DRIVER("Pipe C FIFO underrun\n"); I915_WRITE(GEN7_ERR_INT, err_int); } @@ -1640,7 +1297,6 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) { struct drm_i915_private *dev_priv = dev->dev_private; - enum pipe pipe; if (de_iir & DE_AUX_CHANNEL_A) dp_aux_irq_handler(dev); @@ -1648,26 +1304,31 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) if (de_iir & DE_GSE) intel_opregion_asle_intr(dev); + if (de_iir & DE_PIPEA_VBLANK) + drm_handle_vblank(dev, 0); + + if (de_iir & DE_PIPEB_VBLANK) + drm_handle_vblank(dev, 1); + if (de_iir & DE_POISON) DRM_ERROR("Poison interrupt\n"); - for_each_pipe(pipe) { - if (de_iir & DE_PIPE_VBLANK(pipe)) - drm_handle_vblank(dev, pipe); + if (de_iir & DE_PIPEA_FIFO_UNDERRUN) + if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, false)) + DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n"); - if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe)) - if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, false)) - DRM_DEBUG_DRIVER("Pipe %c FIFO underrun\n", - pipe_name(pipe)); + if (de_iir & DE_PIPEB_FIFO_UNDERRUN) + if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, false)) + DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n"); - if (de_iir & DE_PIPE_CRC_DONE(pipe)) - i9xx_pipe_crc_irq_handler(dev, pipe); + if (de_iir & DE_PLANEA_FLIP_DONE) { + intel_prepare_page_flip(dev, 0); + intel_finish_page_flip_plane(dev, 0); + } - /* plane/pipes map 1:1 on ilk+ */ - if (de_iir & DE_PLANE_FLIP_DONE(pipe)) { - intel_prepare_page_flip(dev, pipe); - intel_finish_page_flip_plane(dev, pipe); - } + if (de_iir & DE_PLANEB_FLIP_DONE) { + intel_prepare_page_flip(dev, 1); + intel_finish_page_flip_plane(dev, 1); } /* check event from PCH */ @@ -1690,7 +1351,7 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir) { struct drm_i915_private *dev_priv = dev->dev_private; - enum pipe i; + int i; if (de_iir & DE_ERR_INT_IVB) ivb_err_int_handler(dev); @@ -1701,12 +1362,10 @@ static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir) if (de_iir & DE_GSE_IVB) intel_opregion_asle_intr(dev); - for_each_pipe(i) { - if (de_iir & (DE_PIPE_VBLANK_IVB(i))) + for (i = 0; i < 3; i++) { + if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i))) drm_handle_vblank(dev, i); - - /* plane/pipes map 1:1 on ilk+ */ - if (de_iir & DE_PLANE_FLIP_DONE_IVB(i)) { + if (de_iir & (DE_PLANEA_FLIP_DONE_IVB << (5 * i))) { intel_prepare_page_flip(dev, i); intel_finish_page_flip_plane(dev, i); } @@ -1729,6 +1388,7 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 de_iir, gt_iir, de_ier, sde_ier = 0; irqreturn_t ret = IRQ_NONE; + bool err_int_reenable = false; atomic_inc(&dev_priv->irq_received); @@ -1752,6 +1412,17 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) POSTING_READ(SDEIER); } + /* On Haswell, also mask ERR_INT because we don't want to risk + * generating "unclaimed register" interrupts from inside the interrupt + * handler. */ + if (IS_HASWELL(dev)) { + spin_lock(&dev_priv->irq_lock); + err_int_reenable = ~dev_priv->irq_mask & DE_ERR_INT_IVB; + if (err_int_reenable) + ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB); + spin_unlock(&dev_priv->irq_lock); + } + gt_iir = I915_READ(GTIIR); if (gt_iir) { if (INTEL_INFO(dev)->gen >= 6) @@ -1781,6 +1452,13 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) } } + if (err_int_reenable) { + spin_lock(&dev_priv->irq_lock); + if (ivb_can_enable_err_int(dev)) + ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB); + spin_unlock(&dev_priv->irq_lock); + } + I915_WRITE(DEIER, de_ier); POSTING_READ(DEIER); if (!HAS_PCH_NOP(dev)) { @@ -1791,117 +1469,6 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) return ret; } -static irqreturn_t gen8_irq_handler(int irq, void *arg) -{ - struct drm_device *dev = arg; - struct drm_i915_private *dev_priv = dev->dev_private; - u32 master_ctl; - irqreturn_t ret = IRQ_NONE; - uint32_t tmp = 0; - enum pipe pipe; - - atomic_inc(&dev_priv->irq_received); - - master_ctl = I915_READ(GEN8_MASTER_IRQ); - master_ctl &= ~GEN8_MASTER_IRQ_CONTROL; - if (!master_ctl) - return IRQ_NONE; - - I915_WRITE(GEN8_MASTER_IRQ, 0); - POSTING_READ(GEN8_MASTER_IRQ); - - ret = gen8_gt_irq_handler(dev, dev_priv, master_ctl); - - if (master_ctl & GEN8_DE_MISC_IRQ) { - tmp = I915_READ(GEN8_DE_MISC_IIR); - if (tmp & GEN8_DE_MISC_GSE) - intel_opregion_asle_intr(dev); - else if (tmp) - DRM_ERROR("Unexpected DE Misc interrupt\n"); - else - DRM_ERROR("The master control interrupt lied (DE MISC)!\n"); - - if (tmp) { - I915_WRITE(GEN8_DE_MISC_IIR, tmp); - ret = IRQ_HANDLED; - } - } - - if (master_ctl & GEN8_DE_PORT_IRQ) { - tmp = I915_READ(GEN8_DE_PORT_IIR); - if (tmp & GEN8_AUX_CHANNEL_A) - dp_aux_irq_handler(dev); - else if (tmp) - DRM_ERROR("Unexpected DE Port interrupt\n"); - else - DRM_ERROR("The master control interrupt lied (DE PORT)!\n"); - - if (tmp) { - I915_WRITE(GEN8_DE_PORT_IIR, tmp); - ret = IRQ_HANDLED; - } - } - - for_each_pipe(pipe) { - uint32_t pipe_iir; - - if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe))) - continue; - - pipe_iir = I915_READ(GEN8_DE_PIPE_IIR(pipe)); - if (pipe_iir & GEN8_PIPE_VBLANK) - drm_handle_vblank(dev, pipe); - - if (pipe_iir & GEN8_PIPE_FLIP_DONE) { - intel_prepare_page_flip(dev, pipe); - intel_finish_page_flip_plane(dev, pipe); - } - - if (pipe_iir & GEN8_PIPE_CDCLK_CRC_DONE) - hsw_pipe_crc_irq_handler(dev, pipe); - - if (pipe_iir & GEN8_PIPE_FIFO_UNDERRUN) { - if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, - false)) - DRM_DEBUG_DRIVER("Pipe %c FIFO underrun\n", - pipe_name(pipe)); - } - - if (pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS) { - DRM_ERROR("Fault errors on pipe %c\n: 0x%08x", - pipe_name(pipe), - pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS); - } - - if (pipe_iir) { - ret = IRQ_HANDLED; - I915_WRITE(GEN8_DE_PIPE_IIR(pipe), pipe_iir); - } else - DRM_ERROR("The master control interrupt lied (DE PIPE)!\n"); - } - - if (!HAS_PCH_NOP(dev) && master_ctl & GEN8_DE_PCH_IRQ) { - /* - * FIXME(BDW): Assume for now that the new interrupt handling - * scheme also closed the SDE interrupt handling race we've seen - * on older pch-split platforms. But this needs testing. - */ - u32 pch_iir = I915_READ(SDEIIR); - - cpt_irq_handler(dev, pch_iir); - - if (pch_iir) { - I915_WRITE(SDEIIR, pch_iir); - ret = IRQ_HANDLED; - } - } - - I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); - POSTING_READ(GEN8_MASTER_IRQ); - - return ret; -} - static void i915_error_wake_up(struct drm_i915_private *dev_priv, bool reset_completed) { @@ -1949,7 +1516,7 @@ static void i915_error_work_func(struct work_struct *work) char *reset_done_event[] = { I915_ERROR_UEVENT "=0", NULL }; int ret; - kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, error_event); + kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event); /* * Note that there's only one work item which does gpu resets, so we @@ -1963,7 +1530,7 @@ static void i915_error_work_func(struct work_struct *work) */ if (i915_reset_in_progress(error) && !i915_terminally_wedged(error)) { DRM_DEBUG_DRIVER("resetting chip\n"); - kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, + kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event); /* @@ -1990,7 +1557,7 @@ static void i915_error_work_func(struct work_struct *work) smp_mb__before_atomic_inc(); atomic_inc(&dev_priv->gpu_error.reset_counter); - kobject_uevent_env(&dev->primary->kdev->kobj, + kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event); } else { atomic_set(&error->reset_counter, I915_WEDGED); @@ -2220,7 +1787,7 @@ static int ironlake_enable_vblank(struct drm_device *dev, int pipe) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; uint32_t bit = (INTEL_INFO(dev)->gen >= 7) ? DE_PIPE_VBLANK_IVB(pipe) : - DE_PIPE_VBLANK(pipe); + DE_PIPE_VBLANK_ILK(pipe); if (!i915_pipe_enabled(dev, pipe)) return -EINVAL; @@ -2243,7 +1810,7 @@ static int valleyview_enable_vblank(struct drm_device *dev, int pipe) spin_lock_irqsave(&dev_priv->irq_lock, irqflags); imr = I915_READ(VLV_IMR); - if (pipe == PIPE_A) + if (pipe == 0) imr &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; else imr &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; @@ -2255,22 +1822,6 @@ static int valleyview_enable_vblank(struct drm_device *dev, int pipe) return 0; } -static int gen8_enable_vblank(struct drm_device *dev, int pipe) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - unsigned long irqflags; - - if (!i915_pipe_enabled(dev, pipe)) - return -EINVAL; - - spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - dev_priv->de_irq_mask[pipe] &= ~GEN8_PIPE_VBLANK; - I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]); - POSTING_READ(GEN8_DE_PIPE_IMR(pipe)); - spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); - return 0; -} - /* Called from drm generic code, passed 'crtc' which * we use as a pipe index */ @@ -2294,7 +1845,7 @@ static void ironlake_disable_vblank(struct drm_device *dev, int pipe) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; uint32_t bit = (INTEL_INFO(dev)->gen >= 7) ? DE_PIPE_VBLANK_IVB(pipe) : - DE_PIPE_VBLANK(pipe); + DE_PIPE_VBLANK_ILK(pipe); spin_lock_irqsave(&dev_priv->irq_lock, irqflags); ironlake_disable_display_irq(dev_priv, bit); @@ -2311,7 +1862,7 @@ static void valleyview_disable_vblank(struct drm_device *dev, int pipe) i915_disable_pipestat(dev_priv, pipe, PIPE_START_VBLANK_INTERRUPT_ENABLE); imr = I915_READ(VLV_IMR); - if (pipe == PIPE_A) + if (pipe == 0) imr |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; else imr |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; @@ -2319,21 +1870,6 @@ static void valleyview_disable_vblank(struct drm_device *dev, int pipe) spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } -static void gen8_disable_vblank(struct drm_device *dev, int pipe) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - unsigned long irqflags; - - if (!i915_pipe_enabled(dev, pipe)) - return; - - spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - dev_priv->de_irq_mask[pipe] |= GEN8_PIPE_VBLANK; - I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]); - POSTING_READ(GEN8_DE_PIPE_IMR(pipe)); - spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); -} - static u32 ring_last_seqno(struct intel_ring_buffer *ring) { @@ -2429,7 +1965,6 @@ ring_stuck(struct intel_ring_buffer *ring, u32 acthd) if (tmp & RING_WAIT) { DRM_ERROR("Kicking stuck wait on %s\n", ring->name); - i915_handle_error(dev, false); I915_WRITE_CTL(ring, tmp); return HANGCHECK_KICK; } @@ -2441,7 +1976,6 @@ ring_stuck(struct intel_ring_buffer *ring, u32 acthd) case 1: DRM_ERROR("Kicking stuck semaphore on %s\n", ring->name); - i915_handle_error(dev, false); I915_WRITE_CTL(ring, tmp); return HANGCHECK_KICK; case 0: @@ -2487,21 +2021,12 @@ static void i915_hangcheck_elapsed(unsigned long data) if (ring->hangcheck.seqno == seqno) { if (ring_idle(ring, seqno)) { - ring->hangcheck.action = HANGCHECK_IDLE; - if (waitqueue_active(&ring->irq_queue)) { /* Issue a wake-up to catch stuck h/w. */ - if (!test_and_set_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings)) { - if (!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(ring))) - DRM_ERROR("Hangcheck timer elapsed... %s idle\n", - ring->name); - else - DRM_INFO("Fake missed irq on %s\n", - ring->name); - wake_up_all(&ring->irq_queue); - } - /* Safeguard against driver failure */ - ring->hangcheck.score += BUSY; + DRM_ERROR("Hangcheck timer elapsed... %s idle\n", + ring->name); + wake_up_all(&ring->irq_queue); + ring->hangcheck.score += HUNG; } else busy = false; } else { @@ -2524,7 +2049,6 @@ static void i915_hangcheck_elapsed(unsigned long data) acthd); switch (ring->hangcheck.action) { - case HANGCHECK_IDLE: case HANGCHECK_WAIT: break; case HANGCHECK_ACTIVE: @@ -2540,8 +2064,6 @@ static void i915_hangcheck_elapsed(unsigned long data) } } } else { - ring->hangcheck.action = HANGCHECK_ACTIVE; - /* Gradually reduce the count so that we catch DoS * attempts across multiple batches. */ @@ -2668,53 +2190,6 @@ static void valleyview_irq_preinstall(struct drm_device *dev) POSTING_READ(VLV_IER); } -static void gen8_irq_preinstall(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - int pipe; - - atomic_set(&dev_priv->irq_received, 0); - - I915_WRITE(GEN8_MASTER_IRQ, 0); - POSTING_READ(GEN8_MASTER_IRQ); - - /* IIR can theoretically queue up two events. Be paranoid */ -#define GEN8_IRQ_INIT_NDX(type, which) do { \ - I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \ - POSTING_READ(GEN8_##type##_IMR(which)); \ - I915_WRITE(GEN8_##type##_IER(which), 0); \ - I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \ - POSTING_READ(GEN8_##type##_IIR(which)); \ - I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \ - } while (0) - -#define GEN8_IRQ_INIT(type) do { \ - I915_WRITE(GEN8_##type##_IMR, 0xffffffff); \ - POSTING_READ(GEN8_##type##_IMR); \ - I915_WRITE(GEN8_##type##_IER, 0); \ - I915_WRITE(GEN8_##type##_IIR, 0xffffffff); \ - POSTING_READ(GEN8_##type##_IIR); \ - I915_WRITE(GEN8_##type##_IIR, 0xffffffff); \ - } while (0) - - GEN8_IRQ_INIT_NDX(GT, 0); - GEN8_IRQ_INIT_NDX(GT, 1); - GEN8_IRQ_INIT_NDX(GT, 2); - GEN8_IRQ_INIT_NDX(GT, 3); - - for_each_pipe(pipe) { - GEN8_IRQ_INIT_NDX(DE_PIPE, pipe); - } - - GEN8_IRQ_INIT(DE_PORT); - GEN8_IRQ_INIT(DE_MISC); - GEN8_IRQ_INIT(PCU); -#undef GEN8_IRQ_INIT -#undef GEN8_IRQ_INIT_NDX - - POSTING_READ(GEN8_PCU_IIR); -} - static void ibx_hpd_irq_setup(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -2779,10 +2254,10 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) pm_irqs = gt_irqs = 0; dev_priv->gt_irq_mask = ~0; - if (HAS_L3_DPF(dev)) { + if (HAS_L3_GPU_CACHE(dev)) { /* L3 parity interrupt is always unmasked. */ - dev_priv->gt_irq_mask = ~GT_PARITY_ERROR(dev); - gt_irqs |= GT_PARITY_ERROR(dev); + dev_priv->gt_irq_mask = ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT; + gt_irqs |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT; } gt_irqs |= GT_RENDER_USER_INTERRUPT; @@ -2831,10 +2306,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev) } else { display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE | - DE_AUX_CHANNEL_A | - DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | - DE_PIPEB_CRC_DONE | DE_PIPEA_CRC_DONE | - DE_POISON); + DE_AUX_CHANNEL_A | DE_PIPEB_FIFO_UNDERRUN | + DE_PIPEA_FIFO_UNDERRUN | DE_POISON); extra_mask = DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT; } @@ -2868,8 +2341,7 @@ static int valleyview_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 enable_mask; - u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV | - PIPE_CRC_DONE_ENABLE; + u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV; unsigned long irqflags; enable_mask = I915_DISPLAY_PORT_INTERRUPT; @@ -2899,9 +2371,9 @@ static int valleyview_irq_postinstall(struct drm_device *dev) /* Interrupt setup is already guaranteed to be single-threaded, this is * just to make the assert_spin_locked check happy. */ spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - i915_enable_pipestat(dev_priv, PIPE_A, pipestat_enable); - i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_EVENT_ENABLE); - i915_enable_pipestat(dev_priv, PIPE_B, pipestat_enable); + i915_enable_pipestat(dev_priv, 0, pipestat_enable); + i915_enable_pipestat(dev_priv, 0, PIPE_GMBUS_EVENT_ENABLE); + i915_enable_pipestat(dev_priv, 1, pipestat_enable); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); I915_WRITE(VLV_IIR, 0xffffffff); @@ -2920,117 +2392,6 @@ static int valleyview_irq_postinstall(struct drm_device *dev) return 0; } -static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv) -{ - int i; - - /* These are interrupts we'll toggle with the ring mask register */ - uint32_t gt_interrupts[] = { - GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT | - GT_RENDER_L3_PARITY_ERROR_INTERRUPT | - GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT, - GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT | - GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT, - 0, - GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT - }; - - for (i = 0; i < ARRAY_SIZE(gt_interrupts); i++) { - u32 tmp = I915_READ(GEN8_GT_IIR(i)); - if (tmp) - DRM_ERROR("Interrupt (%d) should have been masked in pre-install 0x%08x\n", - i, tmp); - I915_WRITE(GEN8_GT_IMR(i), ~gt_interrupts[i]); - I915_WRITE(GEN8_GT_IER(i), gt_interrupts[i]); - } - POSTING_READ(GEN8_GT_IER(0)); -} - -static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) -{ - struct drm_device *dev = dev_priv->dev; - uint32_t de_pipe_masked = GEN8_PIPE_FLIP_DONE | - GEN8_PIPE_CDCLK_CRC_DONE | - GEN8_PIPE_FIFO_UNDERRUN | - GEN8_DE_PIPE_IRQ_FAULT_ERRORS; - uint32_t de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK; - int pipe; - dev_priv->de_irq_mask[PIPE_A] = ~de_pipe_masked; - dev_priv->de_irq_mask[PIPE_B] = ~de_pipe_masked; - dev_priv->de_irq_mask[PIPE_C] = ~de_pipe_masked; - - for_each_pipe(pipe) { - u32 tmp = I915_READ(GEN8_DE_PIPE_IIR(pipe)); - if (tmp) - DRM_ERROR("Interrupt (%d) should have been masked in pre-install 0x%08x\n", - pipe, tmp); - I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]); - I915_WRITE(GEN8_DE_PIPE_IER(pipe), de_pipe_enables); - } - POSTING_READ(GEN8_DE_PIPE_ISR(0)); - - I915_WRITE(GEN8_DE_PORT_IMR, ~GEN8_AUX_CHANNEL_A); - I915_WRITE(GEN8_DE_PORT_IER, GEN8_AUX_CHANNEL_A); - POSTING_READ(GEN8_DE_PORT_IER); -} - -static int gen8_irq_postinstall(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - gen8_gt_irq_postinstall(dev_priv); - gen8_de_irq_postinstall(dev_priv); - - ibx_irq_postinstall(dev); - - I915_WRITE(GEN8_MASTER_IRQ, DE_MASTER_IRQ_CONTROL); - POSTING_READ(GEN8_MASTER_IRQ); - - return 0; -} - -static void gen8_irq_uninstall(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - int pipe; - - if (!dev_priv) - return; - - atomic_set(&dev_priv->irq_received, 0); - - I915_WRITE(GEN8_MASTER_IRQ, 0); - -#define GEN8_IRQ_FINI_NDX(type, which) do { \ - I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \ - I915_WRITE(GEN8_##type##_IER(which), 0); \ - I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \ - } while (0) - -#define GEN8_IRQ_FINI(type) do { \ - I915_WRITE(GEN8_##type##_IMR, 0xffffffff); \ - I915_WRITE(GEN8_##type##_IER, 0); \ - I915_WRITE(GEN8_##type##_IIR, 0xffffffff); \ - } while (0) - - GEN8_IRQ_FINI_NDX(GT, 0); - GEN8_IRQ_FINI_NDX(GT, 1); - GEN8_IRQ_FINI_NDX(GT, 2); - GEN8_IRQ_FINI_NDX(GT, 3); - - for_each_pipe(pipe) { - GEN8_IRQ_FINI_NDX(DE_PIPE, pipe); - } - - GEN8_IRQ_FINI(DE_PORT); - GEN8_IRQ_FINI(DE_MISC); - GEN8_IRQ_FINI(PCU); -#undef GEN8_IRQ_FINI -#undef GEN8_IRQ_FINI_NDX - - POSTING_READ(GEN8_PCU_IIR); -} - static void valleyview_irq_uninstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -3103,7 +2464,6 @@ static void i8xx_irq_preinstall(struct drm_device * dev) static int i8xx_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - unsigned long irqflags; I915_WRITE16(EMR, ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH)); @@ -3124,13 +2484,6 @@ static int i8xx_irq_postinstall(struct drm_device *dev) I915_USER_INTERRUPT); POSTING_READ16(IER); - /* Interrupt setup is already guaranteed to be single-threaded, this is - * just to make the assert_spin_locked check happy. */ - spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_ENABLE); - i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_ENABLE); - spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); - return 0; } @@ -3217,14 +2570,13 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) if (iir & I915_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[RCS]); - for_each_pipe(pipe) { - if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS && - i8xx_handle_vblank(dev, pipe, iir)) - flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe); + if (pipe_stats[0] & PIPE_VBLANK_INTERRUPT_STATUS && + i8xx_handle_vblank(dev, 0, iir)) + flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(0); - if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) - i9xx_pipe_crc_irq_handler(dev, pipe); - } + if (pipe_stats[1] & PIPE_VBLANK_INTERRUPT_STATUS && + i8xx_handle_vblank(dev, 1, iir)) + flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(1); iir = new_iir; } @@ -3271,7 +2623,6 @@ static int i915_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 enable_mask; - unsigned long irqflags; I915_WRITE(EMR, ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH)); @@ -3307,13 +2658,6 @@ static int i915_irq_postinstall(struct drm_device *dev) i915_enable_asle_pipestat(dev); - /* Interrupt setup is already guaranteed to be single-threaded, this is - * just to make the assert_spin_locked check happy. */ - spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_ENABLE); - i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_ENABLE); - spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); - return 0; } @@ -3425,9 +2769,6 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) blc_event = true; - - if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) - i9xx_pipe_crc_irq_handler(dev, pipe); } if (blc_event || (iir & I915_ASLE_INTERRUPT)) @@ -3526,9 +2867,7 @@ static int i965_irq_postinstall(struct drm_device *dev) /* Interrupt setup is already guaranteed to be single-threaded, this is * just to make the assert_spin_locked check happy. */ spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_EVENT_ENABLE); - i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_ENABLE); - i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_ENABLE); + i915_enable_pipestat(dev_priv, 0, PIPE_GMBUS_EVENT_ENABLE); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); /* @@ -3674,9 +3013,6 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) blc_event = true; - - if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) - i9xx_pipe_crc_irq_handler(dev, pipe); } @@ -3786,21 +3122,18 @@ void intel_irq_init(struct drm_device *dev) pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); - if (IS_GEN2(dev)) { - dev->max_vblank_count = 0; - dev->driver->get_vblank_counter = i8xx_get_vblank_counter; - } else if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { + dev->driver->get_vblank_counter = i915_get_vblank_counter; + dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ + if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */ dev->driver->get_vblank_counter = gm45_get_vblank_counter; - } else { - dev->driver->get_vblank_counter = i915_get_vblank_counter; - dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ } - if (drm_core_check_feature(dev, DRIVER_MODESET)) { + if (drm_core_check_feature(dev, DRIVER_MODESET)) dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp; - dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; - } + else + dev->driver->get_vblank_timestamp = NULL; + dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; if (IS_VALLEYVIEW(dev)) { dev->driver->irq_handler = valleyview_irq_handler; @@ -3810,14 +3143,6 @@ void intel_irq_init(struct drm_device *dev) dev->driver->enable_vblank = valleyview_enable_vblank; dev->driver->disable_vblank = valleyview_disable_vblank; dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; - } else if (IS_GEN8(dev)) { - dev->driver->irq_handler = gen8_irq_handler; - dev->driver->irq_preinstall = gen8_irq_preinstall; - dev->driver->irq_postinstall = gen8_irq_postinstall; - dev->driver->irq_uninstall = gen8_irq_uninstall; - dev->driver->enable_vblank = gen8_enable_vblank; - dev->driver->disable_vblank = gen8_disable_vblank; - dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup; } else if (HAS_PCH_SPLIT(dev)) { dev->driver->irq_handler = ironlake_irq_handler; dev->driver->irq_preinstall = ironlake_irq_preinstall; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ee27421..ef9b354 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -26,7 +26,6 @@ #define _I915_REG_H_ #define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) -#define _PIPE_INC(pipe, base, inc) ((base) + (pipe)*(inc)) #define _TRANSCODER(tran, a, b) ((a) + (tran)*((b)-(a))) #define _PORT(port, a, b) ((a) + (port)*((b)-(a))) @@ -110,9 +109,6 @@ #define RING_PP_DIR_DCLV(ring) ((ring)->mmio_base+0x220) #define PP_DIR_DCLV_2G 0xffffffff -#define GEN8_RING_PDP_UDW(ring, n) ((ring)->mmio_base+0x270 + ((n) * 8 + 4)) -#define GEN8_RING_PDP_LDW(ring, n) ((ring)->mmio_base+0x270 + (n) * 8) - #define GAM_ECOCHK 0x4090 #define ECOCHK_SNB_BIT (1<<10) #define HSW_ECOCHK_ARB_PRIO_SOL (1<<6) @@ -235,7 +231,6 @@ */ #define MI_LOAD_REGISTER_IMM(x) MI_INSTR(0x22, 2*x-1) #define MI_STORE_REGISTER_MEM(x) MI_INSTR(0x24, 2*x-1) -#define MI_SRM_LRM_GLOBAL_GTT (1<<22) #define MI_FLUSH_DW MI_INSTR(0x26, 1) /* for GEN6 */ #define MI_FLUSH_DW_STORE_INDEX (1<<21) #define MI_INVALIDATE_TLB (1<<18) @@ -251,7 +246,6 @@ #define MI_BATCH_NON_SECURE_HSW (1<<13) #define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0) #define MI_BATCH_GTT (2<<6) /* aliased with (1<<7) on gen4 */ -#define MI_BATCH_BUFFER_START_GEN8 MI_INSTR(0x31, 1) #define MI_SEMAPHORE_MBOX MI_INSTR(0x16, 1) /* gen6+ */ #define MI_SEMAPHORE_GLOBAL_GTT (1<<22) #define MI_SEMAPHORE_UPDATE (1<<21) @@ -270,11 +264,6 @@ #define MI_SEMAPHORE_SYNC_VVE (1<<16) /* VECS wait for VCS (VEVSYNC) */ #define MI_SEMAPHORE_SYNC_RVE (2<<16) /* VECS wait for RCS (VERSYNC) */ #define MI_SEMAPHORE_SYNC_INVALID (3<<16) - -#define MI_PREDICATE_RESULT_2 (0x2214) -#define LOWER_SLICE_ENABLED (1<<0) -#define LOWER_SLICE_DISABLED (0<<0) - /* * 3D instructions used by the kernel */ @@ -357,25 +346,12 @@ #define IOSF_PORT_PUNIT 0x4 #define IOSF_PORT_NC 0x11 #define IOSF_PORT_DPIO 0x12 -#define IOSF_PORT_GPIO_NC 0x13 -#define IOSF_PORT_CCK 0x14 -#define IOSF_PORT_CCU 0xA9 -#define IOSF_PORT_GPS_CORE 0x48 #define VLV_IOSF_DATA (VLV_DISPLAY_BASE + 0x2104) #define VLV_IOSF_ADDR (VLV_DISPLAY_BASE + 0x2108) #define PUNIT_OPCODE_REG_READ 6 #define PUNIT_OPCODE_REG_WRITE 7 -#define PUNIT_REG_PWRGT_CTRL 0x60 -#define PUNIT_REG_PWRGT_STATUS 0x61 -#define PUNIT_CLK_GATE 1 -#define PUNIT_PWR_RESET 2 -#define PUNIT_PWR_GATE 3 -#define RENDER_PWRGT (PUNIT_PWR_GATE << 0) -#define MEDIA_PWRGT (PUNIT_PWR_GATE << 2) -#define DISP2D_PWRGT (PUNIT_PWR_GATE << 6) - #define PUNIT_REG_GPU_LFM 0xd3 #define PUNIT_REG_GPU_FREQ_REQ 0xd4 #define PUNIT_REG_GPU_FREQ_STS 0xd8 @@ -396,40 +372,6 @@ #define FB_FMAX_VMIN_FREQ_LO_SHIFT 27 #define FB_FMAX_VMIN_FREQ_LO_MASK 0xf8000000 -/* vlv2 north clock has */ -#define CCK_FUSE_REG 0x8 -#define CCK_FUSE_HPLL_FREQ_MASK 0x3 -#define CCK_REG_DSI_PLL_FUSE 0x44 -#define CCK_REG_DSI_PLL_CONTROL 0x48 -#define DSI_PLL_VCO_EN (1 << 31) -#define DSI_PLL_LDO_GATE (1 << 30) -#define DSI_PLL_P1_POST_DIV_SHIFT 17 -#define DSI_PLL_P1_POST_DIV_MASK (0x1ff << 17) -#define DSI_PLL_P2_MUX_DSI0_DIV2 (1 << 13) -#define DSI_PLL_P3_MUX_DSI1_DIV2 (1 << 12) -#define DSI_PLL_MUX_MASK (3 << 9) -#define DSI_PLL_MUX_DSI0_DSIPLL (0 << 10) -#define DSI_PLL_MUX_DSI0_CCK (1 << 10) -#define DSI_PLL_MUX_DSI1_DSIPLL (0 << 9) -#define DSI_PLL_MUX_DSI1_CCK (1 << 9) -#define DSI_PLL_CLK_GATE_MASK (0xf << 5) -#define DSI_PLL_CLK_GATE_DSI0_DSIPLL (1 << 8) -#define DSI_PLL_CLK_GATE_DSI1_DSIPLL (1 << 7) -#define DSI_PLL_CLK_GATE_DSI0_CCK (1 << 6) -#define DSI_PLL_CLK_GATE_DSI1_CCK (1 << 5) -#define DSI_PLL_LOCK (1 << 0) -#define CCK_REG_DSI_PLL_DIVIDER 0x4c -#define DSI_PLL_LFSR (1 << 31) -#define DSI_PLL_FRACTION_EN (1 << 30) -#define DSI_PLL_FRAC_COUNTER_SHIFT 27 -#define DSI_PLL_FRAC_COUNTER_MASK (7 << 27) -#define DSI_PLL_USYNC_CNT_SHIFT 18 -#define DSI_PLL_USYNC_CNT_MASK (0x1ff << 18) -#define DSI_PLL_N1_DIV_SHIFT 16 -#define DSI_PLL_N1_DIV_MASK (3 << 16) -#define DSI_PLL_M1_DIV_SHIFT 0 -#define DSI_PLL_M1_DIV_MASK (0x1ff << 0) - /* * DPIO - a special bus for various display related registers to hide behind * @@ -445,11 +387,11 @@ #define DPIO_MODSEL1 (1<<3) /* if ref clk b == 27 */ #define DPIO_MODSEL0 (1<<2) /* if ref clk a == 27 */ #define DPIO_SFR_BYPASS (1<<1) -#define DPIO_CMNRST (1<<0) +#define DPIO_RESET (1<<0) #define _DPIO_TX3_SWING_CTL4_A 0x690 #define _DPIO_TX3_SWING_CTL4_B 0x2a90 -#define DPIO_TX3_SWING_CTL4(pipe) _PIPE(pipe, _DPIO_TX3_SWING_CTL4_A, \ +#define DPIO_TX3_SWING_CTL4(pipe) _PIPE(pipe, _DPIO_TX_SWING_CTL4_A, \ _DPIO_TX3_SWING_CTL4_B) /* @@ -660,9 +602,6 @@ #define ARB_MODE 0x04030 #define ARB_MODE_SWIZZLE_SNB (1<<4) #define ARB_MODE_SWIZZLE_IVB (1<<5) -#define GAMTARBMODE 0x04a08 -#define ARB_MODE_BWGTLB_DISABLE (1<<9) -#define ARB_MODE_SWIZZLE_BDW (1<<1) #define RENDER_HWS_PGA_GEN7 (0x04080) #define RING_FAULT_REG(ring) (0x4094 + 0x100*(ring)->id) #define RING_FAULT_GTTSEL_MASK (1<<11) @@ -670,7 +609,6 @@ #define RING_FAULT_FAULT_TYPE(x) ((x >> 1) & 0x3) #define RING_FAULT_VALID (1<<0) #define DONE_REG 0x40b0 -#define GEN8_PRIVATE_PAT 0x40e0 #define BSD_HWS_PGA_GEN7 (0x04180) #define BLT_HWS_PGA_GEN7 (0x04280) #define VEBOX_HWS_PGA_GEN7 (0x04380) @@ -731,18 +669,13 @@ #define NOPID 0x02094 #define HWSTAM 0x02098 #define DMA_FADD_I8XX 0x020d0 -#define RING_BBSTATE(base) ((base)+0x110) #define ERROR_GEN6 0x040a0 #define GEN7_ERR_INT 0x44040 #define ERR_INT_POISON (1<<31) #define ERR_INT_MMIO_UNCLAIMED (1<<13) -#define ERR_INT_PIPE_CRC_DONE_C (1<<8) #define ERR_INT_FIFO_UNDERRUN_C (1<<6) -#define ERR_INT_PIPE_CRC_DONE_B (1<<5) #define ERR_INT_FIFO_UNDERRUN_B (1<<3) -#define ERR_INT_PIPE_CRC_DONE_A (1<<2) -#define ERR_INT_PIPE_CRC_DONE(pipe) (1<<(2 + pipe*3)) #define ERR_INT_FIFO_UNDERRUN_A (1<<0) #define ERR_INT_FIFO_UNDERRUN(pipe) (1<<(pipe*3)) @@ -750,7 +683,6 @@ #define FPGA_DBG_RM_NOCLAIM (1<<31) #define DERRMR 0x44050 -/* Note that HBLANK events are reserved on bdw+ */ #define DERRMR_PIPEA_SCANLINE (1<<0) #define DERRMR_PIPEA_PRI_FLIP_DONE (1<<1) #define DERRMR_PIPEA_SPR_FLIP_DONE (1<<2) @@ -784,7 +716,6 @@ #define _3D_CHICKEN3 0x02090 #define _3D_CHICKEN_SF_DISABLE_OBJEND_CULL (1 << 10) #define _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL (1 << 5) -#define _3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(x) ((x)<<1) #define MI_MODE 0x0209c # define VS_TIMER_DISPATCH (1 << 6) @@ -959,7 +890,6 @@ #define GT_BLT_USER_INTERRUPT (1 << 22) #define GT_BSD_CS_ERROR_INTERRUPT (1 << 15) #define GT_BSD_USER_INTERRUPT (1 << 12) -#define GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 (1 << 11) /* hsw+; rsvd on snb, ivb, vlv */ #define GT_RENDER_L3_PARITY_ERROR_INTERRUPT (1 << 5) /* !snb */ #define GT_RENDER_PIPECTL_NOTIFY_INTERRUPT (1 << 4) #define GT_RENDER_CS_MASTER_ERROR_INTERRUPT (1 << 3) @@ -970,10 +900,6 @@ #define PM_VEBOX_CS_ERROR_INTERRUPT (1 << 12) /* hsw+ */ #define PM_VEBOX_USER_INTERRUPT (1 << 10) /* hsw+ */ -#define GT_PARITY_ERROR(dev) \ - (GT_RENDER_L3_PARITY_ERROR_INTERRUPT | \ - (IS_HASWELL(dev) ? GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 : 0)) - /* These are all the "old" interrupts */ #define ILK_BSD_USER_INTERRUPT (1<<5) #define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18) @@ -1122,6 +1048,9 @@ _HSW_PIPE_SLICE_CHICKEN_1_A, + \ _HSW_PIPE_SLICE_CHICKEN_1_B) +#define HSW_CLKGATE_DISABLE_PART_1 0x46500 +#define HSW_DPFC_GATING_DISABLE (1<<23) + /* * GPIO regs */ @@ -1458,12 +1387,6 @@ #define MI_ARB_VLV (VLV_DISPLAY_BASE + 0x6504) -#define CZCLK_CDCLK_FREQ_RATIO (VLV_DISPLAY_BASE + 0x6508) -#define CDCLK_FREQ_SHIFT 4 -#define CDCLK_FREQ_MASK (0x1f << CDCLK_FREQ_SHIFT) -#define CZCLK_FREQ_MASK 0xf -#define GMBUSFREQ_VLV (VLV_DISPLAY_BASE + 0x6510) - /* * Palette regs */ @@ -1481,15 +1404,13 @@ * device 0 function 0's pci config register 0x44 or 0x48 and matches it in * every way. It is not accessible from the CP register read instructions. * - * Starting from Haswell, you can't write registers using the MCHBAR mirror, - * just read. */ #define MCHBAR_MIRROR_BASE 0x10000 #define MCHBAR_MIRROR_BASE_SNB 0x140000 /* Memory controller frequency in MCHBAR for Haswell (possible SNB+) */ -#define DCLK (MCHBAR_MIRROR_BASE_SNB + 0x5e04) +#define DCLK 0x5e04 /** 915-945 and GM965 MCH register controlling DRAM channel access */ #define DCC 0x10200 @@ -1784,9 +1705,9 @@ #define GEN6_GT_THREAD_STATUS_CORE_MASK 0x7 #define GEN6_GT_THREAD_STATUS_CORE_MASK_HSW (0x7 | (0x07 << 16)) -#define GEN6_GT_PERF_STATUS (MCHBAR_MIRROR_BASE_SNB + 0x5948) -#define GEN6_RP_STATE_LIMITS (MCHBAR_MIRROR_BASE_SNB + 0x5994) -#define GEN6_RP_STATE_CAP (MCHBAR_MIRROR_BASE_SNB + 0x5998) +#define GEN6_GT_PERF_STATUS 0x145948 +#define GEN6_RP_STATE_LIMITS 0x145994 +#define GEN6_RP_STATE_CAP 0x145998 /* * Logical Context regs @@ -1831,12 +1752,6 @@ * on HSW) - so the final size is 66944 bytes, which rounds to 17 pages. */ #define HSW_CXT_TOTAL_SIZE (17 * PAGE_SIZE) -/* Same as Haswell, but 72064 bytes now. */ -#define GEN8_CXT_TOTAL_SIZE (18 * PAGE_SIZE) - - -#define VLV_CLK_CTL2 0x101104 -#define CLK_CTL2_CZCOUNT_30NS_SHIFT 28 /* * Overlay regs @@ -1856,83 +1771,6 @@ * Display engine regs */ -/* Pipe A CRC regs */ -#define _PIPE_CRC_CTL_A (dev_priv->info->display_mmio_offset + 0x60050) -#define PIPE_CRC_ENABLE (1 << 31) -/* ivb+ source selection */ -#define PIPE_CRC_SOURCE_PRIMARY_IVB (0 << 29) -#define PIPE_CRC_SOURCE_SPRITE_IVB (1 << 29) -#define PIPE_CRC_SOURCE_PF_IVB (2 << 29) -/* ilk+ source selection */ -#define PIPE_CRC_SOURCE_PRIMARY_ILK (0 << 28) -#define PIPE_CRC_SOURCE_SPRITE_ILK (1 << 28) -#define PIPE_CRC_SOURCE_PIPE_ILK (2 << 28) -/* embedded DP port on the north display block, reserved on ivb */ -#define PIPE_CRC_SOURCE_PORT_A_ILK (4 << 28) -#define PIPE_CRC_SOURCE_FDI_ILK (5 << 28) /* reserved on ivb */ -/* vlv source selection */ -#define PIPE_CRC_SOURCE_PIPE_VLV (0 << 27) -#define PIPE_CRC_SOURCE_HDMIB_VLV (1 << 27) -#define PIPE_CRC_SOURCE_HDMIC_VLV (2 << 27) -/* with DP port the pipe source is invalid */ -#define PIPE_CRC_SOURCE_DP_D_VLV (3 << 27) -#define PIPE_CRC_SOURCE_DP_B_VLV (6 << 27) -#define PIPE_CRC_SOURCE_DP_C_VLV (7 << 27) -/* gen3+ source selection */ -#define PIPE_CRC_SOURCE_PIPE_I9XX (0 << 28) -#define PIPE_CRC_SOURCE_SDVOB_I9XX (1 << 28) -#define PIPE_CRC_SOURCE_SDVOC_I9XX (2 << 28) -/* with DP/TV port the pipe source is invalid */ -#define PIPE_CRC_SOURCE_DP_D_G4X (3 << 28) -#define PIPE_CRC_SOURCE_TV_PRE (4 << 28) -#define PIPE_CRC_SOURCE_TV_POST (5 << 28) -#define PIPE_CRC_SOURCE_DP_B_G4X (6 << 28) -#define PIPE_CRC_SOURCE_DP_C_G4X (7 << 28) -/* gen2 doesn't have source selection bits */ -#define PIPE_CRC_INCLUDE_BORDER_I8XX (1 << 30) - -#define _PIPE_CRC_RES_1_A_IVB 0x60064 -#define _PIPE_CRC_RES_2_A_IVB 0x60068 -#define _PIPE_CRC_RES_3_A_IVB 0x6006c -#define _PIPE_CRC_RES_4_A_IVB 0x60070 -#define _PIPE_CRC_RES_5_A_IVB 0x60074 - -#define _PIPE_CRC_RES_RED_A (dev_priv->info->display_mmio_offset + 0x60060) -#define _PIPE_CRC_RES_GREEN_A (dev_priv->info->display_mmio_offset + 0x60064) -#define _PIPE_CRC_RES_BLUE_A (dev_priv->info->display_mmio_offset + 0x60068) -#define _PIPE_CRC_RES_RES1_A_I915 (dev_priv->info->display_mmio_offset + 0x6006c) -#define _PIPE_CRC_RES_RES2_A_G4X (dev_priv->info->display_mmio_offset + 0x60080) - -/* Pipe B CRC regs */ -#define _PIPE_CRC_RES_1_B_IVB 0x61064 -#define _PIPE_CRC_RES_2_B_IVB 0x61068 -#define _PIPE_CRC_RES_3_B_IVB 0x6106c -#define _PIPE_CRC_RES_4_B_IVB 0x61070 -#define _PIPE_CRC_RES_5_B_IVB 0x61074 - -#define PIPE_CRC_CTL(pipe) _PIPE_INC(pipe, _PIPE_CRC_CTL_A, 0x01000) -#define PIPE_CRC_RES_1_IVB(pipe) \ - _PIPE(pipe, _PIPE_CRC_RES_1_A_IVB, _PIPE_CRC_RES_1_B_IVB) -#define PIPE_CRC_RES_2_IVB(pipe) \ - _PIPE(pipe, _PIPE_CRC_RES_2_A_IVB, _PIPE_CRC_RES_2_B_IVB) -#define PIPE_CRC_RES_3_IVB(pipe) \ - _PIPE(pipe, _PIPE_CRC_RES_3_A_IVB, _PIPE_CRC_RES_3_B_IVB) -#define PIPE_CRC_RES_4_IVB(pipe) \ - _PIPE(pipe, _PIPE_CRC_RES_4_A_IVB, _PIPE_CRC_RES_4_B_IVB) -#define PIPE_CRC_RES_5_IVB(pipe) \ - _PIPE(pipe, _PIPE_CRC_RES_5_A_IVB, _PIPE_CRC_RES_5_B_IVB) - -#define PIPE_CRC_RES_RED(pipe) \ - _PIPE_INC(pipe, _PIPE_CRC_RES_RED_A, 0x01000) -#define PIPE_CRC_RES_GREEN(pipe) \ - _PIPE_INC(pipe, _PIPE_CRC_RES_GREEN_A, 0x01000) -#define PIPE_CRC_RES_BLUE(pipe) \ - _PIPE_INC(pipe, _PIPE_CRC_RES_BLUE_A, 0x01000) -#define PIPE_CRC_RES_RES1_I915(pipe) \ - _PIPE_INC(pipe, _PIPE_CRC_RES_RES1_A_I915, 0x01000) -#define PIPE_CRC_RES_RES2_G4X(pipe) \ - _PIPE_INC(pipe, _PIPE_CRC_RES_RES2_A_G4X, 0x01000) - /* Pipe A timing regs */ #define _HTOTAL_A (dev_priv->info->display_mmio_offset + 0x60000) #define _HBLANK_A (dev_priv->info->display_mmio_offset + 0x60004) @@ -1955,6 +1793,7 @@ #define _BCLRPAT_B (dev_priv->info->display_mmio_offset + 0x61020) #define _VSYNCSHIFT_B (dev_priv->info->display_mmio_offset + 0x61028) + #define HTOTAL(trans) _TRANSCODER(trans, _HTOTAL_A, _HTOTAL_B) #define HBLANK(trans) _TRANSCODER(trans, _HBLANK_A, _HBLANK_B) #define HSYNC(trans) _TRANSCODER(trans, _HSYNC_A, _HSYNC_B) @@ -1964,9 +1803,8 @@ #define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B) #define VSYNCSHIFT(trans) _TRANSCODER(trans, _VSYNCSHIFT_A, _VSYNCSHIFT_B) -/* HSW+ eDP PSR registers */ -#define EDP_PSR_BASE(dev) (IS_HASWELL(dev) ? 0x64800 : 0x6f800) -#define EDP_PSR_CTL(dev) (EDP_PSR_BASE(dev) + 0) +/* HSW eDP PSR registers */ +#define EDP_PSR_CTL 0x64800 #define EDP_PSR_ENABLE (1<<31) #define EDP_PSR_LINK_DISABLE (0<<27) #define EDP_PSR_LINK_STANDBY (1<<27) @@ -1989,16 +1827,16 @@ #define EDP_PSR_TP1_TIME_0us (3<<4) #define EDP_PSR_IDLE_FRAME_SHIFT 0 -#define EDP_PSR_AUX_CTL(dev) (EDP_PSR_BASE(dev) + 0x10) -#define EDP_PSR_AUX_DATA1(dev) (EDP_PSR_BASE(dev) + 0x14) +#define EDP_PSR_AUX_CTL 0x64810 +#define EDP_PSR_AUX_DATA1 0x64814 #define EDP_PSR_DPCD_COMMAND 0x80060000 -#define EDP_PSR_AUX_DATA2(dev) (EDP_PSR_BASE(dev) + 0x18) +#define EDP_PSR_AUX_DATA2 0x64818 #define EDP_PSR_DPCD_NORMAL_OPERATION (1<<24) -#define EDP_PSR_AUX_DATA3(dev) (EDP_PSR_BASE(dev) + 0x1c) -#define EDP_PSR_AUX_DATA4(dev) (EDP_PSR_BASE(dev) + 0x20) -#define EDP_PSR_AUX_DATA5(dev) (EDP_PSR_BASE(dev) + 0x24) +#define EDP_PSR_AUX_DATA3 0x6481c +#define EDP_PSR_AUX_DATA4 0x64820 +#define EDP_PSR_AUX_DATA5 0x64824 -#define EDP_PSR_STATUS_CTL(dev) (EDP_PSR_BASE(dev) + 0x40) +#define EDP_PSR_STATUS_CTL 0x64840 #define EDP_PSR_STATUS_STATE_MASK (7<<29) #define EDP_PSR_STATUS_STATE_IDLE (0<<29) #define EDP_PSR_STATUS_STATE_SRDONACK (1<<29) @@ -2022,10 +1860,10 @@ #define EDP_PSR_STATUS_SENDING_TP1 (1<<4) #define EDP_PSR_STATUS_IDLE_MASK 0xf -#define EDP_PSR_PERF_CNT(dev) (EDP_PSR_BASE(dev) + 0x44) +#define EDP_PSR_PERF_CNT 0x64844 #define EDP_PSR_PERF_CNT_MASK 0xffffff -#define EDP_PSR_DEBUG_CTL(dev) (EDP_PSR_BASE(dev) + 0x60) +#define EDP_PSR_DEBUG_CTL 0x64860 #define EDP_PSR_DEBUG_MASK_LPSP (1<<27) #define EDP_PSR_DEBUG_MASK_MEMUP (1<<26) #define EDP_PSR_DEBUG_MASK_HPD (1<<25) @@ -2168,14 +2006,6 @@ #define PCH_HDMIC 0xe1150 #define PCH_HDMID 0xe1160 -#define PORT_DFT_I9XX 0x61150 -#define DC_BALANCE_RESET (1 << 25) -#define PORT_DFT2_G4X 0x61154 -#define DC_BALANCE_RESET_VLV (1 << 31) -#define PIPE_SCRAMBLE_RESET_MASK (0x3 << 0) -#define PIPE_B_SCRAMBLE_RESET (1 << 1) -#define PIPE_A_SCRAMBLE_RESET (1 << 0) - /* Gen 3 SDVO bits: */ #define SDVO_ENABLE (1 << 31) #define SDVO_PIPE_SEL(pipe) ((pipe) << 30) @@ -2204,7 +2034,6 @@ /* Gen 4 SDVO/HDMI bits: */ #define SDVO_COLOR_FORMAT_8bpc (0 << 26) -#define SDVO_COLOR_FORMAT_MASK (7 << 26) #define SDVO_ENCODING_SDVO (0 << 10) #define SDVO_ENCODING_HDMI (2 << 10) #define HDMI_MODE_SELECT_HDMI (1 << 9) /* HDMI only */ @@ -2409,21 +2238,6 @@ #define PFIT_AUTO_RATIOS (dev_priv->info->display_mmio_offset + 0x61238) -#define _VLV_BLC_PWM_CTL2_A (dev_priv->info->display_mmio_offset + 0x61250) -#define _VLV_BLC_PWM_CTL2_B (dev_priv->info->display_mmio_offset + 0x61350) -#define VLV_BLC_PWM_CTL2(pipe) _PIPE(pipe, _VLV_BLC_PWM_CTL2_A, \ - _VLV_BLC_PWM_CTL2_B) - -#define _VLV_BLC_PWM_CTL_A (dev_priv->info->display_mmio_offset + 0x61254) -#define _VLV_BLC_PWM_CTL_B (dev_priv->info->display_mmio_offset + 0x61354) -#define VLV_BLC_PWM_CTL(pipe) _PIPE(pipe, _VLV_BLC_PWM_CTL_A, \ - _VLV_BLC_PWM_CTL_B) - -#define _VLV_BLC_HIST_CTL_A (dev_priv->info->display_mmio_offset + 0x61260) -#define _VLV_BLC_HIST_CTL_B (dev_priv->info->display_mmio_offset + 0x61360) -#define VLV_BLC_HIST_CTL(pipe) _PIPE(pipe, _VLV_BLC_HIST_CTL_A, \ - _VLV_BLC_HIST_CTL_B) - /* Backlight control */ #define BLC_PWM_CTL2 (dev_priv->info->display_mmio_offset + 0x61250) /* 965+ only */ #define BLM_PWM_ENABLE (1 << 31) @@ -3172,7 +2986,6 @@ #define PIPECONF_DISABLE 0 #define PIPECONF_DOUBLE_WIDE (1<<30) #define I965_PIPECONF_ACTIVE (1<<30) -#define PIPECONF_DSI_PLL_LOCKED (1<<29) /* vlv & pipe A only */ #define PIPECONF_FRAME_START_DELAY_MASK (3<<27) #define PIPECONF_SINGLE_WIDE 0 #define PIPECONF_PIPE_UNLOCKED 0 @@ -3255,18 +3068,6 @@ #define PIPEFRAMEPIXEL(pipe) _PIPE(pipe, _PIPEAFRAMEPIXEL, _PIPEBFRAMEPIXEL) #define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT) -#define _PIPE_MISC_A 0x70030 -#define _PIPE_MISC_B 0x71030 -#define PIPEMISC_DITHER_BPC_MASK (7<<5) -#define PIPEMISC_DITHER_8_BPC (0<<5) -#define PIPEMISC_DITHER_10_BPC (1<<5) -#define PIPEMISC_DITHER_6_BPC (2<<5) -#define PIPEMISC_DITHER_12_BPC (3<<5) -#define PIPEMISC_DITHER_ENABLE (1<<4) -#define PIPEMISC_DITHER_TYPE_MASK (3<<2) -#define PIPEMISC_DITHER_TYPE_SP (0<<2) -#define PIPEMISC(pipe) _PIPE(pipe, _PIPE_MISC_A, _PIPE_MISC_B) - #define VLV_DPFLIPSTAT (VLV_DISPLAY_BASE + 0x70028) #define PIPEB_LINE_COMPARE_INT_EN (1<<29) #define PIPEB_HLINE_INT_EN (1<<28) @@ -3383,11 +3184,11 @@ /* define the Watermark register on Ironlake */ #define WM0_PIPEA_ILK 0x45100 -#define WM0_PIPE_PLANE_MASK (0xffff<<16) +#define WM0_PIPE_PLANE_MASK (0x7f<<16) #define WM0_PIPE_PLANE_SHIFT 16 -#define WM0_PIPE_SPRITE_MASK (0xff<<8) +#define WM0_PIPE_SPRITE_MASK (0x3f<<8) #define WM0_PIPE_SPRITE_SHIFT 8 -#define WM0_PIPE_CURSOR_MASK (0xff) +#define WM0_PIPE_CURSOR_MASK (0x1f) #define WM0_PIPEB_ILK 0x45104 #define WM0_PIPEC_IVB 0x45200 @@ -3397,10 +3198,9 @@ #define WM1_LP_LATENCY_MASK (0x7f<<24) #define WM1_LP_FBC_MASK (0xf<<20) #define WM1_LP_FBC_SHIFT 20 -#define WM1_LP_FBC_SHIFT_BDW 19 -#define WM1_LP_SR_MASK (0x7ff<<8) +#define WM1_LP_SR_MASK (0x1ff<<8) #define WM1_LP_SR_SHIFT 8 -#define WM1_LP_CURSOR_MASK (0xff) +#define WM1_LP_CURSOR_MASK (0x3f) #define WM2_LP_ILK 0x4510c #define WM2_LP_EN (1<<31) #define WM3_LP_ILK 0x45110 @@ -3481,17 +3281,17 @@ * } while (high1 != high2); * frame = (high1 << 8) | low1; */ -#define _PIPEAFRAMEHIGH 0x70040 +#define _PIPEAFRAMEHIGH (dev_priv->info->display_mmio_offset + 0x70040) #define PIPE_FRAME_HIGH_MASK 0x0000ffff #define PIPE_FRAME_HIGH_SHIFT 0 -#define _PIPEAFRAMEPIXEL 0x70044 +#define _PIPEAFRAMEPIXEL (dev_priv->info->display_mmio_offset + 0x70044) #define PIPE_FRAME_LOW_MASK 0xff000000 #define PIPE_FRAME_LOW_SHIFT 24 #define PIPE_PIXEL_MASK 0x00ffffff #define PIPE_PIXEL_SHIFT 0 /* GM45+ just has to be different */ -#define _PIPEA_FRMCOUNT_GM45 (dev_priv->info->display_mmio_offset + 0x70040) -#define _PIPEA_FLIPCOUNT_GM45 (dev_priv->info->display_mmio_offset + 0x70044) +#define _PIPEA_FRMCOUNT_GM45 0x70040 +#define _PIPEA_FLIPCOUNT_GM45 0x70044 #define PIPE_FRMCOUNT_GM45(pipe) _PIPE(pipe, _PIPEA_FRMCOUNT_GM45, _PIPEB_FRMCOUNT_GM45) /* Cursor A & B regs */ @@ -3622,10 +3422,10 @@ #define _PIPEBDSL (dev_priv->info->display_mmio_offset + 0x71000) #define _PIPEBCONF (dev_priv->info->display_mmio_offset + 0x71008) #define _PIPEBSTAT (dev_priv->info->display_mmio_offset + 0x71024) -#define _PIPEBFRAMEHIGH 0x71040 -#define _PIPEBFRAMEPIXEL 0x71044 -#define _PIPEB_FRMCOUNT_GM45 (dev_priv->info->display_mmio_offset + 0x71040) -#define _PIPEB_FLIPCOUNT_GM45 (dev_priv->info->display_mmio_offset + 0x71044) +#define _PIPEBFRAMEHIGH (dev_priv->info->display_mmio_offset + 0x71040) +#define _PIPEBFRAMEPIXEL (dev_priv->info->display_mmio_offset + 0x71044) +#define _PIPEB_FRMCOUNT_GM45 0x71040 +#define _PIPEB_FLIPCOUNT_GM45 0x71044 /* Display B control */ @@ -3980,7 +3780,6 @@ #define DE_SPRITEA_FLIP_DONE (1 << 28) #define DE_PLANEB_FLIP_DONE (1 << 27) #define DE_PLANEA_FLIP_DONE (1 << 26) -#define DE_PLANE_FLIP_DONE(plane) (1 << (26 + (plane))) #define DE_PCU_EVENT (1 << 25) #define DE_GTT_FAULT (1 << 24) #define DE_POISON (1 << 23) @@ -3994,18 +3793,13 @@ #define DE_PIPEB_ODD_FIELD (1 << 13) #define DE_PIPEB_LINE_COMPARE (1 << 12) #define DE_PIPEB_VSYNC (1 << 11) -#define DE_PIPEB_CRC_DONE (1 << 10) #define DE_PIPEB_FIFO_UNDERRUN (1 << 8) #define DE_PIPEA_VBLANK (1 << 7) -#define DE_PIPE_VBLANK(pipe) (1 << (7 + 8*(pipe))) #define DE_PIPEA_EVEN_FIELD (1 << 6) #define DE_PIPEA_ODD_FIELD (1 << 5) #define DE_PIPEA_LINE_COMPARE (1 << 4) #define DE_PIPEA_VSYNC (1 << 3) -#define DE_PIPEA_CRC_DONE (1 << 2) -#define DE_PIPE_CRC_DONE(pipe) (1 << (2 + 8*(pipe))) #define DE_PIPEA_FIFO_UNDERRUN (1 << 0) -#define DE_PIPE_FIFO_UNDERRUN(pipe) (1 << (8*(pipe))) /* More Ivybridge lolz */ #define DE_ERR_INT_IVB (1<<30) @@ -4021,8 +3815,9 @@ #define DE_PIPEB_VBLANK_IVB (1<<5) #define DE_SPRITEA_FLIP_DONE_IVB (1<<4) #define DE_PLANEA_FLIP_DONE_IVB (1<<3) -#define DE_PLANE_FLIP_DONE_IVB(plane) (1<< (3 + 5*(plane))) #define DE_PIPEA_VBLANK_IVB (1<<0) + +#define DE_PIPE_VBLANK_ILK(pipe) (1 << ((pipe * 8) + 7)) #define DE_PIPE_VBLANK_IVB(pipe) (1 << (pipe * 5)) #define VLV_MASTER_IER 0x4400c /* Gunit master IER */ @@ -4038,71 +3833,6 @@ #define GTIIR 0x44018 #define GTIER 0x4401c -#define GEN8_MASTER_IRQ 0x44200 -#define GEN8_MASTER_IRQ_CONTROL (1<<31) -#define GEN8_PCU_IRQ (1<<30) -#define GEN8_DE_PCH_IRQ (1<<23) -#define GEN8_DE_MISC_IRQ (1<<22) -#define GEN8_DE_PORT_IRQ (1<<20) -#define GEN8_DE_PIPE_C_IRQ (1<<18) -#define GEN8_DE_PIPE_B_IRQ (1<<17) -#define GEN8_DE_PIPE_A_IRQ (1<<16) -#define GEN8_DE_PIPE_IRQ(pipe) (1<<(16+pipe)) -#define GEN8_GT_VECS_IRQ (1<<6) -#define GEN8_GT_VCS2_IRQ (1<<3) -#define GEN8_GT_VCS1_IRQ (1<<2) -#define GEN8_GT_BCS_IRQ (1<<1) -#define GEN8_GT_RCS_IRQ (1<<0) - -#define GEN8_GT_ISR(which) (0x44300 + (0x10 * (which))) -#define GEN8_GT_IMR(which) (0x44304 + (0x10 * (which))) -#define GEN8_GT_IIR(which) (0x44308 + (0x10 * (which))) -#define GEN8_GT_IER(which) (0x4430c + (0x10 * (which))) - -#define GEN8_BCS_IRQ_SHIFT 16 -#define GEN8_RCS_IRQ_SHIFT 0 -#define GEN8_VCS2_IRQ_SHIFT 16 -#define GEN8_VCS1_IRQ_SHIFT 0 -#define GEN8_VECS_IRQ_SHIFT 0 - -#define GEN8_DE_PIPE_ISR(pipe) (0x44400 + (0x10 * (pipe))) -#define GEN8_DE_PIPE_IMR(pipe) (0x44404 + (0x10 * (pipe))) -#define GEN8_DE_PIPE_IIR(pipe) (0x44408 + (0x10 * (pipe))) -#define GEN8_DE_PIPE_IER(pipe) (0x4440c + (0x10 * (pipe))) -#define GEN8_PIPE_FIFO_UNDERRUN (1 << 31) -#define GEN8_PIPE_CDCLK_CRC_ERROR (1 << 29) -#define GEN8_PIPE_CDCLK_CRC_DONE (1 << 28) -#define GEN8_PIPE_CURSOR_FAULT (1 << 10) -#define GEN8_PIPE_SPRITE_FAULT (1 << 9) -#define GEN8_PIPE_PRIMARY_FAULT (1 << 8) -#define GEN8_PIPE_SPRITE_FLIP_DONE (1 << 5) -#define GEN8_PIPE_FLIP_DONE (1 << 4) -#define GEN8_PIPE_SCAN_LINE_EVENT (1 << 2) -#define GEN8_PIPE_VSYNC (1 << 1) -#define GEN8_PIPE_VBLANK (1 << 0) -#define GEN8_DE_PIPE_IRQ_FAULT_ERRORS \ - (GEN8_PIPE_CURSOR_FAULT | \ - GEN8_PIPE_SPRITE_FAULT | \ - GEN8_PIPE_PRIMARY_FAULT) - -#define GEN8_DE_PORT_ISR 0x44440 -#define GEN8_DE_PORT_IMR 0x44444 -#define GEN8_DE_PORT_IIR 0x44448 -#define GEN8_DE_PORT_IER 0x4444c -#define GEN8_PORT_DP_A_HOTPLUG (1 << 3) -#define GEN8_AUX_CHANNEL_A (1 << 0) - -#define GEN8_DE_MISC_ISR 0x44460 -#define GEN8_DE_MISC_IMR 0x44464 -#define GEN8_DE_MISC_IIR 0x44468 -#define GEN8_DE_MISC_IER 0x4446c -#define GEN8_DE_MISC_GSE (1 << 27) - -#define GEN8_PCU_ISR 0x444e0 -#define GEN8_PCU_IMR 0x444e4 -#define GEN8_PCU_IIR 0x444e8 -#define GEN8_PCU_IER 0x444ec - #define ILK_DISPLAY_CHICKEN2 0x42004 /* Required on all Ironlake and Sandybridge according to the B-Spec. */ #define ILK_ELPIN_409_SELECT (1 << 25) @@ -4128,14 +3858,8 @@ # define CHICKEN3_DGMG_DONE_FIX_DISABLE (1 << 2) #define CHICKEN_PAR1_1 0x42080 -#define DPA_MASK_VBLANK_SRD (1 << 15) #define FORCE_ARB_IDLE_PLANES (1 << 14) -#define _CHICKEN_PIPESL_1_A 0x420b0 -#define _CHICKEN_PIPESL_1_B 0x420b4 -#define DPRS_MASK_VBLANK_SRD (1 << 0) -#define CHICKEN_PIPESL_1(pipe) _PIPE(pipe, _CHICKEN_PIPESL_1_A, _CHICKEN_PIPESL_1_B) - #define DISP_ARB_CTL 0x45000 #define DISP_TILE_SURFACE_SWIZZLING (1<<13) #define DISP_FBC_WM_DIS (1<<15) @@ -4146,8 +3870,6 @@ /* GEN7 chicken */ #define GEN7_COMMON_SLICE_CHICKEN1 0x7010 # define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC ((1<<10) | (1<<26)) -#define COMMON_SLICE_CHICKEN2 0x7014 -# define GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE (1<<0) #define GEN7_L3CNTLREG1 0xB01C #define GEN7_WA_FOR_GEN7_L3_CONTROL 0x3C4FFF8C @@ -4694,8 +4416,6 @@ #define PIPEA_PP_STATUS (VLV_DISPLAY_BASE + 0x61200) #define PIPEA_PP_CONTROL (VLV_DISPLAY_BASE + 0x61204) #define PIPEA_PP_ON_DELAYS (VLV_DISPLAY_BASE + 0x61208) -#define PANEL_PORT_SELECT_DPB_VLV (1 << 30) -#define PANEL_PORT_SELECT_DPC_VLV (2 << 30) #define PIPEA_PP_OFF_DELAYS (VLV_DISPLAY_BASE + 0x6120c) #define PIPEA_PP_DIVISOR (VLV_DISPLAY_BASE + 0x61210) @@ -4727,6 +4447,7 @@ #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) @@ -4735,6 +4456,11 @@ #define PANEL_LIGHT_ON_DELAY_SHIFT 0 #define PCH_PP_OFF_DELAYS 0xc720c +#define PANEL_POWER_PORT_SELECT_MASK (0x3 << 30) +#define PANEL_POWER_PORT_LVDS (0 << 30) +#define PANEL_POWER_PORT_DP_A (1 << 30) +#define PANEL_POWER_PORT_DP_C (2 << 30) +#define PANEL_POWER_PORT_DP_D (3 << 30) #define PANEL_POWER_DOWN_DELAY_MASK (0x1fff0000) #define PANEL_POWER_DOWN_DELAY_SHIFT 16 #define PANEL_LIGHT_OFF_DELAY_MASK (0x1fff) @@ -4912,7 +4638,7 @@ #define GEN6_RP_UP_IDLE_MIN (0x1<<3) #define GEN6_RP_UP_BUSY_AVG (0x2<<3) #define GEN6_RP_UP_BUSY_CONT (0x4<<3) -#define GEN6_RP_DOWN_IDLE_AVG (0x2<<0) +#define GEN7_RP_DOWN_IDLE_AVG (0x2<<0) #define GEN6_RP_DOWN_IDLE_CONT (0x1<<0) #define GEN6_RP_UP_THRESHOLD 0xA02C #define GEN6_RP_DOWN_THRESHOLD 0xA030 @@ -4957,10 +4683,6 @@ GEN6_PM_RP_DOWN_TIMEOUT) #define GEN6_GT_GFX_RC6_LOCKED 0x138104 -#define VLV_COUNTER_CONTROL 0x138104 -#define VLV_COUNT_RANGE_HIGH (1<<15) -#define VLV_MEDIA_RC6_COUNT_EN (1<<1) -#define VLV_RENDER_RC6_COUNT_EN (1<<0) #define GEN6_GT_GFX_RC6 0x138108 #define GEN6_GT_GFX_RC6p 0x13810C #define GEN6_GT_GFX_RC6pp 0x138110 @@ -4972,11 +4694,8 @@ #define GEN6_PCODE_READ_MIN_FREQ_TABLE 0x9 #define GEN6_PCODE_WRITE_RC6VIDS 0x4 #define GEN6_PCODE_READ_RC6VIDS 0x5 -#define GEN6_PCODE_READ_D_COMP 0x10 -#define GEN6_PCODE_WRITE_D_COMP 0x11 #define GEN6_ENCODE_RC6_VID(mv) (((mv) - 245) / 5) #define GEN6_DECODE_RC6_VID(vids) (((vids) * 5) + 245) -#define DISPLAY_IPS_CONTROL 0x19 #define GEN6_PCODE_DATA 0x138128 #define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8 #define GEN6_PCODE_FREQ_RING_RATIO_SHIFT 16 @@ -4994,7 +4713,6 @@ /* IVYBRIDGE DPF */ #define GEN7_L3CDERRST1 0xB008 /* L3CD Error Status 1 */ -#define HSW_L3CDERRST11 0xB208 /* L3CD Error Status register 1 slice 1 */ #define GEN7_L3CDERRST1_ROW_MASK (0x7ff<<14) #define GEN7_PARITY_ERROR_VALID (1<<13) #define GEN7_L3CDERRST1_BANK_MASK (3<<11) @@ -5008,13 +4726,11 @@ #define GEN7_L3CDERRST1_ENABLE (1<<7) #define GEN7_L3LOG_BASE 0xB070 -#define HSW_L3LOG_BASE_SLICE1 0xB270 #define GEN7_L3LOG_SIZE 0x80 #define GEN7_HALF_SLICE_CHICKEN1 0xe100 /* IVB GT1 + VLV */ #define GEN7_HALF_SLICE_CHICKEN1_GT2 0xf100 #define GEN7_MAX_PS_THREAD_DEP (8<<12) -#define GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE (1<<10) #define GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE (1<<3) #define GEN7_ROW_CHICKEN2 0xe4f4 @@ -5024,10 +4740,6 @@ #define HSW_ROW_CHICKEN3 0xe49c #define HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE (1 << 6) -#define HALF_SLICE_CHICKEN3 0xe184 -#define GEN8_CENTROID_PIXEL_OPT_DIS (1<<8) -#define GEN8_SAMPLER_POWER_BYPASS_DIS (1<<1) - #define G4X_AUD_VID_DID (dev_priv->info->display_mmio_offset + 0x62020) #define INTEL_AUDIO_DEVCL 0x808629FB #define INTEL_AUDIO_DEVBLC 0x80862801 @@ -5069,18 +4781,6 @@ CPT_AUD_CNTL_ST_B) #define CPT_AUD_CNTRL_ST2 0xE50C0 -#define VLV_HDMIW_HDMIEDID_A (VLV_DISPLAY_BASE + 0x62050) -#define VLV_HDMIW_HDMIEDID_B (VLV_DISPLAY_BASE + 0x62150) -#define VLV_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \ - VLV_HDMIW_HDMIEDID_A, \ - VLV_HDMIW_HDMIEDID_B) -#define VLV_AUD_CNTL_ST_A (VLV_DISPLAY_BASE + 0x620B4) -#define VLV_AUD_CNTL_ST_B (VLV_DISPLAY_BASE + 0x621B4) -#define VLV_AUD_CNTL_ST(pipe) _PIPE(pipe, \ - VLV_AUD_CNTL_ST_A, \ - VLV_AUD_CNTL_ST_B) -#define VLV_AUD_CNTL_ST2 (VLV_DISPLAY_BASE + 0x620C0) - /* These are the 4 32-bit write offset registers for each stream * output buffer. It determines the offset from the * 3DSTATE_SO_BUFFERs that the next streamed vertex output goes to. @@ -5097,12 +4797,6 @@ #define CPT_AUD_CFG(pipe) _PIPE(pipe, \ CPT_AUD_CONFIG_A, \ CPT_AUD_CONFIG_B) -#define VLV_AUD_CONFIG_A (VLV_DISPLAY_BASE + 0x62000) -#define VLV_AUD_CONFIG_B (VLV_DISPLAY_BASE + 0x62100) -#define VLV_AUD_CFG(pipe) _PIPE(pipe, \ - VLV_AUD_CONFIG_A, \ - VLV_AUD_CONFIG_B) - #define AUD_CONFIG_N_VALUE_INDEX (1 << 29) #define AUD_CONFIG_N_PROG_ENABLE (1 << 28) #define AUD_CONFIG_UPPER_N_SHIFT 20 @@ -5110,17 +4804,7 @@ #define AUD_CONFIG_LOWER_N_SHIFT 4 #define AUD_CONFIG_LOWER_N_VALUE (0xfff << 4) #define AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT 16 -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK (0xf << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 (0 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 (1 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 (2 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 (3 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 (4 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 (5 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 (6 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 (7 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 (8 << 16) -#define AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 (9 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI (0xf << 16) #define AUD_CONFIG_DISABLE_NCTS (1 << 3) /* HSW Audio */ @@ -5245,7 +4929,6 @@ #define DDI_BUF_CTL_B 0x64100 #define DDI_BUF_CTL(port) _PORT(port, DDI_BUF_CTL_A, DDI_BUF_CTL_B) #define DDI_BUF_CTL_ENABLE (1<<31) -/* Haswell */ #define DDI_BUF_EMP_400MV_0DB_HSW (0<<24) /* Sel0 */ #define DDI_BUF_EMP_400MV_3_5DB_HSW (1<<24) /* Sel1 */ #define DDI_BUF_EMP_400MV_6DB_HSW (2<<24) /* Sel2 */ @@ -5255,16 +4938,6 @@ #define DDI_BUF_EMP_600MV_6DB_HSW (6<<24) /* Sel6 */ #define DDI_BUF_EMP_800MV_0DB_HSW (7<<24) /* Sel7 */ #define DDI_BUF_EMP_800MV_3_5DB_HSW (8<<24) /* Sel8 */ -/* Broadwell */ -#define DDI_BUF_EMP_400MV_0DB_BDW (0<<24) /* Sel0 */ -#define DDI_BUF_EMP_400MV_3_5DB_BDW (1<<24) /* Sel1 */ -#define DDI_BUF_EMP_400MV_6DB_BDW (2<<24) /* Sel2 */ -#define DDI_BUF_EMP_600MV_0DB_BDW (3<<24) /* Sel3 */ -#define DDI_BUF_EMP_600MV_3_5DB_BDW (4<<24) /* Sel4 */ -#define DDI_BUF_EMP_600MV_6DB_BDW (5<<24) /* Sel5 */ -#define DDI_BUF_EMP_800MV_0DB_BDW (6<<24) /* Sel6 */ -#define DDI_BUF_EMP_800MV_3_5DB_BDW (7<<24) /* Sel7 */ -#define DDI_BUF_EMP_1200MV_0DB_BDW (8<<24) /* Sel8 */ #define DDI_BUF_EMP_MASK (0xf<<24) #define DDI_BUF_PORT_REVERSAL (1<<16) #define DDI_BUF_IS_IDLE (1<<7) @@ -5374,9 +5047,6 @@ #define LCPLL_PLL_LOCK (1<<30) #define LCPLL_CLK_FREQ_MASK (3<<26) #define LCPLL_CLK_FREQ_450 (0<<26) -#define LCPLL_CLK_FREQ_54O_BDW (1<<26) -#define LCPLL_CLK_FREQ_337_5_BDW (2<<26) -#define LCPLL_CLK_FREQ_675_BDW (3<<26) #define LCPLL_CD_CLOCK_DISABLE (1<<25) #define LCPLL_CD2X_CLOCK_DISABLE (1<<23) #define LCPLL_POWER_DOWN_ALLOW (1<<22) @@ -5458,414 +5128,4 @@ #define PIPE_CSC_POSTOFF_ME(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, _PIPE_B_CSC_POSTOFF_ME) #define PIPE_CSC_POSTOFF_LO(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, _PIPE_B_CSC_POSTOFF_LO) -/* VLV MIPI registers */ - -#define _MIPIA_PORT_CTRL (VLV_DISPLAY_BASE + 0x61190) -#define _MIPIB_PORT_CTRL (VLV_DISPLAY_BASE + 0x61700) -#define MIPI_PORT_CTRL(pipe) _PIPE(pipe, _MIPIA_PORT_CTRL, _MIPIB_PORT_CTRL) -#define DPI_ENABLE (1 << 31) /* A + B */ -#define MIPIA_MIPI4DPHY_DELAY_COUNT_SHIFT 27 -#define MIPIA_MIPI4DPHY_DELAY_COUNT_MASK (0xf << 27) -#define DUAL_LINK_MODE_MASK (1 << 26) -#define DUAL_LINK_MODE_FRONT_BACK (0 << 26) -#define DUAL_LINK_MODE_PIXEL_ALTERNATIVE (1 << 26) -#define DITHERING_ENABLE (1 << 25) /* A + B */ -#define FLOPPED_HSTX (1 << 23) -#define DE_INVERT (1 << 19) /* XXX */ -#define MIPIA_FLISDSI_DELAY_COUNT_SHIFT 18 -#define MIPIA_FLISDSI_DELAY_COUNT_MASK (0xf << 18) -#define AFE_LATCHOUT (1 << 17) -#define LP_OUTPUT_HOLD (1 << 16) -#define MIPIB_FLISDSI_DELAY_COUNT_HIGH_SHIFT 15 -#define MIPIB_FLISDSI_DELAY_COUNT_HIGH_MASK (1 << 15) -#define MIPIB_MIPI4DPHY_DELAY_COUNT_SHIFT 11 -#define MIPIB_MIPI4DPHY_DELAY_COUNT_MASK (0xf << 11) -#define CSB_SHIFT 9 -#define CSB_MASK (3 << 9) -#define CSB_20MHZ (0 << 9) -#define CSB_10MHZ (1 << 9) -#define CSB_40MHZ (2 << 9) -#define BANDGAP_MASK (1 << 8) -#define BANDGAP_PNW_CIRCUIT (0 << 8) -#define BANDGAP_LNC_CIRCUIT (1 << 8) -#define MIPIB_FLISDSI_DELAY_COUNT_LOW_SHIFT 5 -#define MIPIB_FLISDSI_DELAY_COUNT_LOW_MASK (7 << 5) -#define TEARING_EFFECT_DELAY (1 << 4) /* A + B */ -#define TEARING_EFFECT_SHIFT 2 /* A + B */ -#define TEARING_EFFECT_MASK (3 << 2) -#define TEARING_EFFECT_OFF (0 << 2) -#define TEARING_EFFECT_DSI (1 << 2) -#define TEARING_EFFECT_GPIO (2 << 2) -#define LANE_CONFIGURATION_SHIFT 0 -#define LANE_CONFIGURATION_MASK (3 << 0) -#define LANE_CONFIGURATION_4LANE (0 << 0) -#define LANE_CONFIGURATION_DUAL_LINK_A (1 << 0) -#define LANE_CONFIGURATION_DUAL_LINK_B (2 << 0) - -#define _MIPIA_TEARING_CTRL (VLV_DISPLAY_BASE + 0x61194) -#define _MIPIB_TEARING_CTRL (VLV_DISPLAY_BASE + 0x61704) -#define MIPI_TEARING_CTRL(pipe) _PIPE(pipe, _MIPIA_TEARING_CTRL, _MIPIB_TEARING_CTRL) -#define TEARING_EFFECT_DELAY_SHIFT 0 -#define TEARING_EFFECT_DELAY_MASK (0xffff << 0) - -/* XXX: all bits reserved */ -#define _MIPIA_AUTOPWG (VLV_DISPLAY_BASE + 0x611a0) - -/* MIPI DSI Controller and D-PHY registers */ - -#define _MIPIA_DEVICE_READY (VLV_DISPLAY_BASE + 0xb000) -#define _MIPIB_DEVICE_READY (VLV_DISPLAY_BASE + 0xb800) -#define MIPI_DEVICE_READY(pipe) _PIPE(pipe, _MIPIA_DEVICE_READY, _MIPIB_DEVICE_READY) -#define BUS_POSSESSION (1 << 3) /* set to give bus to receiver */ -#define ULPS_STATE_MASK (3 << 1) -#define ULPS_STATE_ENTER (2 << 1) -#define ULPS_STATE_EXIT (1 << 1) -#define ULPS_STATE_NORMAL_OPERATION (0 << 1) -#define DEVICE_READY (1 << 0) - -#define _MIPIA_INTR_STAT (VLV_DISPLAY_BASE + 0xb004) -#define _MIPIB_INTR_STAT (VLV_DISPLAY_BASE + 0xb804) -#define MIPI_INTR_STAT(pipe) _PIPE(pipe, _MIPIA_INTR_STAT, _MIPIB_INTR_STAT) -#define _MIPIA_INTR_EN (VLV_DISPLAY_BASE + 0xb008) -#define _MIPIB_INTR_EN (VLV_DISPLAY_BASE + 0xb808) -#define MIPI_INTR_EN(pipe) _PIPE(pipe, _MIPIA_INTR_EN, _MIPIB_INTR_EN) -#define TEARING_EFFECT (1 << 31) -#define SPL_PKT_SENT_INTERRUPT (1 << 30) -#define GEN_READ_DATA_AVAIL (1 << 29) -#define LP_GENERIC_WR_FIFO_FULL (1 << 28) -#define HS_GENERIC_WR_FIFO_FULL (1 << 27) -#define RX_PROT_VIOLATION (1 << 26) -#define RX_INVALID_TX_LENGTH (1 << 25) -#define ACK_WITH_NO_ERROR (1 << 24) -#define TURN_AROUND_ACK_TIMEOUT (1 << 23) -#define LP_RX_TIMEOUT (1 << 22) -#define HS_TX_TIMEOUT (1 << 21) -#define DPI_FIFO_UNDERRUN (1 << 20) -#define LOW_CONTENTION (1 << 19) -#define HIGH_CONTENTION (1 << 18) -#define TXDSI_VC_ID_INVALID (1 << 17) -#define TXDSI_DATA_TYPE_NOT_RECOGNISED (1 << 16) -#define TXCHECKSUM_ERROR (1 << 15) -#define TXECC_MULTIBIT_ERROR (1 << 14) -#define TXECC_SINGLE_BIT_ERROR (1 << 13) -#define TXFALSE_CONTROL_ERROR (1 << 12) -#define RXDSI_VC_ID_INVALID (1 << 11) -#define RXDSI_DATA_TYPE_NOT_REGOGNISED (1 << 10) -#define RXCHECKSUM_ERROR (1 << 9) -#define RXECC_MULTIBIT_ERROR (1 << 8) -#define RXECC_SINGLE_BIT_ERROR (1 << 7) -#define RXFALSE_CONTROL_ERROR (1 << 6) -#define RXHS_RECEIVE_TIMEOUT_ERROR (1 << 5) -#define RX_LP_TX_SYNC_ERROR (1 << 4) -#define RXEXCAPE_MODE_ENTRY_ERROR (1 << 3) -#define RXEOT_SYNC_ERROR (1 << 2) -#define RXSOT_SYNC_ERROR (1 << 1) -#define RXSOT_ERROR (1 << 0) - -#define _MIPIA_DSI_FUNC_PRG (VLV_DISPLAY_BASE + 0xb00c) -#define _MIPIB_DSI_FUNC_PRG (VLV_DISPLAY_BASE + 0xb80c) -#define MIPI_DSI_FUNC_PRG(pipe) _PIPE(pipe, _MIPIA_DSI_FUNC_PRG, _MIPIB_DSI_FUNC_PRG) -#define CMD_MODE_DATA_WIDTH_MASK (7 << 13) -#define CMD_MODE_NOT_SUPPORTED (0 << 13) -#define CMD_MODE_DATA_WIDTH_16_BIT (1 << 13) -#define CMD_MODE_DATA_WIDTH_9_BIT (2 << 13) -#define CMD_MODE_DATA_WIDTH_8_BIT (3 << 13) -#define CMD_MODE_DATA_WIDTH_OPTION1 (4 << 13) -#define CMD_MODE_DATA_WIDTH_OPTION2 (5 << 13) -#define VID_MODE_FORMAT_MASK (0xf << 7) -#define VID_MODE_NOT_SUPPORTED (0 << 7) -#define VID_MODE_FORMAT_RGB565 (1 << 7) -#define VID_MODE_FORMAT_RGB666 (2 << 7) -#define VID_MODE_FORMAT_RGB666_LOOSE (3 << 7) -#define VID_MODE_FORMAT_RGB888 (4 << 7) -#define CMD_MODE_CHANNEL_NUMBER_SHIFT 5 -#define CMD_MODE_CHANNEL_NUMBER_MASK (3 << 5) -#define VID_MODE_CHANNEL_NUMBER_SHIFT 3 -#define VID_MODE_CHANNEL_NUMBER_MASK (3 << 3) -#define DATA_LANES_PRG_REG_SHIFT 0 -#define DATA_LANES_PRG_REG_MASK (7 << 0) - -#define _MIPIA_HS_TX_TIMEOUT (VLV_DISPLAY_BASE + 0xb010) -#define _MIPIB_HS_TX_TIMEOUT (VLV_DISPLAY_BASE + 0xb810) -#define MIPI_HS_TX_TIMEOUT(pipe) _PIPE(pipe, _MIPIA_HS_TX_TIMEOUT, _MIPIB_HS_TX_TIMEOUT) -#define HIGH_SPEED_TX_TIMEOUT_COUNTER_MASK 0xffffff - -#define _MIPIA_LP_RX_TIMEOUT (VLV_DISPLAY_BASE + 0xb014) -#define _MIPIB_LP_RX_TIMEOUT (VLV_DISPLAY_BASE + 0xb814) -#define MIPI_LP_RX_TIMEOUT(pipe) _PIPE(pipe, _MIPIA_LP_RX_TIMEOUT, _MIPIB_LP_RX_TIMEOUT) -#define LOW_POWER_RX_TIMEOUT_COUNTER_MASK 0xffffff - -#define _MIPIA_TURN_AROUND_TIMEOUT (VLV_DISPLAY_BASE + 0xb018) -#define _MIPIB_TURN_AROUND_TIMEOUT (VLV_DISPLAY_BASE + 0xb818) -#define MIPI_TURN_AROUND_TIMEOUT(pipe) _PIPE(pipe, _MIPIA_TURN_AROUND_TIMEOUT, _MIPIB_TURN_AROUND_TIMEOUT) -#define TURN_AROUND_TIMEOUT_MASK 0x3f - -#define _MIPIA_DEVICE_RESET_TIMER (VLV_DISPLAY_BASE + 0xb01c) -#define _MIPIB_DEVICE_RESET_TIMER (VLV_DISPLAY_BASE + 0xb81c) -#define MIPI_DEVICE_RESET_TIMER(pipe) _PIPE(pipe, _MIPIA_DEVICE_RESET_TIMER, _MIPIB_DEVICE_RESET_TIMER) -#define DEVICE_RESET_TIMER_MASK 0xffff - -#define _MIPIA_DPI_RESOLUTION (VLV_DISPLAY_BASE + 0xb020) -#define _MIPIB_DPI_RESOLUTION (VLV_DISPLAY_BASE + 0xb820) -#define MIPI_DPI_RESOLUTION(pipe) _PIPE(pipe, _MIPIA_DPI_RESOLUTION, _MIPIB_DPI_RESOLUTION) -#define VERTICAL_ADDRESS_SHIFT 16 -#define VERTICAL_ADDRESS_MASK (0xffff << 16) -#define HORIZONTAL_ADDRESS_SHIFT 0 -#define HORIZONTAL_ADDRESS_MASK 0xffff - -#define _MIPIA_DBI_FIFO_THROTTLE (VLV_DISPLAY_BASE + 0xb024) -#define _MIPIB_DBI_FIFO_THROTTLE (VLV_DISPLAY_BASE + 0xb824) -#define MIPI_DBI_FIFO_THROTTLE(pipe) _PIPE(pipe, _MIPIA_DBI_FIFO_THROTTLE, _MIPIB_DBI_FIFO_THROTTLE) -#define DBI_FIFO_EMPTY_HALF (0 << 0) -#define DBI_FIFO_EMPTY_QUARTER (1 << 0) -#define DBI_FIFO_EMPTY_7_LOCATIONS (2 << 0) - -/* regs below are bits 15:0 */ -#define _MIPIA_HSYNC_PADDING_COUNT (VLV_DISPLAY_BASE + 0xb028) -#define _MIPIB_HSYNC_PADDING_COUNT (VLV_DISPLAY_BASE + 0xb828) -#define MIPI_HSYNC_PADDING_COUNT(pipe) _PIPE(pipe, _MIPIA_HSYNC_PADDING_COUNT, _MIPIB_HSYNC_PADDING_COUNT) - -#define _MIPIA_HBP_COUNT (VLV_DISPLAY_BASE + 0xb02c) -#define _MIPIB_HBP_COUNT (VLV_DISPLAY_BASE + 0xb82c) -#define MIPI_HBP_COUNT(pipe) _PIPE(pipe, _MIPIA_HBP_COUNT, _MIPIB_HBP_COUNT) - -#define _MIPIA_HFP_COUNT (VLV_DISPLAY_BASE + 0xb030) -#define _MIPIB_HFP_COUNT (VLV_DISPLAY_BASE + 0xb830) -#define MIPI_HFP_COUNT(pipe) _PIPE(pipe, _MIPIA_HFP_COUNT, _MIPIB_HFP_COUNT) - -#define _MIPIA_HACTIVE_AREA_COUNT (VLV_DISPLAY_BASE + 0xb034) -#define _MIPIB_HACTIVE_AREA_COUNT (VLV_DISPLAY_BASE + 0xb834) -#define MIPI_HACTIVE_AREA_COUNT(pipe) _PIPE(pipe, _MIPIA_HACTIVE_AREA_COUNT, _MIPIB_HACTIVE_AREA_COUNT) - -#define _MIPIA_VSYNC_PADDING_COUNT (VLV_DISPLAY_BASE + 0xb038) -#define _MIPIB_VSYNC_PADDING_COUNT (VLV_DISPLAY_BASE + 0xb838) -#define MIPI_VSYNC_PADDING_COUNT(pipe) _PIPE(pipe, _MIPIA_VSYNC_PADDING_COUNT, _MIPIB_VSYNC_PADDING_COUNT) - -#define _MIPIA_VBP_COUNT (VLV_DISPLAY_BASE + 0xb03c) -#define _MIPIB_VBP_COUNT (VLV_DISPLAY_BASE + 0xb83c) -#define MIPI_VBP_COUNT(pipe) _PIPE(pipe, _MIPIA_VBP_COUNT, _MIPIB_VBP_COUNT) - -#define _MIPIA_VFP_COUNT (VLV_DISPLAY_BASE + 0xb040) -#define _MIPIB_VFP_COUNT (VLV_DISPLAY_BASE + 0xb840) -#define MIPI_VFP_COUNT(pipe) _PIPE(pipe, _MIPIA_VFP_COUNT, _MIPIB_VFP_COUNT) - -#define _MIPIA_HIGH_LOW_SWITCH_COUNT (VLV_DISPLAY_BASE + 0xb044) -#define _MIPIB_HIGH_LOW_SWITCH_COUNT (VLV_DISPLAY_BASE + 0xb844) -#define MIPI_HIGH_LOW_SWITCH_COUNT(pipe) _PIPE(pipe, _MIPIA_HIGH_LOW_SWITCH_COUNT, _MIPIB_HIGH_LOW_SWITCH_COUNT) -/* regs above are bits 15:0 */ - -#define _MIPIA_DPI_CONTROL (VLV_DISPLAY_BASE + 0xb048) -#define _MIPIB_DPI_CONTROL (VLV_DISPLAY_BASE + 0xb848) -#define MIPI_DPI_CONTROL(pipe) _PIPE(pipe, _MIPIA_DPI_CONTROL, _MIPIB_DPI_CONTROL) -#define DPI_LP_MODE (1 << 6) -#define BACKLIGHT_OFF (1 << 5) -#define BACKLIGHT_ON (1 << 4) -#define COLOR_MODE_OFF (1 << 3) -#define COLOR_MODE_ON (1 << 2) -#define TURN_ON (1 << 1) -#define SHUTDOWN (1 << 0) - -#define _MIPIA_DPI_DATA (VLV_DISPLAY_BASE + 0xb04c) -#define _MIPIB_DPI_DATA (VLV_DISPLAY_BASE + 0xb84c) -#define MIPI_DPI_DATA(pipe) _PIPE(pipe, _MIPIA_DPI_DATA, _MIPIB_DPI_DATA) -#define COMMAND_BYTE_SHIFT 0 -#define COMMAND_BYTE_MASK (0x3f << 0) - -#define _MIPIA_INIT_COUNT (VLV_DISPLAY_BASE + 0xb050) -#define _MIPIB_INIT_COUNT (VLV_DISPLAY_BASE + 0xb850) -#define MIPI_INIT_COUNT(pipe) _PIPE(pipe, _MIPIA_INIT_COUNT, _MIPIB_INIT_COUNT) -#define MASTER_INIT_TIMER_SHIFT 0 -#define MASTER_INIT_TIMER_MASK (0xffff << 0) - -#define _MIPIA_MAX_RETURN_PKT_SIZE (VLV_DISPLAY_BASE + 0xb054) -#define _MIPIB_MAX_RETURN_PKT_SIZE (VLV_DISPLAY_BASE + 0xb854) -#define MIPI_MAX_RETURN_PKT_SIZE(pipe) _PIPE(pipe, _MIPIA_MAX_RETURN_PKT_SIZE, _MIPIB_MAX_RETURN_PKT_SIZE) -#define MAX_RETURN_PKT_SIZE_SHIFT 0 -#define MAX_RETURN_PKT_SIZE_MASK (0x3ff << 0) - -#define _MIPIA_VIDEO_MODE_FORMAT (VLV_DISPLAY_BASE + 0xb058) -#define _MIPIB_VIDEO_MODE_FORMAT (VLV_DISPLAY_BASE + 0xb858) -#define MIPI_VIDEO_MODE_FORMAT(pipe) _PIPE(pipe, _MIPIA_VIDEO_MODE_FORMAT, _MIPIB_VIDEO_MODE_FORMAT) -#define RANDOM_DPI_DISPLAY_RESOLUTION (1 << 4) -#define DISABLE_VIDEO_BTA (1 << 3) -#define IP_TG_CONFIG (1 << 2) -#define VIDEO_MODE_NON_BURST_WITH_SYNC_PULSE (1 << 0) -#define VIDEO_MODE_NON_BURST_WITH_SYNC_EVENTS (2 << 0) -#define VIDEO_MODE_BURST (3 << 0) - -#define _MIPIA_EOT_DISABLE (VLV_DISPLAY_BASE + 0xb05c) -#define _MIPIB_EOT_DISABLE (VLV_DISPLAY_BASE + 0xb85c) -#define MIPI_EOT_DISABLE(pipe) _PIPE(pipe, _MIPIA_EOT_DISABLE, _MIPIB_EOT_DISABLE) -#define LP_RX_TIMEOUT_ERROR_RECOVERY_DISABLE (1 << 7) -#define HS_RX_TIMEOUT_ERROR_RECOVERY_DISABLE (1 << 6) -#define LOW_CONTENTION_RECOVERY_DISABLE (1 << 5) -#define HIGH_CONTENTION_RECOVERY_DISABLE (1 << 4) -#define TXDSI_TYPE_NOT_RECOGNISED_ERROR_RECOVERY_DISABLE (1 << 3) -#define TXECC_MULTIBIT_ERROR_RECOVERY_DISABLE (1 << 2) -#define CLOCKSTOP (1 << 1) -#define EOT_DISABLE (1 << 0) - -#define _MIPIA_LP_BYTECLK (VLV_DISPLAY_BASE + 0xb060) -#define _MIPIB_LP_BYTECLK (VLV_DISPLAY_BASE + 0xb860) -#define MIPI_LP_BYTECLK(pipe) _PIPE(pipe, _MIPIA_LP_BYTECLK, _MIPIB_LP_BYTECLK) -#define LP_BYTECLK_SHIFT 0 -#define LP_BYTECLK_MASK (0xffff << 0) - -/* bits 31:0 */ -#define _MIPIA_LP_GEN_DATA (VLV_DISPLAY_BASE + 0xb064) -#define _MIPIB_LP_GEN_DATA (VLV_DISPLAY_BASE + 0xb864) -#define MIPI_LP_GEN_DATA(pipe) _PIPE(pipe, _MIPIA_LP_GEN_DATA, _MIPIB_LP_GEN_DATA) - -/* bits 31:0 */ -#define _MIPIA_HS_GEN_DATA (VLV_DISPLAY_BASE + 0xb068) -#define _MIPIB_HS_GEN_DATA (VLV_DISPLAY_BASE + 0xb868) -#define MIPI_HS_GEN_DATA(pipe) _PIPE(pipe, _MIPIA_HS_GEN_DATA, _MIPIB_HS_GEN_DATA) - -#define _MIPIA_LP_GEN_CTRL (VLV_DISPLAY_BASE + 0xb06c) -#define _MIPIB_LP_GEN_CTRL (VLV_DISPLAY_BASE + 0xb86c) -#define MIPI_LP_GEN_CTRL(pipe) _PIPE(pipe, _MIPIA_LP_GEN_CTRL, _MIPIB_LP_GEN_CTRL) -#define _MIPIA_HS_GEN_CTRL (VLV_DISPLAY_BASE + 0xb070) -#define _MIPIB_HS_GEN_CTRL (VLV_DISPLAY_BASE + 0xb870) -#define MIPI_HS_GEN_CTRL(pipe) _PIPE(pipe, _MIPIA_HS_GEN_CTRL, _MIPIB_HS_GEN_CTRL) -#define LONG_PACKET_WORD_COUNT_SHIFT 8 -#define LONG_PACKET_WORD_COUNT_MASK (0xffff << 8) -#define SHORT_PACKET_PARAM_SHIFT 8 -#define SHORT_PACKET_PARAM_MASK (0xffff << 8) -#define VIRTUAL_CHANNEL_SHIFT 6 -#define VIRTUAL_CHANNEL_MASK (3 << 6) -#define DATA_TYPE_SHIFT 0 -#define DATA_TYPE_MASK (3f << 0) -/* data type values, see include/video/mipi_display.h */ - -#define _MIPIA_GEN_FIFO_STAT (VLV_DISPLAY_BASE + 0xb074) -#define _MIPIB_GEN_FIFO_STAT (VLV_DISPLAY_BASE + 0xb874) -#define MIPI_GEN_FIFO_STAT(pipe) _PIPE(pipe, _MIPIA_GEN_FIFO_STAT, _MIPIB_GEN_FIFO_STAT) -#define DPI_FIFO_EMPTY (1 << 28) -#define DBI_FIFO_EMPTY (1 << 27) -#define LP_CTRL_FIFO_EMPTY (1 << 26) -#define LP_CTRL_FIFO_HALF_EMPTY (1 << 25) -#define LP_CTRL_FIFO_FULL (1 << 24) -#define HS_CTRL_FIFO_EMPTY (1 << 18) -#define HS_CTRL_FIFO_HALF_EMPTY (1 << 17) -#define HS_CTRL_FIFO_FULL (1 << 16) -#define LP_DATA_FIFO_EMPTY (1 << 10) -#define LP_DATA_FIFO_HALF_EMPTY (1 << 9) -#define LP_DATA_FIFO_FULL (1 << 8) -#define HS_DATA_FIFO_EMPTY (1 << 2) -#define HS_DATA_FIFO_HALF_EMPTY (1 << 1) -#define HS_DATA_FIFO_FULL (1 << 0) - -#define _MIPIA_HS_LS_DBI_ENABLE (VLV_DISPLAY_BASE + 0xb078) -#define _MIPIB_HS_LS_DBI_ENABLE (VLV_DISPLAY_BASE + 0xb878) -#define MIPI_HS_LP_DBI_ENABLE(pipe) _PIPE(pipe, _MIPIA_HS_LS_DBI_ENABLE, _MIPIB_HS_LS_DBI_ENABLE) -#define DBI_HS_LP_MODE_MASK (1 << 0) -#define DBI_LP_MODE (1 << 0) -#define DBI_HS_MODE (0 << 0) - -#define _MIPIA_DPHY_PARAM (VLV_DISPLAY_BASE + 0xb080) -#define _MIPIB_DPHY_PARAM (VLV_DISPLAY_BASE + 0xb880) -#define MIPI_DPHY_PARAM(pipe) _PIPE(pipe, _MIPIA_DPHY_PARAM, _MIPIB_DPHY_PARAM) -#define EXIT_ZERO_COUNT_SHIFT 24 -#define EXIT_ZERO_COUNT_MASK (0x3f << 24) -#define TRAIL_COUNT_SHIFT 16 -#define TRAIL_COUNT_MASK (0x1f << 16) -#define CLK_ZERO_COUNT_SHIFT 8 -#define CLK_ZERO_COUNT_MASK (0xff << 8) -#define PREPARE_COUNT_SHIFT 0 -#define PREPARE_COUNT_MASK (0x3f << 0) - -/* bits 31:0 */ -#define _MIPIA_DBI_BW_CTRL (VLV_DISPLAY_BASE + 0xb084) -#define _MIPIB_DBI_BW_CTRL (VLV_DISPLAY_BASE + 0xb884) -#define MIPI_DBI_BW_CTRL(pipe) _PIPE(pipe, _MIPIA_DBI_BW_CTRL, _MIPIB_DBI_BW_CTRL) - -#define _MIPIA_CLK_LANE_SWITCH_TIME_CNT (VLV_DISPLAY_BASE + 0xb088) -#define _MIPIB_CLK_LANE_SWITCH_TIME_CNT (VLV_DISPLAY_BASE + 0xb888) -#define MIPI_CLK_LANE_SWITCH_TIME_CNT(pipe) _PIPE(pipe, _MIPIA_CLK_LANE_SWITCH_TIME_CNT, _MIPIB_CLK_LANE_SWITCH_TIME_CNT) -#define LP_HS_SSW_CNT_SHIFT 16 -#define LP_HS_SSW_CNT_MASK (0xffff << 16) -#define HS_LP_PWR_SW_CNT_SHIFT 0 -#define HS_LP_PWR_SW_CNT_MASK (0xffff << 0) - -#define _MIPIA_STOP_STATE_STALL (VLV_DISPLAY_BASE + 0xb08c) -#define _MIPIB_STOP_STATE_STALL (VLV_DISPLAY_BASE + 0xb88c) -#define MIPI_STOP_STATE_STALL(pipe) _PIPE(pipe, _MIPIA_STOP_STATE_STALL, _MIPIB_STOP_STATE_STALL) -#define STOP_STATE_STALL_COUNTER_SHIFT 0 -#define STOP_STATE_STALL_COUNTER_MASK (0xff << 0) - -#define _MIPIA_INTR_STAT_REG_1 (VLV_DISPLAY_BASE + 0xb090) -#define _MIPIB_INTR_STAT_REG_1 (VLV_DISPLAY_BASE + 0xb890) -#define MIPI_INTR_STAT_REG_1(pipe) _PIPE(pipe, _MIPIA_INTR_STAT_REG_1, _MIPIB_INTR_STAT_REG_1) -#define _MIPIA_INTR_EN_REG_1 (VLV_DISPLAY_BASE + 0xb094) -#define _MIPIB_INTR_EN_REG_1 (VLV_DISPLAY_BASE + 0xb894) -#define MIPI_INTR_EN_REG_1(pipe) _PIPE(pipe, _MIPIA_INTR_EN_REG_1, _MIPIB_INTR_EN_REG_1) -#define RX_CONTENTION_DETECTED (1 << 0) - -/* XXX: only pipe A ?!? */ -#define MIPIA_DBI_TYPEC_CTRL (VLV_DISPLAY_BASE + 0xb100) -#define DBI_TYPEC_ENABLE (1 << 31) -#define DBI_TYPEC_WIP (1 << 30) -#define DBI_TYPEC_OPTION_SHIFT 28 -#define DBI_TYPEC_OPTION_MASK (3 << 28) -#define DBI_TYPEC_FREQ_SHIFT 24 -#define DBI_TYPEC_FREQ_MASK (0xf << 24) -#define DBI_TYPEC_OVERRIDE (1 << 8) -#define DBI_TYPEC_OVERRIDE_COUNTER_SHIFT 0 -#define DBI_TYPEC_OVERRIDE_COUNTER_MASK (0xff << 0) - - -/* MIPI adapter registers */ - -#define _MIPIA_CTRL (VLV_DISPLAY_BASE + 0xb104) -#define _MIPIB_CTRL (VLV_DISPLAY_BASE + 0xb904) -#define MIPI_CTRL(pipe) _PIPE(pipe, _MIPIA_CTRL, _MIPIB_CTRL) -#define ESCAPE_CLOCK_DIVIDER_SHIFT 5 /* A only */ -#define ESCAPE_CLOCK_DIVIDER_MASK (3 << 5) -#define ESCAPE_CLOCK_DIVIDER_1 (0 << 5) -#define ESCAPE_CLOCK_DIVIDER_2 (1 << 5) -#define ESCAPE_CLOCK_DIVIDER_4 (2 << 5) -#define READ_REQUEST_PRIORITY_SHIFT 3 -#define READ_REQUEST_PRIORITY_MASK (3 << 3) -#define READ_REQUEST_PRIORITY_LOW (0 << 3) -#define READ_REQUEST_PRIORITY_HIGH (3 << 3) -#define RGB_FLIP_TO_BGR (1 << 2) - -#define _MIPIA_DATA_ADDRESS (VLV_DISPLAY_BASE + 0xb108) -#define _MIPIB_DATA_ADDRESS (VLV_DISPLAY_BASE + 0xb908) -#define MIPI_DATA_ADDRESS(pipe) _PIPE(pipe, _MIPIA_DATA_ADDRESS, _MIPIB_DATA_ADDRESS) -#define DATA_MEM_ADDRESS_SHIFT 5 -#define DATA_MEM_ADDRESS_MASK (0x7ffffff << 5) -#define DATA_VALID (1 << 0) - -#define _MIPIA_DATA_LENGTH (VLV_DISPLAY_BASE + 0xb10c) -#define _MIPIB_DATA_LENGTH (VLV_DISPLAY_BASE + 0xb90c) -#define MIPI_DATA_LENGTH(pipe) _PIPE(pipe, _MIPIA_DATA_LENGTH, _MIPIB_DATA_LENGTH) -#define DATA_LENGTH_SHIFT 0 -#define DATA_LENGTH_MASK (0xfffff << 0) - -#define _MIPIA_COMMAND_ADDRESS (VLV_DISPLAY_BASE + 0xb110) -#define _MIPIB_COMMAND_ADDRESS (VLV_DISPLAY_BASE + 0xb910) -#define MIPI_COMMAND_ADDRESS(pipe) _PIPE(pipe, _MIPIA_COMMAND_ADDRESS, _MIPIB_COMMAND_ADDRESS) -#define COMMAND_MEM_ADDRESS_SHIFT 5 -#define COMMAND_MEM_ADDRESS_MASK (0x7ffffff << 5) -#define AUTO_PWG_ENABLE (1 << 2) -#define MEMORY_WRITE_DATA_FROM_PIPE_RENDERING (1 << 1) -#define COMMAND_VALID (1 << 0) - -#define _MIPIA_COMMAND_LENGTH (VLV_DISPLAY_BASE + 0xb114) -#define _MIPIB_COMMAND_LENGTH (VLV_DISPLAY_BASE + 0xb914) -#define MIPI_COMMAND_LENGTH(pipe) _PIPE(pipe, _MIPIA_COMMAND_LENGTH, _MIPIB_COMMAND_LENGTH) -#define COMMAND_LENGTH_SHIFT(n) (8 * (n)) /* n: 0...3 */ -#define COMMAND_LENGTH_MASK(n) (0xff << (8 * (n))) - -#define _MIPIA_READ_DATA_RETURN0 (VLV_DISPLAY_BASE + 0xb118) -#define _MIPIB_READ_DATA_RETURN0 (VLV_DISPLAY_BASE + 0xb918) -#define MIPI_READ_DATA_RETURN(pipe, n) \ - (_PIPE(pipe, _MIPIA_READ_DATA_RETURN0, _MIPIB_READ_DATA_RETURN0) + 4 * (n)) /* n: 0...7 */ - -#define _MIPIA_READ_DATA_VALID (VLV_DISPLAY_BASE + 0xb138) -#define _MIPIB_READ_DATA_VALID (VLV_DISPLAY_BASE + 0xb938) -#define MIPI_READ_DATA_VALID(pipe) _PIPE(pipe, _MIPIA_READ_DATA_VALID, _MIPIB_READ_DATA_VALID) -#define READ_DATA_VALID(n) (1 << (n)) - #endif /* _I915_REG_H_ */ diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 98790c7..70db618 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -214,22 +214,6 @@ static void i915_save_display(struct drm_device *dev) dev_priv->regfile.saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2); if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS); - } else if (IS_VALLEYVIEW(dev)) { - dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL); - dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); - - dev_priv->regfile.saveBLC_PWM_CTL = - I915_READ(VLV_BLC_PWM_CTL(PIPE_A)); - dev_priv->regfile.saveBLC_HIST_CTL = - I915_READ(VLV_BLC_HIST_CTL(PIPE_A)); - dev_priv->regfile.saveBLC_PWM_CTL2 = - I915_READ(VLV_BLC_PWM_CTL2(PIPE_A)); - dev_priv->regfile.saveBLC_PWM_CTL_B = - I915_READ(VLV_BLC_PWM_CTL(PIPE_B)); - dev_priv->regfile.saveBLC_HIST_CTL_B = - I915_READ(VLV_BLC_HIST_CTL(PIPE_B)); - dev_priv->regfile.saveBLC_PWM_CTL2_B = - I915_READ(VLV_BLC_PWM_CTL2(PIPE_B)); } else { dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL); dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); @@ -318,19 +302,6 @@ static void i915_restore_display(struct drm_device *dev) I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL); I915_WRITE(RSTDBYCTL, dev_priv->regfile.saveMCHBAR_RENDER_STANDBY); - } else if (IS_VALLEYVIEW(dev)) { - I915_WRITE(VLV_BLC_PWM_CTL(PIPE_A), - dev_priv->regfile.saveBLC_PWM_CTL); - I915_WRITE(VLV_BLC_HIST_CTL(PIPE_A), - dev_priv->regfile.saveBLC_HIST_CTL); - I915_WRITE(VLV_BLC_PWM_CTL2(PIPE_A), - dev_priv->regfile.saveBLC_PWM_CTL2); - I915_WRITE(VLV_BLC_PWM_CTL(PIPE_B), - dev_priv->regfile.saveBLC_PWM_CTL); - I915_WRITE(VLV_BLC_HIST_CTL(PIPE_B), - dev_priv->regfile.saveBLC_HIST_CTL); - I915_WRITE(VLV_BLC_PWM_CTL2(PIPE_B), - dev_priv->regfile.saveBLC_PWM_CTL2); } else { I915_WRITE(PFIT_PGM_RATIOS, dev_priv->regfile.savePFIT_PGM_RATIOS); I915_WRITE(BLC_PWM_CTL, dev_priv->regfile.saveBLC_PWM_CTL); @@ -369,9 +340,7 @@ int i915_save_state(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int i; - if (INTEL_INFO(dev)->gen <= 4) - pci_read_config_byte(dev->pdev, LBB, - &dev_priv->regfile.saveLBB); + pci_read_config_byte(dev->pdev, LBB, &dev_priv->regfile.saveLBB); mutex_lock(&dev->struct_mutex); @@ -398,8 +367,7 @@ int i915_save_state(struct drm_device *dev) intel_disable_gt_powersave(dev); /* Cache mode state */ - if (INTEL_INFO(dev)->gen < 7) - dev_priv->regfile.saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); + dev_priv->regfile.saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); /* Memory Arbitration state */ dev_priv->regfile.saveMI_ARB_STATE = I915_READ(MI_ARB_STATE); @@ -422,9 +390,7 @@ int i915_restore_state(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int i; - if (INTEL_INFO(dev)->gen <= 4) - pci_write_config_byte(dev->pdev, LBB, - dev_priv->regfile.saveLBB); + pci_write_config_byte(dev->pdev, LBB, dev_priv->regfile.saveLBB); mutex_lock(&dev->struct_mutex); @@ -448,9 +414,7 @@ int i915_restore_state(struct drm_device *dev) } /* Cache mode state */ - if (INTEL_INFO(dev)->gen < 7) - I915_WRITE(CACHE_MODE_0, dev_priv->regfile.saveCACHE_MODE_0 | - 0xffff0000); + I915_WRITE(CACHE_MODE_0, dev_priv->regfile.saveCACHE_MODE_0 | 0xffff0000); /* Memory arbitration state */ I915_WRITE(MI_ARB_STATE, dev_priv->regfile.saveMI_ARB_STATE | 0xffff0000); diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index cef38fd..c8c4112 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -32,50 +32,30 @@ #include "intel_drv.h" #include "i915_drv.h" -#define dev_to_drm_minor(d) dev_get_drvdata((d)) - #ifdef CONFIG_PM static u32 calc_residency(struct drm_device *dev, const u32 reg) { struct drm_i915_private *dev_priv = dev->dev_private; u64 raw_time; /* 32b value may overflow during fixed point math */ - u64 units = 128ULL, div = 100000ULL, bias = 100ULL; if (!intel_enable_rc6(dev)) return 0; - /* On VLV, residency time is in CZ units rather than 1.28us */ - if (IS_VALLEYVIEW(dev)) { - u32 clkctl2; - - clkctl2 = I915_READ(VLV_CLK_CTL2) >> - CLK_CTL2_CZCOUNT_30NS_SHIFT; - if (!clkctl2) { - WARN(!clkctl2, "bogus CZ count value"); - return 0; - } - units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2); - if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH) - units <<= 8; - - div = 1000000ULL * bias; - } - - raw_time = I915_READ(reg) * units; - return DIV_ROUND_UP_ULL(raw_time, div); + raw_time = I915_READ(reg) * 128ULL; + return DIV_ROUND_UP_ULL(raw_time, 100000); } static ssize_t show_rc6_mask(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *dminor = dev_to_drm_minor(kdev); + struct drm_minor *dminor = container_of(kdev, struct drm_minor, kdev); return snprintf(buf, PAGE_SIZE, "%x\n", intel_enable_rc6(dminor->dev)); } static ssize_t show_rc6_ms(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *dminor = dev_get_drvdata(kdev); + struct drm_minor *dminor = container_of(kdev, struct drm_minor, kdev); u32 rc6_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6); return snprintf(buf, PAGE_SIZE, "%u\n", rc6_residency); } @@ -83,20 +63,16 @@ show_rc6_ms(struct device *kdev, struct device_attribute *attr, char *buf) static ssize_t show_rc6p_ms(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *dminor = dev_to_drm_minor(kdev); + struct drm_minor *dminor = container_of(kdev, struct drm_minor, kdev); u32 rc6p_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6p); - if (IS_VALLEYVIEW(dminor->dev)) - rc6p_residency = 0; return snprintf(buf, PAGE_SIZE, "%u\n", rc6p_residency); } static ssize_t show_rc6pp_ms(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *dminor = dev_to_drm_minor(kdev); + struct drm_minor *dminor = container_of(kdev, struct drm_minor, kdev); u32 rc6pp_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6pp); - if (IS_VALLEYVIEW(dminor->dev)) - rc6pp_residency = 0; return snprintf(buf, PAGE_SIZE, "%u\n", rc6pp_residency); } @@ -121,7 +97,7 @@ static struct attribute_group rc6_attr_group = { static int l3_access_valid(struct drm_device *dev, loff_t offset) { - if (!HAS_L3_DPF(dev)) + if (!HAS_L3_GPU_CACHE(dev)) return -EPERM; if (offset % 4 != 0) @@ -139,34 +115,31 @@ i915_l3_read(struct file *filp, struct kobject *kobj, loff_t offset, size_t count) { struct device *dev = container_of(kobj, struct device, kobj); - struct drm_minor *dminor = dev_to_drm_minor(dev); + struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); struct drm_device *drm_dev = dminor->dev; struct drm_i915_private *dev_priv = drm_dev->dev_private; - int slice = (int)(uintptr_t)attr->private; - int ret; - - count = round_down(count, 4); + uint32_t misccpctl; + int i, ret; ret = l3_access_valid(drm_dev, offset); if (ret) return ret; - count = min_t(size_t, GEN7_L3LOG_SIZE - offset, count); - ret = i915_mutex_lock_interruptible(drm_dev); if (ret) return ret; - if (dev_priv->l3_parity.remap_info[slice]) - memcpy(buf, - dev_priv->l3_parity.remap_info[slice] + (offset/4), - count); - else - memset(buf, 0, count); + misccpctl = I915_READ(GEN7_MISCCPCTL); + I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); + + for (i = offset; count >= 4 && i < GEN7_L3LOG_SIZE; i += 4, count -= 4) + *((uint32_t *)(&buf[i])) = I915_READ(GEN7_L3LOG_BASE + i); + + I915_WRITE(GEN7_MISCCPCTL, misccpctl); mutex_unlock(&drm_dev->struct_mutex); - return count; + return i - offset; } static ssize_t @@ -175,26 +148,21 @@ i915_l3_write(struct file *filp, struct kobject *kobj, loff_t offset, size_t count) { struct device *dev = container_of(kobj, struct device, kobj); - struct drm_minor *dminor = dev_to_drm_minor(dev); + struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); struct drm_device *drm_dev = dminor->dev; struct drm_i915_private *dev_priv = drm_dev->dev_private; - struct i915_hw_context *ctx; u32 *temp = NULL; /* Just here to make handling failures easy */ - int slice = (int)(uintptr_t)attr->private; int ret; ret = l3_access_valid(drm_dev, offset); if (ret) return ret; - if (dev_priv->hw_contexts_disabled) - return -ENXIO; - ret = i915_mutex_lock_interruptible(drm_dev); if (ret) return ret; - if (!dev_priv->l3_parity.remap_info[slice]) { + if (!dev_priv->l3_parity.remap_info) { temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL); if (!temp) { mutex_unlock(&drm_dev->struct_mutex); @@ -214,13 +182,13 @@ i915_l3_write(struct file *filp, struct kobject *kobj, * at this point it is left as a TODO. */ if (temp) - dev_priv->l3_parity.remap_info[slice] = temp; + dev_priv->l3_parity.remap_info = temp; - memcpy(dev_priv->l3_parity.remap_info[slice] + (offset/4), buf, count); + memcpy(dev_priv->l3_parity.remap_info + (offset/4), + buf + (offset/4), + count); - /* NB: We defer the remapping until we switch to the context */ - list_for_each_entry(ctx, &dev_priv->context_list, link) - ctx->remap_slice |= (1<<slice); + i915_gem_l3_remap(drm_dev); mutex_unlock(&drm_dev->struct_mutex); @@ -232,29 +200,17 @@ static struct bin_attribute dpf_attrs = { .size = GEN7_L3LOG_SIZE, .read = i915_l3_read, .write = i915_l3_write, - .mmap = NULL, - .private = (void *)0 -}; - -static struct bin_attribute dpf_attrs_1 = { - .attr = {.name = "l3_parity_slice_1", .mode = (S_IRUSR | S_IWUSR)}, - .size = GEN7_L3LOG_SIZE, - .read = i915_l3_read, - .write = i915_l3_write, - .mmap = NULL, - .private = (void *)1 + .mmap = NULL }; static ssize_t gt_cur_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev); struct drm_device *dev = minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; int ret; - flush_delayed_work(&dev_priv->rps.delayed_resume_work); - mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev_priv->dev)) { u32 freq; @@ -271,7 +227,7 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev, static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev); struct drm_device *dev = minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -282,13 +238,11 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev, static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev); struct drm_device *dev = minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; int ret; - flush_delayed_work(&dev_priv->rps.delayed_resume_work); - mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev_priv->dev)) ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.max_delay); @@ -303,7 +257,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, struct device_attribute *attr, const char *buf, size_t count) { - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev); struct drm_device *dev = minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 val, rp_state_cap, hw_max, hw_min, non_oc_max; @@ -313,8 +267,6 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, if (ret) return ret; - flush_delayed_work(&dev_priv->rps.delayed_resume_work); - mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev_priv->dev)) { @@ -358,13 +310,11 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev); struct drm_device *dev = minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; int ret; - flush_delayed_work(&dev_priv->rps.delayed_resume_work); - mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev_priv->dev)) ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.min_delay); @@ -379,7 +329,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, struct device_attribute *attr, const char *buf, size_t count) { - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev); struct drm_device *dev = minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 val, rp_state_cap, hw_max, hw_min; @@ -389,8 +339,6 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, if (ret) return ret; - flush_delayed_work(&dev_priv->rps.delayed_resume_work); - mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev)) { @@ -440,7 +388,7 @@ static DEVICE_ATTR(gt_RPn_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL); /* For now we have a static number of RP states */ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev); struct drm_device *dev = minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 val, rp_state_cap; @@ -488,7 +436,7 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj, { struct device *kdev = container_of(kobj, struct device, kobj); - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev); struct drm_device *dev = minor->dev; struct i915_error_state_file_priv error_priv; struct drm_i915_error_state_buf error_str; @@ -523,7 +471,7 @@ static ssize_t error_state_write(struct file *file, struct kobject *kobj, loff_t off, size_t count) { struct device *kdev = container_of(kobj, struct device, kobj); - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev); struct drm_device *dev = minor->dev; int ret; @@ -553,34 +501,27 @@ void i915_setup_sysfs(struct drm_device *dev) #ifdef CONFIG_PM if (INTEL_INFO(dev)->gen >= 6) { - ret = sysfs_merge_group(&dev->primary->kdev->kobj, + ret = sysfs_merge_group(&dev->primary->kdev.kobj, &rc6_attr_group); if (ret) DRM_ERROR("RC6 residency sysfs setup failed\n"); } #endif - if (HAS_L3_DPF(dev)) { - ret = device_create_bin_file(dev->primary->kdev, &dpf_attrs); + if (HAS_L3_GPU_CACHE(dev)) { + ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs); if (ret) DRM_ERROR("l3 parity sysfs setup failed\n"); - - if (NUM_L3_SLICES(dev) > 1) { - ret = device_create_bin_file(dev->primary->kdev, - &dpf_attrs_1); - if (ret) - DRM_ERROR("l3 parity slice 1 setup failed\n"); - } } ret = 0; if (IS_VALLEYVIEW(dev)) - ret = sysfs_create_files(&dev->primary->kdev->kobj, vlv_attrs); + ret = sysfs_create_files(&dev->primary->kdev.kobj, vlv_attrs); else if (INTEL_INFO(dev)->gen >= 6) - ret = sysfs_create_files(&dev->primary->kdev->kobj, gen6_attrs); + ret = sysfs_create_files(&dev->primary->kdev.kobj, gen6_attrs); if (ret) DRM_ERROR("RPS sysfs setup failed\n"); - ret = sysfs_create_bin_file(&dev->primary->kdev->kobj, + ret = sysfs_create_bin_file(&dev->primary->kdev.kobj, &error_state_attr); if (ret) DRM_ERROR("error_state sysfs setup failed\n"); @@ -588,14 +529,13 @@ void i915_setup_sysfs(struct drm_device *dev) void i915_teardown_sysfs(struct drm_device *dev) { - sysfs_remove_bin_file(&dev->primary->kdev->kobj, &error_state_attr); + sysfs_remove_bin_file(&dev->primary->kdev.kobj, &error_state_attr); if (IS_VALLEYVIEW(dev)) - sysfs_remove_files(&dev->primary->kdev->kobj, vlv_attrs); + sysfs_remove_files(&dev->primary->kdev.kobj, vlv_attrs); else - sysfs_remove_files(&dev->primary->kdev->kobj, gen6_attrs); - device_remove_bin_file(dev->primary->kdev, &dpf_attrs_1); - device_remove_bin_file(dev->primary->kdev, &dpf_attrs); + sysfs_remove_files(&dev->primary->kdev.kobj, gen6_attrs); + device_remove_bin_file(&dev->primary->kdev, &dpf_attrs); #ifdef CONFIG_PM - sysfs_unmerge_group(&dev->primary->kdev->kobj, &rc6_attr_group); + sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group); #endif } diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 6e580c9..e2c5ee6 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -233,47 +233,6 @@ TRACE_EVENT(i915_gem_evict_everything, TP_printk("dev=%d", __entry->dev) ); -TRACE_EVENT(i915_gem_evict_vm, - TP_PROTO(struct i915_address_space *vm), - TP_ARGS(vm), - - TP_STRUCT__entry( - __field(struct i915_address_space *, vm) - ), - - TP_fast_assign( - __entry->vm = vm; - ), - - TP_printk("dev=%d, vm=%p", __entry->vm->dev->primary->index, __entry->vm) -); - -TRACE_EVENT(i915_gem_ring_sync_to, - TP_PROTO(struct intel_ring_buffer *from, - struct intel_ring_buffer *to, - u32 seqno), - TP_ARGS(from, to, seqno), - - TP_STRUCT__entry( - __field(u32, dev) - __field(u32, sync_from) - __field(u32, sync_to) - __field(u32, seqno) - ), - - TP_fast_assign( - __entry->dev = from->dev->primary->index; - __entry->sync_from = from->id; - __entry->sync_to = to->id; - __entry->seqno = seqno; - ), - - TP_printk("dev=%u, sync-from=%u, sync-to=%u, seqno=%u", - __entry->dev, - __entry->sync_from, __entry->sync_to, - __entry->seqno) -); - TRACE_EVENT(i915_gem_ring_dispatch, TP_PROTO(struct intel_ring_buffer *ring, u32 seqno, u32 flags), TP_ARGS(ring, seqno, flags), @@ -345,24 +304,9 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_add, TP_ARGS(ring, seqno) ); -TRACE_EVENT(i915_gem_request_complete, - TP_PROTO(struct intel_ring_buffer *ring), - TP_ARGS(ring), - - TP_STRUCT__entry( - __field(u32, dev) - __field(u32, ring) - __field(u32, seqno) - ), - - TP_fast_assign( - __entry->dev = ring->dev->primary->index; - __entry->ring = ring->id; - __entry->seqno = ring->get_seqno(ring, false); - ), - - TP_printk("dev=%u, ring=%u, seqno=%u", - __entry->dev, __entry->ring, __entry->seqno) +DEFINE_EVENT(i915_gem_request, i915_gem_request_complete, + TP_PROTO(struct intel_ring_buffer *ring, u32 seqno), + TP_ARGS(ring, seqno) ); DEFINE_EVENT(i915_gem_request, i915_gem_request_retire, diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c index dfff090..57fe1ae 100644 --- a/drivers/gpu/drm/i915/intel_acpi.c +++ b/drivers/gpu/drm/i915/intel_acpi.c @@ -193,14 +193,16 @@ out: static bool intel_dsm_pci_probe(struct pci_dev *pdev) { - acpi_handle dhandle; + acpi_handle dhandle, intel_handle; + acpi_status status; int ret; - dhandle = ACPI_HANDLE(&pdev->dev); + dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); if (!dhandle) return false; - if (!acpi_has_method(dhandle, "_DSM")) { + status = acpi_get_handle(dhandle, "_DSM", &intel_handle); + if (ACPI_FAILURE(status)) { DRM_DEBUG_KMS("no _DSM method for intel device\n"); return false; } diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index e4fba39..53f2bed 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -389,7 +389,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, { struct sdvo_device_mapping *p_mapping; struct bdb_general_definitions *p_defs; - union child_device_config *p_child; + struct child_device_config *p_child; int i, child_device_num, count; u16 block_size; @@ -416,36 +416,36 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, count = 0; for (i = 0; i < child_device_num; i++) { p_child = &(p_defs->devices[i]); - if (!p_child->old.device_type) { + if (!p_child->device_type) { /* skip the device block if device type is invalid */ continue; } - if (p_child->old.slave_addr != SLAVE_ADDR1 && - p_child->old.slave_addr != SLAVE_ADDR2) { + if (p_child->slave_addr != SLAVE_ADDR1 && + p_child->slave_addr != SLAVE_ADDR2) { /* * If the slave address is neither 0x70 nor 0x72, * it is not a SDVO device. Skip it. */ continue; } - if (p_child->old.dvo_port != DEVICE_PORT_DVOB && - p_child->old.dvo_port != DEVICE_PORT_DVOC) { + 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"); continue; } DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on" " %s port\n", - p_child->old.slave_addr, - (p_child->old.dvo_port == DEVICE_PORT_DVOB) ? + p_child->slave_addr, + (p_child->dvo_port == DEVICE_PORT_DVOB) ? "SDVOB" : "SDVOC"); - p_mapping = &(dev_priv->sdvo_mappings[p_child->old.dvo_port - 1]); + p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]); if (!p_mapping->initialized) { - p_mapping->dvo_port = p_child->old.dvo_port; - p_mapping->slave_addr = p_child->old.slave_addr; - p_mapping->dvo_wiring = p_child->old.dvo_wiring; - p_mapping->ddc_pin = p_child->old.ddc_pin; - p_mapping->i2c_pin = p_child->old.i2c_pin; + p_mapping->dvo_port = p_child->dvo_port; + p_mapping->slave_addr = p_child->slave_addr; + 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->initialized = 1; DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n", p_mapping->dvo_port, @@ -457,7 +457,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, DRM_DEBUG_KMS("Maybe one SDVO port is shared by " "two SDVO device.\n"); } - if (p_child->old.slave2_addr) { + if (p_child->slave2_addr) { /* Maybe this is a SDVO device with multiple inputs */ /* And the mapping info is not added */ DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this" @@ -477,13 +477,15 @@ static void parse_driver_features(struct drm_i915_private *dev_priv, struct bdb_header *bdb) { + struct drm_device *dev = dev_priv->dev; struct bdb_driver_features *driver; driver = find_section(bdb, BDB_DRIVER_FEATURES); if (!driver) return; - if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP) + if (SUPPORTS_EDP(dev) && + driver->lvds_config == BDB_DRIVER_FEATURE_EDP) dev_priv->vbt.edp_support = 1; if (driver->dual_frequency) @@ -499,7 +501,7 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) edp = find_section(bdb, BDB_EDP); if (!edp) { - if (dev_priv->vbt.edp_support) + if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->vbt.edp_support) DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n"); return; } @@ -567,149 +569,11 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) } static void -parse_mipi(struct drm_i915_private *dev_priv, struct bdb_header *bdb) -{ - struct bdb_mipi *mipi; - - mipi = find_section(bdb, BDB_MIPI); - if (!mipi) { - DRM_DEBUG_KMS("No MIPI BDB found"); - return; - } - - /* XXX: add more info */ - dev_priv->vbt.dsi.panel_id = mipi->panel_id; -} - -static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, - struct bdb_header *bdb) -{ - union child_device_config *it, *child = NULL; - struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port]; - uint8_t hdmi_level_shift; - int i, j; - bool is_dvi, is_hdmi, is_dp, is_edp, is_crt; - uint8_t aux_channel; - /* Each DDI port can have more than one value on the "DVO Port" field, - * so look for all the possible values for each port and abort if more - * than one is found. */ - int dvo_ports[][2] = { - {DVO_PORT_HDMIA, DVO_PORT_DPA}, - {DVO_PORT_HDMIB, DVO_PORT_DPB}, - {DVO_PORT_HDMIC, DVO_PORT_DPC}, - {DVO_PORT_HDMID, DVO_PORT_DPD}, - {DVO_PORT_CRT, -1 /* Port E can only be DVO_PORT_CRT */ }, - }; - - /* Find the child device to use, abort if more than one found. */ - for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - it = dev_priv->vbt.child_dev + i; - - for (j = 0; j < 2; j++) { - if (dvo_ports[port][j] == -1) - break; - - if (it->common.dvo_port == dvo_ports[port][j]) { - if (child) { - DRM_DEBUG_KMS("More than one child device for port %c in VBT.\n", - port_name(port)); - return; - } - child = it; - } - } - } - if (!child) - return; - - aux_channel = child->raw[25]; - - is_dvi = child->common.device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING; - is_dp = child->common.device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT; - is_crt = child->common.device_type & DEVICE_TYPE_ANALOG_OUTPUT; - is_hdmi = is_dvi && (child->common.device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT) == 0; - is_edp = is_dp && (child->common.device_type & DEVICE_TYPE_INTERNAL_CONNECTOR); - - info->supports_dvi = is_dvi; - info->supports_hdmi = is_hdmi; - info->supports_dp = is_dp; - - DRM_DEBUG_KMS("Port %c VBT info: DP:%d HDMI:%d DVI:%d EDP:%d CRT:%d\n", - port_name(port), is_dp, is_hdmi, is_dvi, is_edp, is_crt); - - if (is_edp && is_dvi) - DRM_DEBUG_KMS("Internal DP port %c is TMDS compatible\n", - port_name(port)); - if (is_crt && port != PORT_E) - DRM_DEBUG_KMS("Port %c is analog\n", port_name(port)); - if (is_crt && (is_dvi || is_dp)) - DRM_DEBUG_KMS("Analog port %c is also DP or TMDS compatible\n", - port_name(port)); - if (is_dvi && (port == PORT_A || port == PORT_E)) - DRM_DEBUG_KMS("Port %c is TMDS compabile\n", port_name(port)); - if (!is_dvi && !is_dp && !is_crt) - DRM_DEBUG_KMS("Port %c is not DP/TMDS/CRT compatible\n", - port_name(port)); - if (is_edp && (port == PORT_B || port == PORT_C || port == PORT_E)) - DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port)); - - if (is_dvi) { - if (child->common.ddc_pin == 0x05 && port != PORT_B) - DRM_DEBUG_KMS("Unexpected DDC pin for port B\n"); - if (child->common.ddc_pin == 0x04 && port != PORT_C) - DRM_DEBUG_KMS("Unexpected DDC pin for port C\n"); - if (child->common.ddc_pin == 0x06 && port != PORT_D) - DRM_DEBUG_KMS("Unexpected DDC pin for port D\n"); - } - - if (is_dp) { - if (aux_channel == 0x40 && port != PORT_A) - DRM_DEBUG_KMS("Unexpected AUX channel for port A\n"); - if (aux_channel == 0x10 && port != PORT_B) - DRM_DEBUG_KMS("Unexpected AUX channel for port B\n"); - if (aux_channel == 0x20 && port != PORT_C) - DRM_DEBUG_KMS("Unexpected AUX channel for port C\n"); - if (aux_channel == 0x30 && port != PORT_D) - DRM_DEBUG_KMS("Unexpected AUX channel for port D\n"); - } - - if (bdb->version >= 158) { - /* The VBT HDMI level shift values match the table we have. */ - hdmi_level_shift = child->raw[7] & 0xF; - if (hdmi_level_shift < 0xC) { - DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n", - port_name(port), - hdmi_level_shift); - info->hdmi_level_shift = hdmi_level_shift; - } - } -} - -static void parse_ddi_ports(struct drm_i915_private *dev_priv, - struct bdb_header *bdb) -{ - struct drm_device *dev = dev_priv->dev; - enum port port; - - if (!HAS_DDI(dev)) - return; - - if (!dev_priv->vbt.child_dev_num) - return; - - if (bdb->version < 155) - return; - - for (port = PORT_A; port < I915_MAX_PORTS; port++) - parse_ddi_port(dev_priv, port, bdb); -} - -static void parse_device_mapping(struct drm_i915_private *dev_priv, struct bdb_header *bdb) { struct bdb_general_definitions *p_defs; - union child_device_config *p_child, *child_dev_ptr; + struct child_device_config *p_child, *child_dev_ptr; int i, child_device_num, count; u16 block_size; @@ -737,7 +601,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, /* get the number of child device that is present */ for (i = 0; i < child_device_num; i++) { p_child = &(p_defs->devices[i]); - if (!p_child->common.device_type) { + if (!p_child->device_type) { /* skip the device block if device type is invalid */ continue; } @@ -757,7 +621,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, count = 0; for (i = 0; i < child_device_num; i++) { p_child = &(p_defs->devices[i]); - if (!p_child->common.device_type) { + if (!p_child->device_type) { /* skip the device block if device type is invalid */ continue; } @@ -773,7 +637,6 @@ static void init_vbt_defaults(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; - enum port port; dev_priv->vbt.crt_ddc_pin = GMBUS_PORT_VGADDC; @@ -790,25 +653,8 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) /* Default to using SSC */ dev_priv->vbt.lvds_use_ssc = 1; - /* - * Core/SandyBridge/IvyBridge use alternative (120MHz) reference - * clock for LVDS. - */ - dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev, - !HAS_PCH_SPLIT(dev)); + dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1); DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq); - - for (port = PORT_A; port < I915_MAX_PORTS; port++) { - struct ddi_vbt_port_info *info = - &dev_priv->vbt.ddi_port_info[port]; - - /* Recommended BSpec default: 800mV 0dB. */ - info->hdmi_level_shift = 6; - - info->supports_dvi = (port != PORT_A && port != PORT_E); - info->supports_hdmi = info->supports_dvi; - info->supports_dp = (port != PORT_E); - } } static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id) @@ -899,8 +745,6 @@ intel_parse_bios(struct drm_device *dev) parse_device_mapping(dev_priv, bdb); parse_driver_features(dev_priv, bdb); parse_edp(dev_priv, bdb); - parse_mipi(dev_priv, bdb); - parse_ddi_ports(dev_priv, bdb); if (bios) pci_unmap_rom(pdev, bios); diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index f580a2b..e088d6f 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -104,7 +104,6 @@ struct vbios_data { #define BDB_LVDS_LFP_DATA 42 #define BDB_LVDS_BACKLIGHT 43 #define BDB_LVDS_POWER 44 -#define BDB_MIPI 50 #define BDB_SKIP 254 /* VBIOS private block, ignore */ struct bdb_general_features { @@ -202,10 +201,7 @@ struct bdb_general_features { #define DEVICE_PORT_DVOB 0x01 #define DEVICE_PORT_DVOC 0x02 -/* We used to keep this struct but without any version control. We should avoid - * using it in the future, but it should be safe to keep using it in the old - * code. */ -struct old_child_dev_config { +struct child_device_config { u16 handle; u16 device_type; u8 device_id[10]; /* ascii string */ @@ -227,32 +223,6 @@ struct old_child_dev_config { u8 dvo_function; } __attribute__((packed)); -/* This one contains field offsets that are known to be common for all BDB - * versions. Notice that the meaning of the contents contents may still change, - * but at least the offsets are consistent. */ -struct common_child_dev_config { - u16 handle; - u16 device_type; - u8 not_common1[12]; - u8 dvo_port; - u8 not_common2[2]; - u8 ddc_pin; - u16 edid_ptr; -} __attribute__((packed)); - -/* This field changes depending on the BDB version, so the most reliable way to - * read it is by checking the BDB version and reading the raw pointer. */ -union child_device_config { - /* This one is safe to be used anywhere, but the code should still check - * the BDB version. */ - u8 raw[33]; - /* This one should only be kept for legacy code. */ - struct old_child_dev_config old; - /* This one should also be safe to use anywhere, even without version - * checks. */ - struct common_child_dev_config common; -}; - struct bdb_general_definitions { /* DDC GPIO */ u8 crt_ddc_gmbus_pin; @@ -278,7 +248,7 @@ struct bdb_general_definitions { * number = (block_size - sizeof(bdb_general_definitions))/ * sizeof(child_device_config); */ - union child_device_config devices[0]; + struct child_device_config devices[0]; } __attribute__((packed)); struct bdb_lvds_options { @@ -638,40 +608,6 @@ int intel_parse_bios(struct drm_device *dev); #define DEVICE_TYPE_DP 0x68C6 #define DEVICE_TYPE_eDP 0x78C6 -#define DEVICE_TYPE_CLASS_EXTENSION (1 << 15) -#define DEVICE_TYPE_POWER_MANAGEMENT (1 << 14) -#define DEVICE_TYPE_HOTPLUG_SIGNALING (1 << 13) -#define DEVICE_TYPE_INTERNAL_CONNECTOR (1 << 12) -#define DEVICE_TYPE_NOT_HDMI_OUTPUT (1 << 11) -#define DEVICE_TYPE_MIPI_OUTPUT (1 << 10) -#define DEVICE_TYPE_COMPOSITE_OUTPUT (1 << 9) -#define DEVICE_TYPE_DUAL_CHANNEL (1 << 8) -#define DEVICE_TYPE_HIGH_SPEED_LINK (1 << 6) -#define DEVICE_TYPE_LVDS_SINGALING (1 << 5) -#define DEVICE_TYPE_TMDS_DVI_SIGNALING (1 << 4) -#define DEVICE_TYPE_VIDEO_SIGNALING (1 << 3) -#define DEVICE_TYPE_DISPLAYPORT_OUTPUT (1 << 2) -#define DEVICE_TYPE_DIGITAL_OUTPUT (1 << 1) -#define DEVICE_TYPE_ANALOG_OUTPUT (1 << 0) - -/* - * Bits we care about when checking for DEVICE_TYPE_eDP - * Depending on the system, the other bits may or may not - * be set for eDP outputs. - */ -#define DEVICE_TYPE_eDP_BITS \ - (DEVICE_TYPE_INTERNAL_CONNECTOR | \ - DEVICE_TYPE_NOT_HDMI_OUTPUT | \ - DEVICE_TYPE_MIPI_OUTPUT | \ - DEVICE_TYPE_COMPOSITE_OUTPUT | \ - DEVICE_TYPE_DUAL_CHANNEL | \ - DEVICE_TYPE_LVDS_SINGALING | \ - DEVICE_TYPE_TMDS_DVI_SIGNALING | \ - DEVICE_TYPE_VIDEO_SIGNALING | \ - DEVICE_TYPE_DISPLAYPORT_OUTPUT | \ - DEVICE_TYPE_DIGITAL_OUTPUT | \ - DEVICE_TYPE_ANALOG_OUTPUT) - /* define the DVO port for HDMI output type */ #define DVO_B 1 #define DVO_C 2 @@ -682,57 +618,4 @@ int intel_parse_bios(struct drm_device *dev); #define PORT_IDPC 8 #define PORT_IDPD 9 -/* Possible values for the "DVO Port" field for versions >= 155: */ -#define DVO_PORT_HDMIA 0 -#define DVO_PORT_HDMIB 1 -#define DVO_PORT_HDMIC 2 -#define DVO_PORT_HDMID 3 -#define DVO_PORT_LVDS 4 -#define DVO_PORT_TV 5 -#define DVO_PORT_CRT 6 -#define DVO_PORT_DPB 7 -#define DVO_PORT_DPC 8 -#define DVO_PORT_DPD 9 -#define DVO_PORT_DPA 10 - -/* MIPI DSI panel info */ -struct bdb_mipi { - u16 panel_id; - u16 bridge_revision; - - /* General params */ - u32 dithering:1; - u32 bpp_pixel_format:1; - u32 rsvd1:1; - u32 dphy_valid:1; - u32 resvd2:28; - - u16 port_info; - u16 rsvd3:2; - u16 num_lanes:2; - u16 rsvd4:12; - - /* DSI config */ - u16 virt_ch_num:2; - u16 vtm:2; - u16 rsvd5:12; - - u32 dsi_clock; - u32 bridge_ref_clk; - u16 rsvd_pwr; - - /* Dphy Params */ - u32 prepare_cnt:5; - u32 rsvd6:3; - u32 clk_zero_cnt:8; - u32 trail_cnt:5; - u32 rsvd7:3; - u32 exit_zero_cnt:6; - u32 rsvd8:2; - - u32 hl_switch_cnt; - u32 lp_byte_clk; - u32 clk_lane_switch_cnt; -} __attribute__((packed)); - #endif /* _I830_BIOS_H_ */ diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index b5b1b9b..10d1de5 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -107,17 +107,7 @@ static unsigned int intel_crt_get_flags(struct intel_encoder *encoder) static void intel_crt_get_config(struct intel_encoder *encoder, struct intel_crtc_config *pipe_config) { - struct drm_device *dev = encoder->base.dev; - int dotclock; - pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder); - - dotclock = pipe_config->port_clock; - - if (HAS_PCH_SPLIT(dev)) - ironlake_check_encoder_dotclock(pipe_config, dotclock); - - pipe_config->adjusted_mode.crtc_clock = dotclock; } static void hsw_crt_get_config(struct intel_encoder *encoder, @@ -274,7 +264,7 @@ static void intel_crt_mode_set(struct intel_encoder *encoder) struct drm_display_mode *adjusted_mode = &crtc->config.adjusted_mode; u32 adpa; - if (INTEL_INFO(dev)->gen >= 5) + if (HAS_PCH_SPLIT(dev)) adpa = ADPA_HOTPLUG_BITS; else adpa = 0; @@ -376,6 +366,9 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector) DRM_DEBUG_KMS("valleyview hotplug adpa=0x%x, result %d\n", adpa, ret); + /* FIXME: debug force function and remove */ + ret = true; + return ret; } @@ -677,6 +670,7 @@ intel_crt_detect(struct drm_connector *connector, bool force) static void intel_crt_destroy(struct drm_connector *connector) { + drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -782,7 +776,7 @@ void intel_crt_init(struct drm_device *dev) if (!crt) return; - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); if (!intel_connector) { kfree(crt); return; @@ -822,15 +816,16 @@ void intel_crt_init(struct drm_device *dev) crt->base.mode_set = intel_crt_mode_set; crt->base.disable = intel_disable_crt; crt->base.enable = intel_enable_crt; + if (IS_HASWELL(dev)) + crt->base.get_config = hsw_crt_get_config; + else + crt->base.get_config = intel_crt_get_config; if (I915_HAS_HOTPLUG(dev)) crt->base.hpd_pin = HPD_CRT; - if (HAS_DDI(dev)) { - crt->base.get_config = hsw_crt_get_config; + if (HAS_DDI(dev)) crt->base.get_hw_state = intel_ddi_get_hw_state; - } else { - crt->base.get_config = intel_crt_get_config; + else crt->base.get_hw_state = intel_crt_get_hw_state; - } intel_connector->get_hw_state = intel_connector_get_hw_state; drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 526c8de..b53fff8 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -42,6 +42,7 @@ static const u32 hsw_ddi_translations_dp[] = { 0x80C30FFF, 0x000B0000, 0x00FFFFFF, 0x00040006, 0x80D75FFF, 0x000B0000, + 0x00FFFFFF, 0x00040006 /* HDMI parameters */ }; static const u32 hsw_ddi_translations_fdi[] = { @@ -54,64 +55,10 @@ static const u32 hsw_ddi_translations_fdi[] = { 0x00C30FFF, 0x001E0000, 0x00FFFFFF, 0x00060006, 0x00D75FFF, 0x001E0000, + 0x00FFFFFF, 0x00040006 /* HDMI parameters */ }; -static const u32 hsw_ddi_translations_hdmi[] = { - /* Idx NT mV diff T mV diff db */ - 0x00FFFFFF, 0x0006000E, /* 0: 400 400 0 */ - 0x00E79FFF, 0x000E000C, /* 1: 400 500 2 */ - 0x00D75FFF, 0x0005000A, /* 2: 400 600 3.5 */ - 0x00FFFFFF, 0x0005000A, /* 3: 600 600 0 */ - 0x00E79FFF, 0x001D0007, /* 4: 600 750 2 */ - 0x00D75FFF, 0x000C0004, /* 5: 600 900 3.5 */ - 0x00FFFFFF, 0x00040006, /* 6: 800 800 0 */ - 0x80E79FFF, 0x00030002, /* 7: 800 1000 2 */ - 0x00FFFFFF, 0x00140005, /* 8: 850 850 0 */ - 0x00FFFFFF, 0x000C0004, /* 9: 900 900 0 */ - 0x00FFFFFF, 0x001C0003, /* 10: 950 950 0 */ - 0x80FFFFFF, 0x00030002, /* 11: 1000 1000 0 */ -}; - -static const u32 bdw_ddi_translations_edp[] = { - 0x00FFFFFF, 0x00000012, /* DP parameters */ - 0x00EBAFFF, 0x00020011, - 0x00C71FFF, 0x0006000F, - 0x00FFFFFF, 0x00020011, - 0x00DB6FFF, 0x0005000F, - 0x00BEEFFF, 0x000A000C, - 0x00FFFFFF, 0x0005000F, - 0x00DB6FFF, 0x000A000C, - 0x00FFFFFF, 0x000A000C, - 0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/ -}; - -static const u32 bdw_ddi_translations_dp[] = { - 0x00FFFFFF, 0x0007000E, /* DP parameters */ - 0x00D75FFF, 0x000E000A, - 0x00BEFFFF, 0x00140006, - 0x00FFFFFF, 0x000E000A, - 0x00D75FFF, 0x00180004, - 0x80CB2FFF, 0x001B0002, - 0x00F7DFFF, 0x00180004, - 0x80D75FFF, 0x001B0002, - 0x80FFFFFF, 0x001B0002, - 0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/ -}; - -static const u32 bdw_ddi_translations_fdi[] = { - 0x00FFFFFF, 0x0001000E, /* FDI parameters */ - 0x00D75FFF, 0x0004000A, - 0x00C30FFF, 0x00070006, - 0x00AAAFFF, 0x000C0000, - 0x00FFFFFF, 0x0004000A, - 0x00D75FFF, 0x00090004, - 0x00C30FFF, 0x000C0000, - 0x00FFFFFF, 0x00070006, - 0x00D75FFF, 0x000C0000, - 0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/ -}; - -enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) +static enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) { struct drm_encoder *encoder = &intel_encoder->base; int type = intel_encoder->type; @@ -131,9 +78,8 @@ enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) } } -/* - * Starting with Haswell, DDI port buffers must be programmed with correct - * values in advance. The buffer values are different for FDI and DP modes, +/* On Haswell, DDI port buffers must be programmed with correct values + * in advance. The buffer values are different for FDI and DP modes, * but the HDMI/DVI fields are shared among those. So we program the DDI * in either FDI or DP modes only, as HDMI connections will work with both * of those @@ -143,58 +89,15 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) struct drm_i915_private *dev_priv = dev->dev_private; u32 reg; int i; - int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; - const u32 *ddi_translations_fdi; - const u32 *ddi_translations_dp; - const u32 *ddi_translations_edp; - const u32 *ddi_translations; - - if (IS_BROADWELL(dev)) { - ddi_translations_fdi = bdw_ddi_translations_fdi; - ddi_translations_dp = bdw_ddi_translations_dp; - ddi_translations_edp = bdw_ddi_translations_edp; - } else if (IS_HASWELL(dev)) { - ddi_translations_fdi = hsw_ddi_translations_fdi; - ddi_translations_dp = hsw_ddi_translations_dp; - ddi_translations_edp = hsw_ddi_translations_dp; - } else { - WARN(1, "ddi translation table missing\n"); - ddi_translations_edp = bdw_ddi_translations_dp; - ddi_translations_fdi = bdw_ddi_translations_fdi; - ddi_translations_dp = bdw_ddi_translations_dp; - } - - switch (port) { - case PORT_A: - ddi_translations = ddi_translations_edp; - break; - case PORT_B: - case PORT_C: - ddi_translations = ddi_translations_dp; - break; - case PORT_D: - if (intel_dp_is_edp(dev, PORT_D)) - ddi_translations = ddi_translations_edp; - else - ddi_translations = ddi_translations_dp; - break; - case PORT_E: - ddi_translations = ddi_translations_fdi; - break; - default: - BUG(); - } + const u32 *ddi_translations = (port == PORT_E) ? + hsw_ddi_translations_fdi : + hsw_ddi_translations_dp; for (i = 0, reg = DDI_BUF_TRANS(port); i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) { I915_WRITE(reg, ddi_translations[i]); reg += 4; } - /* Entry 9 is for HDMI: */ - for (i = 0; i < 2; i++) { - I915_WRITE(reg, hsw_ddi_translations_hdmi[hdmi_level * 2 + i]); - reg += 4; - } } /* Program DDI buffers translations for DP. By default, program ports A-D in DP @@ -393,6 +296,9 @@ static void intel_ddi_mode_set(struct intel_encoder *encoder) DRM_DEBUG_DRIVER("DP audio: write eld information\n"); intel_write_eld(&encoder->base, adjusted_mode); } + + intel_dp_init_link_config(intel_dp); + } else if (type == INTEL_OUTPUT_HDMI) { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); @@ -833,8 +739,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); struct drm_encoder *encoder = &intel_encoder->base; - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = crtc->dev->dev_private; enum pipe pipe = intel_crtc->pipe; enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; enum port port = intel_ddi_get_encoder_port(intel_encoder); @@ -862,19 +767,18 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) BUG(); } - if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_PVSYNC) + if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC) temp |= TRANS_DDI_PVSYNC; - if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_PHSYNC) + if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC) temp |= TRANS_DDI_PHSYNC; if (cpu_transcoder == TRANSCODER_EDP) { switch (pipe) { case PIPE_A: - /* On Haswell, can only use the always-on power well for - * eDP when not using the panel fitter, and when not - * using motion blur mitigation (which we don't - * support). */ - if (IS_HASWELL(dev) && intel_crtc->config.pch_pfit.enabled) + /* Can only use the always-on power well for eDP when + * not using the panel fitter, and when not using motion + * blur mitigation (which we don't support). */ + if (intel_crtc->config.pch_pfit.enabled) temp |= TRANS_DDI_EDP_INPUT_A_ONOFF; else temp |= TRANS_DDI_EDP_INPUT_A_ON; @@ -1158,10 +1062,9 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder) if (wait) intel_wait_ddi_buf_idle(dev_priv, port); - if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { + if (type == INTEL_OUTPUT_EDP) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); ironlake_edp_panel_vdd_on(intel_dp); - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); ironlake_edp_panel_off(intel_dp); } @@ -1236,29 +1139,18 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder) int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv) { - struct drm_device *dev = dev_priv->dev; uint32_t lcpll = I915_READ(LCPLL_CTL); - uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; - if (lcpll & LCPLL_CD_SOURCE_FCLK) { + if (lcpll & LCPLL_CD_SOURCE_FCLK) return 800000; - } else if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT) { + else if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT) return 450000; - } else if (freq == LCPLL_CLK_FREQ_450) { + else if ((lcpll & LCPLL_CLK_FREQ_MASK) == LCPLL_CLK_FREQ_450) return 450000; - } else if (IS_HASWELL(dev)) { - if (IS_ULT(dev)) - return 337500; - else - return 540000; - } else { - if (freq == LCPLL_CLK_FREQ_54O_BDW) - return 540000; - else if (freq == LCPLL_CLK_FREQ_337_5_BDW) - return 337500; - else - return 675000; - } + else if (IS_ULT(dev_priv->dev)) + return 337500; + else + return 540000; } void intel_ddi_pll_init(struct drm_device *dev) @@ -1310,7 +1202,7 @@ void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder) val = DP_TP_CTL_ENABLE | DP_TP_CTL_MODE_SST | DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE; - if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) + if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN) val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE; I915_WRITE(DP_TP_CTL(port), val); POSTING_READ(DP_TP_CTL(port)); @@ -1393,40 +1285,6 @@ void intel_ddi_get_config(struct intel_encoder *encoder, default: break; } - - switch (temp & TRANS_DDI_MODE_SELECT_MASK) { - case TRANS_DDI_MODE_SELECT_HDMI: - case TRANS_DDI_MODE_SELECT_DVI: - case TRANS_DDI_MODE_SELECT_FDI: - break; - case TRANS_DDI_MODE_SELECT_DP_SST: - case TRANS_DDI_MODE_SELECT_DP_MST: - pipe_config->has_dp_encoder = true; - intel_dp_get_m_n(intel_crtc, pipe_config); - break; - default: - break; - } - - if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp_bpp && - pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) { - /* - * This is a big fat ugly hack. - * - * Some machines in UEFI boot mode provide us a VBT that has 18 - * bpp and 1.62 GHz link bandwidth for eDP, which for reasons - * unknown we fail to light up. Yet the same BIOS boots up with - * 24 bpp and 2.7 GHz link. Use the same bpp as the BIOS uses as - * max, not what it tells us to use. - * - * Note: This will still be broken if the eDP panel is not lit - * up by the BIOS, and thus we can't get the mode at module - * load. - */ - DRM_DEBUG_KMS("pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n", - pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp); - dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp; - } } static void intel_ddi_destroy(struct drm_encoder *encoder) @@ -1456,41 +1314,6 @@ static const struct drm_encoder_funcs intel_ddi_funcs = { .destroy = intel_ddi_destroy, }; -static struct intel_connector * -intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port) -{ - struct intel_connector *connector; - enum port port = intel_dig_port->port; - - connector = kzalloc(sizeof(*connector), GFP_KERNEL); - if (!connector) - return NULL; - - intel_dig_port->dp.output_reg = DDI_BUF_CTL(port); - if (!intel_dp_init_connector(intel_dig_port, connector)) { - kfree(connector); - return NULL; - } - - return connector; -} - -static struct intel_connector * -intel_ddi_init_hdmi_connector(struct intel_digital_port *intel_dig_port) -{ - struct intel_connector *connector; - enum port port = intel_dig_port->port; - - connector = kzalloc(sizeof(*connector), GFP_KERNEL); - if (!connector) - return NULL; - - intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port); - intel_hdmi_init_connector(intel_dig_port, connector); - - return connector; -} - void intel_ddi_init(struct drm_device *dev, enum port port) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -1499,22 +1322,17 @@ void intel_ddi_init(struct drm_device *dev, enum port port) struct drm_encoder *encoder; struct intel_connector *hdmi_connector = NULL; struct intel_connector *dp_connector = NULL; - bool init_hdmi, init_dp; - - init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi || - dev_priv->vbt.ddi_port_info[port].supports_hdmi); - init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp; - if (!init_dp && !init_hdmi) { - DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible\n", - port_name(port)); - init_hdmi = true; - init_dp = true; - } - intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); + intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL); if (!intel_dig_port) return; + dp_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); + if (!dp_connector) { + kfree(intel_dig_port); + return; + } + intel_encoder = &intel_dig_port->base; encoder = &intel_encoder->base; @@ -1534,22 +1352,28 @@ void intel_ddi_init(struct drm_device *dev, enum port port) intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) & (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES); + intel_dig_port->dp.output_reg = DDI_BUF_CTL(port); intel_encoder->type = INTEL_OUTPUT_UNKNOWN; intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->cloneable = false; intel_encoder->hot_plug = intel_ddi_hot_plug; - if (init_dp) - dp_connector = intel_ddi_init_dp_connector(intel_dig_port); - - /* In theory we don't need the encoder->type check, but leave it just in - * case we have some really bad VBTs... */ - if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi) - hdmi_connector = intel_ddi_init_hdmi_connector(intel_dig_port); - - if (!dp_connector && !hdmi_connector) { + if (!intel_dp_init_connector(intel_dig_port, dp_connector)) { drm_encoder_cleanup(encoder); kfree(intel_dig_port); + kfree(dp_connector); + return; + } + + if (intel_encoder->type != INTEL_OUTPUT_EDP) { + hdmi_connector = kzalloc(sizeof(struct intel_connector), + GFP_KERNEL); + if (!hdmi_connector) { + return; + } + + intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port); + intel_hdmi_init_connector(intel_dig_port, hdmi_connector); } } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 080f6fd..d78d33f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -41,13 +41,14 @@ #include <drm/drm_crtc_helper.h> #include <linux/dma_remapping.h> +bool intel_pipe_has_type(struct drm_crtc *crtc, int type); static void intel_increase_pllclock(struct drm_crtc *crtc); static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on); static void i9xx_crtc_clock_get(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config); -static void ironlake_pch_clock_get(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config); +static void ironlake_crtc_clock_get(struct intel_crtc *crtc, + struct intel_crtc_config *pipe_config); static int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *old_fb); @@ -68,6 +69,9 @@ struct intel_limit { intel_p2_t p2; }; +/* FDI */ +#define IRONLAKE_FDI_FREQ 2700000 /* in kHz for mode->clock */ + int intel_pch_rawclk(struct drm_device *dev) { @@ -309,44 +313,44 @@ static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = { .p2_slow = 7, .p2_fast = 7 }, }; -static const intel_limit_t intel_limits_vlv = { - /* - * These are the data rate limits (measured in fast clocks) - * since those are the strictest limits we have. The fast - * clock and actual rate limits are more relaxed, so checking - * them would make no difference. - */ - .dot = { .min = 25000 * 5, .max = 270000 * 5 }, +static const intel_limit_t intel_limits_vlv_dac = { + .dot = { .min = 25000, .max = 270000 }, .vco = { .min = 4000000, .max = 6000000 }, .n = { .min = 1, .max = 7 }, + .m = { .min = 22, .max = 450 }, /* guess */ .m1 = { .min = 2, .max = 3 }, .m2 = { .min = 11, .max = 156 }, - .p1 = { .min = 2, .max = 3 }, - .p2 = { .p2_slow = 2, .p2_fast = 20 }, /* slow=min, fast=max */ + .p = { .min = 10, .max = 30 }, + .p1 = { .min = 1, .max = 3 }, + .p2 = { .dot_limit = 270000, + .p2_slow = 2, .p2_fast = 20 }, }; -static void vlv_clock(int refclk, intel_clock_t *clock) -{ - clock->m = clock->m1 * clock->m2; - clock->p = clock->p1 * clock->p2; - clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n); - clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); -} - -/** - * Returns whether any output on the specified pipe is of the specified type - */ -static bool intel_pipe_has_type(struct drm_crtc *crtc, int type) -{ - struct drm_device *dev = crtc->dev; - struct intel_encoder *encoder; - - for_each_encoder_on_crtc(dev, crtc, encoder) - if (encoder->type == type) - return true; +static const intel_limit_t intel_limits_vlv_hdmi = { + .dot = { .min = 25000, .max = 270000 }, + .vco = { .min = 4000000, .max = 6000000 }, + .n = { .min = 1, .max = 7 }, + .m = { .min = 60, .max = 300 }, /* guess */ + .m1 = { .min = 2, .max = 3 }, + .m2 = { .min = 11, .max = 156 }, + .p = { .min = 10, .max = 30 }, + .p1 = { .min = 2, .max = 3 }, + .p2 = { .dot_limit = 270000, + .p2_slow = 2, .p2_fast = 20 }, +}; - return false; -} +static const intel_limit_t intel_limits_vlv_dp = { + .dot = { .min = 25000, .max = 270000 }, + .vco = { .min = 4000000, .max = 6000000 }, + .n = { .min = 1, .max = 7 }, + .m = { .min = 22, .max = 450 }, + .m1 = { .min = 2, .max = 3 }, + .m2 = { .min = 11, .max = 156 }, + .p = { .min = 10, .max = 30 }, + .p1 = { .min = 1, .max = 3 }, + .p2 = { .dot_limit = 270000, + .p2_slow = 2, .p2_fast = 20 }, +}; static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc, int refclk) @@ -408,7 +412,12 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc, int refclk) else limit = &intel_limits_pineview_sdvo; } else if (IS_VALLEYVIEW(dev)) { - limit = &intel_limits_vlv; + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) + limit = &intel_limits_vlv_dac; + else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) + limit = &intel_limits_vlv_hdmi; + else + limit = &intel_limits_vlv_dp; } else if (!IS_GEN2(dev)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) limit = &intel_limits_i9xx_lvds; @@ -430,8 +439,8 @@ static void pineview_clock(int refclk, intel_clock_t *clock) { clock->m = clock->m2 + 2; clock->p = clock->p1 * clock->p2; - clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n); - clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); + clock->vco = refclk * clock->m / clock->n; + clock->dot = clock->vco / clock->p; } static uint32_t i9xx_dpll_compute_m(struct dpll *dpll) @@ -443,8 +452,23 @@ static void i9xx_clock(int refclk, intel_clock_t *clock) { clock->m = i9xx_dpll_compute_m(clock); clock->p = clock->p1 * clock->p2; - clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2); - clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); + clock->vco = refclk * clock->m / (clock->n + 2); + clock->dot = clock->vco / clock->p; +} + +/** + * Returns whether any output on the specified pipe is of the specified type + */ +bool intel_pipe_has_type(struct drm_crtc *crtc, int type) +{ + struct drm_device *dev = crtc->dev; + struct intel_encoder *encoder; + + for_each_encoder_on_crtc(dev, crtc, encoder) + if (encoder->type == type) + return true; + + return false; } #define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0) @@ -457,26 +481,20 @@ static bool intel_PLL_is_valid(struct drm_device *dev, const intel_limit_t *limit, const intel_clock_t *clock) { - if (clock->n < limit->n.min || limit->n.max < clock->n) - INTELPllInvalid("n out of range\n"); if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) INTELPllInvalid("p1 out of range\n"); + if (clock->p < limit->p.min || limit->p.max < clock->p) + INTELPllInvalid("p out of range\n"); if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2) INTELPllInvalid("m2 out of range\n"); if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) INTELPllInvalid("m1 out of range\n"); - - if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev)) - if (clock->m1 <= clock->m2) - INTELPllInvalid("m1 <= m2\n"); - - if (!IS_VALLEYVIEW(dev)) { - if (clock->p < limit->p.min || limit->p.max < clock->p) - INTELPllInvalid("p out of range\n"); - if (clock->m < limit->m.min || limit->m.max < clock->m) - INTELPllInvalid("m out of range\n"); - } - + if (clock->m1 <= clock->m2 && !IS_PINEVIEW(dev)) + INTELPllInvalid("m1 <= m2\n"); + if (clock->m < limit->m.min || limit->m.max < clock->m) + INTELPllInvalid("m out of range\n"); + if (clock->n < limit->n.min || limit->n.max < clock->n) + INTELPllInvalid("n out of range\n"); if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) INTELPllInvalid("vco out of range\n"); /* XXX: We may need to be checking "Dot clock" depending on the multiplier, @@ -670,73 +688,67 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *match_clock, intel_clock_t *best_clock) { - struct drm_device *dev = crtc->dev; - intel_clock_t clock; - unsigned int bestppm = 1000000; - /* min update 19.2 MHz */ - int max_n = min(limit->n.max, refclk / 19200); - bool found = false; - - target *= 5; /* fast clock */ - - memset(best_clock, 0, sizeof(*best_clock)); + u32 p1, p2, m1, m2, vco, bestn, bestm1, bestm2, bestp1, bestp2; + u32 m, n, fastclk; + u32 updrate, minupdate, p; + unsigned long bestppm, ppm, absppm; + int dotclk, flag; + + flag = 0; + dotclk = target * 1000; + bestppm = 1000000; + ppm = absppm = 0; + fastclk = dotclk / (2*100); + updrate = 0; + minupdate = 19200; + n = p = p1 = p2 = m = m1 = m2 = vco = bestn = 0; + bestm1 = bestm2 = bestp1 = bestp2 = 0; /* based on hardware requirement, prefer smaller n to precision */ - for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) { - for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) { - for (clock.p2 = limit->p2.p2_fast; clock.p2 >= limit->p2.p2_slow; - clock.p2 -= clock.p2 > 10 ? 2 : 1) { - clock.p = clock.p1 * clock.p2; + for (n = limit->n.min; n <= ((refclk) / minupdate); n++) { + updrate = refclk / n; + for (p1 = limit->p1.max; p1 > limit->p1.min; p1--) { + for (p2 = limit->p2.p2_fast+1; p2 > 0; p2--) { + if (p2 > 10) + p2 = p2 - 1; + p = p1 * p2; /* based on hardware requirement, prefer bigger m1,m2 values */ - for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { - unsigned int ppm, diff; - - clock.m2 = DIV_ROUND_CLOSEST(target * clock.p * clock.n, - refclk * clock.m1); - - vlv_clock(refclk, &clock); - - if (!intel_PLL_is_valid(dev, limit, - &clock)) - continue; - - diff = abs(clock.dot - target); - ppm = div_u64(1000000ULL * diff, target); - - if (ppm < 100 && clock.p > best_clock->p) { - bestppm = 0; - *best_clock = clock; - found = true; - } - - if (bestppm >= 10 && ppm < bestppm - 10) { - bestppm = ppm; - *best_clock = clock; - found = true; + for (m1 = limit->m1.min; m1 <= limit->m1.max; m1++) { + m2 = (((2*(fastclk * p * n / m1 )) + + refclk) / (2*refclk)); + m = m1 * m2; + vco = updrate * m; + if (vco >= limit->vco.min && vco < limit->vco.max) { + ppm = 1000000 * ((vco / p) - fastclk) / fastclk; + absppm = (ppm > 0) ? ppm : (-ppm); + if (absppm < 100 && ((p1 * p2) > (bestp1 * bestp2))) { + bestppm = 0; + flag = 1; + } + if (absppm < bestppm - 10) { + bestppm = absppm; + flag = 1; + } + if (flag) { + bestn = n; + bestm1 = m1; + bestm2 = m2; + bestp1 = p1; + bestp2 = p2; + flag = 0; + } } } } } } + best_clock->n = bestn; + best_clock->m1 = bestm1; + best_clock->m2 = bestm2; + best_clock->p1 = bestp1; + best_clock->p2 = bestp2; - return found; -} - -bool intel_crtc_active(struct drm_crtc *crtc) -{ - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - /* Be paranoid as we can arrive here with only partial - * state retrieved from the hardware during setup. - * - * We can ditch the adjusted_mode.crtc_clock check as soon - * as Haswell has gained clock readout/fastboot support. - * - * We can ditch the crtc->fb check as soon as we can - * properly reconstruct framebuffers. - */ - return intel_crtc->active && crtc->fb && - intel_crtc->config.adjusted_mode.crtc_clock; + return true; } enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, @@ -800,25 +812,6 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe) DRM_DEBUG_KMS("vblank wait timed out\n"); } -static bool pipe_dsl_stopped(struct drm_device *dev, enum pipe pipe) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - u32 reg = PIPEDSL(pipe); - u32 line1, line2; - u32 line_mask; - - if (IS_GEN2(dev)) - line_mask = DSL_LINEMASK_GEN2; - else - line_mask = DSL_LINEMASK_GEN3; - - line1 = I915_READ(reg) & line_mask; - mdelay(5); - line2 = I915_READ(reg) & line_mask; - - return line1 == line2; -} - /* * intel_wait_for_pipe_off - wait for pipe to turn off * @dev: drm device @@ -850,8 +843,22 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe) 100)) WARN(1, "pipe_off wait timed out\n"); } else { + u32 last_line, line_mask; + int reg = PIPEDSL(pipe); + unsigned long timeout = jiffies + msecs_to_jiffies(100); + + if (IS_GEN2(dev)) + line_mask = DSL_LINEMASK_GEN2; + else + line_mask = DSL_LINEMASK_GEN3; + /* Wait for the display line to settle */ - if (wait_for(pipe_dsl_stopped(dev, pipe), 100)) + do { + last_line = I915_READ(reg) & line_mask; + mdelay(5); + } while (((I915_READ(reg) & line_mask) != last_line) && + time_after(timeout, jiffies)); + if (time_after(jiffies, timeout)) WARN(1, "pipe_off wait timed out\n"); } } @@ -922,24 +929,6 @@ void assert_pll(struct drm_i915_private *dev_priv, state_string(state), state_string(cur_state)); } -/* XXX: the dsi pll is shared between MIPI DSI ports */ -static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state) -{ - u32 val; - bool cur_state; - - mutex_lock(&dev_priv->dpio_lock); - val = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); - mutex_unlock(&dev_priv->dpio_lock); - - cur_state = val & DSI_PLL_VCO_EN; - WARN(cur_state != state, - "DSI PLL state assertion failure (expected %s, current %s)\n", - state_string(state), state_string(cur_state)); -} -#define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true) -#define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false) - struct intel_shared_dpll * intel_crtc_to_shared_dpll(struct intel_crtc *crtc) { @@ -1080,26 +1069,6 @@ static void assert_panel_unlocked(struct drm_i915_private *dev_priv, pipe_name(pipe)); } -static void assert_cursor(struct drm_i915_private *dev_priv, - enum pipe pipe, bool state) -{ - struct drm_device *dev = dev_priv->dev; - bool cur_state; - - if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) - cur_state = I915_READ(CURCNTR_IVB(pipe)) & CURSOR_MODE; - else if (IS_845G(dev) || IS_I865G(dev)) - cur_state = I915_READ(_CURACNTR) & CURSOR_ENABLE; - else - cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; - - WARN(cur_state != state, - "cursor on pipe %c assertion failure (expected %s, current %s)\n", - pipe_name(pipe), state_string(state), state_string(cur_state)); -} -#define assert_cursor_enabled(d, p) assert_cursor(d, p, true) -#define assert_cursor_disabled(d, p) assert_cursor(d, p, false) - void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state) { @@ -1354,26 +1323,6 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMID); } -static void intel_init_dpio(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (!IS_VALLEYVIEW(dev)) - return; - - /* - * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx - - * 6. De-assert cmn_reset/side_reset. Same as VLV X0. - * a. GUnit 0x2110 bit[0] set to 1 (def 0) - * b. The other bits such as sfr settings / modesel may all be set - * to 0. - * - * This should only be done on init and resume from S3 with both - * PLLs disabled, or we risk losing DPIO and PLL synchronization. - */ - I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) | DPIO_CMNRST); -} - static void vlv_enable_pll(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; @@ -1480,20 +1429,6 @@ static void i9xx_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) POSTING_READ(DPLL(pipe)); } -static void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) -{ - u32 val = 0; - - /* Make sure the pipe isn't still relying on us */ - assert_pipe_disabled(dev_priv, pipe); - - /* Leave integrated clock source enabled */ - if (pipe == PIPE_B) - val = DPLL_INTEGRATED_CRI_CLK_VLV; - I915_WRITE(DPLL(pipe), val); - POSTING_READ(DPLL(pipe)); -} - void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port) { u32 port_mask; @@ -1726,7 +1661,7 @@ static void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv) * returning. */ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, - bool pch_port, bool dsi) + bool pch_port) { enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, pipe); @@ -1735,7 +1670,6 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, u32 val; assert_planes_disabled(dev_priv, pipe); - assert_cursor_disabled(dev_priv, pipe); assert_sprites_disabled(dev_priv, pipe); if (HAS_PCH_LPT(dev_priv->dev)) @@ -1749,10 +1683,7 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, * need the check. */ if (!HAS_PCH_SPLIT(dev_priv->dev)) - if (dsi) - assert_dsi_pll_enabled(dev_priv); - else - assert_pll_enabled(dev_priv, pipe); + assert_pll_enabled(dev_priv, pipe); else { if (pch_port) { /* if driving the PCH, we need FDI enabled */ @@ -1797,7 +1728,6 @@ static void intel_disable_pipe(struct drm_i915_private *dev_priv, * or we might hang the display. */ assert_planes_disabled(dev_priv, pipe); - assert_cursor_disabled(dev_priv, pipe); assert_sprites_disabled(dev_priv, pipe); /* Don't disable pipe A or pipe A PLLs if needed */ @@ -1817,75 +1747,63 @@ static void intel_disable_pipe(struct drm_i915_private *dev_priv, * Plane regs are double buffered, going from enabled->disabled needs a * trigger in order to latch. The display address reg provides this. */ -void intel_flush_primary_plane(struct drm_i915_private *dev_priv, - enum plane plane) +void intel_flush_display_plane(struct drm_i915_private *dev_priv, + enum plane plane) { - u32 reg = dev_priv->info->gen >= 4 ? DSPSURF(plane) : DSPADDR(plane); - - I915_WRITE(reg, I915_READ(reg)); - POSTING_READ(reg); + if (dev_priv->info->gen >= 4) + I915_WRITE(DSPSURF(plane), I915_READ(DSPSURF(plane))); + else + I915_WRITE(DSPADDR(plane), I915_READ(DSPADDR(plane))); } /** - * intel_enable_primary_plane - enable the primary plane on a given pipe + * intel_enable_plane - enable a display plane on a given pipe * @dev_priv: i915 private structure * @plane: plane to enable * @pipe: pipe being fed * * Enable @plane on @pipe, making sure that @pipe is running first. */ -static void intel_enable_primary_plane(struct drm_i915_private *dev_priv, - enum plane plane, enum pipe pipe) +static void intel_enable_plane(struct drm_i915_private *dev_priv, + enum plane plane, enum pipe pipe) { - struct intel_crtc *intel_crtc = - to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); int reg; u32 val; /* If the pipe isn't enabled, we can't pump pixels and may hang */ assert_pipe_enabled(dev_priv, pipe); - WARN(intel_crtc->primary_enabled, "Primary plane already enabled\n"); - - intel_crtc->primary_enabled = true; - reg = DSPCNTR(plane); val = I915_READ(reg); if (val & DISPLAY_PLANE_ENABLE) return; I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE); - intel_flush_primary_plane(dev_priv, plane); + intel_flush_display_plane(dev_priv, plane); intel_wait_for_vblank(dev_priv->dev, pipe); } /** - * intel_disable_primary_plane - disable the primary plane + * intel_disable_plane - disable a display plane * @dev_priv: i915 private structure * @plane: plane to disable * @pipe: pipe consuming the data * * Disable @plane; should be an independent operation. */ -static void intel_disable_primary_plane(struct drm_i915_private *dev_priv, - enum plane plane, enum pipe pipe) +static void intel_disable_plane(struct drm_i915_private *dev_priv, + enum plane plane, enum pipe pipe) { - struct intel_crtc *intel_crtc = - to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); int reg; u32 val; - WARN(!intel_crtc->primary_enabled, "Primary plane already disabled\n"); - - intel_crtc->primary_enabled = false; - reg = DSPCNTR(plane); val = I915_READ(reg); if ((val & DISPLAY_PLANE_ENABLE) == 0) return; I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE); - intel_flush_primary_plane(dev_priv, plane); + intel_flush_display_plane(dev_priv, plane); intel_wait_for_vblank(dev_priv->dev, pipe); } @@ -1921,7 +1839,10 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, alignment = 0; break; case I915_TILING_Y: - WARN(1, "Y tiled bo slipped through, driver bug!\n"); + /* Despite that we check this in framebuffer_init userspace can + * screw us over and change the tiling after the fact. Only + * pinned buffers can't change their tiling. */ + DRM_DEBUG_DRIVER("Y tiled not allowed for scan out buffers\n"); return -EINVAL; default: BUG(); @@ -2156,7 +2077,7 @@ static int ironlake_update_plane(struct drm_crtc *crtc, else dspcntr &= ~DISPPLANE_TILED; - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_HASWELL(dev)) dspcntr &= ~DISPPLANE_TRICKLE_FEED_DISABLE; else dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; @@ -2176,7 +2097,7 @@ static int ironlake_update_plane(struct drm_crtc *crtc, I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); I915_MODIFY_DISPBASE(DSPSURF(plane), i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + if (IS_HASWELL(dev)) { I915_WRITE(DSPOFFSET(plane), (y << 16) | x); } else { I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); @@ -2323,26 +2244,11 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, return ret; } - /* - * Update pipe size and adjust fitter if needed: the reason for this is - * that in compute_mode_changes we check the native mode (not the pfit - * mode) to see if we can flip rather than do a full mode set. In the - * fastboot case, we'll flip, but if we don't update the pipesrc and - * pfit state, we'll end up with a big fb scanned out into the wrong - * sized surface. - * - * To fix this properly, we need to hoist the checks up into - * compute_mode_changes (or above), check the actual pfit state and - * whether the platform allows pfit disable with pipe active, and only - * then update the pipesrc and pfit state, even on the flip path. - */ + /* Update pipe size and adjust fitter if needed */ if (i915_fastboot) { - const struct drm_display_mode *adjusted_mode = - &intel_crtc->config.adjusted_mode; - I915_WRITE(PIPESRC(intel_crtc->pipe), - ((adjusted_mode->crtc_hdisplay - 1) << 16) | - (adjusted_mode->crtc_vdisplay - 1)); + ((crtc->mode.hdisplay - 1) << 16) | + (crtc->mode.vdisplay - 1)); if (!intel_crtc->config.pch_pfit.enabled && (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) { @@ -2967,7 +2873,6 @@ static void lpt_program_iclkip(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - int clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; u32 divsel, phaseinc, auxdiv, phasedir = 0; u32 temp; @@ -2985,14 +2890,14 @@ static void lpt_program_iclkip(struct drm_crtc *crtc) SBI_ICLK); /* 20MHz is a corner case which is out of range for the 7-bit divisor */ - if (clock == 20000) { + if (crtc->mode.clock == 20000) { auxdiv = 1; divsel = 0x41; phaseinc = 0x20; } else { /* The iCLK virtual clock root frequency is in MHz, - * but the adjusted_mode->crtc_clock in in KHz. To get the - * divisors, it is necessary to divide one by another, so we + * but the crtc->mode.clock in in KHz. To get the divisors, + * it is necessary to divide one by another, so we * convert the virtual clock precision to KHz here for higher * precision. */ @@ -3000,7 +2905,7 @@ static void lpt_program_iclkip(struct drm_crtc *crtc) u32 iclk_pi_range = 64; u32 desired_divisor, msb_divisor_value, pi_value; - desired_divisor = (iclk_virtual_root_freq / clock); + desired_divisor = (iclk_virtual_root_freq / crtc->mode.clock); msb_divisor_value = desired_divisor / iclk_pi_range; pi_value = desired_divisor % iclk_pi_range; @@ -3016,7 +2921,7 @@ static void lpt_program_iclkip(struct drm_crtc *crtc) ~SBI_SSCDIVINTPHASE_INCVAL_MASK); DRM_DEBUG_KMS("iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n", - clock, + crtc->mode.clock, auxdiv, divsel, phasedir, @@ -3381,108 +3286,6 @@ static void intel_disable_planes(struct drm_crtc *crtc) intel_plane_disable(&intel_plane->base); } -void hsw_enable_ips(struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - - if (!crtc->config.ips_enabled) - return; - - /* We can only enable IPS after we enable a plane and wait for a vblank. - * We guarantee that the plane is enabled by calling intel_enable_ips - * only after intel_enable_plane. And intel_enable_plane already waits - * for a vblank, so all we need to do here is to enable the IPS bit. */ - assert_plane_enabled(dev_priv, crtc->plane); - if (IS_BROADWELL(crtc->base.dev)) { - mutex_lock(&dev_priv->rps.hw_lock); - WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0xc0000000)); - mutex_unlock(&dev_priv->rps.hw_lock); - /* Quoting Art Runyan: "its not safe to expect any particular - * value in IPS_CTL bit 31 after enabling IPS through the - * mailbox." Therefore we need to defer waiting on the state - * change. - * TODO: need to fix this for state checker - */ - } else { - I915_WRITE(IPS_CTL, IPS_ENABLE); - /* The bit only becomes 1 in the next vblank, so this wait here - * is essentially intel_wait_for_vblank. If we don't have this - * and don't wait for vblanks until the end of crtc_enable, then - * the HW state readout code will complain that the expected - * IPS_CTL value is not the one we read. */ - if (wait_for(I915_READ_NOTRACE(IPS_CTL) & IPS_ENABLE, 50)) - DRM_ERROR("Timed out waiting for IPS enable\n"); - } -} - -void hsw_disable_ips(struct intel_crtc *crtc) -{ - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - - if (!crtc->config.ips_enabled) - return; - - assert_plane_enabled(dev_priv, crtc->plane); - if (IS_BROADWELL(crtc->base.dev)) { - mutex_lock(&dev_priv->rps.hw_lock); - WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0)); - mutex_unlock(&dev_priv->rps.hw_lock); - } else - I915_WRITE(IPS_CTL, 0); - POSTING_READ(IPS_CTL); - - /* We need to wait for a vblank before we can disable the plane. */ - intel_wait_for_vblank(dev, crtc->pipe); -} - -/** Loads the palette/gamma unit for the CRTC with the prepared values */ -static void intel_crtc_load_lut(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; - int palreg = PALETTE(pipe); - int i; - bool reenable_ips = false; - - /* The clocks have to be on to load the palette. */ - if (!crtc->enabled || !intel_crtc->active) - return; - - if (!HAS_PCH_SPLIT(dev_priv->dev)) { - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI)) - assert_dsi_pll_enabled(dev_priv); - else - assert_pll_enabled(dev_priv, pipe); - } - - /* use legacy palette for Ironlake */ - if (HAS_PCH_SPLIT(dev)) - palreg = LGC_PALETTE(pipe); - - /* Workaround : Do not read or write the pipe palette/gamma data while - * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled. - */ - if (intel_crtc->config.ips_enabled && - ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) == - GAMMA_MODE_MODE_SPLIT)) { - hsw_disable_ips(intel_crtc); - reenable_ips = true; - } - - for (i = 0; i < 256; i++) { - I915_WRITE(palreg + 4 * i, - (intel_crtc->lut_r[i] << 16) | - (intel_crtc->lut_g[i] << 8) | - intel_crtc->lut_b[i]); - } - - if (reenable_ips) - hsw_enable_ips(intel_crtc); -} - static void ironlake_crtc_enable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -3502,6 +3305,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); intel_set_pch_fifo_underrun_reporting(dev, pipe, true); + intel_update_watermarks(dev); + for_each_encoder_on_crtc(dev, crtc, encoder) if (encoder->pre_enable) encoder->pre_enable(encoder); @@ -3524,10 +3329,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) */ intel_crtc_load_lut(crtc); - intel_update_watermarks(crtc); intel_enable_pipe(dev_priv, pipe, - intel_crtc->config.has_pch_encoder, false); - intel_enable_primary_plane(dev_priv, plane, pipe); + intel_crtc->config.has_pch_encoder); + intel_enable_plane(dev_priv, plane, pipe); intel_enable_planes(crtc); intel_crtc_update_cursor(crtc, true); @@ -3561,74 +3365,34 @@ static bool hsw_crtc_supports_ips(struct intel_crtc *crtc) return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A; } -static void haswell_crtc_enable_planes(struct drm_crtc *crtc) +static void hsw_enable_ips(struct intel_crtc *crtc) { - 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; - int plane = intel_crtc->plane; - - intel_enable_primary_plane(dev_priv, plane, pipe); - intel_enable_planes(crtc); - intel_crtc_update_cursor(crtc, true); - - hsw_enable_ips(intel_crtc); - - mutex_lock(&dev->struct_mutex); - intel_update_fbc(dev); - mutex_unlock(&dev->struct_mutex); -} - -static void haswell_crtc_disable_planes(struct drm_crtc *crtc) -{ - 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; - int plane = intel_crtc->plane; - - intel_crtc_wait_for_pending_flips(crtc); - drm_vblank_off(dev, pipe); - - /* FBC must be disabled before disabling the plane on HSW. */ - if (dev_priv->fbc.plane == plane) - intel_disable_fbc(dev); + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - hsw_disable_ips(intel_crtc); + if (!crtc->config.ips_enabled) + return; - intel_crtc_update_cursor(crtc, false); - intel_disable_planes(crtc); - intel_disable_primary_plane(dev_priv, plane, pipe); + /* We can only enable IPS after we enable a plane and wait for a vblank. + * We guarantee that the plane is enabled by calling intel_enable_ips + * only after intel_enable_plane. And intel_enable_plane already waits + * for a vblank, so all we need to do here is to enable the IPS bit. */ + assert_plane_enabled(dev_priv, crtc->plane); + I915_WRITE(IPS_CTL, IPS_ENABLE); } -/* - * This implements the workaround described in the "notes" section of the mode - * set sequence documentation. When going from no pipes or single pipe to - * multiple pipes, and planes are enabled after the pipe, we need to wait at - * least 2 vblanks on the first pipe before enabling planes on the second pipe. - */ -static void haswell_mode_set_planes_workaround(struct intel_crtc *crtc) +static void hsw_disable_ips(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; - struct intel_crtc *crtc_it, *other_active_crtc = NULL; - - /* We want to get the other_active_crtc only if there's only 1 other - * active crtc. */ - list_for_each_entry(crtc_it, &dev->mode_config.crtc_list, base.head) { - if (!crtc_it->active || crtc_it == crtc) - continue; - - if (other_active_crtc) - return; + struct drm_i915_private *dev_priv = dev->dev_private; - other_active_crtc = crtc_it; - } - if (!other_active_crtc) + if (!crtc->config.ips_enabled) return; - intel_wait_for_vblank(dev, other_active_crtc->pipe); - intel_wait_for_vblank(dev, other_active_crtc->pipe); + assert_plane_enabled(dev_priv, crtc->plane); + I915_WRITE(IPS_CTL, 0); + + /* We need to wait for a vblank before we can disable the plane. */ + intel_wait_for_vblank(dev, crtc->pipe); } static void haswell_crtc_enable(struct drm_crtc *crtc) @@ -3638,6 +3402,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; + int plane = intel_crtc->plane; WARN_ON(!crtc->enabled); @@ -3650,6 +3415,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) if (intel_crtc->config.has_pch_encoder) intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true); + intel_update_watermarks(dev); + if (intel_crtc->config.has_pch_encoder) dev_priv->display.fdi_link_train(crtc); @@ -3670,22 +3437,23 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) intel_ddi_set_pipe_settings(crtc); intel_ddi_enable_transcoder_func(crtc); - intel_update_watermarks(crtc); intel_enable_pipe(dev_priv, pipe, - intel_crtc->config.has_pch_encoder, false); + intel_crtc->config.has_pch_encoder); + intel_enable_plane(dev_priv, plane, pipe); + intel_enable_planes(crtc); + intel_crtc_update_cursor(crtc, true); + + hsw_enable_ips(intel_crtc); if (intel_crtc->config.has_pch_encoder) lpt_pch_enable(crtc); - for_each_encoder_on_crtc(dev, crtc, encoder) { - encoder->enable(encoder); - intel_opregion_notify_encoder(encoder, true); - } + mutex_lock(&dev->struct_mutex); + intel_update_fbc(dev); + mutex_unlock(&dev->struct_mutex); - /* If we change the relative order between pipe/planes enabling, we need - * to change the workaround. */ - haswell_mode_set_planes_workaround(intel_crtc); - haswell_crtc_enable_planes(crtc); + for_each_encoder_on_crtc(dev, crtc, encoder) + encoder->enable(encoder); /* * There seems to be a race in PCH platform hw (at least on some @@ -3738,7 +3506,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) intel_crtc_update_cursor(crtc, false); intel_disable_planes(crtc); - intel_disable_primary_plane(dev_priv, plane, pipe); + intel_disable_plane(dev_priv, plane, pipe); if (intel_crtc->config.has_pch_encoder) intel_set_pch_fifo_underrun_reporting(dev, pipe, false); @@ -3779,7 +3547,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) } intel_crtc->active = false; - intel_update_watermarks(crtc); + intel_update_watermarks(dev); mutex_lock(&dev->struct_mutex); intel_update_fbc(dev); @@ -3793,17 +3561,27 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; + int plane = intel_crtc->plane; enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; if (!intel_crtc->active) return; - haswell_crtc_disable_planes(crtc); - - for_each_encoder_on_crtc(dev, crtc, encoder) { - intel_opregion_notify_encoder(encoder, false); + for_each_encoder_on_crtc(dev, crtc, encoder) encoder->disable(encoder); - } + + intel_crtc_wait_for_pending_flips(crtc); + drm_vblank_off(dev, pipe); + + /* FBC must be disabled before disabling the plane on HSW. */ + if (dev_priv->fbc.plane == plane) + intel_disable_fbc(dev); + + hsw_disable_ips(intel_crtc); + + intel_crtc_update_cursor(crtc, false); + intel_disable_planes(crtc); + intel_disable_plane(dev_priv, plane, pipe); if (intel_crtc->config.has_pch_encoder) intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, false); @@ -3826,7 +3604,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) } intel_crtc->active = false; - intel_update_watermarks(crtc); + intel_update_watermarks(dev); mutex_lock(&dev->struct_mutex); intel_update_fbc(dev); @@ -3918,7 +3696,6 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) struct intel_encoder *encoder; int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; - bool is_dsi; WARN_ON(!crtc->enabled); @@ -3926,15 +3703,13 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) return; intel_crtc->active = true; + intel_update_watermarks(dev); for_each_encoder_on_crtc(dev, crtc, encoder) if (encoder->pre_pll_enable) encoder->pre_pll_enable(encoder); - is_dsi = intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI); - - if (!is_dsi) - vlv_enable_pll(intel_crtc); + vlv_enable_pll(intel_crtc); for_each_encoder_on_crtc(dev, crtc, encoder) if (encoder->pre_enable) @@ -3944,9 +3719,8 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) intel_crtc_load_lut(crtc); - intel_update_watermarks(crtc); - intel_enable_pipe(dev_priv, pipe, false, is_dsi); - intel_enable_primary_plane(dev_priv, plane, pipe); + intel_enable_pipe(dev_priv, pipe, false); + intel_enable_plane(dev_priv, plane, pipe); intel_enable_planes(crtc); intel_crtc_update_cursor(crtc, true); @@ -3971,6 +3745,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) return; intel_crtc->active = true; + intel_update_watermarks(dev); for_each_encoder_on_crtc(dev, crtc, encoder) if (encoder->pre_enable) @@ -3982,9 +3757,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) intel_crtc_load_lut(crtc); - intel_update_watermarks(crtc); - intel_enable_pipe(dev_priv, pipe, false, false); - intel_enable_primary_plane(dev_priv, plane, pipe); + intel_enable_pipe(dev_priv, pipe, false); + intel_enable_plane(dev_priv, plane, pipe); intel_enable_planes(crtc); /* The fixup needs to happen before cursor is enabled */ if (IS_G4X(dev)) @@ -4040,7 +3814,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) intel_crtc_dpms_overlay(intel_crtc, false); intel_crtc_update_cursor(crtc, false); intel_disable_planes(crtc); - intel_disable_primary_plane(dev_priv, plane, pipe); + intel_disable_plane(dev_priv, plane, pipe); intel_disable_pipe(dev_priv, pipe); @@ -4050,15 +3824,11 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) if (encoder->post_disable) encoder->post_disable(encoder); - if (IS_VALLEYVIEW(dev) && !intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI)) - vlv_disable_pll(dev_priv, pipe); - else if (!IS_VALLEYVIEW(dev)) - i9xx_disable_pll(dev_priv, pipe); + i9xx_disable_pll(dev_priv, pipe); intel_crtc->active = false; - intel_update_watermarks(crtc); - intel_update_fbc(dev); + intel_update_watermarks(dev); } static void i9xx_crtc_off(struct drm_crtc *crtc) @@ -4132,7 +3902,6 @@ static void intel_crtc_disable(struct drm_crtc *crtc) dev_priv->display.off(crtc); assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane); - assert_cursor_disabled(dev_priv, to_intel_crtc(crtc)->pipe); assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe); if (crtc->fb) { @@ -4260,7 +4029,7 @@ static bool ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, return false; } - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + if (IS_HASWELL(dev)) { if (pipe_config->fdi_lanes > 2) { DRM_DEBUG_KMS("only 2 lanes on haswell, required: %i lanes\n", pipe_config->fdi_lanes); @@ -4322,7 +4091,8 @@ retry: */ link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; - fdi_dotclock = adjusted_mode->crtc_clock; + fdi_dotclock = adjusted_mode->clock; + fdi_dotclock /= pipe_config->pixel_multiplier; lane = ironlake_get_lanes_required(fdi_dotclock, link_bw, pipe_config->pipe_bpp); @@ -4364,39 +4134,13 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, struct drm_device *dev = crtc->base.dev; struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; - /* FIXME should check pixel clock limits on all platforms */ - if (INTEL_INFO(dev)->gen < 4) { - struct drm_i915_private *dev_priv = dev->dev_private; - int clock_limit = - dev_priv->display.get_display_clock_speed(dev); - - /* - * Enable pixel doubling when the dot clock - * is > 90% of the (display) core speed. - * - * GDG double wide on either pipe, - * otherwise pipe A only. - */ - if ((crtc->pipe == PIPE_A || IS_I915G(dev)) && - adjusted_mode->crtc_clock > clock_limit * 9 / 10) { - clock_limit *= 2; - pipe_config->double_wide = true; - } - - if (adjusted_mode->crtc_clock > clock_limit * 9 / 10) + if (HAS_PCH_SPLIT(dev)) { + /* FDI link clock is fixed at 2.7G */ + if (pipe_config->requested_mode.clock * 3 + > IRONLAKE_FDI_FREQ * 4) return -EINVAL; } - /* - * Pipe horizontal size must be even in: - * - DVO ganged mode - * - LVDS dual channel mode - * - Double wide pipe - */ - if ((intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) && - intel_is_dual_link_lvds(dev)) || pipe_config->double_wide) - pipe_config->pipe_src_w &= ~1; - /* Cantiga+ cannot handle modes with a hsync front porch of 0. * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw. */ @@ -4560,6 +4304,28 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE); } +static int vlv_get_refclk(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int refclk = 27000; /* for DP & HDMI */ + + return 100000; /* only one validated so far */ + + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { + refclk = 96000; + } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { + if (intel_panel_use_ssc(dev_priv)) + refclk = 100000; + else + refclk = 96000; + } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) { + refclk = 100000; + } + + return refclk; +} + static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) { struct drm_device *dev = crtc->dev; @@ -4567,7 +4333,7 @@ static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) int refclk; if (IS_VALLEYVIEW(dev)) { - refclk = 100000; + refclk = vlv_get_refclk(crtc); } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { refclk = dev_priv->vbt.lvds_ssc_freq * 1000; @@ -4625,8 +4391,7 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc, } } -static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe - pipe) +static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv) { u32 reg_val; @@ -4634,24 +4399,24 @@ static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe * PLLB opamp always calibrates to max value of 0x3f, force enable it * and set it to a reasonable value instead. */ - reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF(1)); + reg_val = vlv_dpio_read(dev_priv, DPIO_IREF(1)); reg_val &= 0xffffff00; reg_val |= 0x00000030; - vlv_dpio_write(dev_priv, pipe, DPIO_IREF(1), reg_val); + vlv_dpio_write(dev_priv, DPIO_IREF(1), reg_val); - reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_CALIBRATION); + reg_val = vlv_dpio_read(dev_priv, DPIO_CALIBRATION); reg_val &= 0x8cffffff; reg_val = 0x8c000000; - vlv_dpio_write(dev_priv, pipe, DPIO_CALIBRATION, reg_val); + vlv_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val); - reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF(1)); + reg_val = vlv_dpio_read(dev_priv, DPIO_IREF(1)); reg_val &= 0xffffff00; - vlv_dpio_write(dev_priv, pipe, DPIO_IREF(1), reg_val); + vlv_dpio_write(dev_priv, DPIO_IREF(1), reg_val); - reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_CALIBRATION); + reg_val = vlv_dpio_read(dev_priv, DPIO_CALIBRATION); reg_val &= 0x00ffffff; reg_val |= 0xb0000000; - vlv_dpio_write(dev_priv, pipe, DPIO_CALIBRATION, reg_val); + vlv_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val); } static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc, @@ -4717,18 +4482,18 @@ static void vlv_update_pll(struct intel_crtc *crtc) /* PLL B needs special handling */ if (pipe) - vlv_pllb_recal_opamp(dev_priv, pipe); + vlv_pllb_recal_opamp(dev_priv); /* Set up Tx target for periodic Rcomp update */ - vlv_dpio_write(dev_priv, pipe, DPIO_IREF_BCAST, 0x0100000f); + vlv_dpio_write(dev_priv, DPIO_IREF_BCAST, 0x0100000f); /* Disable target IRef on PLL */ - reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF_CTL(pipe)); + reg_val = vlv_dpio_read(dev_priv, DPIO_IREF_CTL(pipe)); reg_val &= 0x00ffffff; - vlv_dpio_write(dev_priv, pipe, DPIO_IREF_CTL(pipe), reg_val); + vlv_dpio_write(dev_priv, DPIO_IREF_CTL(pipe), reg_val); /* Disable fast lock */ - vlv_dpio_write(dev_priv, pipe, DPIO_FASTCLK_DISABLE, 0x610); + vlv_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x610); /* Set idtafcrecal before PLL is enabled */ mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK)); @@ -4742,55 +4507,55 @@ static void vlv_update_pll(struct intel_crtc *crtc) * Note: don't use the DAC post divider as it seems unstable. */ mdiv |= (DPIO_POST_DIV_HDMIDP << DPIO_POST_DIV_SHIFT); - vlv_dpio_write(dev_priv, pipe, DPIO_DIV(pipe), mdiv); + vlv_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv); mdiv |= DPIO_ENABLE_CALIBRATION; - vlv_dpio_write(dev_priv, pipe, DPIO_DIV(pipe), mdiv); + vlv_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv); /* Set HBR and RBR LPF coefficients */ if (crtc->config.port_clock == 162000 || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_ANALOG) || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI)) - vlv_dpio_write(dev_priv, pipe, DPIO_LPF_COEFF(pipe), + vlv_dpio_write(dev_priv, DPIO_LPF_COEFF(pipe), 0x009f0003); else - vlv_dpio_write(dev_priv, pipe, DPIO_LPF_COEFF(pipe), + vlv_dpio_write(dev_priv, DPIO_LPF_COEFF(pipe), 0x00d0000f); if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) { /* Use SSC source */ if (!pipe) - vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe), + vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe), 0x0df40000); else - vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe), + vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe), 0x0df70000); } else { /* HDMI or VGA */ /* Use bend source */ if (!pipe) - vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe), + vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe), 0x0df70000); else - vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe), + vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe), 0x0df40000); } - coreclk = vlv_dpio_read(dev_priv, pipe, DPIO_CORE_CLK(pipe)); + coreclk = vlv_dpio_read(dev_priv, DPIO_CORE_CLK(pipe)); coreclk = (coreclk & 0x0000ff00) | 0x01c00000; if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT) || intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP)) coreclk |= 0x01000000; - vlv_dpio_write(dev_priv, pipe, DPIO_CORE_CLK(pipe), coreclk); + vlv_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), coreclk); - vlv_dpio_write(dev_priv, pipe, DPIO_PLL_CML(pipe), 0x87871000); + vlv_dpio_write(dev_priv, DPIO_PLL_CML(pipe), 0x87871000); /* Enable DPIO clock input */ dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV; - /* We should never disable this, set it here for state tracking */ - if (pipe == PIPE_B) + if (pipe) dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; + dpll |= DPLL_VCO_ENABLE; crtc->config.dpll_hw_state.dpll = dpll; @@ -4928,6 +4693,7 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc) enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; struct drm_display_mode *adjusted_mode = &intel_crtc->config.adjusted_mode; + struct drm_display_mode *mode = &intel_crtc->config.requested_mode; uint32_t vsyncshift, crtc_vtotal, crtc_vblank_end; /* We need to be careful not to changed the adjusted mode, for otherwise @@ -4980,8 +4746,7 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc) * always be the user's requested size. */ I915_WRITE(PIPESRC(pipe), - ((intel_crtc->config.pipe_src_w - 1) << 16) | - (intel_crtc->config.pipe_src_h - 1)); + ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); } static void intel_get_pipe_timings(struct intel_crtc *crtc, @@ -5019,11 +4784,8 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc, } tmp = I915_READ(PIPESRC(crtc->pipe)); - pipe_config->pipe_src_h = (tmp & 0xffff) + 1; - pipe_config->pipe_src_w = ((tmp >> 16) & 0xffff) + 1; - - pipe_config->requested_mode.vdisplay = pipe_config->pipe_src_h; - pipe_config->requested_mode.hdisplay = pipe_config->pipe_src_w; + pipe_config->requested_mode.vdisplay = (tmp & 0xffff) + 1; + pipe_config->requested_mode.hdisplay = ((tmp >> 16) & 0xffff) + 1; } static void intel_crtc_mode_from_pipe_config(struct intel_crtc *intel_crtc, @@ -5043,7 +4805,7 @@ static void intel_crtc_mode_from_pipe_config(struct intel_crtc *intel_crtc, crtc->mode.flags = pipe_config->adjusted_mode.flags; - crtc->mode.clock = pipe_config->adjusted_mode.crtc_clock; + crtc->mode.clock = pipe_config->adjusted_mode.clock; crtc->mode.flags |= pipe_config->adjusted_mode.flags; } @@ -5059,8 +4821,17 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) I915_READ(PIPECONF(intel_crtc->pipe)) & PIPECONF_ENABLE) pipeconf |= PIPECONF_ENABLE; - if (intel_crtc->config.double_wide) - pipeconf |= PIPECONF_DOUBLE_WIDE; + if (intel_crtc->pipe == 0 && INTEL_INFO(dev)->gen < 4) { + /* Enable pixel doubling when the dot clock is > 90% of the (display) + * core speed. + * + * XXX: No double-wide on 915GM pipe B. Is that the only reason for the + * pipe == 0 check? + */ + if (intel_crtc->config.requested_mode.clock > + dev_priv->display.get_display_clock_speed(dev) * 9 / 10) + pipeconf |= PIPECONF_DOUBLE_WIDE; + } /* only g4x and later have fancy bpc/dither controls */ if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) { @@ -5114,13 +4885,14 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_display_mode *mode = &intel_crtc->config.requested_mode; int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; int refclk, num_connectors = 0; intel_clock_t clock, reduced_clock; u32 dspcntr; bool ok, has_reduced_clock = false; - bool is_lvds = false, is_dsi = false; + bool is_lvds = false; struct intel_encoder *encoder; const intel_limit_t *limit; int ret; @@ -5130,49 +4902,42 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, case INTEL_OUTPUT_LVDS: is_lvds = true; break; - case INTEL_OUTPUT_DSI: - is_dsi = true; - break; } num_connectors++; } - if (is_dsi) - goto skip_dpll; + refclk = i9xx_get_refclk(crtc, num_connectors); - if (!intel_crtc->config.clock_set) { - refclk = i9xx_get_refclk(crtc, num_connectors); + /* + * Returns a set of divisors for the desired target clock with the given + * refclk, or FALSE. The returned values represent the clock equation: + * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + */ + limit = intel_limit(crtc, refclk); + ok = dev_priv->display.find_dpll(limit, crtc, + intel_crtc->config.port_clock, + refclk, NULL, &clock); + if (!ok && !intel_crtc->config.clock_set) { + DRM_ERROR("Couldn't find PLL settings for mode!\n"); + return -EINVAL; + } + if (is_lvds && dev_priv->lvds_downclock_avail) { /* - * Returns a set of divisors for the desired target clock with - * the given refclk, or FALSE. The returned values represent - * the clock equation: reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + - * 2) / p1 / p2. - */ - limit = intel_limit(crtc, refclk); - ok = dev_priv->display.find_dpll(limit, crtc, - intel_crtc->config.port_clock, - refclk, NULL, &clock); - if (!ok) { - DRM_ERROR("Couldn't find PLL settings for mode!\n"); - return -EINVAL; - } - - if (is_lvds && dev_priv->lvds_downclock_avail) { - /* - * Ensure we match the reduced clock's P to the target - * clock. If the clocks don't match, we can't switch - * the display clock by using the FP0/FP1. In such case - * we will disable the LVDS downclock feature. - */ - has_reduced_clock = - dev_priv->display.find_dpll(limit, crtc, - dev_priv->lvds_downclock, - refclk, &clock, - &reduced_clock); - } - /* Compat-code for transition, will disappear. */ + * Ensure we match the reduced clock's P to the target clock. + * If the clocks don't match, we can't switch the display clock + * by using the FP0/FP1. In such case we will disable the LVDS + * downclock feature. + */ + has_reduced_clock = + dev_priv->display.find_dpll(limit, crtc, + dev_priv->lvds_downclock, + refclk, &clock, + &reduced_clock); + } + /* Compat-code for transition, will disappear. */ + if (!intel_crtc->config.clock_set) { intel_crtc->config.dpll.n = clock.n; intel_crtc->config.dpll.m1 = clock.m1; intel_crtc->config.dpll.m2 = clock.m2; @@ -5180,19 +4945,17 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, intel_crtc->config.dpll.p2 = clock.p2; } - if (IS_GEN2(dev)) { + if (IS_GEN2(dev)) i8xx_update_pll(intel_crtc, has_reduced_clock ? &reduced_clock : NULL, num_connectors); - } else if (IS_VALLEYVIEW(dev)) { + else if (IS_VALLEYVIEW(dev)) vlv_update_pll(intel_crtc); - } else { + else i9xx_update_pll(intel_crtc, has_reduced_clock ? &reduced_clock : NULL, num_connectors); - } -skip_dpll: /* Set up the display plane register */ dspcntr = DISPPLANE_GAMMA_ENABLE; @@ -5209,8 +4972,8 @@ skip_dpll: * which should always be the user's requested size. */ I915_WRITE(DSPSIZE(plane), - ((intel_crtc->config.pipe_src_h - 1) << 16) | - (intel_crtc->config.pipe_src_w - 1)); + ((mode->vdisplay - 1) << 16) | + (mode->hdisplay - 1)); I915_WRITE(DSPPOS(plane), 0); i9xx_set_pipeconf(intel_crtc); @@ -5220,6 +4983,8 @@ skip_dpll: ret = intel_pipe_set_base(crtc, x, y, fb); + intel_update_watermarks(dev); + return ret; } @@ -5250,32 +5015,6 @@ static void i9xx_get_pfit_config(struct intel_crtc *crtc, I915_READ(LVDS) & LVDS_BORDER_ENABLE; } -static void vlv_crtc_clock_get(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) -{ - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int pipe = pipe_config->cpu_transcoder; - intel_clock_t clock; - u32 mdiv; - int refclk = 100000; - - mutex_lock(&dev_priv->dpio_lock); - mdiv = vlv_dpio_read(dev_priv, pipe, DPIO_DIV(pipe)); - mutex_unlock(&dev_priv->dpio_lock); - - clock.m1 = (mdiv >> DPIO_M1DIV_SHIFT) & 7; - clock.m2 = mdiv & DPIO_M2DIV_MASK; - clock.n = (mdiv >> DPIO_N_SHIFT) & 0xf; - clock.p1 = (mdiv >> DPIO_P1_SHIFT) & 7; - clock.p2 = (mdiv >> DPIO_P2_SHIFT) & 0x1f; - - vlv_clock(refclk, &clock); - - /* clock.dot is the fast clock */ - pipe_config->port_clock = clock.dot / 5; -} - static bool i9xx_get_pipe_config(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) { @@ -5306,9 +5045,6 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, } } - if (INTEL_INFO(dev)->gen < 4) - pipe_config->double_wide = tmp & PIPECONF_DOUBLE_WIDE; - intel_get_pipe_timings(crtc, pipe_config); i9xx_get_pfit_config(crtc, pipe_config); @@ -5341,11 +5077,6 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, DPLL_PORTB_READY_MASK); } - if (IS_VALLEYVIEW(dev)) - vlv_crtc_clock_get(crtc, pipe_config); - else - i9xx_crtc_clock_get(crtc, pipe_config); - return true; } @@ -5815,7 +5546,7 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc) uint16_t postoff = 0; if (intel_crtc->config.limited_color_range) - postoff = (16 * (1 << 12) / 255) & 0x1fff; + postoff = (16 * (1 << 13) / 255) & 0x1fff; I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff); I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff); @@ -5834,16 +5565,14 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc) static void haswell_set_pipeconf(struct drm_crtc *crtc) { - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = crtc->dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; uint32_t val; val = 0; - if (IS_HASWELL(dev) && intel_crtc->config.dither) + if (intel_crtc->config.dither) val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP); if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) @@ -5856,33 +5585,6 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc) I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT); POSTING_READ(GAMMA_MODE(intel_crtc->pipe)); - - if (IS_BROADWELL(dev)) { - val = 0; - - switch (intel_crtc->config.pipe_bpp) { - case 18: - val |= PIPEMISC_DITHER_6_BPC; - break; - case 24: - val |= PIPEMISC_DITHER_8_BPC; - break; - case 30: - val |= PIPEMISC_DITHER_10_BPC; - break; - case 36: - val |= PIPEMISC_DITHER_12_BPC; - break; - default: - /* Case prevented by pipe_config_set_bpp. */ - BUG(); - } - - if (intel_crtc->config.dither) - val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP; - - I915_WRITE(PIPEMISC(pipe), val); - } } static bool ironlake_compute_clocks(struct drm_crtc *crtc, @@ -6117,6 +5819,11 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, else intel_crtc->lowfreq_avail = false; + if (intel_crtc->config.has_pch_encoder) { + pll = intel_crtc_to_shared_dpll(intel_crtc); + + } + intel_set_pipe_timings(intel_crtc); if (intel_crtc->config.has_pch_encoder) { @@ -6132,67 +5839,25 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, ret = intel_pipe_set_base(crtc, x, y, fb); - return ret; -} - -static void intel_pch_transcoder_get_m_n(struct intel_crtc *crtc, - struct intel_link_m_n *m_n) -{ - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - enum pipe pipe = crtc->pipe; + intel_update_watermarks(dev); - m_n->link_m = I915_READ(PCH_TRANS_LINK_M1(pipe)); - m_n->link_n = I915_READ(PCH_TRANS_LINK_N1(pipe)); - m_n->gmch_m = I915_READ(PCH_TRANS_DATA_M1(pipe)) - & ~TU_SIZE_MASK; - m_n->gmch_n = I915_READ(PCH_TRANS_DATA_N1(pipe)); - m_n->tu = ((I915_READ(PCH_TRANS_DATA_M1(pipe)) - & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1; + return ret; } -static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc, - enum transcoder transcoder, - struct intel_link_m_n *m_n) +static void ironlake_get_fdi_m_n_config(struct intel_crtc *crtc, + struct intel_crtc_config *pipe_config) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - enum pipe pipe = crtc->pipe; + enum transcoder transcoder = pipe_config->cpu_transcoder; - if (INTEL_INFO(dev)->gen >= 5) { - m_n->link_m = I915_READ(PIPE_LINK_M1(transcoder)); - m_n->link_n = I915_READ(PIPE_LINK_N1(transcoder)); - m_n->gmch_m = I915_READ(PIPE_DATA_M1(transcoder)) - & ~TU_SIZE_MASK; - m_n->gmch_n = I915_READ(PIPE_DATA_N1(transcoder)); - m_n->tu = ((I915_READ(PIPE_DATA_M1(transcoder)) - & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1; - } else { - m_n->link_m = I915_READ(PIPE_LINK_M_G4X(pipe)); - m_n->link_n = I915_READ(PIPE_LINK_N_G4X(pipe)); - m_n->gmch_m = I915_READ(PIPE_DATA_M_G4X(pipe)) - & ~TU_SIZE_MASK; - m_n->gmch_n = I915_READ(PIPE_DATA_N_G4X(pipe)); - m_n->tu = ((I915_READ(PIPE_DATA_M_G4X(pipe)) - & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1; - } -} - -void intel_dp_get_m_n(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) -{ - if (crtc->config.has_pch_encoder) - intel_pch_transcoder_get_m_n(crtc, &pipe_config->dp_m_n); - else - intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder, - &pipe_config->dp_m_n); -} - -static void ironlake_get_fdi_m_n_config(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) -{ - intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder, - &pipe_config->fdi_m_n); + pipe_config->fdi_m_n.link_m = I915_READ(PIPE_LINK_M1(transcoder)); + pipe_config->fdi_m_n.link_n = I915_READ(PIPE_LINK_N1(transcoder)); + pipe_config->fdi_m_n.gmch_m = I915_READ(PIPE_DATA_M1(transcoder)) + & ~TU_SIZE_MASK; + pipe_config->fdi_m_n.gmch_n = I915_READ(PIPE_DATA_N1(transcoder)); + pipe_config->fdi_m_n.tu = ((I915_READ(PIPE_DATA_M1(transcoder)) + & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1; } static void ironlake_get_pfit_config(struct intel_crtc *crtc, @@ -6281,8 +5946,6 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, pipe_config->pixel_multiplier = ((tmp & PLL_REF_SDVO_HDMI_MULTIPLIER_MASK) >> PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT) + 1; - - ironlake_pch_clock_get(crtc, pipe_config); } else { pipe_config->pixel_multiplier = 1; } @@ -6339,8 +6002,8 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) * register. Callers should take care of disabling all the display engine * functions, doing the mode unset, fixing interrupts, etc. */ -static void hsw_disable_lcpll(struct drm_i915_private *dev_priv, - bool switch_to_fclk, bool allow_power_down) +void hsw_disable_lcpll(struct drm_i915_private *dev_priv, + bool switch_to_fclk, bool allow_power_down) { uint32_t val; @@ -6368,10 +6031,7 @@ static void hsw_disable_lcpll(struct drm_i915_private *dev_priv, val = I915_READ(D_COMP); val |= D_COMP_COMP_DISABLE; - mutex_lock(&dev_priv->rps.hw_lock); - if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP, val)) - DRM_ERROR("Failed to disable D_COMP\n"); - mutex_unlock(&dev_priv->rps.hw_lock); + I915_WRITE(D_COMP, val); POSTING_READ(D_COMP); ndelay(100); @@ -6390,7 +6050,7 @@ static void hsw_disable_lcpll(struct drm_i915_private *dev_priv, * Fully restores LCPLL, disallowing power down and switching back to LCPLL * source. */ -static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) +void hsw_restore_lcpll(struct drm_i915_private *dev_priv) { uint32_t val; @@ -6402,7 +6062,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) /* Make sure we're not on PC8 state before disabling PC8, otherwise * we'll hang the machine! */ - gen6_gt_force_wake_get(dev_priv); + dev_priv->uncore.funcs.force_wake_get(dev_priv); if (val & LCPLL_POWER_DOWN_ALLOW) { val &= ~LCPLL_POWER_DOWN_ALLOW; @@ -6413,10 +6073,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) val = I915_READ(D_COMP); val |= D_COMP_COMP_FORCE; val &= ~D_COMP_COMP_DISABLE; - mutex_lock(&dev_priv->rps.hw_lock); - if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP, val)) - DRM_ERROR("Failed to enable D_COMP\n"); - mutex_unlock(&dev_priv->rps.hw_lock); + I915_WRITE(D_COMP, val); POSTING_READ(D_COMP); val = I915_READ(LCPLL_CTL); @@ -6436,7 +6093,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv) DRM_ERROR("Switching back to LCPLL failed\n"); } - gen6_gt_force_wake_put(dev_priv); + dev_priv->uncore.funcs.force_wake_put(dev_priv); } void hsw_enable_pc8_work(struct work_struct *__work) @@ -6518,9 +6175,6 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv) void hsw_enable_package_c8(struct drm_i915_private *dev_priv) { - if (!HAS_PC8(dev_priv->dev)) - return; - mutex_lock(&dev_priv->pc8.lock); __hsw_enable_package_c8(dev_priv); mutex_unlock(&dev_priv->pc8.lock); @@ -6528,9 +6182,6 @@ void hsw_enable_package_c8(struct drm_i915_private *dev_priv) void hsw_disable_package_c8(struct drm_i915_private *dev_priv) { - if (!HAS_PC8(dev_priv->dev)) - return; - mutex_lock(&dev_priv->pc8.lock); __hsw_disable_package_c8(dev_priv); mutex_unlock(&dev_priv->pc8.lock); @@ -6568,9 +6219,6 @@ static void hsw_update_package_c8(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; bool allow; - if (!HAS_PC8(dev_priv->dev)) - return; - if (!i915_enable_pc8) return; @@ -6594,103 +6242,36 @@ done: static void hsw_package_c8_gpu_idle(struct drm_i915_private *dev_priv) { - if (!HAS_PC8(dev_priv->dev)) - return; - - mutex_lock(&dev_priv->pc8.lock); if (!dev_priv->pc8.gpu_idle) { dev_priv->pc8.gpu_idle = true; - __hsw_enable_package_c8(dev_priv); + hsw_enable_package_c8(dev_priv); } - mutex_unlock(&dev_priv->pc8.lock); } static void hsw_package_c8_gpu_busy(struct drm_i915_private *dev_priv) { - if (!HAS_PC8(dev_priv->dev)) - return; - - mutex_lock(&dev_priv->pc8.lock); if (dev_priv->pc8.gpu_idle) { dev_priv->pc8.gpu_idle = false; - __hsw_disable_package_c8(dev_priv); + hsw_disable_package_c8(dev_priv); } - mutex_unlock(&dev_priv->pc8.lock); -} - -#define for_each_power_domain(domain, mask) \ - for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \ - if ((1 << (domain)) & (mask)) - -static unsigned long get_pipe_power_domains(struct drm_device *dev, - enum pipe pipe, bool pfit_enabled) -{ - unsigned long mask; - enum transcoder transcoder; - - transcoder = intel_pipe_to_cpu_transcoder(dev->dev_private, pipe); - - mask = BIT(POWER_DOMAIN_PIPE(pipe)); - mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder)); - if (pfit_enabled) - mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe)); - - return mask; } -void intel_display_set_init_power(struct drm_device *dev, bool enable) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (dev_priv->power_domains.init_power_on == enable) - return; - - if (enable) - intel_display_power_get(dev, POWER_DOMAIN_INIT); - else - intel_display_power_put(dev, POWER_DOMAIN_INIT); - - dev_priv->power_domains.init_power_on = enable; -} - -static void modeset_update_power_wells(struct drm_device *dev) +static void haswell_modeset_global_resources(struct drm_device *dev) { - unsigned long pipe_domains[I915_MAX_PIPES] = { 0, }; + bool enable = false; struct intel_crtc *crtc; - /* - * First get all needed power domains, then put all unneeded, to avoid - * any unnecessary toggling of the power wells. - */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { - enum intel_display_power_domain domain; - if (!crtc->base.enabled) continue; - pipe_domains[crtc->pipe] = get_pipe_power_domains(dev, - crtc->pipe, - crtc->config.pch_pfit.enabled); - - for_each_power_domain(domain, pipe_domains[crtc->pipe]) - intel_display_power_get(dev, domain); + if (crtc->pipe != PIPE_A || crtc->config.pch_pfit.enabled || + crtc->config.cpu_transcoder != TRANSCODER_EDP) + enable = true; } - list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { - enum intel_display_power_domain domain; + intel_set_power_well(dev, enable); - for_each_power_domain(domain, crtc->enabled_power_domains) - intel_display_power_put(dev, domain); - - crtc->enabled_power_domains = pipe_domains[crtc->pipe]; - } - - intel_display_set_init_power(dev, false); -} - -static void haswell_modeset_global_resources(struct drm_device *dev) -{ - modeset_update_power_wells(dev); hsw_update_package_c8(dev); } @@ -6729,6 +6310,8 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc, ret = intel_pipe_set_base(crtc, x, y, fb); + intel_update_watermarks(dev); + return ret; } @@ -6836,44 +6419,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, return 0; } -static struct { - int clock; - u32 config; -} hdmi_audio_clock[] = { - { DIV_ROUND_UP(25200 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 }, - { 25200, AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 }, /* default per bspec */ - { 27000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 }, - { 27000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 }, - { 54000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 }, - { 54000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 }, - { DIV_ROUND_UP(74250 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 }, - { 74250, AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 }, - { DIV_ROUND_UP(148500 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 }, - { 148500, AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 }, -}; - -/* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ -static u32 audio_config_hdmi_pixel_clock(struct drm_display_mode *mode) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(hdmi_audio_clock); i++) { - if (mode->clock == hdmi_audio_clock[i].clock) - break; - } - - if (i == ARRAY_SIZE(hdmi_audio_clock)) { - DRM_DEBUG_KMS("HDMI audio pixel clock setting for %d not found, falling back to defaults\n", mode->clock); - i = 1; - } - - DRM_DEBUG_KMS("Configuring HDMI audio for pixel clock %d (0x%08x)\n", - hdmi_audio_clock[i].clock, - hdmi_audio_clock[i].config); - - return hdmi_audio_clock[i].config; -} - static bool intel_eld_uptodate(struct drm_connector *connector, int reg_eldv, uint32_t bits_eldv, int reg_elda, uint32_t bits_elda, @@ -6904,8 +6449,7 @@ static bool intel_eld_uptodate(struct drm_connector *connector, } static void g4x_write_eld(struct drm_connector *connector, - struct drm_crtc *crtc, - struct drm_display_mode *mode) + struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = connector->dev->dev_private; uint8_t *eld = connector->eld; @@ -6945,8 +6489,7 @@ static void g4x_write_eld(struct drm_connector *connector, } static void haswell_write_eld(struct drm_connector *connector, - struct drm_crtc *crtc, - struct drm_display_mode *mode) + struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = connector->dev->dev_private; uint8_t *eld = connector->eld; @@ -6999,9 +6542,8 @@ static void haswell_write_eld(struct drm_connector *connector, DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ - } else { - I915_WRITE(aud_config, audio_config_hdmi_pixel_clock(mode)); - } + } else + I915_WRITE(aud_config, 0); if (intel_eld_uptodate(connector, aud_cntrl_st2, eldv, @@ -7034,8 +6576,7 @@ static void haswell_write_eld(struct drm_connector *connector, } static void ironlake_write_eld(struct drm_connector *connector, - struct drm_crtc *crtc, - struct drm_display_mode *mode) + struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = connector->dev->dev_private; uint8_t *eld = connector->eld; @@ -7053,11 +6594,6 @@ static void ironlake_write_eld(struct drm_connector *connector, aud_config = IBX_AUD_CFG(pipe); aud_cntl_st = IBX_AUD_CNTL_ST(pipe); aud_cntrl_st2 = IBX_AUD_CNTL_ST2; - } else if (IS_VALLEYVIEW(connector->dev)) { - hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); - aud_config = VLV_AUD_CFG(pipe); - aud_cntl_st = VLV_AUD_CNTL_ST(pipe); - aud_cntrl_st2 = VLV_AUD_CNTL_ST2; } else { hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe); aud_config = CPT_AUD_CFG(pipe); @@ -7067,19 +6603,8 @@ static void ironlake_write_eld(struct drm_connector *connector, DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(pipe)); - if (IS_VALLEYVIEW(connector->dev)) { - struct intel_encoder *intel_encoder; - struct intel_digital_port *intel_dig_port; - - intel_encoder = intel_attached_encoder(connector); - intel_dig_port = enc_to_dig_port(&intel_encoder->base); - i = intel_dig_port->port; - } else { - i = I915_READ(aud_cntl_st); - i = (i >> 29) & DIP_PORT_SEL_MASK; - /* DIP_Port_Select, 0x1 = PortB */ - } - + i = I915_READ(aud_cntl_st); + i = (i >> 29) & DIP_PORT_SEL_MASK; /* DIP_Port_Select, 0x1 = PortB */ if (!i) { DRM_DEBUG_DRIVER("Audio directed to unknown port\n"); /* operate blindly on all ports */ @@ -7095,9 +6620,8 @@ static void ironlake_write_eld(struct drm_connector *connector, DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ - } else { - I915_WRITE(aud_config, audio_config_hdmi_pixel_clock(mode)); - } + } else + I915_WRITE(aud_config, 0); if (intel_eld_uptodate(connector, aud_cntrl_st2, eldv, @@ -7147,7 +6671,50 @@ void intel_write_eld(struct drm_encoder *encoder, connector->eld[6] = drm_av_sync_delay(connector, mode) / 2; if (dev_priv->display.write_eld) - dev_priv->display.write_eld(connector, crtc, mode); + 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) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + enum pipe pipe = intel_crtc->pipe; + int palreg = PALETTE(pipe); + int i; + bool reenable_ips = false; + + /* The clocks have to be on to load the palette. */ + if (!crtc->enabled || !intel_crtc->active) + return; + + if (!HAS_PCH_SPLIT(dev_priv->dev)) + assert_pll_enabled(dev_priv, pipe); + + /* use legacy palette for Ironlake */ + if (HAS_PCH_SPLIT(dev)) + palreg = LGC_PALETTE(pipe); + + /* Workaround : Do not read or write the pipe palette/gamma data while + * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled. + */ + if (intel_crtc->config.ips_enabled && + ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) == + GAMMA_MODE_MODE_SPLIT)) { + hsw_disable_ips(intel_crtc); + reenable_ips = true; + } + + for (i = 0; i < 256; i++) { + I915_WRITE(palreg + 4 * i, + (intel_crtc->lut_r[i] << 16) | + (intel_crtc->lut_g[i] << 8) | + intel_crtc->lut_b[i]); + } + + if (reenable_ips) + hsw_enable_ips(intel_crtc); } static void i845_update_cursor(struct drm_crtc *crtc, u32 base) @@ -7203,9 +6770,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) intel_crtc->cursor_visible = visible; } /* and commit changes on next vblank */ - POSTING_READ(CURCNTR(pipe)); I915_WRITE(CURBASE(pipe), base); - POSTING_READ(CURBASE(pipe)); } static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) @@ -7225,7 +6790,7 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); cntl |= CURSOR_MODE_DISABLE; } - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + if (IS_HASWELL(dev)) { cntl |= CURSOR_PIPE_CSC_ENABLE; cntl &= ~CURSOR_TRICKLE_FEED_DISABLE; } @@ -7234,9 +6799,7 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) intel_crtc->cursor_visible = visible; } /* and commit changes on next vblank */ - POSTING_READ(CURCNTR_IVB(pipe)); I915_WRITE(CURBASE_IVB(pipe), base); - POSTING_READ(CURBASE_IVB(pipe)); } /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ @@ -7249,20 +6812,23 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, int pipe = intel_crtc->pipe; int x = intel_crtc->cursor_x; int y = intel_crtc->cursor_y; - u32 base = 0, pos = 0; + u32 base, pos; bool visible; - if (on) - base = intel_crtc->cursor_addr; + pos = 0; - if (x >= intel_crtc->config.pipe_src_w) - base = 0; + if (on && crtc->enabled && crtc->fb) { + base = intel_crtc->cursor_addr; + if (x > (int) crtc->fb->width) + base = 0; - if (y >= intel_crtc->config.pipe_src_h) + if (y > (int) crtc->fb->height) + base = 0; + } else base = 0; if (x < 0) { - if (x + intel_crtc->cursor_width <= 0) + if (x + intel_crtc->cursor_width < 0) base = 0; pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; @@ -7271,7 +6837,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, pos |= x << CURSOR_X_SHIFT; if (y < 0) { - if (y + intel_crtc->cursor_height <= 0) + if (y + intel_crtc->cursor_height < 0) base = 0; pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; @@ -7283,7 +6849,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, if (!visible && !intel_crtc->cursor_visible) return; - if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev)) { + if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { I915_WRITE(CURPOS_IVB(pipe), pos); ivb_update_cursor(crtc, base); } else { @@ -7414,8 +6980,8 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - intel_crtc->cursor_x = clamp_t(int, x, SHRT_MIN, SHRT_MAX); - intel_crtc->cursor_y = clamp_t(int, y, SHRT_MIN, SHRT_MAX); + intel_crtc->cursor_x = x; + intel_crtc->cursor_y = y; if (intel_crtc->active) intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); @@ -7423,6 +6989,27 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) return 0; } +/** Sets the color ramps on behalf of RandR */ +void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, + u16 blue, int regno) +{ + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + intel_crtc->lut_r[regno] = red >> 8; + intel_crtc->lut_g[regno] = green >> 8; + intel_crtc->lut_b[regno] = blue >> 8; +} + +void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, + u16 *blue, int regno) +{ + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + *red = intel_crtc->lut_r[regno] << 8; + *green = intel_crtc->lut_g[regno] << 8; + *blue = intel_crtc->lut_b[regno] << 8; +} + static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t start, uint32_t size) { @@ -7458,21 +7045,14 @@ intel_framebuffer_create(struct drm_device *dev, return ERR_PTR(-ENOMEM); } - ret = i915_mutex_lock_interruptible(dev); - if (ret) - goto err; - ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj); - mutex_unlock(&dev->struct_mutex); - if (ret) - goto err; + if (ret) { + drm_gem_object_unreference_unlocked(&obj->base); + kfree(intel_fb); + return ERR_PTR(ret); + } return &intel_fb->base; -err: - drm_gem_object_unreference_unlocked(&obj->base); - kfree(intel_fb); - - return ERR_PTR(ret); } static u32 @@ -7515,7 +7095,6 @@ static struct drm_framebuffer * mode_fits_in_fbdev(struct drm_device *dev, struct drm_display_mode *mode) { -#ifdef CONFIG_DRM_I915_FBDEV struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj; struct drm_framebuffer *fb; @@ -7536,9 +7115,6 @@ mode_fits_in_fbdev(struct drm_device *dev, return NULL; return fb; -#else - return NULL; -#endif } bool intel_get_load_detect_pipe(struct drm_connector *connector, @@ -7682,22 +7258,6 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, mutex_unlock(&crtc->mutex); } -static int i9xx_pll_refclk(struct drm_device *dev, - const struct intel_crtc_config *pipe_config) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - u32 dpll = pipe_config->dpll_hw_state.dpll; - - if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN) - return dev_priv->vbt.lvds_ssc_freq * 1000; - else if (HAS_PCH_SPLIT(dev)) - return 120000; - else if (!IS_GEN2(dev)) - return 96000; - else - return 48000; -} - /* Returns the clock of the currently programmed mode of the given pipe. */ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config) @@ -7705,15 +7265,14 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = pipe_config->cpu_transcoder; - u32 dpll = pipe_config->dpll_hw_state.dpll; + u32 dpll = I915_READ(DPLL(pipe)); u32 fp; intel_clock_t clock; - int refclk = i9xx_pll_refclk(dev, pipe_config); if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) - fp = pipe_config->dpll_hw_state.fp0; + fp = I915_READ(FP0(pipe)); else - fp = pipe_config->dpll_hw_state.fp1; + fp = I915_READ(FP1(pipe)); clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; if (IS_PINEVIEW(dev)) { @@ -7744,13 +7303,14 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, default: DRM_DEBUG_KMS("Unknown DPLL mode %08x in programmed " "mode\n", (int)(dpll & DPLL_MODE_MASK)); + pipe_config->adjusted_mode.clock = 0; return; } if (IS_PINEVIEW(dev)) - pineview_clock(refclk, &clock); + pineview_clock(96000, &clock); else - i9xx_clock(refclk, &clock); + i9xx_clock(96000, &clock); } else { bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN); @@ -7758,6 +7318,13 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> DPLL_FPA01_P1_POST_DIV_SHIFT); clock.p2 = 14; + + if ((dpll & PLL_REF_INPUT_MASK) == + PLLB_REF_INPUT_SPREADSPECTRUMIN) { + /* XXX: might not be 66MHz */ + i9xx_clock(66000, &clock); + } else + i9xx_clock(48000, &clock); } else { if (dpll & PLL_P1_DIVIDE_BY_TWO) clock.p1 = 2; @@ -7769,55 +7336,59 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, clock.p2 = 4; else clock.p2 = 2; - } - i9xx_clock(refclk, &clock); + i9xx_clock(48000, &clock); + } } - /* - * This value includes pixel_multiplier. We will use - * port_clock to compute adjusted_mode.crtc_clock in the - * encoder's get_config() function. - */ - pipe_config->port_clock = clock.dot; + pipe_config->adjusted_mode.clock = clock.dot; } -int intel_dotclock_calculate(int link_freq, - const struct intel_link_m_n *m_n) +static void ironlake_crtc_clock_get(struct intel_crtc *crtc, + struct intel_crtc_config *pipe_config) { + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; + int link_freq, repeat; + u64 clock; + u32 link_m, link_n; + + repeat = pipe_config->pixel_multiplier; + /* * The calculation for the data clock is: - * pixel_clock = ((m/n)*(link_clock * nr_lanes))/bpp + * pixel_clock = ((m/n)*(link_clock * nr_lanes * repeat))/bpp * But we want to avoid losing precison if possible, so: - * pixel_clock = ((m * link_clock * nr_lanes)/(n*bpp)) + * pixel_clock = ((m * link_clock * nr_lanes * repeat)/(n*bpp)) * * and the link clock is simpler: - * link_clock = (m * link_clock) / n + * link_clock = (m * link_clock * repeat) / n */ - if (!m_n->link_n) - return 0; + /* + * We need to get the FDI or DP link clock here to derive + * the M/N dividers. + * + * For FDI, we read it from the BIOS or use a fixed 2.7GHz. + * For DP, it's either 1.62GHz or 2.7GHz. + * We do our calculations in 10*MHz since we don't need much precison. + */ + if (pipe_config->has_pch_encoder) + link_freq = intel_fdi_link_freq(dev) * 10000; + else + link_freq = pipe_config->port_clock; - return div_u64((u64)m_n->link_m * link_freq, m_n->link_n); -} + link_m = I915_READ(PIPE_LINK_M1(cpu_transcoder)); + link_n = I915_READ(PIPE_LINK_N1(cpu_transcoder)); -static void ironlake_pch_clock_get(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config) -{ - struct drm_device *dev = crtc->base.dev; + if (!link_m || !link_n) + return; - /* read out port_clock from the DPLL */ - i9xx_crtc_clock_get(crtc, pipe_config); + clock = ((u64)link_m * (u64)link_freq * (u64)repeat); + do_div(clock, link_n); - /* - * This value does not include pixel_multiplier. - * We will check that port_clock and adjusted_mode.crtc_clock - * agree once we know their relationship in the encoder's - * get_config() function. - */ - pipe_config->adjusted_mode.crtc_clock = - intel_dotclock_calculate(intel_fdi_link_freq(dev) * 10000, - &pipe_config->fdi_m_n); + pipe_config->adjusted_mode.clock = clock; } /** Returns the currently programmed mode of the given pipe. */ @@ -7833,7 +7404,6 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, int hsync = I915_READ(HSYNC(cpu_transcoder)); int vtot = I915_READ(VTOTAL(cpu_transcoder)); int vsync = I915_READ(VSYNC(cpu_transcoder)); - enum pipe pipe = intel_crtc->pipe; mode = kzalloc(sizeof(*mode), GFP_KERNEL); if (!mode) @@ -7846,14 +7416,11 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, * Note, if LVDS ever uses a non-1 pixel multiplier, we'll need * to use a real value here instead. */ - pipe_config.cpu_transcoder = (enum transcoder) pipe; + pipe_config.cpu_transcoder = (enum transcoder) intel_crtc->pipe; pipe_config.pixel_multiplier = 1; - pipe_config.dpll_hw_state.dpll = I915_READ(DPLL(pipe)); - pipe_config.dpll_hw_state.fp0 = I915_READ(FP0(pipe)); - pipe_config.dpll_hw_state.fp1 = I915_READ(FP1(pipe)); i9xx_crtc_clock_get(intel_crtc, &pipe_config); - mode->clock = pipe_config.port_clock / pipe_config.pixel_multiplier; + mode->clock = pipe_config.adjusted_mode.clock; mode->hdisplay = (htot & 0xffff) + 1; mode->htotal = ((htot & 0xffff0000) >> 16) + 1; mode->hsync_start = (hsync & 0xffff) + 1; @@ -7959,9 +7526,6 @@ void intel_mark_idle(struct drm_device *dev) intel_decrease_pllclock(crtc); } - - if (dev_priv->info->gen >= 6) - gen6_rps_idle(dev->dev_private); } void intel_mark_fb_busy(struct drm_i915_gem_object *obj, @@ -8150,7 +7714,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev, intel_ring_emit(ring, 0); /* aux display base address, unused */ intel_mark_page_flip_active(intel_crtc); - __intel_ring_advance(ring); + intel_ring_advance(ring); return 0; err_unpin: @@ -8192,7 +7756,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev, intel_ring_emit(ring, MI_NOOP); intel_mark_page_flip_active(intel_crtc); - __intel_ring_advance(ring); + intel_ring_advance(ring); return 0; err_unpin: @@ -8241,7 +7805,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev, intel_ring_emit(ring, pf | pipesrc); intel_mark_page_flip_active(intel_crtc); - __intel_ring_advance(ring); + intel_ring_advance(ring); return 0; err_unpin: @@ -8286,7 +7850,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev, intel_ring_emit(ring, pf | pipesrc); intel_mark_page_flip_active(intel_crtc); - __intel_ring_advance(ring); + intel_ring_advance(ring); return 0; err_unpin: @@ -8354,8 +7918,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE | DERRMR_PIPEB_PRI_FLIP_DONE | DERRMR_PIPEC_PRI_FLIP_DONE)); - intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) | - MI_SRM_LRM_GLOBAL_GTT); + intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1)); intel_ring_emit(ring, DERRMR); intel_ring_emit(ring, ring->scratch.gtt_offset + 256); } @@ -8366,7 +7929,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, intel_ring_emit(ring, (MI_NOOP)); intel_mark_page_flip_active(intel_crtc); - __intel_ring_advance(ring); + intel_ring_advance(ring); return 0; err_unpin: @@ -8411,7 +7974,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, fb->pitches[0] != crtc->fb->pitches[0])) return -EINVAL; - work = kzalloc(sizeof(*work), GFP_KERNEL); + work = kzalloc(sizeof *work, GFP_KERNEL); if (work == NULL) return -ENOMEM; @@ -8646,17 +8209,6 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc, return bpp; } -static void intel_dump_crtc_timings(const struct drm_display_mode *mode) -{ - DRM_DEBUG_KMS("crtc timings: %d %d %d %d %d %d %d %d %d, " - "type: 0x%x flags: 0x%x\n", - mode->crtc_clock, - mode->crtc_hdisplay, mode->crtc_hsync_start, - mode->crtc_hsync_end, mode->crtc_htotal, - mode->crtc_vdisplay, mode->crtc_vsync_start, - mode->crtc_vsync_end, mode->crtc_vtotal, mode->type, mode->flags); -} - static void intel_dump_pipe_config(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config, const char *context) @@ -8673,19 +8225,10 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, pipe_config->fdi_m_n.gmch_m, pipe_config->fdi_m_n.gmch_n, pipe_config->fdi_m_n.link_m, pipe_config->fdi_m_n.link_n, pipe_config->fdi_m_n.tu); - DRM_DEBUG_KMS("dp: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n", - pipe_config->has_dp_encoder, - pipe_config->dp_m_n.gmch_m, pipe_config->dp_m_n.gmch_n, - pipe_config->dp_m_n.link_m, pipe_config->dp_m_n.link_n, - pipe_config->dp_m_n.tu); DRM_DEBUG_KMS("requested mode:\n"); drm_mode_debug_printmodeline(&pipe_config->requested_mode); DRM_DEBUG_KMS("adjusted mode:\n"); drm_mode_debug_printmodeline(&pipe_config->adjusted_mode); - intel_dump_crtc_timings(&pipe_config->adjusted_mode); - DRM_DEBUG_KMS("port clock: %d\n", pipe_config->port_clock); - DRM_DEBUG_KMS("pipe src size: %dx%d\n", - pipe_config->pipe_src_w, pipe_config->pipe_src_h); DRM_DEBUG_KMS("gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n", pipe_config->gmch_pfit.control, pipe_config->gmch_pfit.pgm_ratios, @@ -8695,7 +8238,6 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, pipe_config->pch_pfit.size, pipe_config->pch_pfit.enabled ? "enabled" : "disabled"); DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled); - DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide); } static bool check_encoder_cloning(struct drm_crtc *crtc) @@ -8739,7 +8281,6 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, drm_mode_copy(&pipe_config->adjusted_mode, mode); drm_mode_copy(&pipe_config->requested_mode, mode); - pipe_config->cpu_transcoder = (enum transcoder) to_intel_crtc(crtc)->pipe; pipe_config->shared_dpll = DPLL_ID_PRIVATE; @@ -8766,25 +8307,13 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, if (plane_bpp < 0) goto fail; - /* - * Determine the real pipe dimensions. Note that stereo modes can - * increase the actual pipe size due to the frame doubling and - * insertion of additional space for blanks between the frame. This - * is stored in the crtc timings. We use the requested mode to do this - * computation to clearly distinguish it from the adjusted mode, which - * can be changed by the connectors in the below retry loop. - */ - drm_mode_set_crtcinfo(&pipe_config->requested_mode, CRTC_STEREO_DOUBLE); - pipe_config->pipe_src_w = pipe_config->requested_mode.crtc_hdisplay; - pipe_config->pipe_src_h = pipe_config->requested_mode.crtc_vdisplay; - encoder_retry: /* Ensure the port clock defaults are reset when retrying. */ pipe_config->port_clock = 0; pipe_config->pixel_multiplier = 1; /* Fill in default crtc timings, allow encoders to overwrite them. */ - drm_mode_set_crtcinfo(&pipe_config->adjusted_mode, CRTC_STEREO_DOUBLE); + drm_mode_set_crtcinfo(&pipe_config->adjusted_mode, 0); /* Pass our mode to the connectors and the CRTC to give them a chance to * adjust it according to limitations or connector properties, and also @@ -8805,8 +8334,7 @@ encoder_retry: /* Set default port clock if not overwritten by the encoder. Needs to be * done afterwards in case the encoder adjusts the mode. */ if (!pipe_config->port_clock) - pipe_config->port_clock = pipe_config->adjusted_mode.crtc_clock - * pipe_config->pixel_multiplier; + pipe_config->port_clock = pipe_config->adjusted_mode.clock; ret = intel_crtc_compute_config(to_intel_crtc(crtc), pipe_config); if (ret < 0) { @@ -8993,9 +8521,13 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes) } -static bool intel_fuzzy_clock_check(int clock1, int clock2) +static bool intel_fuzzy_clock_check(struct intel_crtc_config *cur, + struct intel_crtc_config *new) { - int diff; + int clock1, clock2, diff; + + clock1 = cur->adjusted_mode.clock; + clock2 = new->adjusted_mode.clock; if (clock1 == clock2) return true; @@ -9049,15 +8581,6 @@ intel_pipe_config_compare(struct drm_device *dev, return false; \ } -#define PIPE_CONF_CHECK_CLOCK_FUZZY(name) \ - if (!intel_fuzzy_clock_check(current_config->name, pipe_config->name)) { \ - DRM_ERROR("mismatch in " #name " " \ - "(expected %i, found %i)\n", \ - current_config->name, \ - pipe_config->name); \ - return false; \ - } - #define PIPE_CONF_QUIRK(quirk) \ ((current_config->quirks | pipe_config->quirks) & (quirk)) @@ -9071,13 +8594,6 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_I(fdi_m_n.link_n); PIPE_CONF_CHECK_I(fdi_m_n.tu); - PIPE_CONF_CHECK_I(has_dp_encoder); - PIPE_CONF_CHECK_I(dp_m_n.gmch_m); - PIPE_CONF_CHECK_I(dp_m_n.gmch_n); - PIPE_CONF_CHECK_I(dp_m_n.link_m); - PIPE_CONF_CHECK_I(dp_m_n.link_n); - PIPE_CONF_CHECK_I(dp_m_n.tu); - PIPE_CONF_CHECK_I(adjusted_mode.crtc_hdisplay); PIPE_CONF_CHECK_I(adjusted_mode.crtc_htotal); PIPE_CONF_CHECK_I(adjusted_mode.crtc_hblank_start); @@ -9108,8 +8624,8 @@ intel_pipe_config_compare(struct drm_device *dev, DRM_MODE_FLAG_NVSYNC); } - PIPE_CONF_CHECK_I(pipe_src_w); - PIPE_CONF_CHECK_I(pipe_src_h); + PIPE_CONF_CHECK_I(requested_mode.hdisplay); + PIPE_CONF_CHECK_I(requested_mode.vdisplay); PIPE_CONF_CHECK_I(gmch_pfit.control); /* pfit ratios are autocomputed by the hw on gen4+ */ @@ -9124,8 +8640,6 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_I(ips_enabled); - PIPE_CONF_CHECK_I(double_wide); - PIPE_CONF_CHECK_I(shared_dpll); PIPE_CONF_CHECK_X(dpll_hw_state.dpll); PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md); @@ -9135,17 +8649,20 @@ intel_pipe_config_compare(struct drm_device *dev, if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) PIPE_CONF_CHECK_I(pipe_bpp); - if (!IS_HASWELL(dev)) { - PIPE_CONF_CHECK_CLOCK_FUZZY(adjusted_mode.crtc_clock); - PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock); - } - #undef PIPE_CONF_CHECK_X #undef PIPE_CONF_CHECK_I #undef PIPE_CONF_CHECK_FLAGS -#undef PIPE_CONF_CHECK_CLOCK_FUZZY #undef PIPE_CONF_QUIRK + if (!IS_HASWELL(dev)) { + if (!intel_fuzzy_clock_check(current_config, pipe_config)) { + DRM_ERROR("mismatch in clock (expected %d, found %d)\n", + current_config->adjusted_mode.clock, + pipe_config->adjusted_mode.clock); + return false; + } + } + return true; } @@ -9272,10 +8789,14 @@ check_crtc_state(struct drm_device *dev) enum pipe pipe; if (encoder->base.crtc != &crtc->base) continue; - if (encoder->get_hw_state(encoder, &pipe)) + if (encoder->get_config && + encoder->get_hw_state(encoder, &pipe)) encoder->get_config(encoder, &pipe_config); } + if (dev_priv->display.get_clock) + dev_priv->display.get_clock(crtc, &pipe_config); + WARN(crtc->active != active, "crtc active state doesn't match with hw state " "(expected %i, found %i)\n", crtc->active, active); @@ -9350,18 +8871,6 @@ intel_modeset_check_state(struct drm_device *dev) check_shared_dpll_state(dev); } -void ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config, - int dotclock) -{ - /* - * FDI already provided one idea for the dotclock. - * Yell if the encoder disagrees. - */ - WARN(!intel_fuzzy_clock_check(pipe_config->adjusted_mode.crtc_clock, dotclock), - "FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n", - pipe_config->adjusted_mode.crtc_clock, dotclock); -} - static int __intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *fb) @@ -9374,7 +8883,7 @@ static int __intel_set_mode(struct drm_crtc *crtc, unsigned disable_pipes, prepare_pipes, modeset_pipes; int ret = 0; - saved_mode = kcalloc(2, sizeof(*saved_mode), GFP_KERNEL); + saved_mode = kmalloc(2 * sizeof(*saved_mode), GFP_KERNEL); if (!saved_mode) return -ENOMEM; saved_hwmode = saved_mode + 1; @@ -9913,7 +9422,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) struct intel_crtc *intel_crtc; int i; - intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL); + intel_crtc = kzalloc(sizeof(struct intel_crtc) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL); if (intel_crtc == NULL) return; @@ -9942,18 +9451,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); } -enum pipe intel_get_pipe_from_connector(struct intel_connector *connector) -{ - struct drm_encoder *encoder = connector->base.encoder; - - WARN_ON(!mutex_is_locked(&connector->base.dev->mode_config.mutex)); - - if (!encoder) - return INVALID_PIPE; - - return to_intel_crtc(encoder->crtc)->pipe; -} - int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, struct drm_file *file) { @@ -9969,7 +9466,7 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, if (!drmmode_obj) { DRM_ERROR("no such CRTC id\n"); - return -ENOENT; + return -EINVAL; } crtc = to_intel_crtc(obj_to_crtc(drmmode_obj)); @@ -10050,7 +9547,7 @@ static void intel_setup_outputs(struct drm_device *dev) intel_ddi_init(dev, PORT_D); } else if (HAS_PCH_SPLIT(dev)) { int found; - dpd_is_edp = intel_dp_is_edp(dev, PORT_D); + dpd_is_edp = intel_dpd_is_edp(dev); if (has_edp_a(dev)) intel_dp_init(dev, DP_A, PORT_A); @@ -10076,21 +9573,21 @@ static void intel_setup_outputs(struct drm_device *dev) if (I915_READ(PCH_DP_D) & DP_DETECTED) intel_dp_init(dev, PCH_DP_D, PORT_D); } else if (IS_VALLEYVIEW(dev)) { - if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED) { - intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIB, - PORT_B); - if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED) - intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B); - } - + /* Check for built-in panel first. Shares lanes with HDMI on SDVOC */ if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIC) & SDVO_DETECTED) { intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIC, PORT_C); if (I915_READ(VLV_DISPLAY_BASE + DP_C) & DP_DETECTED) - intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, PORT_C); + intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, + PORT_C); } - intel_dsi_init(dev); + if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED) { + intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIB, + PORT_B); + if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED) + intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B); + } } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) { bool found = false; @@ -10146,7 +9643,6 @@ static void intel_setup_outputs(struct drm_device *dev) void intel_framebuffer_fini(struct intel_framebuffer *fb) { drm_framebuffer_cleanup(&fb->base); - WARN_ON(!fb->obj->framebuffer_references--); drm_gem_object_unreference_unlocked(&fb->obj->base); } @@ -10178,12 +9674,9 @@ int intel_framebuffer_init(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_i915_gem_object *obj) { - int aligned_height, tile_height; int pitch_limit; int ret; - WARN_ON(!mutex_is_locked(&dev->struct_mutex)); - if (obj->tiling_mode == I915_TILING_Y) { DRM_DEBUG("hardware does not support tiling Y\n"); return -EINVAL; @@ -10272,16 +9765,8 @@ int intel_framebuffer_init(struct drm_device *dev, if (mode_cmd->offsets[0] != 0) return -EINVAL; - tile_height = IS_GEN2(dev) ? 16 : 8; - aligned_height = ALIGN(mode_cmd->height, - obj->tiling_mode ? tile_height : 1); - /* FIXME drm helper for size checks (especially planar formats)? */ - if (obj->base.size < aligned_height * mode_cmd->pitches[0]) - return -EINVAL; - drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); intel_fb->obj = obj; - intel_fb->obj->framebuffer_references++; ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); if (ret) { @@ -10307,15 +9792,9 @@ intel_user_framebuffer_create(struct drm_device *dev, return intel_framebuffer_create(dev, mode_cmd, obj); } -#ifndef CONFIG_DRM_I915_FBDEV -static inline void intel_fbdev_output_poll_changed(struct drm_device *dev) -{ -} -#endif - static const struct drm_mode_config_funcs intel_mode_funcs = { .fb_create = intel_user_framebuffer_create, - .output_poll_changed = intel_fbdev_output_poll_changed, + .output_poll_changed = intel_fb_output_poll_changed, }; /* Set up chip specific display functions */ @@ -10341,6 +9820,7 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.update_plane = ironlake_update_plane; } else if (HAS_PCH_SPLIT(dev)) { dev_priv->display.get_pipe_config = ironlake_get_pipe_config; + dev_priv->display.get_clock = ironlake_crtc_clock_get; dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set; dev_priv->display.crtc_enable = ironlake_crtc_enable; dev_priv->display.crtc_disable = ironlake_crtc_disable; @@ -10348,6 +9828,7 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.update_plane = ironlake_update_plane; } else if (IS_VALLEYVIEW(dev)) { dev_priv->display.get_pipe_config = i9xx_get_pipe_config; + dev_priv->display.get_clock = i9xx_crtc_clock_get; dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set; dev_priv->display.crtc_enable = valleyview_crtc_enable; dev_priv->display.crtc_disable = i9xx_crtc_disable; @@ -10355,6 +9836,7 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.update_plane = i9xx_update_plane; } else { dev_priv->display.get_pipe_config = i9xx_get_pipe_config; + dev_priv->display.get_clock = i9xx_crtc_clock_get; dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set; dev_priv->display.crtc_enable = i9xx_crtc_enable; dev_priv->display.crtc_disable = i9xx_crtc_disable; @@ -10404,7 +9886,7 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.write_eld = ironlake_write_eld; dev_priv->display.modeset_global_resources = ivb_modeset_global_resources; - } else if (IS_HASWELL(dev) || IS_GEN8(dev)) { + } else if (IS_HASWELL(dev)) { dev_priv->display.fdi_link_train = hsw_fdi_link_train; dev_priv->display.write_eld = haswell_write_eld; dev_priv->display.modeset_global_resources = @@ -10412,8 +9894,7 @@ static void intel_init_display(struct drm_device *dev) } } else if (IS_G4X(dev)) { dev_priv->display.write_eld = g4x_write_eld; - } else if (IS_VALLEYVIEW(dev)) - dev_priv->display.write_eld = ironlake_write_eld; + } /* Default just returns -ENODEV to indicate unsupported */ dev_priv->display.queue_flip = intel_default_queue_flip; @@ -10436,7 +9917,6 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.queue_flip = intel_gen6_queue_flip; break; case 7: - case 8: /* FIXME(BDW): Check that the gen8 RCS flip works. */ dev_priv->display.queue_flip = intel_gen7_queue_flip; break; } @@ -10532,7 +10012,8 @@ static struct intel_quirk intel_quirks[] = { /* ThinkPad T60 needs pipe A force quirk (bug #16494) */ { 0x2782, 0x17aa, 0x201a, quirk_pipea_force }, - /* 830 needs to leave pipe A & dpll A up */ + /* 830/845 need to leave pipe A & dpll A up */ + { 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, { 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, /* Lenovo U160 cannot use SSC on LVDS */ @@ -10541,11 +10022,20 @@ static struct intel_quirk intel_quirks[] = { /* Sony Vaio Y cannot use SSC on LVDS */ { 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable }, - /* - * All GM45 Acer (and its brands eMachines and Packard Bell) laptops - * seem to use inverted backlight PWM. - */ - { 0x2a42, 0x1025, PCI_ANY_ID, quirk_invert_brightness }, + /* Acer Aspire 5734Z must invert backlight brightness */ + { 0x2a42, 0x1025, 0x0459, quirk_invert_brightness }, + + /* Acer/eMachines G725 */ + { 0x2a42, 0x1025, 0x0210, quirk_invert_brightness }, + + /* Acer/eMachines e725 */ + { 0x2a42, 0x1025, 0x0212, quirk_invert_brightness }, + + /* Acer/Packard Bell NCL20 */ + { 0x2a42, 0x1025, 0x034b, quirk_invert_brightness }, + + /* Acer Aspire 4736Z */ + { 0x2a42, 0x1025, 0x0260, quirk_invert_brightness }, /* Dell XPS13 HD Sandy Bridge */ { 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable }, @@ -10594,19 +10084,12 @@ static void i915_disable_vga(struct drm_device *dev) void intel_modeset_init_hw(struct drm_device *dev) { - struct drm_i915_private *dev_priv = dev->dev_private; + intel_init_power_well(dev); intel_prepare_ddi(dev); intel_init_clock_gating(dev); - /* Enable the CRI clock source so we can get at the display */ - if (IS_VALLEYVIEW(dev)) - I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) | - DPLL_INTEGRATED_CRI_CLK_VLV); - - intel_init_dpio(dev); - mutex_lock(&dev->struct_mutex); intel_enable_gt_powersave(dev); mutex_unlock(&dev->struct_mutex); @@ -10874,7 +10357,7 @@ void i915_redisable_vga(struct drm_device *dev) (I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_STATE_ENABLED) == 0) return; - if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) { + if (I915_READ(vga_reg) != VGA_DISP_DISABLE) { DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n"); i915_disable_vga(dev); } @@ -10897,7 +10380,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) &crtc->config); crtc->base.enabled = crtc->active; - crtc->primary_enabled = crtc->active; DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n", crtc->base.base.id, @@ -10931,17 +10413,27 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) if (encoder->get_hw_state(encoder, &pipe)) { crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); encoder->base.crtc = &crtc->base; - encoder->get_config(encoder, &crtc->config); + if (encoder->get_config) + encoder->get_config(encoder, &crtc->config); } else { encoder->base.crtc = NULL; } encoder->connectors_active = false; - DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe %c\n", + DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe=%i\n", encoder->base.base.id, drm_get_encoder_name(&encoder->base), encoder->base.crtc ? "enabled" : "disabled", - pipe_name(pipe)); + pipe); + } + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, + base.head) { + if (!crtc->active) + continue; + if (dev_priv->display.get_clock) + dev_priv->display.get_clock(crtc, + &crtc->config); } list_for_each_entry(connector, &dev->mode_config.connector_list, @@ -10968,6 +10460,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, { struct drm_i915_private *dev_priv = dev->dev_private; enum pipe pipe; + struct drm_plane *plane; struct intel_crtc *crtc; struct intel_encoder *encoder; int i; @@ -11014,12 +10507,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, pll->on = false; } - if (IS_HASWELL(dev)) - ilk_wm_get_hw_state(dev); - if (force_restore) { - i915_redisable_vga(dev); - /* * We need to use raw interfaces for restoring state to avoid * checking (bogus) intermediate states. @@ -11031,6 +10519,10 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, __intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->fb); } + list_for_each_entry(plane, &dev->mode_config.plane_list, head) + intel_plane_restore(plane); + + i915_redisable_vga(dev); } else { intel_modeset_update_staged_output_state(dev); } @@ -11053,7 +10545,6 @@ void intel_modeset_cleanup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; - struct drm_connector *connector; /* * Interrupts and polling as the first thing to avoid creating havoc. @@ -11094,10 +10585,6 @@ void intel_modeset_cleanup(struct drm_device *dev) /* destroy backlight, if any, before the connectors */ intel_panel_destroy_backlight(dev); - /* destroy the sysfs files before encoders/connectors */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) - drm_sysfs_connector_remove(connector); - drm_mode_config_cleanup(dev); intel_cleanup_overlay(dev); @@ -11193,7 +10680,7 @@ intel_display_capture_error_state(struct drm_device *dev) if (INTEL_INFO(dev)->num_pipes == 0) return NULL; - error = kzalloc(sizeof(*error), GFP_ATOMIC); + error = kmalloc(sizeof(*error), GFP_ATOMIC); if (error == NULL) return NULL; @@ -11201,9 +10688,6 @@ intel_display_capture_error_state(struct drm_device *dev) error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER); for_each_pipe(i) { - if (!intel_display_power_enabled(dev, POWER_DOMAIN_PIPE(i))) - continue; - if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) { error->cursor[i].control = I915_READ(CURCNTR(i)); error->cursor[i].position = I915_READ(CURPOS(i)); @@ -11237,10 +10721,6 @@ intel_display_capture_error_state(struct drm_device *dev) for (i = 0; i < error->num_transcoders; i++) { enum transcoder cpu_transcoder = transcoders[i]; - if (!intel_display_power_enabled(dev, - POWER_DOMAIN_TRANSCODER(cpu_transcoder))) - continue; - error->transcoder[i].cpu_transcoder = cpu_transcoder; error->transcoder[i].conf = I915_READ(PIPECONF(cpu_transcoder)); @@ -11252,6 +10732,12 @@ intel_display_capture_error_state(struct drm_device *dev) error->transcoder[i].vsync = I915_READ(VSYNC(cpu_transcoder)); } + /* In the code above we read the registers without checking if the power + * well was on, so here we have to clear the FPGA_DBG_RM_NOCLAIM bit to + * prevent the next I915_WRITE from detecting it and printing an error + * message. */ + intel_uncore_clear_errors(dev); + return error; } @@ -11296,7 +10782,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, } for (i = 0; i < error->num_transcoders; i++) { - err_printf(m, "CPU transcoder: %c\n", + err_printf(m, " CPU transcoder: %c\n", transcoder_name(error->transcoder[i].cpu_transcoder)); err_printf(m, " CONF: %08x\n", error->transcoder[i].conf); err_printf(m, " HTOTAL: %08x\n", error->transcoder[i].htotal); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 30c627c..1a43137 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -38,32 +38,6 @@ #define DP_LINK_CHECK_TIMEOUT (10 * 1000) -struct dp_link_dpll { - int link_bw; - struct dpll dpll; -}; - -static const struct dp_link_dpll gen4_dpll[] = { - { DP_LINK_BW_1_62, - { .p1 = 2, .p2 = 10, .n = 2, .m1 = 23, .m2 = 8 } }, - { DP_LINK_BW_2_7, - { .p1 = 1, .p2 = 10, .n = 1, .m1 = 14, .m2 = 2 } } -}; - -static const struct dp_link_dpll pch_dpll[] = { - { DP_LINK_BW_1_62, - { .p1 = 2, .p2 = 10, .n = 1, .m1 = 12, .m2 = 9 } }, - { DP_LINK_BW_2_7, - { .p1 = 1, .p2 = 10, .n = 2, .m1 = 14, .m2 = 8 } } -}; - -static const struct dp_link_dpll vlv_dpll[] = { - { DP_LINK_BW_1_62, - { .p1 = 3, .p2 = 2, .n = 5, .m1 = 3, .m2 = 81 } }, - { DP_LINK_BW_2_7, - { .p1 = 2, .p2 = 2, .n = 1, .m1 = 2, .m2 = 27 } } -}; - /** * is_edp - is the given port attached to an eDP panel (either CPU or PCH) * @intel_dp: DP struct @@ -237,77 +211,24 @@ intel_hrawclk(struct drm_device *dev) } } -static void -intel_dp_init_panel_power_sequencer(struct drm_device *dev, - struct intel_dp *intel_dp, - struct edp_power_seq *out); -static void -intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, - struct intel_dp *intel_dp, - struct edp_power_seq *out); - -static enum pipe -vlv_power_sequencer_pipe(struct intel_dp *intel_dp) -{ - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_crtc *crtc = intel_dig_port->base.base.crtc; - struct drm_device *dev = intel_dig_port->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - enum port port = intel_dig_port->port; - enum pipe pipe; - - /* modeset should have pipe */ - if (crtc) - return to_intel_crtc(crtc)->pipe; - - /* init time, try to find a pipe with this port selected */ - for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) { - u32 port_sel = I915_READ(VLV_PIPE_PP_ON_DELAYS(pipe)) & - PANEL_PORT_SELECT_MASK; - if (port_sel == PANEL_PORT_SELECT_DPB_VLV && port == PORT_B) - return pipe; - if (port_sel == PANEL_PORT_SELECT_DPC_VLV && port == PORT_C) - return pipe; - } - - /* shrug */ - return PIPE_A; -} - -static u32 _pp_ctrl_reg(struct intel_dp *intel_dp) -{ - struct drm_device *dev = intel_dp_to_dev(intel_dp); - - if (HAS_PCH_SPLIT(dev)) - return PCH_PP_CONTROL; - else - return VLV_PIPE_PP_CONTROL(vlv_power_sequencer_pipe(intel_dp)); -} - -static u32 _pp_stat_reg(struct intel_dp *intel_dp) -{ - struct drm_device *dev = intel_dp_to_dev(intel_dp); - - if (HAS_PCH_SPLIT(dev)) - return PCH_PP_STATUS; - else - return VLV_PIPE_PP_STATUS(vlv_power_sequencer_pipe(intel_dp)); -} - static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = dev->dev_private; + u32 pp_stat_reg; - return (I915_READ(_pp_stat_reg(intel_dp)) & PP_ON) != 0; + pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS; + return (I915_READ(pp_stat_reg) & PP_ON) != 0; } static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = dev->dev_private; + u32 pp_ctrl_reg; - return (I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD) != 0; + pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL; + return (I915_READ(pp_ctrl_reg) & EDP_FORCE_VDD) != 0; } static void @@ -315,15 +236,19 @@ intel_dp_check_edp(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = dev->dev_private; + u32 pp_stat_reg, pp_ctrl_reg; if (!is_edp(intel_dp)) return; + pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS; + pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL; + 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(_pp_stat_reg(intel_dp)), - I915_READ(_pp_ctrl_reg(intel_dp))); + I915_READ(pp_stat_reg), + I915_READ(pp_ctrl_reg)); } } @@ -405,7 +330,6 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, uint32_t status; int try, precharge, clock = 0; bool has_aux_irq = INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev); - uint32_t timeout; /* dp aux is extremely sensitive to irq latency, hence request the * lowest possible wakeup latency and so prevent the cpu from going into @@ -420,11 +344,6 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, else precharge = 5; - if (IS_BROADWELL(dev) && ch_ctl == DPA_AUX_CH_CTL) - timeout = DP_AUX_CH_CTL_TIME_OUT_600us; - else - timeout = DP_AUX_CH_CTL_TIME_OUT_400us; - intel_aux_display_runtime_get(dev_priv); /* Try to wait for any previous AUX channel activity */ @@ -442,12 +361,6 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, goto out; } - /* Only 5 data registers! */ - if (WARN_ON(send_bytes > 20 || recv_size > 20)) { - ret = -E2BIG; - goto out; - } - while ((aux_clock_divider = get_aux_clock_divider(intel_dp, clock++))) { /* Must try at least 3 times according to DP spec */ for (try = 0; try < 5; try++) { @@ -460,7 +373,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, I915_WRITE(ch_ctl, DP_AUX_CH_CTL_SEND_BUSY | (has_aux_irq ? DP_AUX_CH_CTL_INTERRUPT : 0) | - timeout | + DP_AUX_CH_CTL_TIME_OUT_400us | (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | @@ -538,10 +451,9 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp, int msg_bytes; uint8_t ack; - if (WARN_ON(send_bytes > 16)) - return -E2BIG; - intel_dp_check_edp(intel_dp); + if (send_bytes > 16) + return -1; msg[0] = AUX_NATIVE_WRITE << 4; msg[1] = address >> 8; msg[2] = address & 0xff; @@ -582,9 +494,6 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp, uint8_t ack; int ret; - if (WARN_ON(recv_bytes > 19)) - return -E2BIG; - intel_dp_check_edp(intel_dp); msg[0] = AUX_NATIVE_READ << 4; msg[1] = address >> 8; @@ -629,7 +538,6 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, int reply_bytes; int ret; - ironlake_edp_panel_vdd_on(intel_dp); intel_dp_check_edp(intel_dp); /* Set up the command byte */ if (mode & MODE_I2C_READ) @@ -661,18 +569,13 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, break; } - /* - * DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device is - * required to retry at least seven times upon receiving AUX_DEFER - * before giving up the AUX transaction. - */ - for (retry = 0; retry < 7; retry++) { + for (retry = 0; retry < 5; retry++) { ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, reply, reply_bytes); if (ret < 0) { DRM_DEBUG_KMS("aux_ch failed %d\n", ret); - goto out; + return ret; } switch (reply[0] & AUX_NATIVE_REPLY_MASK) { @@ -683,8 +586,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, break; case AUX_NATIVE_REPLY_NACK: DRM_DEBUG_KMS("aux_ch native nack\n"); - ret = -EREMOTEIO; - goto out; + return -EREMOTEIO; case AUX_NATIVE_REPLY_DEFER: /* * For now, just give more slack to branch devices. We @@ -702,8 +604,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, default: DRM_ERROR("aux_ch invalid native reply 0x%02x\n", reply[0]); - ret = -EREMOTEIO; - goto out; + return -EREMOTEIO; } switch (reply[0] & AUX_I2C_REPLY_MASK) { @@ -711,29 +612,22 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, if (mode == MODE_I2C_READ) { *read_byte = reply[1]; } - ret = reply_bytes - 1; - goto out; + return reply_bytes - 1; case AUX_I2C_REPLY_NACK: DRM_DEBUG_KMS("aux_i2c nack\n"); - ret = -EREMOTEIO; - goto out; + return -EREMOTEIO; case AUX_I2C_REPLY_DEFER: DRM_DEBUG_KMS("aux_i2c defer\n"); udelay(100); break; default: DRM_ERROR("aux_i2c invalid reply 0x%02x\n", reply[0]); - ret = -EREMOTEIO; - goto out; + return -EREMOTEIO; } } DRM_ERROR("too many retries, giving up\n"); - ret = -EREMOTEIO; - -out: - ironlake_edp_panel_vdd_off(intel_dp, false); - return ret; + return -EREMOTEIO; } static int @@ -753,9 +647,11 @@ intel_dp_i2c_init(struct intel_dp *intel_dp, 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; + intel_dp->adapter.dev.parent = &intel_connector->base.kdev; + 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; } @@ -764,30 +660,41 @@ intel_dp_set_clock(struct intel_encoder *encoder, struct intel_crtc_config *pipe_config, int link_bw) { struct drm_device *dev = encoder->base.dev; - const struct dp_link_dpll *divisor = NULL; - int i, count = 0; if (IS_G4X(dev)) { - divisor = gen4_dpll; - count = ARRAY_SIZE(gen4_dpll); + if (link_bw == DP_LINK_BW_1_62) { + pipe_config->dpll.p1 = 2; + pipe_config->dpll.p2 = 10; + pipe_config->dpll.n = 2; + pipe_config->dpll.m1 = 23; + pipe_config->dpll.m2 = 8; + } else { + pipe_config->dpll.p1 = 1; + pipe_config->dpll.p2 = 10; + pipe_config->dpll.n = 1; + pipe_config->dpll.m1 = 14; + pipe_config->dpll.m2 = 2; + } + pipe_config->clock_set = true; } else if (IS_HASWELL(dev)) { /* Haswell has special-purpose DP DDI clocks. */ } else if (HAS_PCH_SPLIT(dev)) { - divisor = pch_dpll; - count = ARRAY_SIZE(pch_dpll); - } else if (IS_VALLEYVIEW(dev)) { - divisor = vlv_dpll; - count = ARRAY_SIZE(vlv_dpll); - } - - if (divisor && count) { - for (i = 0; i < count; i++) { - if (link_bw == divisor[i].link_bw) { - pipe_config->dpll = divisor[i].dpll; - pipe_config->clock_set = true; - break; - } + if (link_bw == DP_LINK_BW_1_62) { + pipe_config->dpll.n = 1; + pipe_config->dpll.p1 = 2; + pipe_config->dpll.p2 = 10; + pipe_config->dpll.m1 = 12; + pipe_config->dpll.m2 = 9; + } else { + pipe_config->dpll.n = 2; + pipe_config->dpll.p1 = 1; + pipe_config->dpll.p2 = 10; + pipe_config->dpll.m1 = 14; + pipe_config->dpll.m2 = 8; } + pipe_config->clock_set = true; + } else if (IS_VALLEYVIEW(dev)) { + /* FIXME: Need to figure out optimized DP clocks for vlv. */ } } @@ -830,22 +737,19 @@ intel_dp_compute_config(struct intel_encoder *encoder, DRM_DEBUG_KMS("DP link computation with max lane count %i " "max bw %02x pixel clock %iKHz\n", - max_lane_count, bws[max_clock], - adjusted_mode->crtc_clock); + max_lane_count, bws[max_clock], adjusted_mode->clock); /* Walk through all bpp values. Luckily they're all nicely spaced with 2 * bpc in between. */ bpp = pipe_config->pipe_bpp; - if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp && - dev_priv->vbt.edp_bpp < bpp) { + if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp) { DRM_DEBUG_KMS("clamping bpp for eDP panel to BIOS-provided %i\n", dev_priv->vbt.edp_bpp); - bpp = dev_priv->vbt.edp_bpp; + bpp = min_t(int, bpp, dev_priv->vbt.edp_bpp); } for (; bpp >= 6*3; bpp -= 2*3) { - mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock, - bpp); + mode_rate = intel_dp_link_required(adjusted_mode->clock, bpp); for (clock = 0; clock <= max_clock; clock++) { for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { @@ -890,8 +794,7 @@ found: mode_rate, link_avail); intel_link_compute_m_n(bpp, lane_count, - adjusted_mode->crtc_clock, - pipe_config->port_clock, + adjusted_mode->clock, pipe_config->port_clock, &pipe_config->dp_m_n); intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw); @@ -899,6 +802,21 @@ found: return true; } +void intel_dp_init_link_config(struct intel_dp *intel_dp) +{ + memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); + intel_dp->link_configuration[0] = intel_dp->link_bw; + intel_dp->link_configuration[1] = intel_dp->lane_count; + intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B; + /* + * Check for DPCD version > 1.1 and enhanced framing support + */ + if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 && + (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) { + intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + } +} + static void ironlake_set_pll_cpu_edp(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -971,6 +889,8 @@ static void intel_dp_mode_set(struct intel_encoder *encoder) intel_write_eld(&encoder->base, adjusted_mode); } + intel_dp_init_link_config(intel_dp); + /* Split out the IBX/CPU vs CPT settings */ if (port == PORT_A && IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) { @@ -980,7 +900,7 @@ static void intel_dp_mode_set(struct intel_encoder *encoder) intel_dp->DP |= DP_SYNC_VS_HIGH; intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; - if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) + if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN) intel_dp->DP |= DP_ENHANCED_FRAMING; intel_dp->DP |= crtc->pipe << 29; @@ -994,7 +914,7 @@ static void intel_dp_mode_set(struct intel_encoder *encoder) intel_dp->DP |= DP_SYNC_VS_HIGH; intel_dp->DP |= DP_LINK_TRAIN_OFF; - if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) + if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN) intel_dp->DP |= DP_ENHANCED_FRAMING; if (crtc->pipe == 1) @@ -1024,8 +944,8 @@ static void ironlake_wait_panel_status(struct intel_dp *intel_dp, struct drm_i915_private *dev_priv = dev->dev_private; u32 pp_stat_reg, pp_ctrl_reg; - pp_stat_reg = _pp_stat_reg(intel_dp); - pp_ctrl_reg = _pp_ctrl_reg(intel_dp); + pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS; + pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL; DRM_DEBUG_KMS("mask %08x value %08x status %08x control %08x\n", mask, value, @@ -1067,8 +987,11 @@ static u32 ironlake_get_pp_control(struct intel_dp *intel_dp) struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = dev->dev_private; u32 control; + u32 pp_ctrl_reg; + + pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL; + control = I915_READ(pp_ctrl_reg); - control = I915_READ(_pp_ctrl_reg(intel_dp)); control &= ~PANEL_UNLOCK_MASK; control |= PANEL_UNLOCK_REGS; return control; @@ -1083,16 +1006,17 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) 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)) + if (ironlake_edp_have_panel_vdd(intel_dp)) { + DRM_DEBUG_KMS("eDP VDD already on\n"); return; - - DRM_DEBUG_KMS("Turning eDP VDD on\n"); + } if (!ironlake_edp_have_panel_power(intel_dp)) ironlake_wait_panel_power_cycle(intel_dp); @@ -1100,8 +1024,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) pp = ironlake_get_pp_control(intel_dp); pp |= EDP_FORCE_VDD; - pp_stat_reg = _pp_stat_reg(intel_dp); - pp_ctrl_reg = _pp_ctrl_reg(intel_dp); + pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS; + pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL; I915_WRITE(pp_ctrl_reg, pp); POSTING_READ(pp_ctrl_reg); @@ -1126,13 +1050,11 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp) WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) { - DRM_DEBUG_KMS("Turning eDP VDD off\n"); - pp = ironlake_get_pp_control(intel_dp); pp &= ~EDP_FORCE_VDD; - pp_ctrl_reg = _pp_ctrl_reg(intel_dp); - pp_stat_reg = _pp_stat_reg(intel_dp); + pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS; + pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL; I915_WRITE(pp_ctrl_reg, pp); POSTING_READ(pp_ctrl_reg); @@ -1160,6 +1082,7 @@ 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; @@ -1196,19 +1119,20 @@ void ironlake_edp_panel_on(struct intel_dp *intel_dp) ironlake_wait_panel_power_cycle(intel_dp); - pp_ctrl_reg = _pp_ctrl_reg(intel_dp); pp = ironlake_get_pp_control(intel_dp); if (IS_GEN5(dev)) { /* ILK workaround: disable reset around power sequence */ pp &= ~PANEL_POWER_RESET; - I915_WRITE(pp_ctrl_reg, pp); - POSTING_READ(pp_ctrl_reg); + I915_WRITE(PCH_PP_CONTROL, pp); + POSTING_READ(PCH_PP_CONTROL); } pp |= POWER_TARGET_ON; if (!IS_GEN5(dev)) pp |= PANEL_POWER_RESET; + pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL; + I915_WRITE(pp_ctrl_reg, pp); POSTING_READ(pp_ctrl_reg); @@ -1216,8 +1140,8 @@ void ironlake_edp_panel_on(struct intel_dp *intel_dp) if (IS_GEN5(dev)) { pp |= PANEL_POWER_RESET; /* restore panel reset bit */ - I915_WRITE(pp_ctrl_reg, pp); - POSTING_READ(pp_ctrl_reg); + I915_WRITE(PCH_PP_CONTROL, pp); + POSTING_READ(PCH_PP_CONTROL); } } @@ -1240,7 +1164,7 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp) * panels get very unhappy and cease to work. */ pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE); - pp_ctrl_reg = _pp_ctrl_reg(intel_dp); + pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL; I915_WRITE(pp_ctrl_reg, pp); POSTING_READ(pp_ctrl_reg); @@ -1255,6 +1179,7 @@ void ironlake_edp_backlight_on(struct intel_dp *intel_dp) struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + int pipe = to_intel_crtc(intel_dig_port->base.base.crtc)->pipe; u32 pp; u32 pp_ctrl_reg; @@ -1272,12 +1197,12 @@ void ironlake_edp_backlight_on(struct intel_dp *intel_dp) pp = ironlake_get_pp_control(intel_dp); pp |= EDP_BLC_ENABLE; - pp_ctrl_reg = _pp_ctrl_reg(intel_dp); + pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL; I915_WRITE(pp_ctrl_reg, pp); POSTING_READ(pp_ctrl_reg); - intel_panel_enable_backlight(intel_dp->attached_connector); + intel_panel_enable_backlight(dev, pipe); } void ironlake_edp_backlight_off(struct intel_dp *intel_dp) @@ -1290,13 +1215,13 @@ void ironlake_edp_backlight_off(struct intel_dp *intel_dp) if (!is_edp(intel_dp)) return; - intel_panel_disable_backlight(intel_dp->attached_connector); + intel_panel_disable_backlight(dev); DRM_DEBUG_KMS("\n"); pp = ironlake_get_pp_control(intel_dp); pp &= ~EDP_BLC_ENABLE; - pp_ctrl_reg = _pp_ctrl_reg(intel_dp); + pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL; I915_WRITE(pp_ctrl_reg, pp); POSTING_READ(pp_ctrl_reg); @@ -1443,7 +1368,6 @@ static void intel_dp_get_config(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = dev->dev_private; enum port port = dp_to_dig_port(intel_dp)->port; struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); - int dotclock; if ((port == PORT_A) || !HAS_PCH_CPT(dev)) { tmp = I915_READ(intel_dp->output_reg); @@ -1471,25 +1395,13 @@ static void intel_dp_get_config(struct intel_encoder *encoder, pipe_config->adjusted_mode.flags |= flags; - pipe_config->has_dp_encoder = true; - - intel_dp_get_m_n(crtc, pipe_config); - - if (port == PORT_A) { + if (dp_to_dig_port(intel_dp)->port == PORT_A) { if ((I915_READ(DP_A) & DP_PLL_FREQ_MASK) == DP_PLL_FREQ_160MHZ) pipe_config->port_clock = 162000; else pipe_config->port_clock = 270000; } - dotclock = intel_dotclock_calculate(pipe_config->port_clock, - &pipe_config->dp_m_n); - - if (HAS_PCH_SPLIT(dev_priv->dev) && port != PORT_A) - ironlake_check_encoder_dotclock(pipe_config, dotclock); - - pipe_config->adjusted_mode.crtc_clock = dotclock; - if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp && pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) { /* @@ -1511,21 +1423,20 @@ static void intel_dp_get_config(struct intel_encoder *encoder, } } -static bool is_edp_psr(struct drm_device *dev) +static bool is_edp_psr(struct intel_dp *intel_dp) { - struct drm_i915_private *dev_priv = dev->dev_private; - - return dev_priv->psr.sink_support; + return is_edp(intel_dp) && + intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED; } static bool intel_edp_is_psr_enabled(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - if (!HAS_PSR(dev)) + if (!IS_HASWELL(dev)) return false; - return I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE; + return I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE; } static void intel_edp_psr_write_vsc(struct intel_dp *intel_dp, @@ -1575,7 +1486,7 @@ static void intel_edp_psr_setup(struct intel_dp *intel_dp) intel_edp_psr_write_vsc(intel_dp, &psr_vsc); /* Avoid continuous PSR exit by masking memup and hpd */ - I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP | + I915_WRITE(EDP_PSR_DEBUG_CTL, EDP_PSR_DEBUG_MASK_MEMUP | EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP); intel_dp->psr_setup_done = true; @@ -1600,9 +1511,9 @@ static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp) DP_PSR_MAIN_LINK_ACTIVE); /* Setup AUX registers */ - I915_WRITE(EDP_PSR_AUX_DATA1(dev), EDP_PSR_DPCD_COMMAND); - I915_WRITE(EDP_PSR_AUX_DATA2(dev), EDP_PSR_DPCD_NORMAL_OPERATION); - I915_WRITE(EDP_PSR_AUX_CTL(dev), + I915_WRITE(EDP_PSR_AUX_DATA1, EDP_PSR_DPCD_COMMAND); + I915_WRITE(EDP_PSR_AUX_DATA2, EDP_PSR_DPCD_NORMAL_OPERATION); + I915_WRITE(EDP_PSR_AUX_CTL, DP_AUX_CH_CTL_TIME_OUT_400us | (msg_size << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | @@ -1616,7 +1527,6 @@ static void intel_edp_psr_enable_source(struct intel_dp *intel_dp) uint32_t max_sleep_time = 0x1f; uint32_t idle_frames = 1; uint32_t val = 0x0; - const uint32_t link_entry_time = EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES; if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT) { val |= EDP_PSR_LINK_STANDBY; @@ -1626,8 +1536,8 @@ static void intel_edp_psr_enable_source(struct intel_dp *intel_dp) } else val |= EDP_PSR_LINK_DISABLE; - I915_WRITE(EDP_PSR_CTL(dev), val | - IS_BROADWELL(dev) ? 0 : link_entry_time | + I915_WRITE(EDP_PSR_CTL, val | + EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES | max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT | idle_frames << EDP_PSR_IDLE_FRAME_SHIFT | EDP_PSR_ENABLE); @@ -1643,33 +1553,42 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp) struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj; struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base; - dev_priv->psr.source_ok = false; - - if (!HAS_PSR(dev)) { + if (!IS_HASWELL(dev)) { DRM_DEBUG_KMS("PSR not supported on this platform\n"); + dev_priv->no_psr_reason = PSR_NO_SOURCE; return false; } if ((intel_encoder->type != INTEL_OUTPUT_EDP) || (dig_port->port != PORT_A)) { DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n"); + dev_priv->no_psr_reason = PSR_HSW_NOT_DDIA; + return false; + } + + if (!is_edp_psr(intel_dp)) { + DRM_DEBUG_KMS("PSR not supported by this panel\n"); + dev_priv->no_psr_reason = PSR_NO_SINK; return false; } if (!i915_enable_psr) { DRM_DEBUG_KMS("PSR disable by flag\n"); + dev_priv->no_psr_reason = PSR_MODULE_PARAM; return false; } crtc = dig_port->base.base.crtc; if (crtc == NULL) { DRM_DEBUG_KMS("crtc not active for PSR\n"); + dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE; return false; } intel_crtc = to_intel_crtc(crtc); - if (!intel_crtc_active(crtc)) { + if (!intel_crtc->active || !crtc->fb || !crtc->mode.clock) { DRM_DEBUG_KMS("crtc not active for PSR\n"); + dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE; return false; } @@ -1677,26 +1596,29 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp) if (obj->tiling_mode != I915_TILING_X || obj->fence_reg == I915_FENCE_REG_NONE) { DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n"); + dev_priv->no_psr_reason = PSR_NOT_TILED; return false; } if (I915_READ(SPRCTL(intel_crtc->pipe)) & SPRITE_ENABLE) { DRM_DEBUG_KMS("PSR condition failed: Sprite is Enabled\n"); + dev_priv->no_psr_reason = PSR_SPRITE_ENABLED; return false; } if (I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config.cpu_transcoder)) & S3D_ENABLE) { DRM_DEBUG_KMS("PSR condition failed: Stereo 3D is Enabled\n"); + dev_priv->no_psr_reason = PSR_S3D_ENABLED; return false; } - if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) { + if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) { DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n"); + dev_priv->no_psr_reason = PSR_INTERLACED_ENABLED; return false; } - dev_priv->psr.source_ok = true; return true; } @@ -1735,11 +1657,10 @@ void intel_edp_psr_disable(struct intel_dp *intel_dp) if (!intel_edp_is_psr_enabled(dev)) return; - I915_WRITE(EDP_PSR_CTL(dev), - I915_READ(EDP_PSR_CTL(dev)) & ~EDP_PSR_ENABLE); + I915_WRITE(EDP_PSR_CTL, I915_READ(EDP_PSR_CTL) & ~EDP_PSR_ENABLE); /* Wait till PSR is idle */ - if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev)) & + if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL) & EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10)) DRM_ERROR("Timed out waiting for PSR Idle State\n"); } @@ -1753,7 +1674,7 @@ void intel_edp_psr_update(struct drm_device *dev) if (encoder->type == INTEL_OUTPUT_EDP) { intel_dp = enc_to_intel_dp(&encoder->base); - if (!is_edp_psr(dev)) + if (!is_edp_psr(intel_dp)) return; if (!intel_edp_psr_match_conditions(intel_dp)) @@ -1774,7 +1695,7 @@ static void intel_disable_dp(struct intel_encoder *encoder) * ensure that we have vdd while we switch off the panel. */ ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_backlight_off(intel_dp); - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); ironlake_edp_panel_off(intel_dp); /* cpu edp my only be disable _after_ the cpu pipe/plane is disabled. */ @@ -1812,24 +1733,14 @@ static void intel_enable_dp(struct intel_encoder *encoder) ironlake_edp_panel_vdd_off(intel_dp, true); intel_dp_complete_link_train(intel_dp); intel_dp_stop_link_train(intel_dp); -} - -static void g4x_enable_dp(struct intel_encoder *encoder) -{ - struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); - - intel_enable_dp(encoder); ironlake_edp_backlight_on(intel_dp); } static void vlv_enable_dp(struct intel_encoder *encoder) { - struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); - - ironlake_edp_backlight_on(intel_dp); } -static void g4x_pre_enable_dp(struct intel_encoder *encoder) +static void intel_pre_enable_dp(struct intel_encoder *encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct intel_digital_port *dport = dp_to_dig_port(intel_dp); @@ -1847,59 +1758,53 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder) struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); int port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; - struct edp_power_seq power_seq; u32 val; mutex_lock(&dev_priv->dpio_lock); - val = vlv_dpio_read(dev_priv, pipe, DPIO_DATA_LANE_A(port)); + val = vlv_dpio_read(dev_priv, DPIO_DATA_LANE_A(port)); val = 0; if (pipe) val |= (1<<21); else val &= ~(1<<21); val |= 0x001000c4; - vlv_dpio_write(dev_priv, pipe, DPIO_DATA_CHANNEL(port), val); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF0(port), 0x00760018); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF8(port), 0x00400888); + vlv_dpio_write(dev_priv, DPIO_DATA_CHANNEL(port), val); + vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(port), 0x00760018); + vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(port), 0x00400888); mutex_unlock(&dev_priv->dpio_lock); - /* init power sequencer on this pipe and port */ - intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); - intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, - &power_seq); - intel_enable_dp(encoder); vlv_wait_port_ready(dev_priv, port); } -static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder) +static void intel_dp_pre_pll_enable(struct intel_encoder *encoder) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = - to_intel_crtc(encoder->base.crtc); int port = vlv_dport_to_channel(dport); - int pipe = intel_crtc->pipe; + + if (!IS_VALLEYVIEW(dev)) + return; /* Program Tx lane resets to default */ mutex_lock(&dev_priv->dpio_lock); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port), + vlv_dpio_write(dev_priv, DPIO_PCS_TX(port), DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port), + vlv_dpio_write(dev_priv, DPIO_PCS_CLK(port), DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) | DPIO_PCS_CLK_SOFT_RESET); /* Fix up inter-pair skew failure */ - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER1(port), 0x00750f00); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_CTL(port), 0x00001500); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_LANE(port), 0x40400000); + vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER1(port), 0x00750f00); + vlv_dpio_write(dev_priv, DPIO_TX_CTL(port), 0x00001500); + vlv_dpio_write(dev_priv, DPIO_TX_LANE(port), 0x40400000); mutex_unlock(&dev_priv->dpio_lock); } @@ -1964,7 +1869,7 @@ intel_dp_voltage_max(struct intel_dp *intel_dp) struct drm_device *dev = intel_dp_to_dev(intel_dp); enum port port = dp_to_dig_port(intel_dp)->port; - if (IS_VALLEYVIEW(dev) || IS_BROADWELL(dev)) + if (IS_VALLEYVIEW(dev)) return DP_TRAIN_VOLTAGE_SWING_1200; else if (IS_GEN7(dev) && port == PORT_A) return DP_TRAIN_VOLTAGE_SWING_800; @@ -1980,18 +1885,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) struct drm_device *dev = intel_dp_to_dev(intel_dp); enum port port = dp_to_dig_port(intel_dp)->port; - if (IS_BROADWELL(dev)) { - switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_400: - case DP_TRAIN_VOLTAGE_SWING_600: - return DP_TRAIN_PRE_EMPHASIS_6; - case DP_TRAIN_VOLTAGE_SWING_800: - return DP_TRAIN_PRE_EMPHASIS_3_5; - case DP_TRAIN_VOLTAGE_SWING_1200: - default: - return DP_TRAIN_PRE_EMPHASIS_0; - } - } else if (IS_HASWELL(dev)) { + if (HAS_DDI(dev)) { switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { case DP_TRAIN_VOLTAGE_SWING_400: return DP_TRAIN_PRE_EMPHASIS_9_5; @@ -2045,13 +1939,10 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp) struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = dev->dev_private; struct intel_digital_port *dport = dp_to_dig_port(intel_dp); - struct intel_crtc *intel_crtc = - to_intel_crtc(dport->base.base.crtc); unsigned long demph_reg_value, preemph_reg_value, uniqtranscale_reg_value; uint8_t train_set = intel_dp->train_set[0]; int port = vlv_dport_to_channel(dport); - int pipe = intel_crtc->pipe; switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { case DP_TRAIN_PRE_EMPHASIS_0: @@ -2127,22 +2018,21 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp) } mutex_lock(&dev_priv->dpio_lock); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0x00000000); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL4(port), demph_reg_value); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL2(port), + vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0x00000000); + vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(port), demph_reg_value); + vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(port), uniqtranscale_reg_value); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL3(port), 0x0C782040); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER0(port), 0x00030000); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port), preemph_reg_value); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0x80000000); + vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL3(port), 0x0C782040); + vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER0(port), 0x00030000); + vlv_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port), preemph_reg_value); + vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0x80000000); mutex_unlock(&dev_priv->dpio_lock); return 0; } static void -intel_get_adjust_train(struct intel_dp *intel_dp, - const uint8_t link_status[DP_LINK_STATUS_SIZE]) +intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]) { uint8_t v = 0; uint8_t p = 0; @@ -2303,41 +2193,6 @@ intel_hsw_signal_levels(uint8_t train_set) } } -static uint32_t -intel_bdw_signal_levels(uint8_t train_set) -{ - int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | - DP_TRAIN_PRE_EMPHASIS_MASK); - switch (signal_levels) { - case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0: - return DDI_BUF_EMP_400MV_0DB_BDW; /* Sel0 */ - case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5: - return DDI_BUF_EMP_400MV_3_5DB_BDW; /* Sel1 */ - case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6: - return DDI_BUF_EMP_400MV_6DB_BDW; /* Sel2 */ - - case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0: - return DDI_BUF_EMP_600MV_0DB_BDW; /* Sel3 */ - case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5: - return DDI_BUF_EMP_600MV_3_5DB_BDW; /* Sel4 */ - case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6: - return DDI_BUF_EMP_600MV_6DB_BDW; /* Sel5 */ - - case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0: - return DDI_BUF_EMP_800MV_0DB_BDW; /* Sel6 */ - case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5: - return DDI_BUF_EMP_800MV_3_5DB_BDW; /* Sel7 */ - - case DP_TRAIN_VOLTAGE_SWING_1200 | DP_TRAIN_PRE_EMPHASIS_0: - return DDI_BUF_EMP_1200MV_0DB_BDW; /* Sel8 */ - - default: - DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:" - "0x%x\n", signal_levels); - return DDI_BUF_EMP_400MV_0DB_BDW; /* Sel0 */ - } -} - /* Properly updates "DP" with the correct signal levels. */ static void intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) @@ -2348,10 +2203,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) uint32_t signal_levels, mask; uint8_t train_set = intel_dp->train_set[0]; - if (IS_BROADWELL(dev)) { - signal_levels = intel_bdw_signal_levels(train_set); - mask = DDI_BUF_EMP_MASK; - } else if (IS_HASWELL(dev)) { + if (HAS_DDI(dev)) { signal_levels = intel_hsw_signal_levels(train_set); mask = DDI_BUF_EMP_MASK; } else if (IS_VALLEYVIEW(dev)) { @@ -2375,15 +2227,14 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) static bool intel_dp_set_link_train(struct intel_dp *intel_dp, - uint32_t *DP, + uint32_t dp_reg_value, uint8_t dp_train_pat) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; enum port port = intel_dig_port->port; - uint8_t buf[sizeof(intel_dp->train_set) + 1]; - int ret, len; + int ret; if (HAS_DDI(dev)) { uint32_t temp = I915_READ(DP_TP_CTL(port)); @@ -2412,93 +2263,62 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, I915_WRITE(DP_TP_CTL(port), temp); } else if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) { - *DP &= ~DP_LINK_TRAIN_MASK_CPT; + dp_reg_value &= ~DP_LINK_TRAIN_MASK_CPT; switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { case DP_TRAINING_PATTERN_DISABLE: - *DP |= DP_LINK_TRAIN_OFF_CPT; + dp_reg_value |= DP_LINK_TRAIN_OFF_CPT; break; case DP_TRAINING_PATTERN_1: - *DP |= DP_LINK_TRAIN_PAT_1_CPT; + dp_reg_value |= DP_LINK_TRAIN_PAT_1_CPT; break; case DP_TRAINING_PATTERN_2: - *DP |= DP_LINK_TRAIN_PAT_2_CPT; + dp_reg_value |= DP_LINK_TRAIN_PAT_2_CPT; break; case DP_TRAINING_PATTERN_3: DRM_ERROR("DP training pattern 3 not supported\n"); - *DP |= DP_LINK_TRAIN_PAT_2_CPT; + dp_reg_value |= DP_LINK_TRAIN_PAT_2_CPT; break; } } else { - *DP &= ~DP_LINK_TRAIN_MASK; + dp_reg_value &= ~DP_LINK_TRAIN_MASK; switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { case DP_TRAINING_PATTERN_DISABLE: - *DP |= DP_LINK_TRAIN_OFF; + dp_reg_value |= DP_LINK_TRAIN_OFF; break; case DP_TRAINING_PATTERN_1: - *DP |= DP_LINK_TRAIN_PAT_1; + dp_reg_value |= DP_LINK_TRAIN_PAT_1; break; case DP_TRAINING_PATTERN_2: - *DP |= DP_LINK_TRAIN_PAT_2; + dp_reg_value |= DP_LINK_TRAIN_PAT_2; break; case DP_TRAINING_PATTERN_3: DRM_ERROR("DP training pattern 3 not supported\n"); - *DP |= DP_LINK_TRAIN_PAT_2; + dp_reg_value |= DP_LINK_TRAIN_PAT_2; break; } } - I915_WRITE(intel_dp->output_reg, *DP); + I915_WRITE(intel_dp->output_reg, dp_reg_value); POSTING_READ(intel_dp->output_reg); - buf[0] = dp_train_pat; - if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) == + intel_dp_aux_native_write_1(intel_dp, + DP_TRAINING_PATTERN_SET, + dp_train_pat); + + if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) != DP_TRAINING_PATTERN_DISABLE) { - /* don't write DP_TRAINING_LANEx_SET on disable */ - len = 1; - } else { - /* DP_TRAINING_LANEx_SET follow DP_TRAINING_PATTERN_SET */ - memcpy(buf + 1, intel_dp->train_set, intel_dp->lane_count); - len = intel_dp->lane_count + 1; + ret = intel_dp_aux_native_write(intel_dp, + DP_TRAINING_LANE0_SET, + intel_dp->train_set, + intel_dp->lane_count); + if (ret != intel_dp->lane_count) + return false; } - ret = intel_dp_aux_native_write(intel_dp, DP_TRAINING_PATTERN_SET, - buf, len); - - return ret == len; -} - -static bool -intel_dp_reset_link_train(struct intel_dp *intel_dp, uint32_t *DP, - uint8_t dp_train_pat) -{ - memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set)); - intel_dp_set_signal_levels(intel_dp, DP); - return intel_dp_set_link_train(intel_dp, DP, dp_train_pat); -} - -static bool -intel_dp_update_link_train(struct intel_dp *intel_dp, uint32_t *DP, - const uint8_t link_status[DP_LINK_STATUS_SIZE]) -{ - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = intel_dig_port->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int ret; - - intel_get_adjust_train(intel_dp, link_status); - intel_dp_set_signal_levels(intel_dp, DP); - - I915_WRITE(intel_dp->output_reg, *DP); - POSTING_READ(intel_dp->output_reg); - - ret = intel_dp_aux_native_write(intel_dp, DP_TRAINING_LANE0_SET, - intel_dp->train_set, - intel_dp->lane_count); - - return ret == intel_dp->lane_count; + return true; } static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp) @@ -2542,37 +2362,32 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) uint8_t voltage; int voltage_tries, loop_tries; uint32_t DP = intel_dp->DP; - uint8_t link_config[2]; if (HAS_DDI(dev)) intel_ddi_prepare_link_retrain(encoder); /* Write the link configuration data */ - link_config[0] = intel_dp->link_bw; - link_config[1] = intel_dp->lane_count; - if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) - link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; - intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, link_config, 2); - - link_config[0] = 0; - link_config[1] = DP_SET_ANSI_8B10B; - intel_dp_aux_native_write(intel_dp, DP_DOWNSPREAD_CTRL, link_config, 2); + intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, + intel_dp->link_configuration, + DP_LINK_CONFIGURATION_SIZE); DP |= DP_PORT_EN; - /* clock recovery */ - if (!intel_dp_reset_link_train(intel_dp, &DP, - DP_TRAINING_PATTERN_1 | - DP_LINK_SCRAMBLING_DISABLE)) { - DRM_ERROR("failed to enable link training\n"); - return; - } - + memset(intel_dp->train_set, 0, 4); voltage = 0xff; voltage_tries = 0; loop_tries = 0; for (;;) { - uint8_t link_status[DP_LINK_STATUS_SIZE]; + /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ + uint8_t link_status[DP_LINK_STATUS_SIZE]; + + intel_dp_set_signal_levels(intel_dp, &DP); + + /* Set training pattern 1 */ + if (!intel_dp_set_link_train(intel_dp, DP, + DP_TRAINING_PATTERN_1 | + DP_LINK_SCRAMBLING_DISABLE)) + break; drm_dp_link_train_clock_recovery_delay(intel_dp->dpcd); if (!intel_dp_get_link_status(intel_dp, link_status)) { @@ -2592,12 +2407,10 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) if (i == intel_dp->lane_count) { ++loop_tries; if (loop_tries == 5) { - DRM_ERROR("too many full retries, give up\n"); + DRM_DEBUG_KMS("too many full retries, give up\n"); break; } - intel_dp_reset_link_train(intel_dp, &DP, - DP_TRAINING_PATTERN_1 | - DP_LINK_SCRAMBLING_DISABLE); + memset(intel_dp->train_set, 0, 4); voltage_tries = 0; continue; } @@ -2606,18 +2419,15 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { ++voltage_tries; if (voltage_tries == 5) { - DRM_ERROR("too many voltage retries, give up\n"); + DRM_DEBUG_KMS("too many voltage retries, give up\n"); break; } } else voltage_tries = 0; voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; - /* Update training set as requested by target */ - if (!intel_dp_update_link_train(intel_dp, &DP, link_status)) { - DRM_ERROR("failed to update link training\n"); - break; - } + /* Compute new intel_dp->train_set as requested by target */ + intel_get_adjust_train(intel_dp, link_status); } intel_dp->DP = DP; @@ -2631,18 +2441,11 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) uint32_t DP = intel_dp->DP; /* channel equalization */ - if (!intel_dp_set_link_train(intel_dp, &DP, - DP_TRAINING_PATTERN_2 | - DP_LINK_SCRAMBLING_DISABLE)) { - DRM_ERROR("failed to start channel equalization\n"); - return; - } - tries = 0; cr_tries = 0; channel_eq = false; for (;;) { - uint8_t link_status[DP_LINK_STATUS_SIZE]; + uint8_t link_status[DP_LINK_STATUS_SIZE]; if (cr_tries > 5) { DRM_ERROR("failed to train DP, aborting\n"); @@ -2650,18 +2453,21 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) break; } + intel_dp_set_signal_levels(intel_dp, &DP); + + /* channel eq pattern */ + if (!intel_dp_set_link_train(intel_dp, DP, + DP_TRAINING_PATTERN_2 | + DP_LINK_SCRAMBLING_DISABLE)) + break; + drm_dp_link_train_channel_eq_delay(intel_dp->dpcd); - if (!intel_dp_get_link_status(intel_dp, link_status)) { - DRM_ERROR("failed to get link status\n"); + if (!intel_dp_get_link_status(intel_dp, link_status)) break; - } /* Make sure clock is still ok */ if (!drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) { intel_dp_start_link_train(intel_dp); - intel_dp_set_link_train(intel_dp, &DP, - DP_TRAINING_PATTERN_2 | - DP_LINK_SCRAMBLING_DISABLE); cr_tries++; continue; } @@ -2675,19 +2481,13 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) if (tries > 5) { intel_dp_link_down(intel_dp); intel_dp_start_link_train(intel_dp); - intel_dp_set_link_train(intel_dp, &DP, - DP_TRAINING_PATTERN_2 | - DP_LINK_SCRAMBLING_DISABLE); tries = 0; cr_tries++; continue; } - /* Update training set as requested by target */ - if (!intel_dp_update_link_train(intel_dp, &DP, link_status)) { - DRM_ERROR("failed to update link training\n"); - break; - } + /* Compute new intel_dp->train_set as requested by target */ + intel_get_adjust_train(intel_dp, link_status); ++tries; } @@ -2702,7 +2502,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) void intel_dp_stop_link_train(struct intel_dp *intel_dp) { - intel_dp_set_link_train(intel_dp, &intel_dp->DP, + intel_dp_set_link_train(intel_dp, intel_dp->DP, DP_TRAINING_PATTERN_DISABLE); } @@ -2789,10 +2589,6 @@ intel_dp_link_down(struct intel_dp *intel_dp) static bool intel_dp_get_dpcd(struct intel_dp *intel_dp) { - struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = dig_port->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - char dpcd_hex_dump[sizeof(intel_dp->dpcd) * 3]; if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd, @@ -2808,16 +2604,11 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) /* Check if the panel supports PSR */ memset(intel_dp->psr_dpcd, 0, sizeof(intel_dp->psr_dpcd)); - if (is_edp(intel_dp)) { - intel_dp_aux_native_read_retry(intel_dp, DP_PSR_SUPPORT, - intel_dp->psr_dpcd, - sizeof(intel_dp->psr_dpcd)); - if (intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED) { - dev_priv->psr.sink_support = true; - DRM_DEBUG_KMS("Detected EDP PSR Panel.\n"); - } - } - + intel_dp_aux_native_read_retry(intel_dp, DP_PSR_SUPPORT, + intel_dp->psr_dpcd, + sizeof(intel_dp->psr_dpcd)); + if (is_edp_psr(intel_dp)) + DRM_DEBUG_KMS("Detected EDP PSR Panel.\n"); if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT)) return true; /* native DP sink */ @@ -2937,6 +2728,7 @@ static enum drm_connector_status intel_dp_detect_dpcd(struct intel_dp *intel_dp) { uint8_t *dpcd = intel_dp->dpcd; + bool hpd; uint8_t type; if (!intel_dp_get_dpcd(intel_dp)) @@ -2947,8 +2739,8 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp) return connector_status_connected; /* If we're HPD-aware, SINK_COUNT changes dynamically */ - if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 && - intel_dp->downstream_ports[0] & DP_DS_PORT_HPD) { + hpd = !!(intel_dp->downstream_ports[0] & DP_DS_PORT_HPD); + if (hpd) { uint8_t reg; if (!intel_dp_aux_native_read_retry(intel_dp, DP_SINK_COUNT, ®, 1)) @@ -2962,18 +2754,9 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp) return connector_status_connected; /* Well we tried, say unknown for unreliable port types */ - if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) { - type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK; - if (type == DP_DS_PORT_TYPE_VGA || - type == DP_DS_PORT_TYPE_NON_EDID) - return connector_status_unknown; - } else { - type = intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & - DP_DWN_STRM_PORT_TYPE_MASK; - if (type == DP_DWN_STRM_PORT_TYPE_ANALOG || - type == DP_DWN_STRM_PORT_TYPE_OTHER) - return connector_status_unknown; - } + type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK; + if (type == DP_DS_PORT_TYPE_VGA || type == DP_DS_PORT_TYPE_NON_EDID) + return connector_status_unknown; /* Anything else is out of spec, warn and ignore */ DRM_DEBUG_KMS("Broken DP branch device, ignoring\n"); @@ -3047,11 +2830,19 @@ intel_dp_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) /* use cached edid if we have one */ if (intel_connector->edid) { + struct edid *edid; + int size; + /* invalid edid */ if (IS_ERR(intel_connector->edid)) return NULL; - return drm_edid_duplicate(intel_connector->edid); + size = (intel_connector->edid->extensions + 1) * EDID_LENGTH; + edid = kmemdup(intel_connector->edid, size, GFP_KERNEL); + if (!edid) + return NULL; + + return edid; } return drm_get_edid(connector, adapter); @@ -3259,6 +3050,7 @@ intel_dp_connector_destroy(struct drm_connector *connector) if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) intel_panel_fini(&intel_connector->panel); + drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -3326,19 +3118,11 @@ intel_trans_dp_port_sel(struct drm_crtc *crtc) } /* check the VBT to see whether the eDP is on DP-D port */ -bool intel_dp_is_edp(struct drm_device *dev, enum port port) +bool intel_dpd_is_edp(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - union child_device_config *p_child; + struct child_device_config *p_child; int i; - static const short port_mapping[] = { - [PORT_B] = PORT_IDPB, - [PORT_C] = PORT_IDPC, - [PORT_D] = PORT_IDPD, - }; - - if (port == PORT_A) - return true; if (!dev_priv->vbt.child_dev_num) return false; @@ -3346,9 +3130,8 @@ bool intel_dp_is_edp(struct drm_device *dev, enum port port) for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { p_child = dev_priv->vbt.child_dev + i; - if (p_child->common.dvo_port == port_mapping[port] && - (p_child->common.device_type & DEVICE_TYPE_eDP_BITS) == - (DEVICE_TYPE_eDP & DEVICE_TYPE_eDP_BITS)) + if (p_child->dvo_port == PORT_IDPD && + p_child->device_type == DEVICE_TYPE_eDP) return true; } return false; @@ -3381,26 +3164,24 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; struct edp_power_seq cur, vbt, spec, final; u32 pp_on, pp_off, pp_div, pp; - int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg; + int pp_control_reg, pp_on_reg, pp_off_reg, pp_div_reg; if (HAS_PCH_SPLIT(dev)) { - pp_ctrl_reg = PCH_PP_CONTROL; + pp_control_reg = PCH_PP_CONTROL; pp_on_reg = PCH_PP_ON_DELAYS; pp_off_reg = PCH_PP_OFF_DELAYS; pp_div_reg = PCH_PP_DIVISOR; } else { - enum pipe pipe = vlv_power_sequencer_pipe(intel_dp); - - pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe); - pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe); - pp_off_reg = VLV_PIPE_PP_OFF_DELAYS(pipe); - pp_div_reg = VLV_PIPE_PP_DIVISOR(pipe); + pp_control_reg = PIPEA_PP_CONTROL; + pp_on_reg = PIPEA_PP_ON_DELAYS; + pp_off_reg = PIPEA_PP_OFF_DELAYS; + pp_div_reg = PIPEA_PP_DIVISOR; } /* Workaround: Need to write PP_CONTROL with the unlock key as * the very first thing. */ pp = ironlake_get_pp_control(intel_dp); - I915_WRITE(pp_ctrl_reg, pp); + I915_WRITE(pp_control_reg, pp); pp_on = I915_READ(pp_on_reg); pp_off = I915_READ(pp_off_reg); @@ -3488,11 +3269,9 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, pp_off_reg = PCH_PP_OFF_DELAYS; pp_div_reg = PCH_PP_DIVISOR; } else { - enum pipe pipe = vlv_power_sequencer_pipe(intel_dp); - - pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe); - pp_off_reg = VLV_PIPE_PP_OFF_DELAYS(pipe); - pp_div_reg = VLV_PIPE_PP_DIVISOR(pipe); + pp_on_reg = PIPEA_PP_ON_DELAYS; + pp_off_reg = PIPEA_PP_OFF_DELAYS; + pp_div_reg = PIPEA_PP_DIVISOR; } /* And finally store the new values in the power sequencer. */ @@ -3509,15 +3288,12 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, /* Haswell doesn't have any port selection bits for the panel * power sequencer any more. */ if (IS_VALLEYVIEW(dev)) { - if (dp_to_dig_port(intel_dp)->port == PORT_B) - port_sel = PANEL_PORT_SELECT_DPB_VLV; - else - port_sel = PANEL_PORT_SELECT_DPC_VLV; + port_sel = I915_READ(pp_on_reg) & 0xc0000000; } else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) { if (dp_to_dig_port(intel_dp)->port == PORT_A) - port_sel = PANEL_PORT_SELECT_DPA; + port_sel = PANEL_POWER_PORT_DP_A; else - port_sel = PANEL_PORT_SELECT_DPD; + port_sel = PANEL_POWER_PORT_DP_D; } pp_on |= port_sel; @@ -3570,6 +3346,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, &power_seq); + ironlake_edp_panel_vdd_on(intel_dp); edid = drm_get_edid(connector, &intel_dp->adapter); if (edid) { if (drm_add_edid_modes(connector, edid)) { @@ -3601,6 +3378,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; } + ironlake_edp_panel_vdd_off(intel_dp, false); + intel_panel_init(&intel_connector->panel, fixed_mode); intel_panel_setup_backlight(connector); @@ -3624,10 +3403,26 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, intel_dp->DP = I915_READ(intel_dp->output_reg); intel_dp->attached_connector = intel_connector; - if (intel_dp_is_edp(dev, port)) + type = DRM_MODE_CONNECTOR_DisplayPort; + /* + * FIXME : We need to initialize built-in panels before external panels. + * For X0, DP_C is fixed as eDP. Revisit this as part of VLV eDP cleanup + */ + switch (port) { + case PORT_A: type = DRM_MODE_CONNECTOR_eDP; - else - type = DRM_MODE_CONNECTOR_DisplayPort; + break; + case PORT_C: + if (IS_VALLEYVIEW(dev)) + type = DRM_MODE_CONNECTOR_eDP; + break; + case PORT_D: + if (HAS_PCH_SPLIT(dev) && intel_dpd_is_edp(dev)) + type = DRM_MODE_CONNECTOR_eDP; + break; + default: /* silence GCC warning */ + break; + } /* * For eDP we always set the encoder type to INTEL_OUTPUT_EDP, but @@ -3741,11 +3536,11 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) struct drm_encoder *encoder; struct intel_connector *intel_connector; - intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); + intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL); if (!intel_dig_port) return; - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); if (!intel_connector) { kfree(intel_dig_port); return; @@ -3764,12 +3559,12 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) intel_encoder->get_hw_state = intel_dp_get_hw_state; intel_encoder->get_config = intel_dp_get_config; if (IS_VALLEYVIEW(dev)) { - intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable; + intel_encoder->pre_pll_enable = intel_dp_pre_pll_enable; intel_encoder->pre_enable = vlv_pre_enable_dp; intel_encoder->enable = vlv_enable_dp; } else { - intel_encoder->pre_enable = g4x_pre_enable_dp; - intel_encoder->enable = g4x_enable_dp; + intel_encoder->pre_enable = intel_pre_enable_dp; + intel_encoder->enable = intel_enable_dp; } intel_dig_port->port = port; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a18e88b..7f2b384 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -77,6 +77,7 @@ /* the i915, i945 have a single sDVO i2c bus - which is different */ #define MAX_OUTPUTS 6 /* maximum connectors per crtcs in the mode set */ +#define INTELFB_CONN_LIMIT 4 #define INTEL_I2C_BUS_DVO 1 #define INTEL_I2C_BUS_SDVO 2 @@ -92,17 +93,13 @@ #define INTEL_OUTPUT_HDMI 6 #define INTEL_OUTPUT_DISPLAYPORT 7 #define INTEL_OUTPUT_EDP 8 -#define INTEL_OUTPUT_DSI 9 -#define INTEL_OUTPUT_UNKNOWN 10 +#define INTEL_OUTPUT_UNKNOWN 9 #define INTEL_DVO_CHIP_NONE 0 #define INTEL_DVO_CHIP_LVDS 1 #define INTEL_DVO_CHIP_TMDS 2 #define INTEL_DVO_CHIP_TVOUT 4 -#define INTEL_DSI_COMMAND_MODE 0 -#define INTEL_DSI_VIDEO_MODE 1 - struct intel_framebuffer { struct drm_framebuffer base; struct drm_i915_gem_object *obj; @@ -210,21 +207,8 @@ struct intel_crtc_config { #define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */ unsigned long quirks; - /* User requested mode, only valid as a starting point to - * compute adjusted_mode, except in the case of (S)DVO where - * it's also for the output timings of the (S)DVO chip. - * adjusted_mode will then correspond to the S(DVO) chip's - * preferred input timings. */ struct drm_display_mode requested_mode; - /* Actual pipe timings ie. what we program into the pipe timing - * registers. adjusted_mode.crtc_clock is the pipe pixel clock. */ struct drm_display_mode adjusted_mode; - - /* Pipe source size (ie. panel fitter input size) - * All planes will be positioned inside this space, - * and get clipped at the edges. */ - int pipe_src_w, pipe_src_h; - /* Whether to set up the PCH/FDI. Note that we never allow sharing * between pch encoders and cpu encoders. */ bool has_pch_encoder; @@ -278,8 +262,7 @@ struct intel_crtc_config { /* * Frequence the dpll for the port should run at. Differs from the - * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also - * already multiplied by pixel_multiplier. + * adjusted dotclock e.g. for DP or 12bpc hdmi mode. */ int port_clock; @@ -305,14 +288,6 @@ struct intel_crtc_config { struct intel_link_m_n fdi_m_n; bool ips_enabled; - - bool double_wide; -}; - -struct intel_pipe_wm { - struct intel_wm_level wm[5]; - uint32_t linetime; - bool fbc_wm_enabled; }; struct intel_crtc { @@ -326,9 +301,8 @@ struct intel_crtc { * some outputs connected to this crtc. */ bool active; - unsigned long enabled_power_domains; bool eld_vld; - bool primary_enabled; /* is the primary plane (partially) visible? */ + bool primary_disabled; /* is the crtc obscured by a plane? */ bool lowfreq_avail; struct intel_overlay *overlay; struct intel_unpin_work *unpin_work; @@ -356,12 +330,6 @@ struct intel_crtc { /* Access to these should be protected by dev_priv->irq_lock. */ bool cpu_fifo_underrun_disabled; bool pch_fifo_underrun_disabled; - - /* per-pipe watermark state */ - struct { - /* watermarks currently being used */ - struct intel_pipe_wm active; - } wm; }; struct intel_plane_wm_parameters { @@ -449,11 +417,13 @@ struct intel_hdmi { }; #define DP_MAX_DOWNSTREAM_PORTS 0x10 +#define DP_LINK_CONFIGURATION_SIZE 9 struct intel_dp { uint32_t output_reg; uint32_t aux_ch_ctl_reg; uint32_t DP; + uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; bool has_audio; enum hdmi_force_audio force_audio; uint32_t color_range; @@ -525,6 +495,80 @@ struct intel_unpin_work { bool enable_stall_check; }; +int intel_pch_rawclk(struct drm_device *dev); + +int intel_connector_update_modes(struct drm_connector *connector, + struct edid *edid); +int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); + +extern void intel_attach_force_audio_property(struct drm_connector *connector); +extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector); + +extern bool intel_pipe_has_type(struct drm_crtc *crtc, int type); +extern void intel_crt_init(struct drm_device *dev); +extern void intel_hdmi_init(struct drm_device *dev, + int hdmi_reg, enum port port); +extern void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, + struct intel_connector *intel_connector); +extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder); +extern bool intel_hdmi_compute_config(struct intel_encoder *encoder, + struct intel_crtc_config *pipe_config); +extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, + bool is_sdvob); +extern void intel_dvo_init(struct drm_device *dev); +extern void intel_tv_init(struct drm_device *dev); +extern void intel_mark_busy(struct drm_device *dev); +extern void intel_mark_fb_busy(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *ring); +extern void intel_mark_idle(struct drm_device *dev); +extern void intel_lvds_init(struct drm_device *dev); +extern bool intel_is_dual_link_lvds(struct drm_device *dev); +extern void intel_dp_init(struct drm_device *dev, int output_reg, + enum port port); +extern bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port, + struct intel_connector *intel_connector); +extern void intel_dp_init_link_config(struct intel_dp *intel_dp); +extern void intel_dp_start_link_train(struct intel_dp *intel_dp); +extern void intel_dp_complete_link_train(struct intel_dp *intel_dp); +extern void intel_dp_stop_link_train(struct intel_dp *intel_dp); +extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); +extern void intel_dp_encoder_destroy(struct drm_encoder *encoder); +extern void intel_dp_check_link_status(struct intel_dp *intel_dp); +extern bool intel_dp_compute_config(struct intel_encoder *encoder, + struct intel_crtc_config *pipe_config); +extern bool intel_dpd_is_edp(struct drm_device *dev); +extern void ironlake_edp_backlight_on(struct intel_dp *intel_dp); +extern void ironlake_edp_backlight_off(struct intel_dp *intel_dp); +extern void ironlake_edp_panel_on(struct intel_dp *intel_dp); +extern void ironlake_edp_panel_off(struct intel_dp *intel_dp); +extern void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp); +extern void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync); +extern int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane); +extern void intel_flush_display_plane(struct drm_i915_private *dev_priv, + enum plane plane); + +/* intel_panel.c */ +extern int intel_panel_init(struct intel_panel *panel, + struct drm_display_mode *fixed_mode); +extern void intel_panel_fini(struct intel_panel *panel); + +extern void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, + struct drm_display_mode *adjusted_mode); +extern void intel_pch_panel_fitting(struct intel_crtc *crtc, + struct intel_crtc_config *pipe_config, + int fitting_mode); +extern void intel_gmch_panel_fitting(struct intel_crtc *crtc, + struct intel_crtc_config *pipe_config, + int fitting_mode); +extern void intel_panel_set_backlight(struct drm_device *dev, + u32 level, u32 max); +extern int intel_panel_setup_backlight(struct drm_connector *connector); +extern void intel_panel_enable_backlight(struct drm_device *dev, + enum pipe pipe); +extern void intel_panel_disable_backlight(struct drm_device *dev); +extern void intel_panel_destroy_backlight(struct drm_device *dev); +extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); + struct intel_set_config { struct drm_encoder **save_connector_encoders; struct drm_crtc **save_encoder_crtcs; @@ -533,14 +577,18 @@ struct intel_set_config { bool mode_changed; }; -struct intel_load_detect_pipe { - struct drm_framebuffer *release_fb; - bool load_detect_temp; - int dpms_mode; -}; +extern void intel_crtc_restore_mode(struct drm_crtc *crtc); +extern void intel_crtc_load_lut(struct drm_crtc *crtc); +extern void intel_crtc_update_dpms(struct drm_crtc *crtc); +extern void intel_encoder_destroy(struct drm_encoder *encoder); +extern void intel_connector_dpms(struct drm_connector *, int mode); +extern bool intel_connector_get_hw_state(struct intel_connector *connector); +extern void intel_modeset_check_state(struct drm_device *dev); +extern void intel_plane_restore(struct drm_plane *plane); +extern void intel_plane_disable(struct drm_plane *plane); + -static inline struct intel_encoder * -intel_attached_encoder(struct drm_connector *connector) +static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector) { return to_intel_connector(connector)->encoder; } @@ -568,95 +616,73 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi) return container_of(intel_hdmi, struct intel_digital_port, hdmi); } - -/* i915_irq.c */ -bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, - enum pipe pipe, bool enable); -bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev, - enum transcoder pch_transcoder, - bool enable); -void ilk_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); -void ilk_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); -void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); -void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); -void hsw_pc8_disable_interrupts(struct drm_device *dev); -void hsw_pc8_restore_interrupts(struct drm_device *dev); - - -/* intel_crt.c */ -void intel_crt_init(struct drm_device *dev); - - -/* intel_ddi.c */ -void intel_prepare_ddi(struct drm_device *dev); -void hsw_fdi_link_train(struct drm_crtc *crtc); -void intel_ddi_init(struct drm_device *dev, enum port port); -enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder); -bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe); -int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv); -void intel_ddi_pll_init(struct drm_device *dev); -void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc); -void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv, - enum transcoder cpu_transcoder); -void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc); -void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc); -void intel_ddi_setup_hw_pll_state(struct drm_device *dev); -bool intel_ddi_pll_mode_set(struct drm_crtc *crtc); -void intel_ddi_put_crtc_pll(struct drm_crtc *crtc); -void intel_ddi_set_pipe_settings(struct drm_crtc *crtc); -void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder); -bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); -void intel_ddi_fdi_disable(struct drm_crtc *crtc); -void intel_ddi_get_config(struct intel_encoder *encoder, - struct intel_crtc_config *pipe_config); - - -/* intel_display.c */ -int intel_pch_rawclk(struct drm_device *dev); -void intel_mark_busy(struct drm_device *dev); -void intel_mark_fb_busy(struct drm_i915_gem_object *obj, - struct intel_ring_buffer *ring); -void intel_mark_idle(struct drm_device *dev); -void intel_crtc_restore_mode(struct drm_crtc *crtc); -void intel_crtc_update_dpms(struct drm_crtc *crtc); -void intel_encoder_destroy(struct drm_encoder *encoder); -void intel_connector_dpms(struct drm_connector *, int mode); -bool intel_connector_get_hw_state(struct intel_connector *connector); -void intel_modeset_check_state(struct drm_device *dev); bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, struct intel_digital_port *port); -void intel_connector_attach_encoder(struct intel_connector *connector, - struct intel_encoder *encoder); -struct drm_encoder *intel_best_encoder(struct drm_connector *connector); -struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, - struct drm_crtc *crtc); -enum pipe intel_get_pipe_from_connector(struct intel_connector *connector); + +extern void intel_connector_attach_encoder(struct intel_connector *connector, + struct intel_encoder *encoder); +extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector); + +extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, + struct drm_crtc *crtc); int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, struct drm_file *file_priv); -enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, - enum pipe pipe); -void intel_wait_for_vblank(struct drm_device *dev, int pipe); -void intel_wait_for_pipe_off(struct drm_device *dev, int pipe); -int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp); -void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port); -bool intel_get_load_detect_pipe(struct drm_connector *connector, - struct drm_display_mode *mode, - struct intel_load_detect_pipe *old); -void intel_release_load_detect_pipe(struct drm_connector *connector, - struct intel_load_detect_pipe *old); -int intel_pin_and_fence_fb_obj(struct drm_device *dev, - struct drm_i915_gem_object *obj, - struct intel_ring_buffer *pipelined); -void intel_unpin_fb_obj(struct drm_i915_gem_object *obj); -int intel_framebuffer_init(struct drm_device *dev, - struct intel_framebuffer *ifb, - struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_i915_gem_object *obj); -void intel_framebuffer_fini(struct intel_framebuffer *fb); -void intel_prepare_page_flip(struct drm_device *dev, int plane); -void intel_finish_page_flip(struct drm_device *dev, int pipe); -void intel_finish_page_flip_plane(struct drm_device *dev, int plane); -struct intel_shared_dpll *intel_crtc_to_shared_dpll(struct intel_crtc *crtc); +extern enum transcoder +intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, + enum pipe pipe); +extern void intel_wait_for_vblank(struct drm_device *dev, int pipe); +extern void intel_wait_for_pipe_off(struct drm_device *dev, int pipe); +extern int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp); +extern void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port); + +struct intel_load_detect_pipe { + struct drm_framebuffer *release_fb; + bool load_detect_temp; + int dpms_mode; +}; +extern bool intel_get_load_detect_pipe(struct drm_connector *connector, + struct drm_display_mode *mode, + struct intel_load_detect_pipe *old); +extern void intel_release_load_detect_pipe(struct drm_connector *connector, + struct intel_load_detect_pipe *old); + +extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, + u16 blue, int regno); +extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, + u16 *blue, int regno); + +extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, + struct drm_i915_gem_object *obj, + struct intel_ring_buffer *pipelined); +extern void intel_unpin_fb_obj(struct drm_i915_gem_object *obj); + +extern int intel_framebuffer_init(struct drm_device *dev, + struct intel_framebuffer *ifb, + struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_i915_gem_object *obj); +extern void intel_framebuffer_fini(struct intel_framebuffer *fb); +extern int intel_fbdev_init(struct drm_device *dev); +extern void intel_fbdev_initial_config(struct drm_device *dev); +extern void intel_fbdev_fini(struct drm_device *dev); +extern void intel_fbdev_set_suspend(struct drm_device *dev, int state); +extern void intel_prepare_page_flip(struct drm_device *dev, int plane); +extern void intel_finish_page_flip(struct drm_device *dev, int pipe); +extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane); + +extern void intel_setup_overlay(struct drm_device *dev); +extern void intel_cleanup_overlay(struct drm_device *dev); +extern int intel_overlay_switch_off(struct intel_overlay *overlay); +extern int intel_overlay_put_image(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int intel_overlay_attrs(struct drm_device *dev, void *data, + struct drm_file *file_priv); + +extern void intel_fb_output_poll_changed(struct drm_device *dev); +extern void intel_fb_restore_mode(struct drm_device *dev); + +struct intel_shared_dpll * +intel_crtc_to_shared_dpll(struct intel_crtc *crtc); + void assert_shared_dpll(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll, bool state); @@ -670,199 +696,104 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, enum pipe pipe, bool state); #define assert_fdi_rx_pll_enabled(d, p) assert_fdi_rx_pll(d, p, true) #define assert_fdi_rx_pll_disabled(d, p) assert_fdi_rx_pll(d, p, false) -void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state); +extern void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, + bool state); #define assert_pipe_enabled(d, p) assert_pipe(d, p, true) #define assert_pipe_disabled(d, p) assert_pipe(d, p, false) -void intel_write_eld(struct drm_encoder *encoder, - struct drm_display_mode *mode); -unsigned long intel_gen4_compute_page_offset(int *x, int *y, - unsigned int tiling_mode, - unsigned int bpp, - unsigned int pitch); -void intel_display_handle_reset(struct drm_device *dev); -void hsw_enable_pc8_work(struct work_struct *__work); -void hsw_enable_package_c8(struct drm_i915_private *dev_priv); -void hsw_disable_package_c8(struct drm_i915_private *dev_priv); -void intel_dp_get_m_n(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config); -int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n); -void -ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config, - int dotclock); -bool intel_crtc_active(struct drm_crtc *crtc); -void i915_disable_vga_mem(struct drm_device *dev); -void hsw_enable_ips(struct intel_crtc *crtc); -void hsw_disable_ips(struct intel_crtc *crtc); -void intel_display_set_init_power(struct drm_device *dev, bool enable); - - -/* intel_dp.c */ -void intel_dp_init(struct drm_device *dev, int output_reg, enum port port); -bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port, - struct intel_connector *intel_connector); -void intel_dp_start_link_train(struct intel_dp *intel_dp); -void intel_dp_complete_link_train(struct intel_dp *intel_dp); -void intel_dp_stop_link_train(struct intel_dp *intel_dp); -void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); -void intel_dp_encoder_destroy(struct drm_encoder *encoder); -void intel_dp_check_link_status(struct intel_dp *intel_dp); -bool intel_dp_compute_config(struct intel_encoder *encoder, - struct intel_crtc_config *pipe_config); -bool intel_dp_is_edp(struct drm_device *dev, enum port port); -void ironlake_edp_backlight_on(struct intel_dp *intel_dp); -void ironlake_edp_backlight_off(struct intel_dp *intel_dp); -void ironlake_edp_panel_on(struct intel_dp *intel_dp); -void ironlake_edp_panel_off(struct intel_dp *intel_dp); -void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp); -void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync); -void intel_edp_psr_enable(struct intel_dp *intel_dp); -void intel_edp_psr_disable(struct intel_dp *intel_dp); -void intel_edp_psr_update(struct drm_device *dev); - - -/* intel_dsi.c */ -bool intel_dsi_init(struct drm_device *dev); - - -/* intel_dvo.c */ -void intel_dvo_init(struct drm_device *dev); - - -/* legacy fbdev emulation in intel_fbdev.c */ -#ifdef CONFIG_DRM_I915_FBDEV -extern int intel_fbdev_init(struct drm_device *dev); -extern void intel_fbdev_initial_config(struct drm_device *dev); -extern void intel_fbdev_fini(struct drm_device *dev); -extern void intel_fbdev_set_suspend(struct drm_device *dev, int state); -extern void intel_fbdev_output_poll_changed(struct drm_device *dev); -extern void intel_fbdev_restore_mode(struct drm_device *dev); -#else -static inline int intel_fbdev_init(struct drm_device *dev) -{ - return 0; -} -static inline void intel_fbdev_initial_config(struct drm_device *dev) -{ -} - -static inline void intel_fbdev_fini(struct drm_device *dev) -{ -} - -static inline void intel_fbdev_set_suspend(struct drm_device *dev, int state) -{ -} - -static inline void intel_fbdev_restore_mode(struct drm_device *dev) -{ -} -#endif - -/* intel_hdmi.c */ -void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port); -void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, - struct intel_connector *intel_connector); -struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder); -bool intel_hdmi_compute_config(struct intel_encoder *encoder, - struct intel_crtc_config *pipe_config); - - -/* intel_lvds.c */ -void intel_lvds_init(struct drm_device *dev); -bool intel_is_dual_link_lvds(struct drm_device *dev); - - -/* intel_modes.c */ -int intel_connector_update_modes(struct drm_connector *connector, - struct edid *edid); -int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); -void intel_attach_force_audio_property(struct drm_connector *connector); -void intel_attach_broadcast_rgb_property(struct drm_connector *connector); - - -/* intel_overlay.c */ -void intel_setup_overlay(struct drm_device *dev); -void intel_cleanup_overlay(struct drm_device *dev); -int intel_overlay_switch_off(struct intel_overlay *overlay); -int intel_overlay_put_image(struct drm_device *dev, void *data, - struct drm_file *file_priv); -int intel_overlay_attrs(struct drm_device *dev, void *data, - struct drm_file *file_priv); - - -/* intel_panel.c */ -int intel_panel_init(struct intel_panel *panel, - struct drm_display_mode *fixed_mode); -void intel_panel_fini(struct intel_panel *panel); -void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, - struct drm_display_mode *adjusted_mode); -void intel_pch_panel_fitting(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config, - int fitting_mode); -void intel_gmch_panel_fitting(struct intel_crtc *crtc, - struct intel_crtc_config *pipe_config, - int fitting_mode); -void intel_panel_set_backlight(struct intel_connector *connector, u32 level, - u32 max); -int intel_panel_setup_backlight(struct drm_connector *connector); -void intel_panel_enable_backlight(struct intel_connector *connector); -void intel_panel_disable_backlight(struct intel_connector *connector); -void intel_panel_destroy_backlight(struct drm_device *dev); -enum drm_connector_status intel_panel_detect(struct drm_device *dev); - - -/* intel_pm.c */ -void intel_init_clock_gating(struct drm_device *dev); -void intel_suspend_hw(struct drm_device *dev); -void intel_update_watermarks(struct drm_crtc *crtc); -void intel_update_sprite_watermarks(struct drm_plane *plane, - struct drm_crtc *crtc, - uint32_t sprite_width, int pixel_size, - bool enabled, bool scaled); -void intel_init_pm(struct drm_device *dev); -bool intel_fbc_enabled(struct drm_device *dev); -void intel_update_fbc(struct drm_device *dev); -void intel_gpu_ips_init(struct drm_i915_private *dev_priv); -void intel_gpu_ips_teardown(void); -int intel_power_domains_init(struct drm_device *dev); -void intel_power_domains_remove(struct drm_device *dev); -bool intel_display_power_enabled(struct drm_device *dev, - enum intel_display_power_domain domain); -void intel_display_power_get(struct drm_device *dev, - enum intel_display_power_domain domain); -void intel_display_power_put(struct drm_device *dev, - enum intel_display_power_domain domain); -void intel_power_domains_init_hw(struct drm_device *dev); -void intel_set_power_well(struct drm_device *dev, bool enable); -void intel_enable_gt_powersave(struct drm_device *dev); -void intel_disable_gt_powersave(struct drm_device *dev); -void ironlake_teardown_rc6(struct drm_device *dev); +extern void intel_init_clock_gating(struct drm_device *dev); +extern void intel_suspend_hw(struct drm_device *dev); +extern void intel_write_eld(struct drm_encoder *encoder, + struct drm_display_mode *mode); +extern void intel_prepare_ddi(struct drm_device *dev); +extern void hsw_fdi_link_train(struct drm_crtc *crtc); +extern void intel_ddi_init(struct drm_device *dev, enum port port); + +/* For use by IVB LP watermark workaround in intel_sprite.c */ +extern void intel_update_watermarks(struct drm_device *dev); +extern void intel_update_sprite_watermarks(struct drm_plane *plane, + struct drm_crtc *crtc, + uint32_t sprite_width, int pixel_size, + bool enabled, bool scaled); + +extern unsigned long intel_gen4_compute_page_offset(int *x, int *y, + unsigned int tiling_mode, + unsigned int bpp, + unsigned int pitch); + +extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data, + struct drm_file *file_priv); + +/* Power-related functions, located in intel_pm.c */ +extern void intel_init_pm(struct drm_device *dev); +/* FBC */ +extern bool intel_fbc_enabled(struct drm_device *dev); +extern void intel_update_fbc(struct drm_device *dev); +/* IPS */ +extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv); +extern void intel_gpu_ips_teardown(void); + +/* Power well */ +extern int i915_init_power_well(struct drm_device *dev); +extern void i915_remove_power_well(struct drm_device *dev); + +extern bool intel_display_power_enabled(struct drm_device *dev, + enum intel_display_power_domain domain); +extern void intel_init_power_well(struct drm_device *dev); +extern void intel_set_power_well(struct drm_device *dev, bool enable); +extern void intel_enable_gt_powersave(struct drm_device *dev); +extern void intel_disable_gt_powersave(struct drm_device *dev); +extern void ironlake_teardown_rc6(struct drm_device *dev); void gen6_update_ring_freq(struct drm_device *dev); -void gen6_rps_idle(struct drm_i915_private *dev_priv); -void gen6_rps_boost(struct drm_i915_private *dev_priv); -void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv); -void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv); -void ilk_wm_get_hw_state(struct drm_device *dev); - - -/* intel_sdvo.c */ -bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob); - - -/* intel_sprite.c */ -int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane); -void intel_flush_primary_plane(struct drm_i915_private *dev_priv, - enum plane plane); -void intel_plane_restore(struct drm_plane *plane); -void intel_plane_disable(struct drm_plane *plane); -int intel_sprite_set_colorkey(struct drm_device *dev, void *data, - struct drm_file *file_priv); -int intel_sprite_get_colorkey(struct drm_device *dev, void *data, - struct drm_file *file_priv); - -/* intel_tv.c */ -void intel_tv_init(struct drm_device *dev); +extern bool intel_ddi_get_hw_state(struct intel_encoder *encoder, + enum pipe *pipe); +extern int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv); +extern void intel_ddi_pll_init(struct drm_device *dev); +extern void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc); +extern void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder); +extern void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc); +extern void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc); +extern void intel_ddi_setup_hw_pll_state(struct drm_device *dev); +extern bool intel_ddi_pll_mode_set(struct drm_crtc *crtc); +extern void intel_ddi_put_crtc_pll(struct drm_crtc *crtc); +extern void intel_ddi_set_pipe_settings(struct drm_crtc *crtc); +extern void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder); +extern bool +intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); +extern void intel_ddi_fdi_disable(struct drm_crtc *crtc); +extern void intel_ddi_get_config(struct intel_encoder *encoder, + struct intel_crtc_config *pipe_config); + +extern void intel_display_handle_reset(struct drm_device *dev); +extern bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, + enum pipe pipe, + bool enable); +extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev, + enum transcoder pch_transcoder, + bool enable); + +extern void intel_edp_psr_enable(struct intel_dp *intel_dp); +extern void intel_edp_psr_disable(struct intel_dp *intel_dp); +extern void intel_edp_psr_update(struct drm_device *dev); +extern void hsw_disable_lcpll(struct drm_i915_private *dev_priv, + bool switch_to_fclk, bool allow_power_down); +extern void hsw_restore_lcpll(struct drm_i915_private *dev_priv); +extern void ilk_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); +extern void ilk_disable_gt_irq(struct drm_i915_private *dev_priv, + uint32_t mask); +extern void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); +extern void snb_disable_pm_irq(struct drm_i915_private *dev_priv, + uint32_t mask); +extern void hsw_enable_pc8_work(struct work_struct *__work); +extern void hsw_enable_package_c8(struct drm_i915_private *dev_priv); +extern void hsw_disable_package_c8(struct drm_i915_private *dev_priv); +extern void hsw_pc8_disable_interrupts(struct drm_device *dev); +extern void hsw_pc8_restore_interrupts(struct drm_device *dev); +extern void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv); +extern void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv); #endif /* __INTEL_DRV_H__ */ diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c deleted file mode 100644 index d257b09..0000000 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ /dev/null @@ -1,620 +0,0 @@ -/* - * Copyright © 2013 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Author: Jani Nikula <jani.nikula@intel.com> - */ - -#include <drm/drmP.h> -#include <drm/drm_crtc.h> -#include <drm/drm_edid.h> -#include <drm/i915_drm.h> -#include <linux/slab.h> -#include "i915_drv.h" -#include "intel_drv.h" -#include "intel_dsi.h" -#include "intel_dsi_cmd.h" - -/* the sub-encoders aka panel drivers */ -static const struct intel_dsi_device intel_dsi_devices[] = { -}; - - -static void vlv_cck_modify(struct drm_i915_private *dev_priv, u32 reg, u32 val, - u32 mask) -{ - u32 tmp = vlv_cck_read(dev_priv, reg); - tmp &= ~mask; - tmp |= val; - vlv_cck_write(dev_priv, reg, tmp); -} - -static void band_gap_wa(struct drm_i915_private *dev_priv) -{ - mutex_lock(&dev_priv->dpio_lock); - - /* Enable bandgap fix in GOP driver */ - vlv_cck_modify(dev_priv, 0x6D, 0x00010000, 0x00030000); - msleep(20); - vlv_cck_modify(dev_priv, 0x6E, 0x00010000, 0x00030000); - msleep(20); - vlv_cck_modify(dev_priv, 0x6F, 0x00010000, 0x00030000); - msleep(20); - vlv_cck_modify(dev_priv, 0x00, 0x00008000, 0x00008000); - msleep(20); - vlv_cck_modify(dev_priv, 0x00, 0x00000000, 0x00008000); - msleep(20); - - /* Turn Display Trunk on */ - vlv_cck_modify(dev_priv, 0x6B, 0x00020000, 0x00030000); - msleep(20); - - vlv_cck_modify(dev_priv, 0x6C, 0x00020000, 0x00030000); - msleep(20); - - vlv_cck_modify(dev_priv, 0x6D, 0x00020000, 0x00030000); - msleep(20); - vlv_cck_modify(dev_priv, 0x6E, 0x00020000, 0x00030000); - msleep(20); - vlv_cck_modify(dev_priv, 0x6F, 0x00020000, 0x00030000); - - mutex_unlock(&dev_priv->dpio_lock); - - /* Need huge delay, otherwise clock is not stable */ - msleep(100); -} - -static struct intel_dsi *intel_attached_dsi(struct drm_connector *connector) -{ - return container_of(intel_attached_encoder(connector), - struct intel_dsi, base); -} - -static inline bool is_vid_mode(struct intel_dsi *intel_dsi) -{ - return intel_dsi->dev.type == INTEL_DSI_VIDEO_MODE; -} - -static inline bool is_cmd_mode(struct intel_dsi *intel_dsi) -{ - return intel_dsi->dev.type == INTEL_DSI_COMMAND_MODE; -} - -static void intel_dsi_hot_plug(struct intel_encoder *encoder) -{ - DRM_DEBUG_KMS("\n"); -} - -static bool intel_dsi_compute_config(struct intel_encoder *encoder, - struct intel_crtc_config *config) -{ - struct intel_dsi *intel_dsi = container_of(encoder, struct intel_dsi, - base); - struct intel_connector *intel_connector = intel_dsi->attached_connector; - struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; - struct drm_display_mode *adjusted_mode = &config->adjusted_mode; - struct drm_display_mode *mode = &config->requested_mode; - - DRM_DEBUG_KMS("\n"); - - if (fixed_mode) - intel_fixed_panel_mode(fixed_mode, adjusted_mode); - - if (intel_dsi->dev.dev_ops->mode_fixup) - return intel_dsi->dev.dev_ops->mode_fixup(&intel_dsi->dev, - mode, adjusted_mode); - - return true; -} - -static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder) -{ - DRM_DEBUG_KMS("\n"); - - vlv_enable_dsi_pll(encoder); -} - -static void intel_dsi_pre_enable(struct intel_encoder *encoder) -{ - DRM_DEBUG_KMS("\n"); -} - -static void intel_dsi_enable(struct intel_encoder *encoder) -{ - struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); - int pipe = intel_crtc->pipe; - u32 temp; - - DRM_DEBUG_KMS("\n"); - - temp = I915_READ(MIPI_DEVICE_READY(pipe)); - if ((temp & DEVICE_READY) == 0) { - temp &= ~ULPS_STATE_MASK; - I915_WRITE(MIPI_DEVICE_READY(pipe), temp | DEVICE_READY); - } else if (temp & ULPS_STATE_MASK) { - temp &= ~ULPS_STATE_MASK; - I915_WRITE(MIPI_DEVICE_READY(pipe), temp | ULPS_STATE_EXIT); - /* - * We need to ensure that there is a minimum of 1 ms time - * available before clearing the UPLS exit state. - */ - msleep(2); - I915_WRITE(MIPI_DEVICE_READY(pipe), temp); - } - - if (is_cmd_mode(intel_dsi)) - I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 8 * 4); - - if (is_vid_mode(intel_dsi)) { - msleep(20); /* XXX */ - dpi_send_cmd(intel_dsi, TURN_ON); - msleep(100); - - /* assert ip_tg_enable signal */ - temp = I915_READ(MIPI_PORT_CTRL(pipe)); - I915_WRITE(MIPI_PORT_CTRL(pipe), temp | DPI_ENABLE); - POSTING_READ(MIPI_PORT_CTRL(pipe)); - } - - intel_dsi->dev.dev_ops->enable(&intel_dsi->dev); -} - -static void intel_dsi_disable(struct intel_encoder *encoder) -{ - struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); - int pipe = intel_crtc->pipe; - u32 temp; - - DRM_DEBUG_KMS("\n"); - - intel_dsi->dev.dev_ops->disable(&intel_dsi->dev); - - if (is_vid_mode(intel_dsi)) { - dpi_send_cmd(intel_dsi, SHUTDOWN); - msleep(10); - - /* de-assert ip_tg_enable signal */ - temp = I915_READ(MIPI_PORT_CTRL(pipe)); - I915_WRITE(MIPI_PORT_CTRL(pipe), temp & ~DPI_ENABLE); - POSTING_READ(MIPI_PORT_CTRL(pipe)); - - msleep(2); - } - - temp = I915_READ(MIPI_DEVICE_READY(pipe)); - if (temp & DEVICE_READY) { - temp &= ~DEVICE_READY; - temp &= ~ULPS_STATE_MASK; - I915_WRITE(MIPI_DEVICE_READY(pipe), temp); - } -} - -static void intel_dsi_post_disable(struct intel_encoder *encoder) -{ - DRM_DEBUG_KMS("\n"); - - vlv_disable_dsi_pll(encoder); -} - -static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, - enum pipe *pipe) -{ - struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; - u32 port, func; - enum pipe p; - - DRM_DEBUG_KMS("\n"); - - /* XXX: this only works for one DSI output */ - for (p = PIPE_A; p <= PIPE_B; p++) { - port = I915_READ(MIPI_PORT_CTRL(p)); - func = I915_READ(MIPI_DSI_FUNC_PRG(p)); - - if ((port & DPI_ENABLE) || (func & CMD_MODE_DATA_WIDTH_MASK)) { - if (I915_READ(MIPI_DEVICE_READY(p)) & DEVICE_READY) { - *pipe = p; - return true; - } - } - } - - return false; -} - -static void intel_dsi_get_config(struct intel_encoder *encoder, - struct intel_crtc_config *pipe_config) -{ - DRM_DEBUG_KMS("\n"); - - /* XXX: read flags, set to adjusted_mode */ -} - -static int intel_dsi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct intel_connector *intel_connector = to_intel_connector(connector); - struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; - struct intel_dsi *intel_dsi = intel_attached_dsi(connector); - - DRM_DEBUG_KMS("\n"); - - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) { - DRM_DEBUG_KMS("MODE_NO_DBLESCAN\n"); - return MODE_NO_DBLESCAN; - } - - if (fixed_mode) { - if (mode->hdisplay > fixed_mode->hdisplay) - return MODE_PANEL; - if (mode->vdisplay > fixed_mode->vdisplay) - return MODE_PANEL; - } - - return intel_dsi->dev.dev_ops->mode_valid(&intel_dsi->dev, mode); -} - -/* return txclkesc cycles in terms of divider and duration in us */ -static u16 txclkesc(u32 divider, unsigned int us) -{ - switch (divider) { - case ESCAPE_CLOCK_DIVIDER_1: - default: - return 20 * us; - case ESCAPE_CLOCK_DIVIDER_2: - return 10 * us; - case ESCAPE_CLOCK_DIVIDER_4: - return 5 * us; - } -} - -/* return pixels in terms of txbyteclkhs */ -static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count) -{ - return DIV_ROUND_UP(DIV_ROUND_UP(pixels * bpp, 8), lane_count); -} - -static void set_dsi_timings(struct drm_encoder *encoder, - const struct drm_display_mode *mode) -{ - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); - int pipe = intel_crtc->pipe; - unsigned int bpp = intel_crtc->config.pipe_bpp; - unsigned int lane_count = intel_dsi->lane_count; - - u16 hactive, hfp, hsync, hbp, vfp, vsync, vbp; - - hactive = mode->hdisplay; - hfp = mode->hsync_start - mode->hdisplay; - hsync = mode->hsync_end - mode->hsync_start; - hbp = mode->htotal - mode->hsync_end; - - vfp = mode->vsync_start - mode->vdisplay; - vsync = mode->vsync_end - mode->vsync_start; - vbp = mode->vtotal - mode->vsync_end; - - /* horizontal values are in terms of high speed byte clock */ - hactive = txbyteclkhs(hactive, bpp, lane_count); - hfp = txbyteclkhs(hfp, bpp, lane_count); - hsync = txbyteclkhs(hsync, bpp, lane_count); - hbp = txbyteclkhs(hbp, bpp, lane_count); - - I915_WRITE(MIPI_HACTIVE_AREA_COUNT(pipe), hactive); - I915_WRITE(MIPI_HFP_COUNT(pipe), hfp); - - /* meaningful for video mode non-burst sync pulse mode only, can be zero - * for non-burst sync events and burst modes */ - I915_WRITE(MIPI_HSYNC_PADDING_COUNT(pipe), hsync); - I915_WRITE(MIPI_HBP_COUNT(pipe), hbp); - - /* vertical values are in terms of lines */ - I915_WRITE(MIPI_VFP_COUNT(pipe), vfp); - I915_WRITE(MIPI_VSYNC_PADDING_COUNT(pipe), vsync); - I915_WRITE(MIPI_VBP_COUNT(pipe), vbp); -} - -static void intel_dsi_mode_set(struct intel_encoder *intel_encoder) -{ - struct drm_encoder *encoder = &intel_encoder->base; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); - struct drm_display_mode *adjusted_mode = - &intel_crtc->config.adjusted_mode; - int pipe = intel_crtc->pipe; - unsigned int bpp = intel_crtc->config.pipe_bpp; - u32 val, tmp; - - DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); - - /* Update the DSI PLL */ - vlv_enable_dsi_pll(intel_encoder); - - /* XXX: Location of the call */ - band_gap_wa(dev_priv); - - /* escape clock divider, 20MHz, shared for A and C. device ready must be - * off when doing this! txclkesc? */ - tmp = I915_READ(MIPI_CTRL(0)); - tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK; - I915_WRITE(MIPI_CTRL(0), tmp | ESCAPE_CLOCK_DIVIDER_1); - - /* read request priority is per pipe */ - tmp = I915_READ(MIPI_CTRL(pipe)); - tmp &= ~READ_REQUEST_PRIORITY_MASK; - I915_WRITE(MIPI_CTRL(pipe), tmp | READ_REQUEST_PRIORITY_HIGH); - - /* XXX: why here, why like this? handling in irq handler?! */ - I915_WRITE(MIPI_INTR_STAT(pipe), 0xffffffff); - I915_WRITE(MIPI_INTR_EN(pipe), 0xffffffff); - - I915_WRITE(MIPI_DPHY_PARAM(pipe), - 0x3c << EXIT_ZERO_COUNT_SHIFT | - 0x1f << TRAIL_COUNT_SHIFT | - 0xc5 << CLK_ZERO_COUNT_SHIFT | - 0x1f << PREPARE_COUNT_SHIFT); - - I915_WRITE(MIPI_DPI_RESOLUTION(pipe), - adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT | - adjusted_mode->hdisplay << HORIZONTAL_ADDRESS_SHIFT); - - set_dsi_timings(encoder, adjusted_mode); - - val = intel_dsi->lane_count << DATA_LANES_PRG_REG_SHIFT; - if (is_cmd_mode(intel_dsi)) { - val |= intel_dsi->channel << CMD_MODE_CHANNEL_NUMBER_SHIFT; - val |= CMD_MODE_DATA_WIDTH_8_BIT; /* XXX */ - } else { - val |= intel_dsi->channel << VID_MODE_CHANNEL_NUMBER_SHIFT; - - /* XXX: cross-check bpp vs. pixel format? */ - val |= intel_dsi->pixel_format; - } - I915_WRITE(MIPI_DSI_FUNC_PRG(pipe), val); - - /* timeouts for recovery. one frame IIUC. if counter expires, EOT and - * stop state. */ - - /* - * In burst mode, value greater than one DPI line Time in byte clock - * (txbyteclkhs) To timeout this timer 1+ of the above said value is - * recommended. - * - * In non-burst mode, Value greater than one DPI frame time in byte - * clock(txbyteclkhs) To timeout this timer 1+ of the above said value - * is recommended. - * - * In DBI only mode, value greater than one DBI frame time in byte - * clock(txbyteclkhs) To timeout this timer 1+ of the above said value - * is recommended. - */ - - if (is_vid_mode(intel_dsi) && - intel_dsi->video_mode_format == VIDEO_MODE_BURST) { - I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe), - txbyteclkhs(adjusted_mode->htotal, bpp, - intel_dsi->lane_count) + 1); - } else { - I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe), - txbyteclkhs(adjusted_mode->vtotal * - adjusted_mode->htotal, - bpp, intel_dsi->lane_count) + 1); - } - I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), 8309); /* max */ - I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), 0x14); /* max */ - I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe), 0xffff); /* max */ - - /* dphy stuff */ - - /* in terms of low power clock */ - I915_WRITE(MIPI_INIT_COUNT(pipe), txclkesc(ESCAPE_CLOCK_DIVIDER_1, 100)); - - /* recovery disables */ - I915_WRITE(MIPI_EOT_DISABLE(pipe), intel_dsi->eot_disable); - - /* in terms of txbyteclkhs. actual high to low switch + - * MIPI_STOP_STATE_STALL * MIPI_LP_BYTECLK. - * - * XXX: write MIPI_STOP_STATE_STALL? - */ - I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe), 0x46); - - /* XXX: low power clock equivalence in terms of byte clock. the number - * of byte clocks occupied in one low power clock. based on txbyteclkhs - * and txclkesc. txclkesc time / txbyteclk time * (105 + - * MIPI_STOP_STATE_STALL) / 105.??? - */ - I915_WRITE(MIPI_LP_BYTECLK(pipe), 4); - - /* the bw essential for transmitting 16 long packets containing 252 - * bytes meant for dcs write memory command is programmed in this - * register in terms of byte clocks. based on dsi transfer rate and the - * number of lanes configured the time taken to transmit 16 long packets - * in a dsi stream varies. */ - I915_WRITE(MIPI_DBI_BW_CTRL(pipe), 0x820); - - I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(pipe), - 0xa << LP_HS_SSW_CNT_SHIFT | - 0x14 << HS_LP_PWR_SW_CNT_SHIFT); - - if (is_vid_mode(intel_dsi)) - I915_WRITE(MIPI_VIDEO_MODE_FORMAT(pipe), - intel_dsi->video_mode_format); -} - -static enum drm_connector_status -intel_dsi_detect(struct drm_connector *connector, bool force) -{ - struct intel_dsi *intel_dsi = intel_attached_dsi(connector); - DRM_DEBUG_KMS("\n"); - return intel_dsi->dev.dev_ops->detect(&intel_dsi->dev); -} - -static int intel_dsi_get_modes(struct drm_connector *connector) -{ - struct intel_connector *intel_connector = to_intel_connector(connector); - struct drm_display_mode *mode; - - DRM_DEBUG_KMS("\n"); - - if (!intel_connector->panel.fixed_mode) { - DRM_DEBUG_KMS("no fixed mode\n"); - return 0; - } - - mode = drm_mode_duplicate(connector->dev, - intel_connector->panel.fixed_mode); - if (!mode) { - DRM_DEBUG_KMS("drm_mode_duplicate failed\n"); - return 0; - } - - drm_mode_probed_add(connector, mode); - return 1; -} - -static void intel_dsi_destroy(struct drm_connector *connector) -{ - struct intel_connector *intel_connector = to_intel_connector(connector); - - DRM_DEBUG_KMS("\n"); - intel_panel_fini(&intel_connector->panel); - drm_connector_cleanup(connector); - kfree(connector); -} - -static const struct drm_encoder_funcs intel_dsi_funcs = { - .destroy = intel_encoder_destroy, -}; - -static const struct drm_connector_helper_funcs intel_dsi_connector_helper_funcs = { - .get_modes = intel_dsi_get_modes, - .mode_valid = intel_dsi_mode_valid, - .best_encoder = intel_best_encoder, -}; - -static const struct drm_connector_funcs intel_dsi_connector_funcs = { - .dpms = intel_connector_dpms, - .detect = intel_dsi_detect, - .destroy = intel_dsi_destroy, - .fill_modes = drm_helper_probe_single_connector_modes, -}; - -bool intel_dsi_init(struct drm_device *dev) -{ - struct intel_dsi *intel_dsi; - struct intel_encoder *intel_encoder; - struct drm_encoder *encoder; - struct intel_connector *intel_connector; - struct drm_connector *connector; - struct drm_display_mode *fixed_mode = NULL; - const struct intel_dsi_device *dsi; - unsigned int i; - - DRM_DEBUG_KMS("\n"); - - intel_dsi = kzalloc(sizeof(*intel_dsi), GFP_KERNEL); - if (!intel_dsi) - return false; - - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); - if (!intel_connector) { - kfree(intel_dsi); - return false; - } - - intel_encoder = &intel_dsi->base; - encoder = &intel_encoder->base; - intel_dsi->attached_connector = intel_connector; - - connector = &intel_connector->base; - - drm_encoder_init(dev, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI); - - /* XXX: very likely not all of these are needed */ - intel_encoder->hot_plug = intel_dsi_hot_plug; - intel_encoder->compute_config = intel_dsi_compute_config; - intel_encoder->pre_pll_enable = intel_dsi_pre_pll_enable; - intel_encoder->pre_enable = intel_dsi_pre_enable; - intel_encoder->enable = intel_dsi_enable; - intel_encoder->mode_set = intel_dsi_mode_set; - intel_encoder->disable = intel_dsi_disable; - intel_encoder->post_disable = intel_dsi_post_disable; - intel_encoder->get_hw_state = intel_dsi_get_hw_state; - intel_encoder->get_config = intel_dsi_get_config; - - intel_connector->get_hw_state = intel_connector_get_hw_state; - - for (i = 0; i < ARRAY_SIZE(intel_dsi_devices); i++) { - dsi = &intel_dsi_devices[i]; - intel_dsi->dev = *dsi; - - if (dsi->dev_ops->init(&intel_dsi->dev)) - break; - } - - if (i == ARRAY_SIZE(intel_dsi_devices)) { - DRM_DEBUG_KMS("no device found\n"); - goto err; - } - - intel_encoder->type = INTEL_OUTPUT_DSI; - intel_encoder->crtc_mask = (1 << 0); /* XXX */ - - intel_encoder->cloneable = false; - drm_connector_init(dev, connector, &intel_dsi_connector_funcs, - DRM_MODE_CONNECTOR_DSI); - - drm_connector_helper_add(connector, &intel_dsi_connector_helper_funcs); - - connector->display_info.subpixel_order = SubPixelHorizontalRGB; /*XXX*/ - connector->interlace_allowed = false; - connector->doublescan_allowed = false; - - intel_connector_attach_encoder(intel_connector, intel_encoder); - - drm_sysfs_connector_add(connector); - - fixed_mode = dsi->dev_ops->get_modes(&intel_dsi->dev); - if (!fixed_mode) { - DRM_DEBUG_KMS("no fixed mode\n"); - goto err; - } - - fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; - intel_panel_init(&intel_connector->panel, fixed_mode); - - return true; - -err: - drm_encoder_cleanup(&intel_encoder->base); - kfree(intel_dsi); - kfree(intel_connector); - - return false; -} diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h deleted file mode 100644 index c7765f3..0000000 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright © 2013 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef _INTEL_DSI_H -#define _INTEL_DSI_H - -#include <drm/drmP.h> -#include <drm/drm_crtc.h> -#include "intel_drv.h" - -struct intel_dsi_device { - unsigned int panel_id; - const char *name; - int type; - const struct intel_dsi_dev_ops *dev_ops; - void *dev_priv; -}; - -struct intel_dsi_dev_ops { - bool (*init)(struct intel_dsi_device *dsi); - - /* This callback must be able to assume DSI commands can be sent */ - void (*enable)(struct intel_dsi_device *dsi); - - /* This callback must be able to assume DSI commands can be sent */ - void (*disable)(struct intel_dsi_device *dsi); - - int (*mode_valid)(struct intel_dsi_device *dsi, - struct drm_display_mode *mode); - - bool (*mode_fixup)(struct intel_dsi_device *dsi, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); - - void (*mode_set)(struct intel_dsi_device *dsi, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); - - enum drm_connector_status (*detect)(struct intel_dsi_device *dsi); - - bool (*get_hw_state)(struct intel_dsi_device *dev); - - struct drm_display_mode *(*get_modes)(struct intel_dsi_device *dsi); - - void (*destroy) (struct intel_dsi_device *dsi); -}; - -struct intel_dsi { - struct intel_encoder base; - - struct intel_dsi_device dev; - - struct intel_connector *attached_connector; - - /* if true, use HS mode, otherwise LP */ - bool hs; - - /* virtual channel */ - int channel; - - /* number of DSI lanes */ - unsigned int lane_count; - - /* video mode pixel format for MIPI_DSI_FUNC_PRG register */ - u32 pixel_format; - - /* video mode format for MIPI_VIDEO_MODE_FORMAT register */ - u32 video_mode_format; - - /* eot for MIPI_EOT_DISABLE register */ - u32 eot_disable; -}; - -static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder) -{ - return container_of(encoder, struct intel_dsi, base.base); -} - -extern void vlv_enable_dsi_pll(struct intel_encoder *encoder); -extern void vlv_disable_dsi_pll(struct intel_encoder *encoder); - -#endif /* _INTEL_DSI_H */ diff --git a/drivers/gpu/drm/i915/intel_dsi_cmd.c b/drivers/gpu/drm/i915/intel_dsi_cmd.c deleted file mode 100644 index 7c40f98..0000000 --- a/drivers/gpu/drm/i915/intel_dsi_cmd.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Copyright © 2013 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Author: Jani Nikula <jani.nikula@intel.com> - */ - -#include <linux/export.h> -#include <drm/drmP.h> -#include <drm/drm_crtc.h> -#include <video/mipi_display.h> -#include "i915_drv.h" -#include "intel_drv.h" -#include "intel_dsi.h" -#include "intel_dsi_cmd.h" - -/* - * XXX: MIPI_DATA_ADDRESS, MIPI_DATA_LENGTH, MIPI_COMMAND_LENGTH, and - * MIPI_COMMAND_ADDRESS registers. - * - * Apparently these registers provide a MIPI adapter level way to send (lots of) - * commands and data to the receiver, without having to write the commands and - * data to MIPI_{HS,LP}_GEN_{CTRL,DATA} registers word by word. - * - * Presumably for anything other than MIPI_DCS_WRITE_MEMORY_START and - * MIPI_DCS_WRITE_MEMORY_CONTINUE (which are used to update the external - * framebuffer in command mode displays) these are just an optimization that can - * come later. - * - * For memory writes, these should probably be used for performance. - */ - -static void print_stat(struct intel_dsi *intel_dsi) -{ - struct drm_encoder *encoder = &intel_dsi->base.base; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; - u32 val; - - val = I915_READ(MIPI_INTR_STAT(pipe)); - -#define STAT_BIT(val, bit) (val) & (bit) ? " " #bit : "" - DRM_DEBUG_KMS("MIPI_INTR_STAT(%d) = %08x" - "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" - "\n", pipe, val, - STAT_BIT(val, TEARING_EFFECT), - STAT_BIT(val, SPL_PKT_SENT_INTERRUPT), - STAT_BIT(val, GEN_READ_DATA_AVAIL), - STAT_BIT(val, LP_GENERIC_WR_FIFO_FULL), - STAT_BIT(val, HS_GENERIC_WR_FIFO_FULL), - STAT_BIT(val, RX_PROT_VIOLATION), - STAT_BIT(val, RX_INVALID_TX_LENGTH), - STAT_BIT(val, ACK_WITH_NO_ERROR), - STAT_BIT(val, TURN_AROUND_ACK_TIMEOUT), - STAT_BIT(val, LP_RX_TIMEOUT), - STAT_BIT(val, HS_TX_TIMEOUT), - STAT_BIT(val, DPI_FIFO_UNDERRUN), - STAT_BIT(val, LOW_CONTENTION), - STAT_BIT(val, HIGH_CONTENTION), - STAT_BIT(val, TXDSI_VC_ID_INVALID), - STAT_BIT(val, TXDSI_DATA_TYPE_NOT_RECOGNISED), - STAT_BIT(val, TXCHECKSUM_ERROR), - STAT_BIT(val, TXECC_MULTIBIT_ERROR), - STAT_BIT(val, TXECC_SINGLE_BIT_ERROR), - STAT_BIT(val, TXFALSE_CONTROL_ERROR), - STAT_BIT(val, RXDSI_VC_ID_INVALID), - STAT_BIT(val, RXDSI_DATA_TYPE_NOT_REGOGNISED), - STAT_BIT(val, RXCHECKSUM_ERROR), - STAT_BIT(val, RXECC_MULTIBIT_ERROR), - STAT_BIT(val, RXECC_SINGLE_BIT_ERROR), - STAT_BIT(val, RXFALSE_CONTROL_ERROR), - STAT_BIT(val, RXHS_RECEIVE_TIMEOUT_ERROR), - STAT_BIT(val, RX_LP_TX_SYNC_ERROR), - STAT_BIT(val, RXEXCAPE_MODE_ENTRY_ERROR), - STAT_BIT(val, RXEOT_SYNC_ERROR), - STAT_BIT(val, RXSOT_SYNC_ERROR), - STAT_BIT(val, RXSOT_ERROR)); -#undef STAT_BIT -} - -enum dsi_type { - DSI_DCS, - DSI_GENERIC, -}; - -/* enable or disable command mode hs transmissions */ -void dsi_hs_mode_enable(struct intel_dsi *intel_dsi, bool enable) -{ - struct drm_encoder *encoder = &intel_dsi->base.base; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; - u32 temp; - u32 mask = DBI_FIFO_EMPTY; - - if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == mask, 50)) - DRM_ERROR("Timeout waiting for DBI FIFO empty\n"); - - temp = I915_READ(MIPI_HS_LP_DBI_ENABLE(pipe)); - temp &= DBI_HS_LP_MODE_MASK; - I915_WRITE(MIPI_HS_LP_DBI_ENABLE(pipe), enable ? DBI_HS_MODE : DBI_LP_MODE); - - intel_dsi->hs = enable; -} - -static int dsi_vc_send_short(struct intel_dsi *intel_dsi, int channel, - u8 data_type, u16 data) -{ - struct drm_encoder *encoder = &intel_dsi->base.base; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; - u32 ctrl_reg; - u32 ctrl; - u32 mask; - - DRM_DEBUG_KMS("channel %d, data_type %d, data %04x\n", - channel, data_type, data); - - if (intel_dsi->hs) { - ctrl_reg = MIPI_HS_GEN_CTRL(pipe); - mask = HS_CTRL_FIFO_FULL; - } else { - ctrl_reg = MIPI_LP_GEN_CTRL(pipe); - mask = LP_CTRL_FIFO_FULL; - } - - if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == 0, 50)) { - DRM_ERROR("Timeout waiting for HS/LP CTRL FIFO !full\n"); - print_stat(intel_dsi); - } - - /* - * Note: This function is also used for long packets, with length passed - * as data, since SHORT_PACKET_PARAM_SHIFT == - * LONG_PACKET_WORD_COUNT_SHIFT. - */ - ctrl = data << SHORT_PACKET_PARAM_SHIFT | - channel << VIRTUAL_CHANNEL_SHIFT | - data_type << DATA_TYPE_SHIFT; - - I915_WRITE(ctrl_reg, ctrl); - - return 0; -} - -static int dsi_vc_send_long(struct intel_dsi *intel_dsi, int channel, - u8 data_type, const u8 *data, int len) -{ - struct drm_encoder *encoder = &intel_dsi->base.base; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; - u32 data_reg; - int i, j, n; - u32 mask; - - DRM_DEBUG_KMS("channel %d, data_type %d, len %04x\n", - channel, data_type, len); - - if (intel_dsi->hs) { - data_reg = MIPI_HS_GEN_DATA(pipe); - mask = HS_DATA_FIFO_FULL; - } else { - data_reg = MIPI_LP_GEN_DATA(pipe); - mask = LP_DATA_FIFO_FULL; - } - - if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == 0, 50)) - DRM_ERROR("Timeout waiting for HS/LP DATA FIFO !full\n"); - - for (i = 0; i < len; i += n) { - u32 val = 0; - n = min_t(int, len - i, 4); - - for (j = 0; j < n; j++) - val |= *data++ << 8 * j; - - I915_WRITE(data_reg, val); - /* XXX: check for data fifo full, once that is set, write 4 - * dwords, then wait for not set, then continue. */ - } - - return dsi_vc_send_short(intel_dsi, channel, data_type, len); -} - -static int dsi_vc_write_common(struct intel_dsi *intel_dsi, - int channel, const u8 *data, int len, - enum dsi_type type) -{ - int ret; - - if (len == 0) { - BUG_ON(type == DSI_GENERIC); - ret = dsi_vc_send_short(intel_dsi, channel, - MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM, - 0); - } else if (len == 1) { - ret = dsi_vc_send_short(intel_dsi, channel, - type == DSI_GENERIC ? - MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM : - MIPI_DSI_DCS_SHORT_WRITE, data[0]); - } else if (len == 2) { - ret = dsi_vc_send_short(intel_dsi, channel, - type == DSI_GENERIC ? - MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM : - MIPI_DSI_DCS_SHORT_WRITE_PARAM, - (data[1] << 8) | data[0]); - } else { - ret = dsi_vc_send_long(intel_dsi, channel, - type == DSI_GENERIC ? - MIPI_DSI_GENERIC_LONG_WRITE : - MIPI_DSI_DCS_LONG_WRITE, data, len); - } - - return ret; -} - -int dsi_vc_dcs_write(struct intel_dsi *intel_dsi, int channel, - const u8 *data, int len) -{ - return dsi_vc_write_common(intel_dsi, channel, data, len, DSI_DCS); -} - -int dsi_vc_generic_write(struct intel_dsi *intel_dsi, int channel, - const u8 *data, int len) -{ - return dsi_vc_write_common(intel_dsi, channel, data, len, DSI_GENERIC); -} - -static int dsi_vc_dcs_send_read_request(struct intel_dsi *intel_dsi, - int channel, u8 dcs_cmd) -{ - return dsi_vc_send_short(intel_dsi, channel, MIPI_DSI_DCS_READ, - dcs_cmd); -} - -static int dsi_vc_generic_send_read_request(struct intel_dsi *intel_dsi, - int channel, u8 *reqdata, - int reqlen) -{ - u16 data; - u8 data_type; - - switch (reqlen) { - case 0: - data_type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM; - data = 0; - break; - case 1: - data_type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM; - data = reqdata[0]; - break; - case 2: - data_type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM; - data = (reqdata[1] << 8) | reqdata[0]; - break; - default: - BUG(); - } - - return dsi_vc_send_short(intel_dsi, channel, data_type, data); -} - -static int dsi_read_data_return(struct intel_dsi *intel_dsi, - u8 *buf, int buflen) -{ - struct drm_encoder *encoder = &intel_dsi->base.base; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; - int i, len = 0; - u32 data_reg, val; - - if (intel_dsi->hs) { - data_reg = MIPI_HS_GEN_DATA(pipe); - } else { - data_reg = MIPI_LP_GEN_DATA(pipe); - } - - while (len < buflen) { - val = I915_READ(data_reg); - for (i = 0; i < 4 && len < buflen; i++, len++) - buf[len] = val >> 8 * i; - } - - return len; -} - -int dsi_vc_dcs_read(struct intel_dsi *intel_dsi, int channel, u8 dcs_cmd, - u8 *buf, int buflen) -{ - struct drm_encoder *encoder = &intel_dsi->base.base; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; - u32 mask; - int ret; - - /* - * XXX: should issue multiple read requests and reads if request is - * longer than MIPI_MAX_RETURN_PKT_SIZE - */ - - I915_WRITE(MIPI_INTR_STAT(pipe), GEN_READ_DATA_AVAIL); - - ret = dsi_vc_dcs_send_read_request(intel_dsi, channel, dcs_cmd); - if (ret) - return ret; - - mask = GEN_READ_DATA_AVAIL; - if (wait_for((I915_READ(MIPI_INTR_STAT(pipe)) & mask) == mask, 50)) - DRM_ERROR("Timeout waiting for read data.\n"); - - ret = dsi_read_data_return(intel_dsi, buf, buflen); - if (ret < 0) - return ret; - - if (ret != buflen) - return -EIO; - - return 0; -} - -int dsi_vc_generic_read(struct intel_dsi *intel_dsi, int channel, - u8 *reqdata, int reqlen, u8 *buf, int buflen) -{ - struct drm_encoder *encoder = &intel_dsi->base.base; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; - u32 mask; - int ret; - - /* - * XXX: should issue multiple read requests and reads if request is - * longer than MIPI_MAX_RETURN_PKT_SIZE - */ - - I915_WRITE(MIPI_INTR_STAT(pipe), GEN_READ_DATA_AVAIL); - - ret = dsi_vc_generic_send_read_request(intel_dsi, channel, reqdata, - reqlen); - if (ret) - return ret; - - mask = GEN_READ_DATA_AVAIL; - if (wait_for((I915_READ(MIPI_INTR_STAT(pipe)) & mask) == mask, 50)) - DRM_ERROR("Timeout waiting for read data.\n"); - - ret = dsi_read_data_return(intel_dsi, buf, buflen); - if (ret < 0) - return ret; - - if (ret != buflen) - return -EIO; - - return 0; -} - -/* - * send a video mode command - * - * XXX: commands with data in MIPI_DPI_DATA? - */ -int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd) -{ - struct drm_encoder *encoder = &intel_dsi->base.base; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; - u32 mask; - - /* XXX: pipe, hs */ - if (intel_dsi->hs) - cmd &= ~DPI_LP_MODE; - else - cmd |= DPI_LP_MODE; - - /* DPI virtual channel?! */ - - mask = DPI_FIFO_EMPTY; - if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == mask, 50)) - DRM_ERROR("Timeout waiting for DPI FIFO empty.\n"); - - /* clear bit */ - I915_WRITE(MIPI_INTR_STAT(pipe), SPL_PKT_SENT_INTERRUPT); - - /* XXX: old code skips write if control unchanged */ - if (cmd == I915_READ(MIPI_DPI_CONTROL(pipe))) - DRM_ERROR("Same special packet %02x twice in a row.\n", cmd); - - I915_WRITE(MIPI_DPI_CONTROL(pipe), cmd); - - mask = SPL_PKT_SENT_INTERRUPT; - if (wait_for((I915_READ(MIPI_INTR_STAT(pipe)) & mask) == mask, 100)) - DRM_ERROR("Video mode command 0x%08x send failed.\n", cmd); - - return 0; -} diff --git a/drivers/gpu/drm/i915/intel_dsi_cmd.h b/drivers/gpu/drm/i915/intel_dsi_cmd.h deleted file mode 100644 index 54c8a23..0000000 --- a/drivers/gpu/drm/i915/intel_dsi_cmd.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright © 2013 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Author: Jani Nikula <jani.nikula@intel.com> - */ - -#ifndef _INTEL_DSI_DSI_H -#define _INTEL_DSI_DSI_H - -#include <drm/drmP.h> -#include <drm/drm_crtc.h> -#include <video/mipi_display.h> -#include "i915_drv.h" -#include "intel_drv.h" -#include "intel_dsi.h" - -void dsi_hs_mode_enable(struct intel_dsi *intel_dsi, bool enable); - -int dsi_vc_dcs_write(struct intel_dsi *intel_dsi, int channel, - const u8 *data, int len); - -int dsi_vc_generic_write(struct intel_dsi *intel_dsi, int channel, - const u8 *data, int len); - -int dsi_vc_dcs_read(struct intel_dsi *intel_dsi, int channel, u8 dcs_cmd, - u8 *buf, int buflen); - -int dsi_vc_generic_read(struct intel_dsi *intel_dsi, int channel, - u8 *reqdata, int reqlen, u8 *buf, int buflen); - -int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd); - -/* XXX: questionable write helpers */ -static inline int dsi_vc_dcs_write_0(struct intel_dsi *intel_dsi, - int channel, u8 dcs_cmd) -{ - return dsi_vc_dcs_write(intel_dsi, channel, &dcs_cmd, 1); -} - -static inline int dsi_vc_dcs_write_1(struct intel_dsi *intel_dsi, - int channel, u8 dcs_cmd, u8 param) -{ - u8 buf[2] = { dcs_cmd, param }; - return dsi_vc_dcs_write(intel_dsi, channel, buf, 2); -} - -static inline int dsi_vc_generic_write_0(struct intel_dsi *intel_dsi, - int channel) -{ - return dsi_vc_generic_write(intel_dsi, channel, NULL, 0); -} - -static inline int dsi_vc_generic_write_1(struct intel_dsi *intel_dsi, - int channel, u8 param) -{ - return dsi_vc_generic_write(intel_dsi, channel, ¶m, 1); -} - -static inline int dsi_vc_generic_write_2(struct intel_dsi *intel_dsi, - int channel, u8 param1, u8 param2) -{ - u8 buf[2] = { param1, param2 }; - return dsi_vc_generic_write(intel_dsi, channel, buf, 2); -} - -/* XXX: questionable read helpers */ -static inline int dsi_vc_generic_read_0(struct intel_dsi *intel_dsi, - int channel, u8 *buf, int buflen) -{ - return dsi_vc_generic_read(intel_dsi, channel, NULL, 0, buf, buflen); -} - -static inline int dsi_vc_generic_read_1(struct intel_dsi *intel_dsi, - int channel, u8 param, u8 *buf, - int buflen) -{ - return dsi_vc_generic_read(intel_dsi, channel, ¶m, 1, buf, buflen); -} - -static inline int dsi_vc_generic_read_2(struct intel_dsi *intel_dsi, - int channel, u8 param1, u8 param2, - u8 *buf, int buflen) -{ - u8 req[2] = { param1, param2 }; - - return dsi_vc_generic_read(intel_dsi, channel, req, 2, buf, buflen); -} - - -#endif /* _INTEL_DSI_DSI_H */ diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c deleted file mode 100644 index 44279b2..0000000 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright © 2013 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Shobhit Kumar <shobhit.kumar@intel.com> - * Yogesh Mohan Marimuthu <yogesh.mohan.marimuthu@intel.com> - */ - -#include <linux/kernel.h> -#include "intel_drv.h" -#include "i915_drv.h" -#include "intel_dsi.h" - -#define DSI_HSS_PACKET_SIZE 4 -#define DSI_HSE_PACKET_SIZE 4 -#define DSI_HSA_PACKET_EXTRA_SIZE 6 -#define DSI_HBP_PACKET_EXTRA_SIZE 6 -#define DSI_HACTIVE_PACKET_EXTRA_SIZE 6 -#define DSI_HFP_PACKET_EXTRA_SIZE 6 -#define DSI_EOTP_PACKET_SIZE 4 - -struct dsi_mnp { - u32 dsi_pll_ctrl; - u32 dsi_pll_div; -}; - -static const u32 lfsr_converts[] = { - 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 62 - 70 */ - 461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */ - 106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */ - 71, 35 /* 91 - 92 */ -}; - -static u32 dsi_rr_formula(const struct drm_display_mode *mode, - int pixel_format, int video_mode_format, - int lane_count, bool eotp) -{ - u32 bpp; - u32 hactive, vactive, hfp, hsync, hbp, vfp, vsync, vbp; - u32 hsync_bytes, hbp_bytes, hactive_bytes, hfp_bytes; - u32 bytes_per_line, bytes_per_frame; - u32 num_frames; - u32 bytes_per_x_frames, bytes_per_x_frames_x_lanes; - u32 dsi_bit_clock_hz; - u32 dsi_clk; - - switch (pixel_format) { - default: - case VID_MODE_FORMAT_RGB888: - case VID_MODE_FORMAT_RGB666_LOOSE: - bpp = 24; - break; - case VID_MODE_FORMAT_RGB666: - bpp = 18; - break; - case VID_MODE_FORMAT_RGB565: - bpp = 16; - break; - } - - hactive = mode->hdisplay; - vactive = mode->vdisplay; - hfp = mode->hsync_start - mode->hdisplay; - hsync = mode->hsync_end - mode->hsync_start; - hbp = mode->htotal - mode->hsync_end; - - vfp = mode->vsync_start - mode->vdisplay; - vsync = mode->vsync_end - mode->vsync_start; - vbp = mode->vtotal - mode->vsync_end; - - hsync_bytes = DIV_ROUND_UP(hsync * bpp, 8); - hbp_bytes = DIV_ROUND_UP(hbp * bpp, 8); - hactive_bytes = DIV_ROUND_UP(hactive * bpp, 8); - hfp_bytes = DIV_ROUND_UP(hfp * bpp, 8); - - bytes_per_line = DSI_HSS_PACKET_SIZE + hsync_bytes + - DSI_HSA_PACKET_EXTRA_SIZE + DSI_HSE_PACKET_SIZE + - hbp_bytes + DSI_HBP_PACKET_EXTRA_SIZE + - hactive_bytes + DSI_HACTIVE_PACKET_EXTRA_SIZE + - hfp_bytes + DSI_HFP_PACKET_EXTRA_SIZE; - - /* - * XXX: Need to accurately calculate LP to HS transition timeout and add - * it to bytes_per_line/bytes_per_frame. - */ - - if (eotp && video_mode_format == VIDEO_MODE_BURST) - bytes_per_line += DSI_EOTP_PACKET_SIZE; - - bytes_per_frame = vsync * bytes_per_line + vbp * bytes_per_line + - vactive * bytes_per_line + vfp * bytes_per_line; - - if (eotp && - (video_mode_format == VIDEO_MODE_NON_BURST_WITH_SYNC_PULSE || - video_mode_format == VIDEO_MODE_NON_BURST_WITH_SYNC_EVENTS)) - bytes_per_frame += DSI_EOTP_PACKET_SIZE; - - num_frames = drm_mode_vrefresh(mode); - bytes_per_x_frames = num_frames * bytes_per_frame; - - bytes_per_x_frames_x_lanes = bytes_per_x_frames / lane_count; - - /* the dsi clock is divided by 2 in the hardware to get dsi ddr clock */ - dsi_bit_clock_hz = bytes_per_x_frames_x_lanes * 8; - dsi_clk = dsi_bit_clock_hz / (1000 * 1000); - - if (eotp && video_mode_format == VIDEO_MODE_BURST) - dsi_clk *= 2; - - return dsi_clk; -} - -#ifdef MNP_FROM_TABLE - -struct dsi_clock_table { - u32 freq; - u8 m; - u8 p; -}; - -static const struct dsi_clock_table dsi_clk_tbl[] = { - {300, 72, 6}, {313, 75, 6}, {323, 78, 6}, {333, 80, 6}, - {343, 82, 6}, {353, 85, 6}, {363, 87, 6}, {373, 90, 6}, - {383, 92, 6}, {390, 78, 5}, {393, 79, 5}, {400, 80, 5}, - {401, 80, 5}, {402, 80, 5}, {403, 81, 5}, {404, 81, 5}, - {405, 81, 5}, {406, 81, 5}, {407, 81, 5}, {408, 82, 5}, - {409, 82, 5}, {410, 82, 5}, {411, 82, 5}, {412, 82, 5}, - {413, 83, 5}, {414, 83, 5}, {415, 83, 5}, {416, 83, 5}, - {417, 83, 5}, {418, 84, 5}, {419, 84, 5}, {420, 84, 5}, - {430, 86, 5}, {440, 88, 5}, {450, 90, 5}, {460, 92, 5}, - {470, 75, 4}, {480, 77, 4}, {490, 78, 4}, {500, 80, 4}, - {510, 82, 4}, {520, 83, 4}, {530, 85, 4}, {540, 86, 4}, - {550, 88, 4}, {560, 90, 4}, {570, 91, 4}, {580, 70, 3}, - {590, 71, 3}, {600, 72, 3}, {610, 73, 3}, {620, 74, 3}, - {630, 76, 3}, {640, 77, 3}, {650, 78, 3}, {660, 79, 3}, - {670, 80, 3}, {680, 82, 3}, {690, 83, 3}, {700, 84, 3}, - {710, 85, 3}, {720, 86, 3}, {730, 88, 3}, {740, 89, 3}, - {750, 90, 3}, {760, 91, 3}, {770, 92, 3}, {780, 62, 2}, - {790, 63, 2}, {800, 64, 2}, {880, 70, 2}, {900, 72, 2}, - {1000, 80, 2}, /* dsi clock frequency in Mhz*/ -}; - -static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp) -{ - unsigned int i; - u8 m; - u8 n; - u8 p; - u32 m_seed; - - if (dsi_clk < 300 || dsi_clk > 1000) - return -ECHRNG; - - for (i = 0; i <= ARRAY_SIZE(dsi_clk_tbl); i++) { - if (dsi_clk_tbl[i].freq > dsi_clk) - break; - } - - m = dsi_clk_tbl[i].m; - p = dsi_clk_tbl[i].p; - m_seed = lfsr_converts[m - 62]; - n = 1; - dsi_mnp->dsi_pll_ctrl = 1 << (DSI_PLL_P1_POST_DIV_SHIFT + p - 2); - dsi_mnp->dsi_pll_div = (n - 1) << DSI_PLL_N1_DIV_SHIFT | - m_seed << DSI_PLL_M1_DIV_SHIFT; - - return 0; -} - -#else - -static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp) -{ - u32 m, n, p; - u32 ref_clk; - u32 error; - u32 tmp_error; - u32 target_dsi_clk; - u32 calc_dsi_clk; - u32 calc_m; - u32 calc_p; - u32 m_seed; - - if (dsi_clk < 300 || dsi_clk > 1150) { - DRM_ERROR("DSI CLK Out of Range\n"); - return -ECHRNG; - } - - ref_clk = 25000; - target_dsi_clk = dsi_clk * 1000; - error = 0xFFFFFFFF; - calc_m = 0; - calc_p = 0; - - for (m = 62; m <= 92; m++) { - for (p = 2; p <= 6; p++) { - - calc_dsi_clk = (m * ref_clk) / p; - if (calc_dsi_clk >= target_dsi_clk) { - tmp_error = calc_dsi_clk - target_dsi_clk; - if (tmp_error < error) { - error = tmp_error; - calc_m = m; - calc_p = p; - } - } - } - } - - m_seed = lfsr_converts[calc_m - 62]; - n = 1; - dsi_mnp->dsi_pll_ctrl = 1 << (DSI_PLL_P1_POST_DIV_SHIFT + calc_p - 2); - dsi_mnp->dsi_pll_div = (n - 1) << DSI_PLL_N1_DIV_SHIFT | - m_seed << DSI_PLL_M1_DIV_SHIFT; - - return 0; -} - -#endif - -/* - * XXX: The muxing and gating is hard coded for now. Need to add support for - * sharing PLLs with two DSI outputs. - */ -static void vlv_configure_dsi_pll(struct intel_encoder *encoder) -{ - struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - const struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode; - struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); - int ret; - struct dsi_mnp dsi_mnp; - u32 dsi_clk; - - dsi_clk = dsi_rr_formula(mode, intel_dsi->pixel_format, - intel_dsi->video_mode_format, - intel_dsi->lane_count, !intel_dsi->eot_disable); - - ret = dsi_calc_mnp(dsi_clk, &dsi_mnp); - if (ret) { - DRM_DEBUG_KMS("dsi_calc_mnp failed\n"); - return; - } - - dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI0_DSIPLL; - - DRM_DEBUG_KMS("dsi pll div %08x, ctrl %08x\n", - dsi_mnp.dsi_pll_div, dsi_mnp.dsi_pll_ctrl); - - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, 0); - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_DIVIDER, dsi_mnp.dsi_pll_div); - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_mnp.dsi_pll_ctrl); -} - -void vlv_enable_dsi_pll(struct intel_encoder *encoder) -{ - struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; - u32 tmp; - - DRM_DEBUG_KMS("\n"); - - mutex_lock(&dev_priv->dpio_lock); - - vlv_configure_dsi_pll(encoder); - - /* wait at least 0.5 us after ungating before enabling VCO */ - usleep_range(1, 10); - - tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); - tmp |= DSI_PLL_VCO_EN; - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp); - - mutex_unlock(&dev_priv->dpio_lock); - - if (wait_for(I915_READ(PIPECONF(PIPE_A)) & PIPECONF_DSI_PLL_LOCKED, 20)) { - DRM_ERROR("DSI PLL lock failed\n"); - return; - } - - DRM_DEBUG_KMS("DSI PLL locked\n"); -} - -void vlv_disable_dsi_pll(struct intel_encoder *encoder) -{ - struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; - u32 tmp; - - DRM_DEBUG_KMS("\n"); - - mutex_lock(&dev_priv->dpio_lock); - - tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); - tmp &= ~DSI_PLL_VCO_EN; - tmp |= DSI_PLL_LDO_GATE; - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp); - - mutex_unlock(&dev_priv->dpio_lock); -} diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 3c77365..7fa7df5 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -153,8 +153,6 @@ static void intel_dvo_get_config(struct intel_encoder *encoder, flags |= DRM_MODE_FLAG_NVSYNC; pipe_config->adjusted_mode.flags |= flags; - - pipe_config->adjusted_mode.crtc_clock = pipe_config->port_clock; } static void intel_disable_dvo(struct intel_encoder *encoder) @@ -173,16 +171,11 @@ static void intel_enable_dvo(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_dvo *intel_dvo = enc_to_dvo(encoder); - struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); u32 dvo_reg = intel_dvo->dev.dvo_reg; u32 temp = I915_READ(dvo_reg); I915_WRITE(dvo_reg, temp | DVO_ENABLE); I915_READ(dvo_reg); - intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, - &crtc->config.requested_mode, - &crtc->config.adjusted_mode); - intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true); } @@ -191,7 +184,6 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode) { struct intel_dvo *intel_dvo = intel_attached_dvo(connector); struct drm_crtc *crtc; - struct intel_crtc_config *config; /* dvo supports only 2 dpms states. */ if (mode != DRM_MODE_DPMS_ON) @@ -212,16 +204,10 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode) /* We call connector dpms manually below in case pipe dpms doesn't * change due to cloning. */ if (mode == DRM_MODE_DPMS_ON) { - config = &to_intel_crtc(crtc)->config; - intel_dvo->base.connectors_active = true; intel_crtc_update_dpms(crtc); - intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, - &config->requested_mode, - &config->adjusted_mode); - intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true); } else { intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false); @@ -281,6 +267,11 @@ static bool intel_dvo_compute_config(struct intel_encoder *encoder, drm_mode_set_crtcinfo(adjusted_mode, 0); } + if (intel_dvo->dev.dev_ops->mode_fixup) + return intel_dvo->dev.dev_ops->mode_fixup(&intel_dvo->dev, + &pipe_config->requested_mode, + adjusted_mode); + return true; } @@ -308,6 +299,10 @@ static void intel_dvo_mode_set(struct intel_encoder *encoder) break; } + intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, + &crtc->config.requested_mode, + adjusted_mode); + /* Save the data order, since I don't know what it should be set to. */ dvo_val = I915_READ(dvo_reg) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); @@ -375,6 +370,7 @@ static int intel_dvo_get_modes(struct drm_connector *connector) static void intel_dvo_destroy(struct drm_connector *connector) { + drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -455,11 +451,11 @@ void intel_dvo_init(struct drm_device *dev) int i; int encoder_type = DRM_MODE_ENCODER_NONE; - intel_dvo = kzalloc(sizeof(*intel_dvo), GFP_KERNEL); + intel_dvo = kzalloc(sizeof(struct intel_dvo), GFP_KERNEL); if (!intel_dvo) return; - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); if (!intel_connector) { kfree(intel_dvo); return; diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fb.c index 895fcb4..bc21000 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -78,8 +78,8 @@ static int intelfb_create(struct drm_fb_helper *helper, mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; - mode_cmd.pitches[0] = ALIGN(mode_cmd.width * - DIV_ROUND_UP(sizes->surface_bpp, 8), 64); + mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) / + 8), 64); mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); @@ -184,27 +184,6 @@ out: return ret; } -/** Sets the color ramps on behalf of RandR */ -static void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, int regno) -{ - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - intel_crtc->lut_r[regno] = red >> 8; - intel_crtc->lut_g[regno] = green >> 8; - intel_crtc->lut_b[regno] = blue >> 8; -} - -static void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, int regno) -{ - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - *red = intel_crtc->lut_r[regno] << 8; - *green = intel_crtc->lut_g[regno] << 8; - *blue = intel_crtc->lut_b[regno] << 8; -} - static struct drm_fb_helper_funcs intel_fb_helper_funcs = { .gamma_set = intel_crtc_fb_gamma_set, .gamma_get = intel_crtc_fb_gamma_get, @@ -237,7 +216,7 @@ int intel_fbdev_init(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int ret; - ifbdev = kzalloc(sizeof(*ifbdev), GFP_KERNEL); + ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL); if (!ifbdev) return -ENOMEM; @@ -246,7 +225,7 @@ int intel_fbdev_init(struct drm_device *dev) ret = drm_fb_helper_init(dev, &ifbdev->helper, INTEL_INFO(dev)->num_pipes, - 4); + INTELFB_CONN_LIMIT); if (ret) { kfree(ifbdev); return ret; @@ -299,13 +278,13 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state) MODULE_LICENSE("GPL and additional rights"); -void intel_fbdev_output_poll_changed(struct drm_device *dev) +void intel_fb_output_poll_changed(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper); } -void intel_fbdev_restore_mode(struct drm_device *dev) +void intel_fb_restore_mode(struct drm_device *dev) { int ret; struct drm_i915_private *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 03f9ca7..4148cc8 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -713,7 +713,6 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; u32 tmp, flags = 0; - int dotclock; tmp = I915_READ(intel_hdmi->hdmi_reg); @@ -728,16 +727,6 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, flags |= DRM_MODE_FLAG_NVSYNC; pipe_config->adjusted_mode.flags |= flags; - - if ((tmp & SDVO_COLOR_FORMAT_MASK) == HDMI_COLOR_FORMAT_12bpc) - dotclock = pipe_config->port_clock * 2 / 3; - else - dotclock = pipe_config->port_clock; - - if (HAS_PCH_SPLIT(dev_priv->dev)) - ironlake_check_encoder_dotclock(pipe_config, dotclock); - - pipe_config->adjusted_mode.crtc_clock = dotclock; } static void intel_enable_hdmi(struct intel_encoder *encoder) @@ -847,7 +836,7 @@ static int hdmi_portclock_limit(struct intel_hdmi *hdmi) if (IS_G4X(dev)) return 165000; - else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) + else if (IS_HASWELL(dev)) return 300000; else return 225000; @@ -873,7 +862,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); struct drm_device *dev = encoder->base.dev; struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; - int clock_12bpc = pipe_config->adjusted_mode.crtc_clock * 3 / 2; + int clock_12bpc = pipe_config->requested_mode.clock * 3 / 2; int portclock_limit = hdmi_portclock_limit(intel_hdmi); int desired_bpp; @@ -915,7 +904,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, pipe_config->pipe_bpp = desired_bpp; } - if (adjusted_mode->crtc_clock > portclock_limit) { + if (adjusted_mode->clock > portclock_limit) { DRM_DEBUG_KMS("too high HDMI clock, rejecting mode\n"); return false; } @@ -1074,7 +1063,7 @@ done: return 0; } -static void vlv_hdmi_pre_enable(struct intel_encoder *encoder) +static void intel_hdmi_pre_enable(struct intel_encoder *encoder) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_device *dev = encoder->base.dev; @@ -1090,35 +1079,35 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder) /* Enable clock channels for this port */ mutex_lock(&dev_priv->dpio_lock); - val = vlv_dpio_read(dev_priv, pipe, DPIO_DATA_LANE_A(port)); + val = vlv_dpio_read(dev_priv, DPIO_DATA_LANE_A(port)); val = 0; if (pipe) val |= (1<<21); else val &= ~(1<<21); val |= 0x001000c4; - vlv_dpio_write(dev_priv, pipe, DPIO_DATA_CHANNEL(port), val); + vlv_dpio_write(dev_priv, DPIO_DATA_CHANNEL(port), val); /* HDMI 1.0V-2dB */ - vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL4(port), + vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0); + vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(port), 0x2b245f5f); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL2(port), + vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(port), 0x5578b83a); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL3(port), + vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL3(port), 0x0c782040); - vlv_dpio_write(dev_priv, pipe, DPIO_TX3_SWING_CTL4(port), + vlv_dpio_write(dev_priv, DPIO_TX3_SWING_CTL4(port), 0x2b247878); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER0(port), 0x00030000); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port), + vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER0(port), 0x00030000); + vlv_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port), 0x00002000); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), + vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), DPIO_TX_OCALINIT_EN); /* Program lane clock */ - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF0(port), + vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(port), 0x00760018); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF8(port), + vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(port), 0x00400888); mutex_unlock(&dev_priv->dpio_lock); @@ -1127,60 +1116,55 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder) vlv_wait_port_ready(dev_priv, port); } -static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder) +static void intel_hdmi_pre_pll_enable(struct intel_encoder *encoder) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = - to_intel_crtc(encoder->base.crtc); int port = vlv_dport_to_channel(dport); - int pipe = intel_crtc->pipe; if (!IS_VALLEYVIEW(dev)) return; /* Program Tx lane resets to default */ mutex_lock(&dev_priv->dpio_lock); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port), + vlv_dpio_write(dev_priv, DPIO_PCS_TX(port), DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port), + vlv_dpio_write(dev_priv, DPIO_PCS_CLK(port), DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) | DPIO_PCS_CLK_SOFT_RESET); /* Fix up inter-pair skew failure */ - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER1(port), 0x00750f00); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_CTL(port), 0x00001500); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_LANE(port), 0x40400000); + vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER1(port), 0x00750f00); + vlv_dpio_write(dev_priv, DPIO_TX_CTL(port), 0x00001500); + vlv_dpio_write(dev_priv, DPIO_TX_LANE(port), 0x40400000); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port), + vlv_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port), 0x00002000); - vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), + vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), DPIO_TX_OCALINIT_EN); mutex_unlock(&dev_priv->dpio_lock); } -static void vlv_hdmi_post_disable(struct intel_encoder *encoder) +static void intel_hdmi_post_disable(struct intel_encoder *encoder) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; - struct intel_crtc *intel_crtc = - to_intel_crtc(encoder->base.crtc); int port = vlv_dport_to_channel(dport); - int pipe = intel_crtc->pipe; /* Reset lanes to avoid HDMI flicker (VLV w/a) */ mutex_lock(&dev_priv->dpio_lock); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port), 0x00000000); - vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port), 0x00e00060); + vlv_dpio_write(dev_priv, DPIO_PCS_TX(port), 0x00000000); + vlv_dpio_write(dev_priv, DPIO_PCS_CLK(port), 0x00e00060); mutex_unlock(&dev_priv->dpio_lock); } static void intel_hdmi_destroy(struct drm_connector *connector) { + drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -1227,7 +1211,6 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, connector->interlace_allowed = 1; connector->doublescan_allowed = 0; - connector->stereo_allowed = 1; switch (port) { case PORT_B: @@ -1292,11 +1275,11 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) struct intel_encoder *intel_encoder; struct intel_connector *intel_connector; - intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); + intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL); if (!intel_dig_port) return; - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); if (!intel_connector) { kfree(intel_dig_port); return; @@ -1313,10 +1296,10 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) intel_encoder->get_hw_state = intel_hdmi_get_hw_state; intel_encoder->get_config = intel_hdmi_get_config; if (IS_VALLEYVIEW(dev)) { - intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable; - intel_encoder->pre_enable = vlv_hdmi_pre_enable; + intel_encoder->pre_pll_enable = intel_hdmi_pre_pll_enable; + intel_encoder->pre_enable = intel_hdmi_pre_enable; intel_encoder->enable = vlv_enable_hdmi; - intel_encoder->post_disable = vlv_hdmi_post_disable; + intel_encoder->post_disable = intel_hdmi_post_disable; } else { intel_encoder->enable = intel_enable_hdmi; } diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 2ca17b1..d1c1e0f7 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -34,11 +34,6 @@ #include <drm/i915_drm.h> #include "i915_drv.h" -enum disp_clk { - CDCLK, - CZCLK -}; - struct gmbus_port { const char *name; int reg; @@ -63,69 +58,10 @@ to_intel_gmbus(struct i2c_adapter *i2c) return container_of(i2c, struct intel_gmbus, adapter); } -static int get_disp_clk_div(struct drm_i915_private *dev_priv, - enum disp_clk clk) -{ - u32 reg_val; - int clk_ratio; - - reg_val = I915_READ(CZCLK_CDCLK_FREQ_RATIO); - - if (clk == CDCLK) - clk_ratio = - ((reg_val & CDCLK_FREQ_MASK) >> CDCLK_FREQ_SHIFT) + 1; - else - clk_ratio = (reg_val & CZCLK_FREQ_MASK) + 1; - - return clk_ratio; -} - -static void gmbus_set_freq(struct drm_i915_private *dev_priv) -{ - int vco_freq[] = { 800, 1600, 2000, 2400 }; - int gmbus_freq = 0, cdclk_div, hpll_freq; - - BUG_ON(!IS_VALLEYVIEW(dev_priv->dev)); - - /* Skip setting the gmbus freq if BIOS has already programmed it */ - if (I915_READ(GMBUSFREQ_VLV) != 0xA0) - return; - - /* Obtain SKU information */ - mutex_lock(&dev_priv->dpio_lock); - hpll_freq = - vlv_cck_read(dev_priv, CCK_FUSE_REG) & CCK_FUSE_HPLL_FREQ_MASK; - mutex_unlock(&dev_priv->dpio_lock); - - /* Get the CDCLK divide ratio */ - cdclk_div = get_disp_clk_div(dev_priv, CDCLK); - - /* - * Program the gmbus_freq based on the cdclk frequency. - * BSpec erroneously claims we should aim for 4MHz, but - * in fact 1MHz is the correct frequency. - */ - if (cdclk_div) - gmbus_freq = (vco_freq[hpll_freq] << 1) / cdclk_div; - - if (WARN_ON(gmbus_freq == 0)) - return; - - I915_WRITE(GMBUSFREQ_VLV, gmbus_freq); -} - void intel_i2c_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - - /* - * In BIOS-less system, program the correct gmbus frequency - * before reading edid. - */ - if (IS_VALLEYVIEW(dev)) - gmbus_set_freq(dev_priv); - I915_WRITE(dev_priv->gpio_mmio_base + GMBUS0, 0); I915_WRITE(dev_priv->gpio_mmio_base + GMBUS4, 0); } diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index c3b4da7..b8af94a 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -92,7 +92,6 @@ static void intel_lvds_get_config(struct intel_encoder *encoder, struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 lvds_reg, tmp, flags = 0; - int dotclock; if (HAS_PCH_SPLIT(dev)) lvds_reg = PCH_LVDS; @@ -117,13 +116,6 @@ static void intel_lvds_get_config(struct intel_encoder *encoder, pipe_config->gmch_pfit.control |= tmp & PANEL_8TO6_DITHER_ENABLE; } - - dotclock = pipe_config->port_clock; - - if (HAS_PCH_SPLIT(dev_priv->dev)) - ironlake_check_encoder_dotclock(pipe_config, dotclock); - - pipe_config->adjusted_mode.crtc_clock = dotclock; } /* The LVDS pin pair needs to be on before the DPLLs are enabled. @@ -206,8 +198,7 @@ static void intel_enable_lvds(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); - struct intel_connector *intel_connector = - &lvds_encoder->attached_connector->base; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct drm_i915_private *dev_priv = dev->dev_private; u32 ctl_reg, stat_reg; @@ -226,15 +217,13 @@ static void intel_enable_lvds(struct intel_encoder *encoder) if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000)) DRM_ERROR("timed out waiting for panel to power on\n"); - intel_panel_enable_backlight(intel_connector); + intel_panel_enable_backlight(dev, intel_crtc->pipe); } static void intel_disable_lvds(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); - struct intel_connector *intel_connector = - &lvds_encoder->attached_connector->base; struct drm_i915_private *dev_priv = dev->dev_private; u32 ctl_reg, stat_reg; @@ -246,7 +235,7 @@ static void intel_disable_lvds(struct intel_encoder *encoder) stat_reg = PP_STATUS; } - intel_panel_disable_backlight(intel_connector); + intel_panel_disable_backlight(dev); I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON); if (wait_for((I915_READ(stat_reg) & PP_ON) == 0, 1000)) @@ -477,6 +466,7 @@ static void intel_lvds_destroy(struct drm_connector *connector) intel_panel_fini(&lvds_connector->base.panel); + drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -812,8 +802,7 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev, return true; for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - union child_device_config *uchild = dev_priv->vbt.child_dev + i; - struct old_child_dev_config *child = &uchild->old; + struct child_device_config *child = dev_priv->vbt.child_dev + i; /* If the device type is not LFP, continue. * We have to check both the new identifiers as well as the @@ -967,11 +956,11 @@ void intel_lvds_init(struct drm_device *dev) } } - lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL); + lvds_encoder = kzalloc(sizeof(struct intel_lvds_encoder), GFP_KERNEL); if (!lvds_encoder) return; - lvds_connector = kzalloc(sizeof(*lvds_connector), GFP_KERNEL); + lvds_connector = kzalloc(sizeof(struct intel_lvds_connector), GFP_KERNEL); if (!lvds_connector) { kfree(lvds_encoder); return; diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 6d69a9b..119771f 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -36,11 +36,8 @@ #include "i915_drv.h" #include "intel_drv.h" -#define PCI_ASLE 0xe4 -#define PCI_ASLS 0xfc -#define PCI_SWSCI 0xe8 -#define PCI_SWSCI_SCISEL (1 << 15) -#define PCI_SWSCI_GSSCIE (1 << 0) +#define PCI_ASLE 0xe4 +#define PCI_ASLS 0xfc #define OPREGION_HEADER_OFFSET 0 #define OPREGION_ACPI_OFFSET 0x100 @@ -110,38 +107,25 @@ struct opregion_asle { u32 epfm; /* enabled panel fitting modes */ u8 plut[74]; /* panel LUT and identifier */ u32 pfmb; /* PWM freq and min brightness */ - u32 cddv; /* color correction default values */ - u32 pcft; /* power conservation features */ - u32 srot; /* supported rotation angles */ - u32 iuer; /* IUER events */ - u8 rsvd[86]; + u8 rsvd[102]; } __attribute__((packed)); /* Driver readiness indicator */ #define ASLE_ARDY_READY (1 << 0) #define ASLE_ARDY_NOT_READY (0 << 0) -/* ASLE Interrupt Command (ASLC) bits */ -#define ASLC_SET_ALS_ILLUM (1 << 0) -#define ASLC_SET_BACKLIGHT (1 << 1) -#define ASLC_SET_PFIT (1 << 2) -#define ASLC_SET_PWM_FREQ (1 << 3) -#define ASLC_SUPPORTED_ROTATION_ANGLES (1 << 4) -#define ASLC_BUTTON_ARRAY (1 << 5) -#define ASLC_CONVERTIBLE_INDICATOR (1 << 6) -#define ASLC_DOCKING_INDICATOR (1 << 7) -#define ASLC_ISCT_STATE_CHANGE (1 << 8) -#define ASLC_REQ_MSK 0x1ff -/* response bits */ -#define ASLC_ALS_ILLUM_FAILED (1 << 10) -#define ASLC_BACKLIGHT_FAILED (1 << 12) -#define ASLC_PFIT_FAILED (1 << 14) -#define ASLC_PWM_FREQ_FAILED (1 << 16) -#define ASLC_ROTATION_ANGLES_FAILED (1 << 18) -#define ASLC_BUTTON_ARRAY_FAILED (1 << 20) -#define ASLC_CONVERTIBLE_FAILED (1 << 22) -#define ASLC_DOCKING_FAILED (1 << 24) -#define ASLC_ISCT_STATE_FAILED (1 << 26) +/* ASLE irq request bits */ +#define ASLE_SET_ALS_ILLUM (1 << 0) +#define ASLE_SET_BACKLIGHT (1 << 1) +#define ASLE_SET_PFIT (1 << 2) +#define ASLE_SET_PWM_FREQ (1 << 3) +#define ASLE_REQ_MSK 0xf + +/* response bits of ASLE irq request */ +#define ASLE_ALS_ILLUM_FAILED (1<<10) +#define ASLE_BACKLIGHT_FAILED (1<<12) +#define ASLE_PFIT_FAILED (1<<14) +#define ASLE_PWM_FREQ_FAILED (1<<16) /* Technology enabled indicator */ #define ASLE_TCHE_ALS_EN (1 << 0) @@ -167,60 +151,6 @@ struct opregion_asle { #define ASLE_CBLV_VALID (1<<31) -/* IUER */ -#define ASLE_IUER_DOCKING (1 << 7) -#define ASLE_IUER_CONVERTIBLE (1 << 6) -#define ASLE_IUER_ROTATION_LOCK_BTN (1 << 4) -#define ASLE_IUER_VOLUME_DOWN_BTN (1 << 3) -#define ASLE_IUER_VOLUME_UP_BTN (1 << 2) -#define ASLE_IUER_WINDOWS_BTN (1 << 1) -#define ASLE_IUER_POWER_BTN (1 << 0) - -/* Software System Control Interrupt (SWSCI) */ -#define SWSCI_SCIC_INDICATOR (1 << 0) -#define SWSCI_SCIC_MAIN_FUNCTION_SHIFT 1 -#define SWSCI_SCIC_MAIN_FUNCTION_MASK (0xf << 1) -#define SWSCI_SCIC_SUB_FUNCTION_SHIFT 8 -#define SWSCI_SCIC_SUB_FUNCTION_MASK (0xff << 8) -#define SWSCI_SCIC_EXIT_PARAMETER_SHIFT 8 -#define SWSCI_SCIC_EXIT_PARAMETER_MASK (0xff << 8) -#define SWSCI_SCIC_EXIT_STATUS_SHIFT 5 -#define SWSCI_SCIC_EXIT_STATUS_MASK (7 << 5) -#define SWSCI_SCIC_EXIT_STATUS_SUCCESS 1 - -#define SWSCI_FUNCTION_CODE(main, sub) \ - ((main) << SWSCI_SCIC_MAIN_FUNCTION_SHIFT | \ - (sub) << SWSCI_SCIC_SUB_FUNCTION_SHIFT) - -/* SWSCI: Get BIOS Data (GBDA) */ -#define SWSCI_GBDA 4 -#define SWSCI_GBDA_SUPPORTED_CALLS SWSCI_FUNCTION_CODE(SWSCI_GBDA, 0) -#define SWSCI_GBDA_REQUESTED_CALLBACKS SWSCI_FUNCTION_CODE(SWSCI_GBDA, 1) -#define SWSCI_GBDA_BOOT_DISPLAY_PREF SWSCI_FUNCTION_CODE(SWSCI_GBDA, 4) -#define SWSCI_GBDA_PANEL_DETAILS SWSCI_FUNCTION_CODE(SWSCI_GBDA, 5) -#define SWSCI_GBDA_TV_STANDARD SWSCI_FUNCTION_CODE(SWSCI_GBDA, 6) -#define SWSCI_GBDA_INTERNAL_GRAPHICS SWSCI_FUNCTION_CODE(SWSCI_GBDA, 7) -#define SWSCI_GBDA_SPREAD_SPECTRUM SWSCI_FUNCTION_CODE(SWSCI_GBDA, 10) - -/* SWSCI: System BIOS Callbacks (SBCB) */ -#define SWSCI_SBCB 6 -#define SWSCI_SBCB_SUPPORTED_CALLBACKS SWSCI_FUNCTION_CODE(SWSCI_SBCB, 0) -#define SWSCI_SBCB_INIT_COMPLETION SWSCI_FUNCTION_CODE(SWSCI_SBCB, 1) -#define SWSCI_SBCB_PRE_HIRES_SET_MODE SWSCI_FUNCTION_CODE(SWSCI_SBCB, 3) -#define SWSCI_SBCB_POST_HIRES_SET_MODE SWSCI_FUNCTION_CODE(SWSCI_SBCB, 4) -#define SWSCI_SBCB_DISPLAY_SWITCH SWSCI_FUNCTION_CODE(SWSCI_SBCB, 5) -#define SWSCI_SBCB_SET_TV_FORMAT SWSCI_FUNCTION_CODE(SWSCI_SBCB, 6) -#define SWSCI_SBCB_ADAPTER_POWER_STATE SWSCI_FUNCTION_CODE(SWSCI_SBCB, 7) -#define SWSCI_SBCB_DISPLAY_POWER_STATE SWSCI_FUNCTION_CODE(SWSCI_SBCB, 8) -#define SWSCI_SBCB_SET_BOOT_DISPLAY SWSCI_FUNCTION_CODE(SWSCI_SBCB, 9) -#define SWSCI_SBCB_SET_PANEL_DETAILS SWSCI_FUNCTION_CODE(SWSCI_SBCB, 10) -#define SWSCI_SBCB_SET_INTERNAL_GFX SWSCI_FUNCTION_CODE(SWSCI_SBCB, 11) -#define SWSCI_SBCB_POST_HIRES_TO_DOS_FS SWSCI_FUNCTION_CODE(SWSCI_SBCB, 16) -#define SWSCI_SBCB_SUSPEND_RESUME SWSCI_FUNCTION_CODE(SWSCI_SBCB, 17) -#define SWSCI_SBCB_SET_SPREAD_SPECTRUM SWSCI_FUNCTION_CODE(SWSCI_SBCB, 18) -#define SWSCI_SBCB_POST_VBE_PM SWSCI_FUNCTION_CODE(SWSCI_SBCB, 19) -#define SWSCI_SBCB_ENABLE_DISABLE_AUDIO SWSCI_FUNCTION_CODE(SWSCI_SBCB, 21) - #define ACPI_OTHER_OUTPUT (0<<8) #define ACPI_VGA_OUTPUT (1<<8) #define ACPI_TV_OUTPUT (2<<8) @@ -228,224 +158,24 @@ struct opregion_asle { #define ACPI_LVDS_OUTPUT (4<<8) #ifdef CONFIG_ACPI -static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct opregion_swsci __iomem *swsci = dev_priv->opregion.swsci; - u32 main_function, sub_function, scic; - u16 pci_swsci; - u32 dslp; - - if (!swsci) - return -ENODEV; - - main_function = (function & SWSCI_SCIC_MAIN_FUNCTION_MASK) >> - SWSCI_SCIC_MAIN_FUNCTION_SHIFT; - sub_function = (function & SWSCI_SCIC_SUB_FUNCTION_MASK) >> - SWSCI_SCIC_SUB_FUNCTION_SHIFT; - - /* Check if we can call the function. See swsci_setup for details. */ - if (main_function == SWSCI_SBCB) { - if ((dev_priv->opregion.swsci_sbcb_sub_functions & - (1 << sub_function)) == 0) - return -EINVAL; - } else if (main_function == SWSCI_GBDA) { - if ((dev_priv->opregion.swsci_gbda_sub_functions & - (1 << sub_function)) == 0) - return -EINVAL; - } - - /* Driver sleep timeout in ms. */ - dslp = ioread32(&swsci->dslp); - if (!dslp) { - /* The spec says 2ms should be the default, but it's too small - * for some machines. */ - dslp = 50; - } else if (dslp > 500) { - /* Hey bios, trust must be earned. */ - WARN_ONCE(1, "excessive driver sleep timeout (DSPL) %u\n", dslp); - dslp = 500; - } - - /* The spec tells us to do this, but we are the only user... */ - scic = ioread32(&swsci->scic); - if (scic & SWSCI_SCIC_INDICATOR) { - DRM_DEBUG_DRIVER("SWSCI request already in progress\n"); - return -EBUSY; - } - - scic = function | SWSCI_SCIC_INDICATOR; - - iowrite32(parm, &swsci->parm); - iowrite32(scic, &swsci->scic); - - /* Ensure SCI event is selected and event trigger is cleared. */ - pci_read_config_word(dev->pdev, PCI_SWSCI, &pci_swsci); - if (!(pci_swsci & PCI_SWSCI_SCISEL) || (pci_swsci & PCI_SWSCI_GSSCIE)) { - pci_swsci |= PCI_SWSCI_SCISEL; - pci_swsci &= ~PCI_SWSCI_GSSCIE; - pci_write_config_word(dev->pdev, PCI_SWSCI, pci_swsci); - } - - /* Use event trigger to tell bios to check the mail. */ - pci_swsci |= PCI_SWSCI_GSSCIE; - pci_write_config_word(dev->pdev, PCI_SWSCI, pci_swsci); - - /* Poll for the result. */ -#define C (((scic = ioread32(&swsci->scic)) & SWSCI_SCIC_INDICATOR) == 0) - if (wait_for(C, dslp)) { - DRM_DEBUG_DRIVER("SWSCI request timed out\n"); - return -ETIMEDOUT; - } - - scic = (scic & SWSCI_SCIC_EXIT_STATUS_MASK) >> - SWSCI_SCIC_EXIT_STATUS_SHIFT; - - /* Note: scic == 0 is an error! */ - if (scic != SWSCI_SCIC_EXIT_STATUS_SUCCESS) { - DRM_DEBUG_DRIVER("SWSCI request error %u\n", scic); - return -EIO; - } - - if (parm_out) - *parm_out = ioread32(&swsci->parm); - - return 0; - -#undef C -} - -#define DISPLAY_TYPE_CRT 0 -#define DISPLAY_TYPE_TV 1 -#define DISPLAY_TYPE_EXTERNAL_FLAT_PANEL 2 -#define DISPLAY_TYPE_INTERNAL_FLAT_PANEL 3 - -int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder, - bool enable) -{ - struct drm_device *dev = intel_encoder->base.dev; - u32 parm = 0; - u32 type = 0; - u32 port; - - /* don't care about old stuff for now */ - if (!HAS_DDI(dev)) - return 0; - - port = intel_ddi_get_encoder_port(intel_encoder); - if (port == PORT_E) { - port = 0; - } else { - parm |= 1 << port; - port++; - } - - if (!enable) - parm |= 4 << 8; - - switch (intel_encoder->type) { - case INTEL_OUTPUT_ANALOG: - type = DISPLAY_TYPE_CRT; - break; - case INTEL_OUTPUT_UNKNOWN: - case INTEL_OUTPUT_DISPLAYPORT: - case INTEL_OUTPUT_HDMI: - type = DISPLAY_TYPE_EXTERNAL_FLAT_PANEL; - break; - case INTEL_OUTPUT_EDP: - type = DISPLAY_TYPE_INTERNAL_FLAT_PANEL; - break; - default: - WARN_ONCE(1, "unsupported intel_encoder type %d\n", - intel_encoder->type); - return -EINVAL; - } - - parm |= type << (16 + port * 3); - - return swsci(dev, SWSCI_SBCB_DISPLAY_POWER_STATE, parm, NULL); -} - -static const struct { - pci_power_t pci_power_state; - u32 parm; -} power_state_map[] = { - { PCI_D0, 0x00 }, - { PCI_D1, 0x01 }, - { PCI_D2, 0x02 }, - { PCI_D3hot, 0x04 }, - { PCI_D3cold, 0x04 }, -}; - -int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state) -{ - int i; - - if (!HAS_DDI(dev)) - return 0; - - for (i = 0; i < ARRAY_SIZE(power_state_map); i++) { - if (state == power_state_map[i].pci_power_state) - return swsci(dev, SWSCI_SBCB_ADAPTER_POWER_STATE, - power_state_map[i].parm, NULL); - } - - return -EINVAL; -} - static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) { struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_encoder *encoder; - struct drm_connector *connector; - struct intel_connector *intel_connector = NULL; - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0]; struct opregion_asle __iomem *asle = dev_priv->opregion.asle; - u32 ret = 0; - bool found = false; DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp); if (!(bclp & ASLE_BCLP_VALID)) - return ASLC_BACKLIGHT_FAILED; + return ASLE_BACKLIGHT_FAILED; bclp &= ASLE_BCLP_MSK; if (bclp > 255) - return ASLC_BACKLIGHT_FAILED; - - mutex_lock(&dev->mode_config.mutex); - /* - * Could match the OpRegion connector here instead, but we'd also need - * to verify the connector could handle a backlight call. - */ - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) - if (encoder->crtc == crtc) { - found = true; - break; - } - - if (!found) { - ret = ASLC_BACKLIGHT_FAILED; - goto out; - } - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) - if (connector->encoder == encoder) - intel_connector = to_intel_connector(connector); - - if (!intel_connector) { - ret = ASLC_BACKLIGHT_FAILED; - goto out; - } + return ASLE_BACKLIGHT_FAILED; - DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp); - intel_panel_set_backlight(intel_connector, bclp, 255); + intel_panel_set_backlight(dev, bclp, 255); iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv); -out: - mutex_unlock(&dev->mode_config.mutex); - - return ret; + return 0; } static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi) @@ -453,13 +183,13 @@ static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi) /* alsi is the current ALS reading in lux. 0 indicates below sensor range, 0xffff indicates above sensor range. 1-0xfffe are valid */ DRM_DEBUG_DRIVER("Illum is not supported\n"); - return ASLC_ALS_ILLUM_FAILED; + return ASLE_ALS_ILLUM_FAILED; } static u32 asle_set_pwm_freq(struct drm_device *dev, u32 pfmb) { DRM_DEBUG_DRIVER("PWM freq is not supported\n"); - return ASLC_PWM_FREQ_FAILED; + return ASLE_PWM_FREQ_FAILED; } static u32 asle_set_pfit(struct drm_device *dev, u32 pfit) @@ -467,118 +197,39 @@ static u32 asle_set_pfit(struct drm_device *dev, u32 pfit) /* Panel fitting is currently controlled by the X code, so this is a noop until modesetting support works fully */ DRM_DEBUG_DRIVER("Pfit is not supported\n"); - return ASLC_PFIT_FAILED; -} - -static u32 asle_set_supported_rotation_angles(struct drm_device *dev, u32 srot) -{ - DRM_DEBUG_DRIVER("SROT is not supported\n"); - return ASLC_ROTATION_ANGLES_FAILED; -} - -static u32 asle_set_button_array(struct drm_device *dev, u32 iuer) -{ - if (!iuer) - DRM_DEBUG_DRIVER("Button array event is not supported (nothing)\n"); - if (iuer & ASLE_IUER_ROTATION_LOCK_BTN) - DRM_DEBUG_DRIVER("Button array event is not supported (rotation lock)\n"); - if (iuer & ASLE_IUER_VOLUME_DOWN_BTN) - DRM_DEBUG_DRIVER("Button array event is not supported (volume down)\n"); - if (iuer & ASLE_IUER_VOLUME_UP_BTN) - DRM_DEBUG_DRIVER("Button array event is not supported (volume up)\n"); - if (iuer & ASLE_IUER_WINDOWS_BTN) - DRM_DEBUG_DRIVER("Button array event is not supported (windows)\n"); - if (iuer & ASLE_IUER_POWER_BTN) - DRM_DEBUG_DRIVER("Button array event is not supported (power)\n"); - - return ASLC_BUTTON_ARRAY_FAILED; -} - -static u32 asle_set_convertible(struct drm_device *dev, u32 iuer) -{ - if (iuer & ASLE_IUER_CONVERTIBLE) - DRM_DEBUG_DRIVER("Convertible is not supported (clamshell)\n"); - else - DRM_DEBUG_DRIVER("Convertible is not supported (slate)\n"); - - return ASLC_CONVERTIBLE_FAILED; + return ASLE_PFIT_FAILED; } -static u32 asle_set_docking(struct drm_device *dev, u32 iuer) -{ - if (iuer & ASLE_IUER_DOCKING) - DRM_DEBUG_DRIVER("Docking is not supported (docked)\n"); - else - DRM_DEBUG_DRIVER("Docking is not supported (undocked)\n"); - - return ASLC_DOCKING_FAILED; -} - -static u32 asle_isct_state(struct drm_device *dev) -{ - DRM_DEBUG_DRIVER("ISCT is not supported\n"); - return ASLC_ISCT_STATE_FAILED; -} - -static void asle_work(struct work_struct *work) +void intel_opregion_asle_intr(struct drm_device *dev) { - struct intel_opregion *opregion = - container_of(work, struct intel_opregion, asle_work); - struct drm_i915_private *dev_priv = - container_of(opregion, struct drm_i915_private, opregion); - struct drm_device *dev = dev_priv->dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct opregion_asle __iomem *asle = dev_priv->opregion.asle; - u32 aslc_stat = 0; - u32 aslc_req; + u32 asle_stat = 0; + u32 asle_req; if (!asle) return; - aslc_req = ioread32(&asle->aslc); + asle_req = ioread32(&asle->aslc) & ASLE_REQ_MSK; - if (!(aslc_req & ASLC_REQ_MSK)) { - DRM_DEBUG_DRIVER("No request on ASLC interrupt 0x%08x\n", - aslc_req); + if (!asle_req) { + DRM_DEBUG_DRIVER("non asle set request??\n"); return; } - if (aslc_req & ASLC_SET_ALS_ILLUM) - aslc_stat |= asle_set_als_illum(dev, ioread32(&asle->alsi)); - - if (aslc_req & ASLC_SET_BACKLIGHT) - aslc_stat |= asle_set_backlight(dev, ioread32(&asle->bclp)); - - if (aslc_req & ASLC_SET_PFIT) - aslc_stat |= asle_set_pfit(dev, ioread32(&asle->pfit)); - - if (aslc_req & ASLC_SET_PWM_FREQ) - aslc_stat |= asle_set_pwm_freq(dev, ioread32(&asle->pfmb)); + if (asle_req & ASLE_SET_ALS_ILLUM) + asle_stat |= asle_set_als_illum(dev, ioread32(&asle->alsi)); - if (aslc_req & ASLC_SUPPORTED_ROTATION_ANGLES) - aslc_stat |= asle_set_supported_rotation_angles(dev, - ioread32(&asle->srot)); + if (asle_req & ASLE_SET_BACKLIGHT) + asle_stat |= asle_set_backlight(dev, ioread32(&asle->bclp)); - if (aslc_req & ASLC_BUTTON_ARRAY) - aslc_stat |= asle_set_button_array(dev, ioread32(&asle->iuer)); + if (asle_req & ASLE_SET_PFIT) + asle_stat |= asle_set_pfit(dev, ioread32(&asle->pfit)); - if (aslc_req & ASLC_CONVERTIBLE_INDICATOR) - aslc_stat |= asle_set_convertible(dev, ioread32(&asle->iuer)); + if (asle_req & ASLE_SET_PWM_FREQ) + asle_stat |= asle_set_pwm_freq(dev, ioread32(&asle->pfmb)); - if (aslc_req & ASLC_DOCKING_INDICATOR) - aslc_stat |= asle_set_docking(dev, ioread32(&asle->iuer)); - - if (aslc_req & ASLC_ISCT_STATE_CHANGE) - aslc_stat |= asle_isct_state(dev); - - iowrite32(aslc_stat, &asle->aslc); -} - -void intel_opregion_asle_intr(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (dev_priv->opregion.asle) - schedule_work(&dev_priv->opregion.asle_work); + iowrite32(asle_stat, &asle->aslc); } #define ACPI_EV_DISPLAY_SWITCH (1<<0) @@ -638,7 +289,7 @@ static void intel_didl_outputs(struct drm_device *dev) u32 temp; int i = 0; - handle = ACPI_HANDLE(&dev->pdev->dev); + handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev); if (!handle || acpi_bus_get_device(handle, &acpi_dev)) return; @@ -781,8 +432,6 @@ void intel_opregion_fini(struct drm_device *dev) if (opregion->asle) iowrite32(ASLE_ARDY_NOT_READY, &opregion->asle->ardy); - cancel_work_sync(&dev_priv->opregion.asle_work); - if (opregion->acpi) { iowrite32(0, &opregion->acpi->drdy); @@ -797,68 +446,8 @@ void intel_opregion_fini(struct drm_device *dev) opregion->swsci = NULL; opregion->asle = NULL; opregion->vbt = NULL; - opregion->lid_state = NULL; } - -static void swsci_setup(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_opregion *opregion = &dev_priv->opregion; - bool requested_callbacks = false; - u32 tmp; - - /* Sub-function code 0 is okay, let's allow them. */ - opregion->swsci_gbda_sub_functions = 1; - opregion->swsci_sbcb_sub_functions = 1; - - /* We use GBDA to ask for supported GBDA calls. */ - if (swsci(dev, SWSCI_GBDA_SUPPORTED_CALLS, 0, &tmp) == 0) { - /* make the bits match the sub-function codes */ - tmp <<= 1; - opregion->swsci_gbda_sub_functions |= tmp; - } - - /* - * We also use GBDA to ask for _requested_ SBCB callbacks. The driver - * must not call interfaces that are not specifically requested by the - * bios. - */ - if (swsci(dev, SWSCI_GBDA_REQUESTED_CALLBACKS, 0, &tmp) == 0) { - /* here, the bits already match sub-function codes */ - opregion->swsci_sbcb_sub_functions |= tmp; - requested_callbacks = true; - } - - /* - * But we use SBCB to ask for _supported_ SBCB calls. This does not mean - * the callback is _requested_. But we still can't call interfaces that - * are not requested. - */ - if (swsci(dev, SWSCI_SBCB_SUPPORTED_CALLBACKS, 0, &tmp) == 0) { - /* make the bits match the sub-function codes */ - u32 low = tmp & 0x7ff; - u32 high = tmp & ~0xfff; /* bit 11 is reserved */ - tmp = (high << 4) | (low << 1) | 1; - - /* best guess what to do with supported wrt requested */ - if (requested_callbacks) { - u32 req = opregion->swsci_sbcb_sub_functions; - if ((req & tmp) != req) - DRM_DEBUG_DRIVER("SWSCI BIOS requested (%08x) SBCB callbacks that are not supported (%08x)\n", req, tmp); - /* XXX: for now, trust the requested callbacks */ - /* opregion->swsci_sbcb_sub_functions &= tmp; */ - } else { - opregion->swsci_sbcb_sub_functions |= tmp; - } - } - - DRM_DEBUG_DRIVER("SWSCI GBDA callbacks %08x, SBCB callbacks %08x\n", - opregion->swsci_gbda_sub_functions, - opregion->swsci_sbcb_sub_functions); -} -#else /* CONFIG_ACPI */ -static inline void swsci_setup(struct drm_device *dev) {} -#endif /* CONFIG_ACPI */ +#endif int intel_opregion_setup(struct drm_device *dev) { @@ -876,10 +465,6 @@ int intel_opregion_setup(struct drm_device *dev) return -ENOTSUPP; } -#ifdef CONFIG_ACPI - INIT_WORK(&opregion->asle_work, asle_work); -#endif - base = acpi_os_ioremap(asls, OPREGION_SIZE); if (!base) return -ENOMEM; @@ -905,7 +490,6 @@ int intel_opregion_setup(struct drm_device *dev) if (mboxes & MBOX_SWSCI) { DRM_DEBUG_DRIVER("SWSCI supported\n"); opregion->swsci = base + OPREGION_SWSCI_OFFSET; - swsci_setup(dev); } if (mboxes & MBOX_ASLE) { DRM_DEBUG_DRIVER("ASLE supported\n"); diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index a98a990..ddfd0ae 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -821,11 +821,14 @@ int intel_overlay_switch_off(struct intel_overlay *overlay) static int check_overlay_possible_on_crtc(struct intel_overlay *overlay, struct intel_crtc *crtc) { + drm_i915_private_t *dev_priv = overlay->dev->dev_private; + if (!crtc->active) return -EINVAL; /* can't use the overlay with double wide pipe */ - if (crtc->config.double_wide) + if (INTEL_INFO(overlay->dev)->gen < 4 && + (I915_READ(PIPECONF(crtc->pipe)) & (PIPECONF_DOUBLE_WIDE | PIPECONF_ENABLE)) != PIPECONF_ENABLE) return -EINVAL; return 0; @@ -1053,7 +1056,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, return ret; } - params = kmalloc(sizeof(*params), GFP_KERNEL); + params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL); if (!params) return -ENOMEM; @@ -1320,7 +1323,7 @@ void intel_setup_overlay(struct drm_device *dev) if (!HAS_OVERLAY(dev)) return; - overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); + overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL); if (!overlay) return; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index f161ac0..293564a 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -50,22 +50,23 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc, struct intel_crtc_config *pipe_config, int fitting_mode) { - struct drm_display_mode *adjusted_mode; + struct drm_display_mode *mode, *adjusted_mode; int x, y, width, height; + mode = &pipe_config->requested_mode; adjusted_mode = &pipe_config->adjusted_mode; x = y = width = height = 0; /* Native modes don't need fitting */ - if (adjusted_mode->hdisplay == pipe_config->pipe_src_w && - adjusted_mode->vdisplay == pipe_config->pipe_src_h) + if (adjusted_mode->hdisplay == mode->hdisplay && + adjusted_mode->vdisplay == mode->vdisplay) goto done; switch (fitting_mode) { case DRM_MODE_SCALE_CENTER: - width = pipe_config->pipe_src_w; - height = pipe_config->pipe_src_h; + width = mode->hdisplay; + height = mode->vdisplay; x = (adjusted_mode->hdisplay - width + 1)/2; y = (adjusted_mode->vdisplay - height + 1)/2; break; @@ -73,19 +74,17 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc, case DRM_MODE_SCALE_ASPECT: /* Scale but preserve the aspect ratio */ { - u32 scaled_width = adjusted_mode->hdisplay - * pipe_config->pipe_src_h; - u32 scaled_height = pipe_config->pipe_src_w - * adjusted_mode->vdisplay; + u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay; + u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay; if (scaled_width > scaled_height) { /* pillar */ - width = scaled_height / pipe_config->pipe_src_h; + width = scaled_height / mode->vdisplay; if (width & 1) width++; x = (adjusted_mode->hdisplay - width + 1) / 2; y = 0; height = adjusted_mode->vdisplay; } else if (scaled_width < scaled_height) { /* letter */ - height = scaled_width / pipe_config->pipe_src_w; + height = scaled_width / mode->hdisplay; if (height & 1) height++; y = (adjusted_mode->vdisplay - height + 1) / 2; @@ -172,96 +171,20 @@ static inline u32 panel_fitter_scaling(u32 source, u32 target) return (FACTOR * ratio + FACTOR/2) / FACTOR; } -static void i965_scale_aspect(struct intel_crtc_config *pipe_config, - u32 *pfit_control) -{ - struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; - u32 scaled_width = adjusted_mode->hdisplay * - pipe_config->pipe_src_h; - u32 scaled_height = pipe_config->pipe_src_w * - adjusted_mode->vdisplay; - - /* 965+ is easy, it does everything in hw */ - if (scaled_width > scaled_height) - *pfit_control |= PFIT_ENABLE | - PFIT_SCALING_PILLAR; - else if (scaled_width < scaled_height) - *pfit_control |= PFIT_ENABLE | - PFIT_SCALING_LETTER; - else if (adjusted_mode->hdisplay != pipe_config->pipe_src_w) - *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; -} - -static void i9xx_scale_aspect(struct intel_crtc_config *pipe_config, - u32 *pfit_control, u32 *pfit_pgm_ratios, - u32 *border) -{ - struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; - u32 scaled_width = adjusted_mode->hdisplay * - pipe_config->pipe_src_h; - u32 scaled_height = pipe_config->pipe_src_w * - adjusted_mode->vdisplay; - u32 bits; - - /* - * For earlier chips we have to calculate the scaling - * ratio by hand and program it into the - * PFIT_PGM_RATIO register - */ - if (scaled_width > scaled_height) { /* pillar */ - centre_horizontally(adjusted_mode, - scaled_height / - pipe_config->pipe_src_h); - - *border = LVDS_BORDER_ENABLE; - if (pipe_config->pipe_src_h != adjusted_mode->vdisplay) { - bits = panel_fitter_scaling(pipe_config->pipe_src_h, - adjusted_mode->vdisplay); - - *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | - bits << PFIT_VERT_SCALE_SHIFT); - *pfit_control |= (PFIT_ENABLE | - VERT_INTERP_BILINEAR | - HORIZ_INTERP_BILINEAR); - } - } else if (scaled_width < scaled_height) { /* letter */ - centre_vertically(adjusted_mode, - scaled_width / - pipe_config->pipe_src_w); - - *border = LVDS_BORDER_ENABLE; - if (pipe_config->pipe_src_w != adjusted_mode->hdisplay) { - bits = panel_fitter_scaling(pipe_config->pipe_src_w, - adjusted_mode->hdisplay); - - *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | - bits << PFIT_VERT_SCALE_SHIFT); - *pfit_control |= (PFIT_ENABLE | - VERT_INTERP_BILINEAR | - HORIZ_INTERP_BILINEAR); - } - } else { - /* Aspects match, Let hw scale both directions */ - *pfit_control |= (PFIT_ENABLE | - VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | - VERT_INTERP_BILINEAR | - HORIZ_INTERP_BILINEAR); - } -} - void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, struct intel_crtc_config *pipe_config, int fitting_mode) { struct drm_device *dev = intel_crtc->base.dev; u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; - struct drm_display_mode *adjusted_mode; + struct drm_display_mode *mode, *adjusted_mode; + mode = &pipe_config->requested_mode; adjusted_mode = &pipe_config->adjusted_mode; /* Native modes don't need fitting */ - if (adjusted_mode->hdisplay == pipe_config->pipe_src_w && - adjusted_mode->vdisplay == pipe_config->pipe_src_h) + if (adjusted_mode->hdisplay == mode->hdisplay && + adjusted_mode->vdisplay == mode->vdisplay) goto out; switch (fitting_mode) { @@ -270,25 +193,81 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, * For centered modes, we have to calculate border widths & * heights and modify the values programmed into the CRTC. */ - centre_horizontally(adjusted_mode, pipe_config->pipe_src_w); - centre_vertically(adjusted_mode, pipe_config->pipe_src_h); + centre_horizontally(adjusted_mode, mode->hdisplay); + centre_vertically(adjusted_mode, mode->vdisplay); border = LVDS_BORDER_ENABLE; break; case DRM_MODE_SCALE_ASPECT: /* Scale but preserve the aspect ratio */ - if (INTEL_INFO(dev)->gen >= 4) - i965_scale_aspect(pipe_config, &pfit_control); - else - i9xx_scale_aspect(pipe_config, &pfit_control, - &pfit_pgm_ratios, &border); + if (INTEL_INFO(dev)->gen >= 4) { + u32 scaled_width = adjusted_mode->hdisplay * + mode->vdisplay; + u32 scaled_height = mode->hdisplay * + adjusted_mode->vdisplay; + + /* 965+ is easy, it does everything in hw */ + if (scaled_width > scaled_height) + pfit_control |= PFIT_ENABLE | + PFIT_SCALING_PILLAR; + else if (scaled_width < scaled_height) + pfit_control |= PFIT_ENABLE | + PFIT_SCALING_LETTER; + else if (adjusted_mode->hdisplay != mode->hdisplay) + pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; + } else { + u32 scaled_width = adjusted_mode->hdisplay * + mode->vdisplay; + u32 scaled_height = mode->hdisplay * + adjusted_mode->vdisplay; + /* + * For earlier chips we have to calculate the scaling + * ratio by hand and program it into the + * PFIT_PGM_RATIO register + */ + if (scaled_width > scaled_height) { /* pillar */ + centre_horizontally(adjusted_mode, + scaled_height / + mode->vdisplay); + + border = LVDS_BORDER_ENABLE; + if (mode->vdisplay != adjusted_mode->vdisplay) { + u32 bits = panel_fitter_scaling(mode->vdisplay, adjusted_mode->vdisplay); + pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | + bits << PFIT_VERT_SCALE_SHIFT); + pfit_control |= (PFIT_ENABLE | + VERT_INTERP_BILINEAR | + HORIZ_INTERP_BILINEAR); + } + } else if (scaled_width < scaled_height) { /* letter */ + centre_vertically(adjusted_mode, + scaled_width / + mode->hdisplay); + + border = LVDS_BORDER_ENABLE; + if (mode->hdisplay != adjusted_mode->hdisplay) { + u32 bits = panel_fitter_scaling(mode->hdisplay, adjusted_mode->hdisplay); + pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | + bits << PFIT_VERT_SCALE_SHIFT); + pfit_control |= (PFIT_ENABLE | + VERT_INTERP_BILINEAR | + HORIZ_INTERP_BILINEAR); + } + } else { + /* Aspects match, Let hw scale both directions */ + pfit_control |= (PFIT_ENABLE | + VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | + VERT_INTERP_BILINEAR | + HORIZ_INTERP_BILINEAR); + } + } break; case DRM_MODE_SCALE_FULLSCREEN: /* * Full scaling, even if it changes the aspect ratio. * Fortunately this is all done for us in hw. */ - if (pipe_config->pipe_src_h != adjusted_mode->vdisplay || - pipe_config->pipe_src_w != adjusted_mode->hdisplay) { + if (mode->vdisplay != adjusted_mode->vdisplay || + mode->hdisplay != adjusted_mode->hdisplay) { pfit_control |= PFIT_ENABLE; if (INTEL_INFO(dev)->gen >= 4) pfit_control |= PFIT_SCALING_AUTO; @@ -329,7 +308,7 @@ static int is_backlight_combination_mode(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - if (IS_GEN4(dev)) + if (INTEL_INFO(dev)->gen >= 4) return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE; if (IS_GEN2(dev)) @@ -341,7 +320,7 @@ static int is_backlight_combination_mode(struct drm_device *dev) /* XXX: query mode clock or hardware clock and program max PWM appropriately * when it's 0. */ -static u32 i915_read_blc_pwm_ctl(struct drm_device *dev, enum pipe pipe) +static u32 i915_read_blc_pwm_ctl(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 val; @@ -358,21 +337,6 @@ static u32 i915_read_blc_pwm_ctl(struct drm_device *dev, enum pipe pipe) val = dev_priv->regfile.saveBLC_PWM_CTL2; I915_WRITE(BLC_PWM_PCH_CTL2, val); } - } else if (IS_VALLEYVIEW(dev)) { - val = I915_READ(VLV_BLC_PWM_CTL(pipe)); - if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { - dev_priv->regfile.saveBLC_PWM_CTL = val; - dev_priv->regfile.saveBLC_PWM_CTL2 = - I915_READ(VLV_BLC_PWM_CTL2(pipe)); - } else if (val == 0) { - val = dev_priv->regfile.saveBLC_PWM_CTL; - I915_WRITE(VLV_BLC_PWM_CTL(pipe), val); - I915_WRITE(VLV_BLC_PWM_CTL2(pipe), - dev_priv->regfile.saveBLC_PWM_CTL2); - } - - if (!val) - val = 0x0f42ffff; } else { val = I915_READ(BLC_PWM_CTL); if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { @@ -392,12 +356,11 @@ static u32 i915_read_blc_pwm_ctl(struct drm_device *dev, enum pipe pipe) return val; } -static u32 intel_panel_get_max_backlight(struct drm_device *dev, - enum pipe pipe) +static u32 intel_panel_get_max_backlight(struct drm_device *dev) { u32 max; - max = i915_read_blc_pwm_ctl(dev, pipe); + max = i915_read_blc_pwm_ctl(dev); if (HAS_PCH_SPLIT(dev)) { max >>= 16; @@ -423,8 +386,7 @@ MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " "to dri-devel@lists.freedesktop.org, if your machine needs it. " "It will then be included in an upcoming module version."); module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600); -static u32 intel_panel_compute_brightness(struct drm_device *dev, - enum pipe pipe, u32 val) +static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -433,7 +395,7 @@ static u32 intel_panel_compute_brightness(struct drm_device *dev, if (i915_panel_invert_brightness > 0 || dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { - u32 max = intel_panel_get_max_backlight(dev, pipe); + u32 max = intel_panel_get_max_backlight(dev); if (max) return max - val; } @@ -441,25 +403,18 @@ static u32 intel_panel_compute_brightness(struct drm_device *dev, return val; } -static u32 intel_panel_get_backlight(struct drm_device *dev, - enum pipe pipe) +static u32 intel_panel_get_backlight(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 val; unsigned long flags; - int reg; spin_lock_irqsave(&dev_priv->backlight.lock, flags); if (HAS_PCH_SPLIT(dev)) { val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; } else { - if (IS_VALLEYVIEW(dev)) - reg = VLV_BLC_PWM_CTL(pipe); - else - reg = BLC_PWM_CTL; - - val = I915_READ(reg) & BACKLIGHT_DUTY_CYCLE_MASK; + val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; if (INTEL_INFO(dev)->gen < 4) val >>= 1; @@ -471,7 +426,7 @@ static u32 intel_panel_get_backlight(struct drm_device *dev, } } - val = intel_panel_compute_brightness(dev, pipe, val); + val = intel_panel_compute_brightness(dev, val); spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); @@ -486,21 +441,19 @@ static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level) I915_WRITE(BLC_PWM_CPU_CTL, val | level); } -static void intel_panel_actually_set_backlight(struct drm_device *dev, - enum pipe pipe, 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; - int reg; DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); - level = intel_panel_compute_brightness(dev, pipe, level); + level = intel_panel_compute_brightness(dev, level); if (HAS_PCH_SPLIT(dev)) return intel_pch_panel_set_backlight(dev, level); if (is_backlight_combination_mode(dev)) { - u32 max = intel_panel_get_max_backlight(dev, pipe); + u32 max = intel_panel_get_max_backlight(dev); u8 lbpc; /* we're screwed, but keep behaviour backwards compatible */ @@ -512,34 +465,23 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc); } - if (IS_VALLEYVIEW(dev)) - reg = VLV_BLC_PWM_CTL(pipe); - else - reg = BLC_PWM_CTL; - - tmp = I915_READ(reg); + tmp = I915_READ(BLC_PWM_CTL); if (INTEL_INFO(dev)->gen < 4) level <<= 1; tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK; - I915_WRITE(reg, tmp | level); + I915_WRITE(BLC_PWM_CTL, tmp | level); } /* set backlight brightness to level in range [0..max] */ -void intel_panel_set_backlight(struct intel_connector *connector, u32 level, - u32 max) +void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max) { - struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - enum pipe pipe = intel_get_pipe_from_connector(connector); u32 freq; unsigned long flags; - if (pipe == INVALID_PIPE) - return; - spin_lock_irqsave(&dev_priv->backlight.lock, flags); - freq = intel_panel_get_max_backlight(dev, pipe); + freq = intel_panel_get_max_backlight(dev); if (!freq) { /* we are screwed, bail out */ goto out; @@ -556,21 +498,16 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level, dev_priv->backlight.device->props.brightness = level; if (dev_priv->backlight.enabled) - intel_panel_actually_set_backlight(dev, pipe, level); + intel_panel_actually_set_backlight(dev, level); out: spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); } -void intel_panel_disable_backlight(struct intel_connector *connector) +void intel_panel_disable_backlight(struct drm_device *dev) { - struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - enum pipe pipe = intel_get_pipe_from_connector(connector); unsigned long flags; - if (pipe == INVALID_PIPE) - return; - /* * Do not disable backlight on the vgaswitcheroo path. When switching * away from i915, the other client may depend on i915 to handle the @@ -585,17 +522,12 @@ void intel_panel_disable_backlight(struct intel_connector *connector) spin_lock_irqsave(&dev_priv->backlight.lock, flags); dev_priv->backlight.enabled = false; - intel_panel_actually_set_backlight(dev, pipe, 0); + intel_panel_actually_set_backlight(dev, 0); if (INTEL_INFO(dev)->gen >= 4) { uint32_t reg, tmp; - if (HAS_PCH_SPLIT(dev)) - reg = BLC_PWM_CPU_CTL2; - else if (IS_VALLEYVIEW(dev)) - reg = VLV_BLC_PWM_CTL2(pipe); - else - reg = BLC_PWM_CTL2; + reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE); @@ -609,25 +541,18 @@ void intel_panel_disable_backlight(struct intel_connector *connector) spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); } -void intel_panel_enable_backlight(struct intel_connector *connector) +void intel_panel_enable_backlight(struct drm_device *dev, + enum pipe pipe) { - struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - enum pipe pipe = intel_get_pipe_from_connector(connector); enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, pipe); unsigned long flags; - if (pipe == INVALID_PIPE) - return; - - DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); - spin_lock_irqsave(&dev_priv->backlight.lock, flags); if (dev_priv->backlight.level == 0) { - dev_priv->backlight.level = intel_panel_get_max_backlight(dev, - pipe); + dev_priv->backlight.level = intel_panel_get_max_backlight(dev); if (dev_priv->backlight.device) dev_priv->backlight.device->props.brightness = dev_priv->backlight.level; @@ -636,12 +561,8 @@ void intel_panel_enable_backlight(struct intel_connector *connector) if (INTEL_INFO(dev)->gen >= 4) { uint32_t reg, tmp; - if (HAS_PCH_SPLIT(dev)) - reg = BLC_PWM_CPU_CTL2; - else if (IS_VALLEYVIEW(dev)) - reg = VLV_BLC_PWM_CTL2(pipe); - else - reg = BLC_PWM_CTL2; + reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; + tmp = I915_READ(reg); @@ -681,41 +602,16 @@ set_level: * registers are set. */ dev_priv->backlight.enabled = true; - intel_panel_actually_set_backlight(dev, pipe, - dev_priv->backlight.level); + intel_panel_actually_set_backlight(dev, dev_priv->backlight.level); spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); } -/* FIXME: use VBT vals to init PWM_CTL and PWM_CTL2 correctly */ -static void intel_panel_init_backlight_regs(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (IS_VALLEYVIEW(dev)) { - enum pipe pipe; - - for_each_pipe(pipe) { - u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe)); - - /* Skip if the modulation freq is already set */ - if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK) - continue; - - cur_val &= BACKLIGHT_DUTY_CYCLE_MASK; - I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) | - cur_val); - } - } -} - static void intel_panel_init_backlight(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - intel_panel_init_backlight_regs(dev); - - dev_priv->backlight.level = intel_panel_get_backlight(dev, 0); + dev_priv->backlight.level = intel_panel_get_backlight(dev); dev_priv->backlight.enabled = dev_priv->backlight.level != 0; } @@ -741,34 +637,19 @@ intel_panel_detect(struct drm_device *dev) } } -#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE static int intel_panel_update_status(struct backlight_device *bd) { - struct intel_connector *connector = bl_get_data(bd); - struct drm_device *dev = connector->base.dev; - - mutex_lock(&dev->mode_config.mutex); - DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n", - bd->props.brightness, bd->props.max_brightness); - intel_panel_set_backlight(connector, bd->props.brightness, + struct drm_device *dev = bl_get_data(bd); + intel_panel_set_backlight(dev, bd->props.brightness, bd->props.max_brightness); - mutex_unlock(&dev->mode_config.mutex); return 0; } static int intel_panel_get_brightness(struct backlight_device *bd) { - struct intel_connector *connector = bl_get_data(bd); - struct drm_device *dev = connector->base.dev; - enum pipe pipe; - - mutex_lock(&dev->mode_config.mutex); - pipe = intel_get_pipe_from_connector(connector); - mutex_unlock(&dev->mode_config.mutex); - if (pipe == INVALID_PIPE) - return 0; - - return intel_panel_get_backlight(connector->base.dev, pipe); + struct drm_device *dev = bl_get_data(bd); + return intel_panel_get_backlight(dev); } static const struct backlight_ops intel_panel_bl_ops = { @@ -793,7 +674,7 @@ int intel_panel_setup_backlight(struct drm_connector *connector) props.brightness = dev_priv->backlight.level; spin_lock_irqsave(&dev_priv->backlight.lock, flags); - props.max_brightness = intel_panel_get_max_backlight(dev, 0); + props.max_brightness = intel_panel_get_max_backlight(dev); spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); if (props.max_brightness == 0) { @@ -802,8 +683,7 @@ int intel_panel_setup_backlight(struct drm_connector *connector) } dev_priv->backlight.device = backlight_device_register("intel_backlight", - connector->kdev, - to_intel_connector(connector), + &connector->kdev, dev, &intel_panel_bl_ops, &props); if (IS_ERR(dev_priv->backlight.device)) { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6e0d5e0..26c2ea3 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -32,27 +32,6 @@ #include <linux/module.h> #include <drm/i915_powerwell.h> -/** - * RC6 is a special power stage which allows the GPU to enter an very - * low-voltage mode when idle, using down to 0V while at this stage. This - * stage is entered automatically when the GPU is idle when RC6 support is - * enabled, and as soon as new workload arises GPU wakes up automatically as well. - * - * There are different RC6 modes available in Intel GPU, which differentiate - * among each other with the latency required to enter and leave RC6 and - * voltage consumed by the GPU in different states. - * - * The combination of the following flags define which states GPU is allowed - * to enter, while RC6 is the normal RC6 state, RC6p is the deep RC6, and - * RC6pp is deepest RC6. Their support by hardware varies according to the - * GPU, BIOS, chipset and platform. RC6 is usually the safest one and the one - * which brings the most power savings; deeper states save more power, but - * require higher latency to switch to and wake up. - */ -#define INTEL_RC6_ENABLE (1<<0) -#define INTEL_RC6p_ENABLE (1<<1) -#define INTEL_RC6pp_ENABLE (1<<2) - /* FBC, or Frame Buffer Compression, is a technique employed to compress the * framebuffer contents in-memory, aiming at reducing the required bandwidth * during in-memory transfers and, therefore, reduce the power packet. @@ -64,6 +43,14 @@ * i915.i915_enable_fbc parameter */ +static bool intel_crtc_active(struct drm_crtc *crtc) +{ + /* Be paranoid as we can arrive here with only partial + * state retrieved from the hardware during setup. + */ + return to_intel_crtc(crtc)->active && crtc->fb && crtc->mode.clock; +} + static void i8xx_disable_fbc(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -254,6 +241,18 @@ static void ironlake_disable_fbc(struct drm_device *dev) dpfc_ctl &= ~DPFC_CTL_EN; I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); + if (IS_IVYBRIDGE(dev)) + /* WaFbcDisableDpfcClockGating:ivb */ + I915_WRITE(ILK_DSPCLK_GATE_D, + I915_READ(ILK_DSPCLK_GATE_D) & + ~ILK_DPFCUNIT_CLOCK_GATE_DISABLE); + + if (IS_HASWELL(dev)) + /* WaFbcDisableDpfcClockGating:hsw */ + I915_WRITE(HSW_CLKGATE_DISABLE_PART_1, + I915_READ(HSW_CLKGATE_DISABLE_PART_1) & + ~HSW_DPFC_GATING_DISABLE); + DRM_DEBUG_KMS("disabled FBC\n"); } } @@ -283,10 +282,18 @@ static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval) if (IS_IVYBRIDGE(dev)) { /* WaFbcAsynchFlipDisableFbcQueue:ivb */ I915_WRITE(ILK_DISPLAY_CHICKEN1, ILK_FBCQ_DIS); + /* WaFbcDisableDpfcClockGating:ivb */ + I915_WRITE(ILK_DSPCLK_GATE_D, + I915_READ(ILK_DSPCLK_GATE_D) | + ILK_DPFCUNIT_CLOCK_GATE_DISABLE); } else { /* WaFbcAsynchFlipDisableFbcQueue:hsw */ I915_WRITE(HSW_PIPE_SLICE_CHICKEN_1(intel_crtc->pipe), HSW_BYPASS_FBC_QUEUE); + /* WaFbcDisableDpfcClockGating:hsw */ + I915_WRITE(HSW_CLKGATE_DISABLE_PART_1, + I915_READ(HSW_CLKGATE_DISABLE_PART_1) | + HSW_DPFC_GATING_DISABLE); } I915_WRITE(SNB_DPFC_CTL_SA, @@ -371,7 +378,7 @@ static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval) intel_cancel_fbc_work(dev_priv); - work = kzalloc(sizeof(*work), GFP_KERNEL); + work = kzalloc(sizeof *work, GFP_KERNEL); if (work == NULL) { DRM_ERROR("Failed to allocate FBC work structure\n"); dev_priv->display.enable_fbc(crtc, interval); @@ -451,8 +458,7 @@ void intel_update_fbc(struct drm_device *dev) struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; struct drm_i915_gem_object *obj; - const struct drm_display_mode *adjusted_mode; - unsigned int max_width, max_height; + unsigned int max_hdisplay, max_vdisplay; if (!I915_HAS_FBC(dev)) { set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED); @@ -476,7 +482,7 @@ void intel_update_fbc(struct drm_device *dev) */ list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { if (intel_crtc_active(tmp_crtc) && - to_intel_crtc(tmp_crtc)->primary_enabled) { + !to_intel_crtc(tmp_crtc)->primary_disabled) { if (crtc) { if (set_no_fbc_reason(dev_priv, FBC_MULTIPLE_PIPES)) DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); @@ -496,7 +502,6 @@ void intel_update_fbc(struct drm_device *dev) fb = crtc->fb; intel_fb = to_intel_framebuffer(fb); obj = intel_fb->obj; - adjusted_mode = &intel_crtc->config.adjusted_mode; if (i915_enable_fbc < 0 && INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev)) { @@ -509,8 +514,8 @@ void intel_update_fbc(struct drm_device *dev) DRM_DEBUG_KMS("fbc disabled per module param\n"); goto out_disable; } - if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) || - (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) { + if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) || + (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) { if (set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED_MODE)) DRM_DEBUG_KMS("mode incompatible with compression, " "disabling\n"); @@ -518,14 +523,14 @@ void intel_update_fbc(struct drm_device *dev) } if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { - max_width = 4096; - max_height = 2048; + max_hdisplay = 4096; + max_vdisplay = 2048; } else { - max_width = 2048; - max_height = 1536; + max_hdisplay = 2048; + max_vdisplay = 1536; } - if (intel_crtc->config.pipe_src_w > max_width || - intel_crtc->config.pipe_src_h > max_height) { + if ((crtc->mode.hdisplay > max_hdisplay) || + (crtc->mode.vdisplay > max_vdisplay)) { if (set_no_fbc_reason(dev_priv, FBC_MODE_TOO_LARGE)) DRM_DEBUG_KMS("mode too large for compression, disabling\n"); goto out_disable; @@ -1082,9 +1087,8 @@ static struct drm_crtc *single_enabled_crtc(struct drm_device *dev) return enabled; } -static void pineview_update_wm(struct drm_crtc *unused_crtc) +static void pineview_update_wm(struct drm_device *dev) { - struct drm_device *dev = unused_crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; const struct cxsr_latency *latency; @@ -1101,12 +1105,8 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc) crtc = single_enabled_crtc(dev); if (crtc) { - const struct drm_display_mode *adjusted_mode; + int clock = crtc->mode.clock; int pixel_size = crtc->fb->bits_per_pixel / 8; - int clock; - - adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; - clock = adjusted_mode->crtc_clock; /* Display SR */ wm = intel_calculate_wm(clock, &pineview_display_wm, @@ -1166,7 +1166,6 @@ static bool g4x_compute_wm0(struct drm_device *dev, int *cursor_wm) { struct drm_crtc *crtc; - const struct drm_display_mode *adjusted_mode; int htotal, hdisplay, clock, pixel_size; int line_time_us, line_count; int entries, tlb_miss; @@ -1178,10 +1177,9 @@ static bool g4x_compute_wm0(struct drm_device *dev, return false; } - adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; - clock = adjusted_mode->crtc_clock; - htotal = adjusted_mode->crtc_htotal; - hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; + htotal = crtc->mode.htotal; + hdisplay = crtc->mode.hdisplay; + clock = crtc->mode.clock; pixel_size = crtc->fb->bits_per_pixel / 8; /* Use the small buffer method to calculate plane watermark */ @@ -1252,7 +1250,6 @@ static bool g4x_compute_srwm(struct drm_device *dev, int *display_wm, int *cursor_wm) { struct drm_crtc *crtc; - const struct drm_display_mode *adjusted_mode; int hdisplay, htotal, pixel_size, clock; unsigned long line_time_us; int line_count, line_size; @@ -1265,10 +1262,9 @@ static bool g4x_compute_srwm(struct drm_device *dev, } crtc = intel_get_crtc_for_plane(dev, plane); - adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; - clock = adjusted_mode->crtc_clock; - htotal = adjusted_mode->crtc_htotal; - hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; + hdisplay = crtc->mode.hdisplay; + htotal = crtc->mode.htotal; + clock = crtc->mode.clock; pixel_size = crtc->fb->bits_per_pixel / 8; line_time_us = (htotal * 1000) / clock; @@ -1307,7 +1303,7 @@ static bool vlv_compute_drain_latency(struct drm_device *dev, if (!intel_crtc_active(crtc)) return false; - clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; + clock = crtc->mode.clock; /* VESA DOT Clock */ pixel_size = crtc->fb->bits_per_pixel / 8; /* BPP */ entries = (clock / 1000) * pixel_size; @@ -1369,9 +1365,8 @@ static void vlv_update_drain_latency(struct drm_device *dev) #define single_plane_enabled(mask) is_power_of_2(mask) -static void valleyview_update_wm(struct drm_crtc *crtc) +static void valleyview_update_wm(struct drm_device *dev) { - struct drm_device *dev = crtc->dev; static const int sr_latency_ns = 12000; struct drm_i915_private *dev_priv = dev->dev_private; int planea_wm, planeb_wm, cursora_wm, cursorb_wm; @@ -1429,9 +1424,8 @@ static void valleyview_update_wm(struct drm_crtc *crtc) (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); } -static void g4x_update_wm(struct drm_crtc *crtc) +static void g4x_update_wm(struct drm_device *dev) { - struct drm_device *dev = crtc->dev; static const int sr_latency_ns = 12000; struct drm_i915_private *dev_priv = dev->dev_private; int planea_wm, planeb_wm, cursora_wm, cursorb_wm; @@ -1482,9 +1476,8 @@ static void g4x_update_wm(struct drm_crtc *crtc) (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); } -static void i965_update_wm(struct drm_crtc *unused_crtc) +static void i965_update_wm(struct drm_device *dev) { - struct drm_device *dev = unused_crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; int srwm = 1; @@ -1495,11 +1488,9 @@ static void i965_update_wm(struct drm_crtc *unused_crtc) if (crtc) { /* self-refresh has much higher latency */ static const int sr_latency_ns = 12000; - const struct drm_display_mode *adjusted_mode = - &to_intel_crtc(crtc)->config.adjusted_mode; - int clock = adjusted_mode->crtc_clock; - int htotal = adjusted_mode->crtc_htotal; - int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; + int clock = crtc->mode.clock; + int htotal = crtc->mode.htotal; + int hdisplay = crtc->mode.hdisplay; int pixel_size = crtc->fb->bits_per_pixel / 8; unsigned long line_time_us; int entries; @@ -1550,9 +1541,8 @@ static void i965_update_wm(struct drm_crtc *unused_crtc) I915_WRITE(DSPFW3, (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); } -static void i9xx_update_wm(struct drm_crtc *unused_crtc) +static void i9xx_update_wm(struct drm_device *dev) { - struct drm_device *dev = unused_crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; const struct intel_watermark_params *wm_info; uint32_t fwater_lo; @@ -1572,13 +1562,11 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) fifo_size = dev_priv->display.get_fifo_size(dev, 0); crtc = intel_get_crtc_for_plane(dev, 0); if (intel_crtc_active(crtc)) { - const struct drm_display_mode *adjusted_mode; int cpp = crtc->fb->bits_per_pixel / 8; if (IS_GEN2(dev)) cpp = 4; - adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; - planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock, + planea_wm = intel_calculate_wm(crtc->mode.clock, wm_info, fifo_size, cpp, latency_ns); enabled = crtc; @@ -1588,13 +1576,11 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) fifo_size = dev_priv->display.get_fifo_size(dev, 1); crtc = intel_get_crtc_for_plane(dev, 1); if (intel_crtc_active(crtc)) { - const struct drm_display_mode *adjusted_mode; int cpp = crtc->fb->bits_per_pixel / 8; if (IS_GEN2(dev)) cpp = 4; - adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; - planeb_wm = intel_calculate_wm(adjusted_mode->crtc_clock, + planeb_wm = intel_calculate_wm(crtc->mode.clock, wm_info, fifo_size, cpp, latency_ns); if (enabled == NULL) @@ -1621,11 +1607,9 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) if (HAS_FW_BLC(dev) && enabled) { /* self-refresh has much higher latency */ static const int sr_latency_ns = 6000; - const struct drm_display_mode *adjusted_mode = - &to_intel_crtc(enabled)->config.adjusted_mode; - int clock = adjusted_mode->crtc_clock; - int htotal = adjusted_mode->crtc_htotal; - int hdisplay = to_intel_crtc(enabled)->config.pipe_src_w; + int clock = enabled->mode.clock; + int htotal = enabled->mode.htotal; + int hdisplay = enabled->mode.hdisplay; int pixel_size = enabled->fb->bits_per_pixel / 8; unsigned long line_time_us; int entries; @@ -1674,12 +1658,10 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) } } -static void i830_update_wm(struct drm_crtc *unused_crtc) +static void i830_update_wm(struct drm_device *dev) { - struct drm_device *dev = unused_crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; - const struct drm_display_mode *adjusted_mode; uint32_t fwater_lo; int planea_wm; @@ -1687,9 +1669,7 @@ static void i830_update_wm(struct drm_crtc *unused_crtc) if (crtc == NULL) return; - adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; - planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock, - &i830_wm_info, + planea_wm = intel_calculate_wm(crtc->mode.clock, &i830_wm_info, dev_priv->display.get_fifo_size(dev, 0), 4, latency_ns); fwater_lo = I915_READ(FW_BLC) & ~0xfff; @@ -1761,7 +1741,6 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane, int *fbc_wm, int *display_wm, int *cursor_wm) { struct drm_crtc *crtc; - const struct drm_display_mode *adjusted_mode; unsigned long line_time_us; int hdisplay, htotal, pixel_size, clock; int line_count, line_size; @@ -1774,10 +1753,9 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane, } crtc = intel_get_crtc_for_plane(dev, plane); - adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; - clock = adjusted_mode->crtc_clock; - htotal = adjusted_mode->crtc_htotal; - hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; + hdisplay = crtc->mode.hdisplay; + htotal = crtc->mode.htotal; + clock = crtc->mode.clock; pixel_size = crtc->fb->bits_per_pixel / 8; line_time_us = (htotal * 1000) / clock; @@ -1807,9 +1785,8 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane, display, cursor); } -static void ironlake_update_wm(struct drm_crtc *crtc) +static void ironlake_update_wm(struct drm_device *dev) { - struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; int fbc_wm, plane_wm, cursor_wm; unsigned int enabled; @@ -1891,9 +1868,8 @@ static void ironlake_update_wm(struct drm_crtc *crtc) */ } -static void sandybridge_update_wm(struct drm_crtc *crtc) +static void sandybridge_update_wm(struct drm_device *dev) { - struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; int latency = dev_priv->wm.pri_latency[0] * 100; /* In unit 0.1us */ u32 val; @@ -1994,9 +1970,8 @@ static void sandybridge_update_wm(struct drm_crtc *crtc) cursor_wm); } -static void ivybridge_update_wm(struct drm_crtc *crtc) +static void ivybridge_update_wm(struct drm_device *dev) { - struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; int latency = dev_priv->wm.pri_latency[0] * 100; /* In unit 0.1us */ u32 val; @@ -2123,7 +2098,7 @@ static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); uint32_t pixel_rate; - pixel_rate = intel_crtc->config.adjusted_mode.crtc_clock; + pixel_rate = intel_crtc->config.adjusted_mode.clock; /* We only use IF-ID interlacing. If we ever use PF-ID we'll need to * adjust the pixel_rate here. */ @@ -2132,8 +2107,8 @@ static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev, uint64_t pipe_w, pipe_h, pfit_w, pfit_h; uint32_t pfit_size = intel_crtc->config.pch_pfit.size; - pipe_w = intel_crtc->config.pipe_src_w; - pipe_h = intel_crtc->config.pipe_src_h; + pipe_w = intel_crtc->config.requested_mode.hdisplay; + pipe_h = intel_crtc->config.requested_mode.vdisplay; pfit_w = (pfit_size >> 16) & 0xFFFF; pfit_h = pfit_size & 0xFFFF; if (pipe_w < pfit_w) @@ -2201,18 +2176,27 @@ struct hsw_wm_maximums { uint16_t fbc; }; +struct hsw_wm_values { + uint32_t wm_pipe[3]; + uint32_t wm_lp[3]; + uint32_t wm_lp_spr[3]; + uint32_t wm_linetime[3]; + bool enable_fbc_wm; +}; + /* used in computing the new watermarks state */ struct intel_wm_config { unsigned int num_pipes_active; bool sprites_enabled; bool sprites_scaled; + bool fbc_wm_enabled; }; /* * For both WM_PIPE and WM_LP. * mem_value must be in 0.1us units. */ -static uint32_t ilk_compute_pri_wm(const struct hsw_pipe_wm_parameters *params, +static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params, uint32_t mem_value, bool is_lp) { @@ -2241,7 +2225,7 @@ static uint32_t ilk_compute_pri_wm(const struct hsw_pipe_wm_parameters *params, * For both WM_PIPE and WM_LP. * mem_value must be in 0.1us units. */ -static uint32_t ilk_compute_spr_wm(const struct hsw_pipe_wm_parameters *params, +static uint32_t ilk_compute_spr_wm(struct hsw_pipe_wm_parameters *params, uint32_t mem_value) { uint32_t method1, method2; @@ -2264,7 +2248,7 @@ static uint32_t ilk_compute_spr_wm(const struct hsw_pipe_wm_parameters *params, * For both WM_PIPE and WM_LP. * mem_value must be in 0.1us units. */ -static uint32_t ilk_compute_cur_wm(const struct hsw_pipe_wm_parameters *params, +static uint32_t ilk_compute_cur_wm(struct hsw_pipe_wm_parameters *params, uint32_t mem_value) { if (!params->active || !params->cur.enabled) @@ -2278,7 +2262,7 @@ static uint32_t ilk_compute_cur_wm(const struct hsw_pipe_wm_parameters *params, } /* Only for WM_LP. */ -static uint32_t ilk_compute_fbc_wm(const struct hsw_pipe_wm_parameters *params, +static uint32_t ilk_compute_fbc_wm(struct hsw_pipe_wm_parameters *params, uint32_t pri_val) { if (!params->active || !params->pri.enabled) @@ -2291,9 +2275,7 @@ static uint32_t ilk_compute_fbc_wm(const struct hsw_pipe_wm_parameters *params, static unsigned int ilk_display_fifo_size(const struct drm_device *dev) { - if (INTEL_INFO(dev)->gen >= 8) - return 3072; - else if (INTEL_INFO(dev)->gen >= 7) + if (INTEL_INFO(dev)->gen >= 7) return 768; else return 512; @@ -2338,9 +2320,7 @@ static unsigned int ilk_plane_wm_max(const struct drm_device *dev, } /* clamp to max that the registers can hold */ - if (INTEL_INFO(dev)->gen >= 8) - max = level == 0 ? 255 : 2047; - else if (INTEL_INFO(dev)->gen >= 7) + if (INTEL_INFO(dev)->gen >= 7) /* IVB/HSW primary/sprite plane watermarks */ max = level == 0 ? 127 : 1023; else if (!is_sprite) @@ -2370,30 +2350,27 @@ static unsigned int ilk_cursor_wm_max(const struct drm_device *dev, } /* Calculate the maximum FBC watermark */ -static unsigned int ilk_fbc_wm_max(struct drm_device *dev) +static unsigned int ilk_fbc_wm_max(void) { /* max that registers can hold */ - if (INTEL_INFO(dev)->gen >= 8) - return 31; - else - return 15; + return 15; } -static void ilk_compute_wm_maximums(struct drm_device *dev, - int level, - const struct intel_wm_config *config, - enum intel_ddb_partitioning ddb_partitioning, - struct hsw_wm_maximums *max) +static void ilk_wm_max(struct drm_device *dev, + int level, + const struct intel_wm_config *config, + enum intel_ddb_partitioning ddb_partitioning, + struct hsw_wm_maximums *max) { max->pri = ilk_plane_wm_max(dev, level, config, ddb_partitioning, false); max->spr = ilk_plane_wm_max(dev, level, config, ddb_partitioning, true); max->cur = ilk_cursor_wm_max(dev, level, config); - max->fbc = ilk_fbc_wm_max(dev); + max->fbc = ilk_fbc_wm_max(); } -static bool ilk_validate_wm_level(int level, - const struct hsw_wm_maximums *max, - struct intel_wm_level *result) +static bool ilk_check_wm(int level, + const struct hsw_wm_maximums *max, + struct intel_wm_level *result) { bool ret; @@ -2429,12 +2406,14 @@ static bool ilk_validate_wm_level(int level, result->enable = true; } + DRM_DEBUG_KMS("WM%d: %sabled\n", level, result->enable ? "en" : "dis"); + return ret; } static void ilk_compute_wm_level(struct drm_i915_private *dev_priv, int level, - const struct hsw_pipe_wm_parameters *p, + struct hsw_pipe_wm_parameters *p, struct intel_wm_level *result) { uint16_t pri_latency = dev_priv->wm.pri_latency[level]; @@ -2455,6 +2434,55 @@ static void ilk_compute_wm_level(struct drm_i915_private *dev_priv, result->enable = true; } +static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv, + int level, struct hsw_wm_maximums *max, + struct hsw_pipe_wm_parameters *params, + struct intel_wm_level *result) +{ + enum pipe pipe; + struct intel_wm_level res[3]; + + for (pipe = PIPE_A; pipe <= PIPE_C; pipe++) + ilk_compute_wm_level(dev_priv, level, ¶ms[pipe], &res[pipe]); + + result->pri_val = max3(res[0].pri_val, res[1].pri_val, res[2].pri_val); + result->spr_val = max3(res[0].spr_val, res[1].spr_val, res[2].spr_val); + result->cur_val = max3(res[0].cur_val, res[1].cur_val, res[2].cur_val); + result->fbc_val = max3(res[0].fbc_val, res[1].fbc_val, res[2].fbc_val); + result->enable = true; + + return ilk_check_wm(level, max, result); +} + +static uint32_t hsw_compute_wm_pipe(struct drm_i915_private *dev_priv, + enum pipe pipe, + struct hsw_pipe_wm_parameters *params) +{ + uint32_t pri_val, cur_val, spr_val; + /* WM0 latency values stored in 0.1us units */ + uint16_t pri_latency = dev_priv->wm.pri_latency[0]; + uint16_t spr_latency = dev_priv->wm.spr_latency[0]; + uint16_t cur_latency = dev_priv->wm.cur_latency[0]; + + pri_val = ilk_compute_pri_wm(params, pri_latency, false); + spr_val = ilk_compute_spr_wm(params, spr_latency); + cur_val = ilk_compute_cur_wm(params, cur_latency); + + WARN(pri_val > 127, + "Primary WM error, mode not supported for pipe %c\n", + pipe_name(pipe)); + WARN(spr_val > 127, + "Sprite WM error, mode not supported for pipe %c\n", + pipe_name(pipe)); + WARN(cur_val > 63, + "Cursor WM error, mode not supported for pipe %c\n", + pipe_name(pipe)); + + return (pri_val << WM0_PIPE_PLANE_SHIFT) | + (spr_val << WM0_PIPE_SPRITE_SHIFT) | + cur_val; +} + static uint32_t hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc) { @@ -2469,9 +2497,8 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc) /* The WM are computed with base on how long it takes to fill a single * row at the given clock rate, multiplied by 8. * */ - linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8, - mode->crtc_clock); - ips_linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8, + linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8, mode->clock); + ips_linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8, intel_ddi_get_cdclk_freq(dev_priv)); return PIPE_WM_LINETIME_IPS_LINETIME(ips_linetime) | @@ -2527,22 +2554,19 @@ static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5]) wm[3] *= 2; } -static int ilk_wm_max_level(const struct drm_device *dev) +static void intel_print_wm_latency(struct drm_device *dev, + const char *name, + const uint16_t wm[5]) { + int level, max_level; + /* how many WM levels are we expecting */ if (IS_HASWELL(dev)) - return 4; + max_level = 4; else if (INTEL_INFO(dev)->gen >= 6) - return 3; + max_level = 3; else - return 2; -} - -static void intel_print_wm_latency(struct drm_device *dev, - const char *name, - const uint16_t wm[5]) -{ - int level, max_level = ilk_wm_max_level(dev); + max_level = 2; for (level = 0; level <= max_level; level++) { unsigned int latency = wm[level]; @@ -2582,321 +2606,218 @@ static void intel_setup_wm_latency(struct drm_device *dev) intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency); } -static void hsw_compute_wm_parameters(struct drm_crtc *crtc, - struct hsw_pipe_wm_parameters *p, - struct intel_wm_config *config) +static void hsw_compute_wm_parameters(struct drm_device *dev, + struct hsw_pipe_wm_parameters *params, + struct hsw_wm_maximums *lp_max_1_2, + struct hsw_wm_maximums *lp_max_5_6) { - struct drm_device *dev = crtc->dev; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; + struct drm_crtc *crtc; struct drm_plane *plane; + enum pipe pipe; + struct intel_wm_config config = {}; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct hsw_pipe_wm_parameters *p; + + pipe = intel_crtc->pipe; + p = ¶ms[pipe]; + + p->active = intel_crtc_active(crtc); + if (!p->active) + continue; + + config.num_pipes_active++; - p->active = intel_crtc_active(crtc); - if (p->active) { p->pipe_htotal = intel_crtc->config.adjusted_mode.htotal; p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc); p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8; p->cur.bytes_per_pixel = 4; - p->pri.horiz_pixels = intel_crtc->config.pipe_src_w; + p->pri.horiz_pixels = + intel_crtc->config.requested_mode.hdisplay; p->cur.horiz_pixels = 64; /* TODO: for now, assume primary and cursor planes are always enabled. */ p->pri.enabled = true; p->cur.enabled = true; } - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) - config->num_pipes_active += intel_crtc_active(crtc); - list_for_each_entry(plane, &dev->mode_config.plane_list, head) { struct intel_plane *intel_plane = to_intel_plane(plane); + struct hsw_pipe_wm_parameters *p; - if (intel_plane->pipe == pipe) - p->spr = intel_plane->wm; + pipe = intel_plane->pipe; + p = ¶ms[pipe]; - config->sprites_enabled |= intel_plane->wm.enabled; - config->sprites_scaled |= intel_plane->wm.scaled; - } -} - -/* Compute new watermarks for the pipe */ -static bool intel_compute_pipe_wm(struct drm_crtc *crtc, - const struct hsw_pipe_wm_parameters *params, - struct intel_pipe_wm *pipe_wm) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int level, max_level = ilk_wm_max_level(dev); - /* LP0 watermark maximums depend on this pipe alone */ - struct intel_wm_config config = { - .num_pipes_active = 1, - .sprites_enabled = params->spr.enabled, - .sprites_scaled = params->spr.scaled, - }; - struct hsw_wm_maximums max; - - /* LP0 watermarks always use 1/2 DDB partitioning */ - ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max); + p->spr = intel_plane->wm; - for (level = 0; level <= max_level; level++) - ilk_compute_wm_level(dev_priv, level, params, - &pipe_wm->wm[level]); + config.sprites_enabled |= p->spr.enabled; + config.sprites_scaled |= p->spr.scaled; + } - pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc); + ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, lp_max_1_2); - /* At least LP0 must be valid */ - return ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]); + /* 5/6 split only in single pipe config on IVB+ */ + if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active <= 1) + ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, lp_max_5_6); + else + *lp_max_5_6 = *lp_max_1_2; } -/* - * Merge the watermarks from all active pipes for a specific level. - */ -static void ilk_merge_wm_level(struct drm_device *dev, - int level, - struct intel_wm_level *ret_wm) +static void hsw_compute_wm_results(struct drm_device *dev, + struct hsw_pipe_wm_parameters *params, + struct hsw_wm_maximums *lp_maximums, + struct hsw_wm_values *results) { - const struct intel_crtc *intel_crtc; - - list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) { - const struct intel_wm_level *wm = - &intel_crtc->wm.active.wm[level]; - - if (!wm->enable) - return; - - ret_wm->pri_val = max(ret_wm->pri_val, wm->pri_val); - ret_wm->spr_val = max(ret_wm->spr_val, wm->spr_val); - ret_wm->cur_val = max(ret_wm->cur_val, wm->cur_val); - ret_wm->fbc_val = max(ret_wm->fbc_val, wm->fbc_val); - } - - ret_wm->enable = true; -} + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_crtc *crtc; + struct intel_wm_level lp_results[4] = {}; + enum pipe pipe; + int level, max_level, wm_lp; -/* - * Merge all low power watermarks for all active pipes. - */ -static void ilk_wm_merge(struct drm_device *dev, - const struct hsw_wm_maximums *max, - struct intel_pipe_wm *merged) -{ - int level, max_level = ilk_wm_max_level(dev); + for (level = 1; level <= 4; level++) + if (!hsw_compute_lp_wm(dev_priv, level, + lp_maximums, params, + &lp_results[level - 1])) + break; + max_level = level - 1; - merged->fbc_wm_enabled = true; + memset(results, 0, sizeof(*results)); - /* merge each WM1+ level */ + /* The spec says it is preferred to disable FBC WMs instead of disabling + * a WM level. */ + results->enable_fbc_wm = true; for (level = 1; level <= max_level; level++) { - struct intel_wm_level *wm = &merged->wm[level]; - - ilk_merge_wm_level(dev, level, wm); - - if (!ilk_validate_wm_level(level, max, wm)) - break; - - /* - * The spec says it is preferred to disable - * FBC WMs instead of disabling a WM level. - */ - if (wm->fbc_val > max->fbc) { - merged->fbc_wm_enabled = false; - wm->fbc_val = 0; + if (lp_results[level - 1].fbc_val > lp_maximums->fbc) { + results->enable_fbc_wm = false; + lp_results[level - 1].fbc_val = 0; } } -} -static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *pipe_wm) -{ - /* LP1,LP2,LP3 levels are either 1,2,3 or 1,3,4 */ - return wm_lp + (wm_lp >= 2 && pipe_wm->wm[4].enable); -} - -static void hsw_compute_wm_results(struct drm_device *dev, - const struct intel_pipe_wm *merged, - enum intel_ddb_partitioning partitioning, - struct hsw_wm_values *results) -{ - struct intel_crtc *intel_crtc; - int level, wm_lp; - - results->enable_fbc_wm = merged->fbc_wm_enabled; - results->partitioning = partitioning; - - /* LP1+ register values */ for (wm_lp = 1; wm_lp <= 3; wm_lp++) { const struct intel_wm_level *r; - level = ilk_wm_lp_to_level(wm_lp, merged); - - r = &merged->wm[level]; - if (!r->enable) + level = (max_level == 4 && wm_lp > 1) ? wm_lp + 1 : wm_lp; + if (level > max_level) break; - results->wm_lp[wm_lp - 1] = WM3_LP_EN | - ((level * 2) << WM1_LP_LATENCY_SHIFT) | - (r->pri_val << WM1_LP_SR_SHIFT) | - r->cur_val; - - if (INTEL_INFO(dev)->gen >= 8) - results->wm_lp[wm_lp - 1] |= - r->fbc_val << WM1_LP_FBC_SHIFT_BDW; - else - results->wm_lp[wm_lp - 1] |= - r->fbc_val << WM1_LP_FBC_SHIFT; - + r = &lp_results[level - 1]; + results->wm_lp[wm_lp - 1] = HSW_WM_LP_VAL(level * 2, + r->fbc_val, + r->pri_val, + r->cur_val); results->wm_lp_spr[wm_lp - 1] = r->spr_val; } - /* LP0 register values */ - list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) { - enum pipe pipe = intel_crtc->pipe; - const struct intel_wm_level *r = - &intel_crtc->wm.active.wm[0]; - - if (WARN_ON(!r->enable)) - continue; - - results->wm_linetime[pipe] = intel_crtc->wm.active.linetime; + for_each_pipe(pipe) + results->wm_pipe[pipe] = hsw_compute_wm_pipe(dev_priv, pipe, + ¶ms[pipe]); - results->wm_pipe[pipe] = - (r->pri_val << WM0_PIPE_PLANE_SHIFT) | - (r->spr_val << WM0_PIPE_SPRITE_SHIFT) | - r->cur_val; + for_each_pipe(pipe) { + crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + results->wm_linetime[pipe] = hsw_compute_linetime_wm(dev, crtc); } } /* Find the result with the highest level enabled. Check for enable_fbc_wm in * case both are at the same level. Prefer r1 in case they're the same. */ -static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev, - struct intel_pipe_wm *r1, - struct intel_pipe_wm *r2) +static struct hsw_wm_values *hsw_find_best_result(struct hsw_wm_values *r1, + struct hsw_wm_values *r2) { - int level, max_level = ilk_wm_max_level(dev); - int level1 = 0, level2 = 0; + int i, val_r1 = 0, val_r2 = 0; - for (level = 1; level <= max_level; level++) { - if (r1->wm[level].enable) - level1 = level; - if (r2->wm[level].enable) - level2 = level; + for (i = 0; i < 3; i++) { + if (r1->wm_lp[i] & WM3_LP_EN) + val_r1 = r1->wm_lp[i] & WM1_LP_LATENCY_MASK; + if (r2->wm_lp[i] & WM3_LP_EN) + val_r2 = r2->wm_lp[i] & WM1_LP_LATENCY_MASK; } - if (level1 == level2) { - if (r2->fbc_wm_enabled && !r1->fbc_wm_enabled) + if (val_r1 == val_r2) { + if (r2->enable_fbc_wm && !r1->enable_fbc_wm) return r2; else return r1; - } else if (level1 > level2) { + } else if (val_r1 > val_r2) { return r1; } else { return r2; } } -/* dirty bits used to track which watermarks need changes */ -#define WM_DIRTY_PIPE(pipe) (1 << (pipe)) -#define WM_DIRTY_LINETIME(pipe) (1 << (8 + (pipe))) -#define WM_DIRTY_LP(wm_lp) (1 << (15 + (wm_lp))) -#define WM_DIRTY_LP_ALL (WM_DIRTY_LP(1) | WM_DIRTY_LP(2) | WM_DIRTY_LP(3)) -#define WM_DIRTY_FBC (1 << 24) -#define WM_DIRTY_DDB (1 << 25) - -static unsigned int ilk_compute_wm_dirty(struct drm_device *dev, - const struct hsw_wm_values *old, - const struct hsw_wm_values *new) -{ - unsigned int dirty = 0; - enum pipe pipe; - int wm_lp; - - for_each_pipe(pipe) { - if (old->wm_linetime[pipe] != new->wm_linetime[pipe]) { - dirty |= WM_DIRTY_LINETIME(pipe); - /* Must disable LP1+ watermarks too */ - dirty |= WM_DIRTY_LP_ALL; - } - - if (old->wm_pipe[pipe] != new->wm_pipe[pipe]) { - dirty |= WM_DIRTY_PIPE(pipe); - /* Must disable LP1+ watermarks too */ - dirty |= WM_DIRTY_LP_ALL; - } - } - - if (old->enable_fbc_wm != new->enable_fbc_wm) { - dirty |= WM_DIRTY_FBC; - /* Must disable LP1+ watermarks too */ - dirty |= WM_DIRTY_LP_ALL; - } - - if (old->partitioning != new->partitioning) { - dirty |= WM_DIRTY_DDB; - /* Must disable LP1+ watermarks too */ - dirty |= WM_DIRTY_LP_ALL; - } - - /* LP1+ watermarks already deemed dirty, no need to continue */ - if (dirty & WM_DIRTY_LP_ALL) - return dirty; - - /* Find the lowest numbered LP1+ watermark in need of an update... */ - for (wm_lp = 1; wm_lp <= 3; wm_lp++) { - if (old->wm_lp[wm_lp - 1] != new->wm_lp[wm_lp - 1] || - old->wm_lp_spr[wm_lp - 1] != new->wm_lp_spr[wm_lp - 1]) - break; - } - - /* ...and mark it and all higher numbered LP1+ watermarks as dirty */ - for (; wm_lp <= 3; wm_lp++) - dirty |= WM_DIRTY_LP(wm_lp); - - return dirty; -} - /* * The spec says we shouldn't write when we don't need, because every write * causes WMs to be re-evaluated, expending some power. */ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, - struct hsw_wm_values *results) + struct hsw_wm_values *results, + enum intel_ddb_partitioning partitioning) { - struct hsw_wm_values *previous = &dev_priv->wm.hw; - unsigned int dirty; + struct hsw_wm_values previous; uint32_t val; - - dirty = ilk_compute_wm_dirty(dev_priv->dev, previous, results); - if (!dirty) + enum intel_ddb_partitioning prev_partitioning; + bool prev_enable_fbc_wm; + + previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK); + previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK); + previous.wm_pipe[2] = I915_READ(WM0_PIPEC_IVB); + previous.wm_lp[0] = I915_READ(WM1_LP_ILK); + previous.wm_lp[1] = I915_READ(WM2_LP_ILK); + previous.wm_lp[2] = I915_READ(WM3_LP_ILK); + previous.wm_lp_spr[0] = I915_READ(WM1S_LP_ILK); + previous.wm_lp_spr[1] = I915_READ(WM2S_LP_IVB); + previous.wm_lp_spr[2] = I915_READ(WM3S_LP_IVB); + previous.wm_linetime[0] = I915_READ(PIPE_WM_LINETIME(PIPE_A)); + previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B)); + previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C)); + + prev_partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ? + INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2; + + prev_enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS); + + if (memcmp(results->wm_pipe, previous.wm_pipe, + sizeof(results->wm_pipe)) == 0 && + memcmp(results->wm_lp, previous.wm_lp, + sizeof(results->wm_lp)) == 0 && + memcmp(results->wm_lp_spr, previous.wm_lp_spr, + sizeof(results->wm_lp_spr)) == 0 && + memcmp(results->wm_linetime, previous.wm_linetime, + sizeof(results->wm_linetime)) == 0 && + partitioning == prev_partitioning && + results->enable_fbc_wm == prev_enable_fbc_wm) return; - if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0) + if (previous.wm_lp[2] != 0) I915_WRITE(WM3_LP_ILK, 0); - if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != 0) + if (previous.wm_lp[1] != 0) I915_WRITE(WM2_LP_ILK, 0); - if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0) + if (previous.wm_lp[0] != 0) I915_WRITE(WM1_LP_ILK, 0); - if (dirty & WM_DIRTY_PIPE(PIPE_A)) + if (previous.wm_pipe[0] != results->wm_pipe[0]) I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]); - if (dirty & WM_DIRTY_PIPE(PIPE_B)) + if (previous.wm_pipe[1] != results->wm_pipe[1]) I915_WRITE(WM0_PIPEB_ILK, results->wm_pipe[1]); - if (dirty & WM_DIRTY_PIPE(PIPE_C)) + if (previous.wm_pipe[2] != results->wm_pipe[2]) I915_WRITE(WM0_PIPEC_IVB, results->wm_pipe[2]); - if (dirty & WM_DIRTY_LINETIME(PIPE_A)) + if (previous.wm_linetime[0] != results->wm_linetime[0]) I915_WRITE(PIPE_WM_LINETIME(PIPE_A), results->wm_linetime[0]); - if (dirty & WM_DIRTY_LINETIME(PIPE_B)) + if (previous.wm_linetime[1] != results->wm_linetime[1]) I915_WRITE(PIPE_WM_LINETIME(PIPE_B), results->wm_linetime[1]); - if (dirty & WM_DIRTY_LINETIME(PIPE_C)) + if (previous.wm_linetime[2] != results->wm_linetime[2]) I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]); - if (dirty & WM_DIRTY_DDB) { + if (prev_partitioning != partitioning) { val = I915_READ(WM_MISC); - if (results->partitioning == INTEL_DDB_PART_1_2) + if (partitioning == INTEL_DDB_PART_1_2) val &= ~WM_MISC_DATA_PARTITION_5_6; else val |= WM_MISC_DATA_PARTITION_5_6; I915_WRITE(WM_MISC, val); } - if (dirty & WM_DIRTY_FBC) { + if (prev_enable_fbc_wm != results->enable_fbc_wm) { val = I915_READ(DISP_ARB_CTL); if (results->enable_fbc_wm) val &= ~DISP_FBC_WM_DIS; @@ -2905,65 +2826,45 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, I915_WRITE(DISP_ARB_CTL, val); } - if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0]) + if (previous.wm_lp_spr[0] != results->wm_lp_spr[0]) I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]); - if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1]) + if (previous.wm_lp_spr[1] != results->wm_lp_spr[1]) I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]); - if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2]) + if (previous.wm_lp_spr[2] != results->wm_lp_spr[2]) I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]); - if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0) + if (results->wm_lp[0] != 0) I915_WRITE(WM1_LP_ILK, results->wm_lp[0]); - if (dirty & WM_DIRTY_LP(2) && results->wm_lp[1] != 0) + if (results->wm_lp[1] != 0) I915_WRITE(WM2_LP_ILK, results->wm_lp[1]); - if (dirty & WM_DIRTY_LP(3) && results->wm_lp[2] != 0) + if (results->wm_lp[2] != 0) I915_WRITE(WM3_LP_ILK, results->wm_lp[2]); - - dev_priv->wm.hw = *results; } -static void haswell_update_wm(struct drm_crtc *crtc) +static void haswell_update_wm(struct drm_device *dev) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct hsw_wm_maximums max; - struct hsw_pipe_wm_parameters params = {}; - struct hsw_wm_values results = {}; + struct hsw_wm_maximums lp_max_1_2, lp_max_5_6; + struct hsw_pipe_wm_parameters params[3]; + struct hsw_wm_values results_1_2, results_5_6, *best_results; enum intel_ddb_partitioning partitioning; - struct intel_pipe_wm pipe_wm = {}; - struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm; - struct intel_wm_config config = {}; - hsw_compute_wm_parameters(crtc, ¶ms, &config); - - intel_compute_pipe_wm(crtc, ¶ms, &pipe_wm); - - if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm))) - return; + hsw_compute_wm_parameters(dev, params, &lp_max_1_2, &lp_max_5_6); - intel_crtc->wm.active = pipe_wm; - - ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max); - ilk_wm_merge(dev, &max, &lp_wm_1_2); - - /* 5/6 split only in single pipe config on IVB+ */ - if (INTEL_INFO(dev)->gen >= 7 && - config.num_pipes_active == 1 && config.sprites_enabled) { - ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max); - ilk_wm_merge(dev, &max, &lp_wm_5_6); - - best_lp_wm = hsw_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6); + hsw_compute_wm_results(dev, params, + &lp_max_1_2, &results_1_2); + if (lp_max_1_2.pri != lp_max_5_6.pri) { + hsw_compute_wm_results(dev, params, + &lp_max_5_6, &results_5_6); + best_results = hsw_find_best_result(&results_1_2, &results_5_6); } else { - best_lp_wm = &lp_wm_1_2; + best_results = &results_1_2; } - partitioning = (best_lp_wm == &lp_wm_1_2) ? + partitioning = (best_results == &results_1_2) ? INTEL_DDB_PART_1_2 : INTEL_DDB_PART_5_6; - hsw_compute_wm_results(dev, best_lp_wm, partitioning, &results); - - hsw_write_wm_values(dev_priv, &results); + hsw_write_wm_values(dev_priv, best_results, partitioning); } static void haswell_update_sprite_wm(struct drm_plane *plane, @@ -2978,7 +2879,7 @@ static void haswell_update_sprite_wm(struct drm_plane *plane, intel_plane->wm.horiz_pixels = sprite_width; intel_plane->wm.bytes_per_pixel = pixel_size; - haswell_update_wm(crtc); + haswell_update_wm(plane->dev); } static bool @@ -2997,7 +2898,7 @@ sandybridge_compute_sprite_wm(struct drm_device *dev, int plane, return false; } - clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; + clock = crtc->mode.clock; /* Use the small buffer method to calculate the sprite watermark */ entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000; @@ -3032,7 +2933,7 @@ sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane, } crtc = intel_get_crtc_for_plane(dev, plane); - clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; + clock = crtc->mode.clock; if (!clock) { *sprite_wm = 0; return false; @@ -3143,74 +3044,6 @@ static void sandybridge_update_sprite_wm(struct drm_plane *plane, I915_WRITE(WM3S_LP_IVB, sprite_wm); } -static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct hsw_wm_values *hw = &dev_priv->wm.hw; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_pipe_wm *active = &intel_crtc->wm.active; - enum pipe pipe = intel_crtc->pipe; - static const unsigned int wm0_pipe_reg[] = { - [PIPE_A] = WM0_PIPEA_ILK, - [PIPE_B] = WM0_PIPEB_ILK, - [PIPE_C] = WM0_PIPEC_IVB, - }; - - hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]); - hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe)); - - if (intel_crtc_active(crtc)) { - u32 tmp = hw->wm_pipe[pipe]; - - /* - * For active pipes LP0 watermark is marked as - * enabled, and LP1+ watermaks as disabled since - * we can't really reverse compute them in case - * multiple pipes are active. - */ - active->wm[0].enable = true; - active->wm[0].pri_val = (tmp & WM0_PIPE_PLANE_MASK) >> WM0_PIPE_PLANE_SHIFT; - active->wm[0].spr_val = (tmp & WM0_PIPE_SPRITE_MASK) >> WM0_PIPE_SPRITE_SHIFT; - active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK; - active->linetime = hw->wm_linetime[pipe]; - } else { - int level, max_level = ilk_wm_max_level(dev); - - /* - * For inactive pipes, all watermark levels - * should be marked as enabled but zeroed, - * which is what we'd compute them to. - */ - for (level = 0; level <= max_level; level++) - active->wm[level].enable = true; - } -} - -void ilk_wm_get_hw_state(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct hsw_wm_values *hw = &dev_priv->wm.hw; - struct drm_crtc *crtc; - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) - ilk_pipe_wm_get_hw_state(crtc); - - hw->wm_lp[0] = I915_READ(WM1_LP_ILK); - hw->wm_lp[1] = I915_READ(WM2_LP_ILK); - hw->wm_lp[2] = I915_READ(WM3_LP_ILK); - - hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK); - hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB); - hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB); - - hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ? - INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2; - - hw->enable_fbc_wm = - !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS); -} - /** * intel_update_watermarks - update FIFO watermark values based on current modes * @@ -3243,12 +3076,12 @@ void ilk_wm_get_hw_state(struct drm_device *dev) * We don't use the sprite, so we can ignore that. And on Crestline we have * to set the non-SR watermarks to 8. */ -void intel_update_watermarks(struct drm_crtc *crtc) +void intel_update_watermarks(struct drm_device *dev) { - struct drm_i915_private *dev_priv = crtc->dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; if (dev_priv->display.update_wm) - dev_priv->display.update_wm(crtc); + dev_priv->display.update_wm(dev); } void intel_update_sprite_watermarks(struct drm_plane *plane, @@ -3454,98 +3287,6 @@ static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 *val) return limits; } -static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val) -{ - int new_power; - - new_power = dev_priv->rps.power; - switch (dev_priv->rps.power) { - case LOW_POWER: - if (val > dev_priv->rps.rpe_delay + 1 && val > dev_priv->rps.cur_delay) - new_power = BETWEEN; - break; - - case BETWEEN: - if (val <= dev_priv->rps.rpe_delay && val < dev_priv->rps.cur_delay) - new_power = LOW_POWER; - else if (val >= dev_priv->rps.rp0_delay && val > dev_priv->rps.cur_delay) - new_power = HIGH_POWER; - break; - - case HIGH_POWER: - if (val < (dev_priv->rps.rp1_delay + dev_priv->rps.rp0_delay) >> 1 && val < dev_priv->rps.cur_delay) - new_power = BETWEEN; - break; - } - /* Max/min bins are special */ - if (val == dev_priv->rps.min_delay) - new_power = LOW_POWER; - if (val == dev_priv->rps.max_delay) - new_power = HIGH_POWER; - if (new_power == dev_priv->rps.power) - return; - - /* Note the units here are not exactly 1us, but 1280ns. */ - switch (new_power) { - case LOW_POWER: - /* Upclock if more than 95% busy over 16ms */ - I915_WRITE(GEN6_RP_UP_EI, 12500); - I915_WRITE(GEN6_RP_UP_THRESHOLD, 11800); - - /* Downclock if less than 85% busy over 32ms */ - I915_WRITE(GEN6_RP_DOWN_EI, 25000); - I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 21250); - - I915_WRITE(GEN6_RP_CONTROL, - GEN6_RP_MEDIA_TURBO | - GEN6_RP_MEDIA_HW_NORMAL_MODE | - GEN6_RP_MEDIA_IS_GFX | - GEN6_RP_ENABLE | - GEN6_RP_UP_BUSY_AVG | - GEN6_RP_DOWN_IDLE_AVG); - break; - - case BETWEEN: - /* Upclock if more than 90% busy over 13ms */ - I915_WRITE(GEN6_RP_UP_EI, 10250); - I915_WRITE(GEN6_RP_UP_THRESHOLD, 9225); - - /* Downclock if less than 75% busy over 32ms */ - I915_WRITE(GEN6_RP_DOWN_EI, 25000); - I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 18750); - - I915_WRITE(GEN6_RP_CONTROL, - GEN6_RP_MEDIA_TURBO | - GEN6_RP_MEDIA_HW_NORMAL_MODE | - GEN6_RP_MEDIA_IS_GFX | - GEN6_RP_ENABLE | - GEN6_RP_UP_BUSY_AVG | - GEN6_RP_DOWN_IDLE_AVG); - break; - - case HIGH_POWER: - /* Upclock if more than 85% busy over 10ms */ - I915_WRITE(GEN6_RP_UP_EI, 8000); - I915_WRITE(GEN6_RP_UP_THRESHOLD, 6800); - - /* Downclock if less than 60% busy over 32ms */ - I915_WRITE(GEN6_RP_DOWN_EI, 25000); - I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 15000); - - I915_WRITE(GEN6_RP_CONTROL, - GEN6_RP_MEDIA_TURBO | - GEN6_RP_MEDIA_HW_NORMAL_MODE | - GEN6_RP_MEDIA_IS_GFX | - GEN6_RP_ENABLE | - GEN6_RP_UP_BUSY_AVG | - GEN6_RP_DOWN_IDLE_AVG); - break; - } - - dev_priv->rps.power = new_power; - dev_priv->rps.last_adj = 0; -} - void gen6_set_rps(struct drm_device *dev, u8 val) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -3558,8 +3299,6 @@ void gen6_set_rps(struct drm_device *dev, u8 val) if (val == dev_priv->rps.cur_delay) return; - gen6_set_rps_thresholds(dev_priv, val); - if (IS_HASWELL(dev)) I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(val)); @@ -3581,32 +3320,6 @@ void gen6_set_rps(struct drm_device *dev, u8 val) trace_intel_gpu_freq_change(val * 50); } -void gen6_rps_idle(struct drm_i915_private *dev_priv) -{ - mutex_lock(&dev_priv->rps.hw_lock); - if (dev_priv->rps.enabled) { - if (dev_priv->info->is_valleyview) - valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_delay); - else - gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay); - dev_priv->rps.last_adj = 0; - } - mutex_unlock(&dev_priv->rps.hw_lock); -} - -void gen6_rps_boost(struct drm_i915_private *dev_priv) -{ - mutex_lock(&dev_priv->rps.hw_lock); - if (dev_priv->rps.enabled) { - if (dev_priv->info->is_valleyview) - valleyview_set_rps(dev_priv->dev, dev_priv->rps.max_delay); - else - gen6_set_rps(dev_priv->dev, dev_priv->rps.max_delay); - dev_priv->rps.last_adj = 0; - } - mutex_unlock(&dev_priv->rps.hw_lock); -} - /* * Wait until the previous freq change has completed, * or the timeout elapsed, and then update our notion @@ -3702,20 +3415,6 @@ static void valleyview_disable_rps(struct drm_device *dev) } } -static void intel_print_rc6_info(struct drm_device *dev, u32 mode) -{ - if (IS_GEN6(dev)) - DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n"); - - if (IS_HASWELL(dev)) - DRM_DEBUG_DRIVER("Haswell: only RC6 available\n"); - - DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", - (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", - (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", - (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); -} - int intel_enable_rc6(const struct drm_device *dev) { /* No RC6 before Ironlake */ @@ -3730,13 +3429,18 @@ int intel_enable_rc6(const struct drm_device *dev) if (INTEL_INFO(dev)->gen == 5) return 0; - if (IS_HASWELL(dev)) + if (IS_HASWELL(dev)) { + DRM_DEBUG_DRIVER("Haswell: only RC6 available\n"); return INTEL_RC6_ENABLE; + } /* snb/ivb have more than one rc6 state. */ - if (INTEL_INFO(dev)->gen == 6) + if (INTEL_INFO(dev)->gen == 6) { + DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n"); return INTEL_RC6_ENABLE; + } + DRM_DEBUG_DRIVER("RC6 and deep RC6 enabled\n"); return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE); } @@ -3763,78 +3467,6 @@ static void gen6_enable_rps_interrupts(struct drm_device *dev) I915_WRITE(GEN6_PMINTRMSK, ~enabled_intrs); } -static void gen8_enable_rps(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_ring_buffer *ring; - uint32_t rc6_mask = 0, rp_state_cap; - int unused; - - /* 1a: Software RC state - RC0 */ - I915_WRITE(GEN6_RC_STATE, 0); - - /* 1c & 1d: Get forcewake during program sequence. Although the driver - * hasn't enabled a state yet where we need forcewake, BIOS may have.*/ - gen6_gt_force_wake_get(dev_priv); - - /* 2a: Disable RC states. */ - I915_WRITE(GEN6_RC_CONTROL, 0); - - rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); - - /* 2b: Program RC6 thresholds.*/ - I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16); - I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ - I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ - for_each_ring(ring, dev_priv, unused) - I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); - I915_WRITE(GEN6_RC_SLEEP, 0); - I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */ - - /* 3: Enable RC6 */ - if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE) - rc6_mask = GEN6_RC_CTL_RC6_ENABLE; - DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off"); - I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | - GEN6_RC_CTL_EI_MODE(1) | - rc6_mask); - - /* 4 Program defaults and thresholds for RPS*/ - I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(10)); /* Request 500 MHz */ - I915_WRITE(GEN6_RC_VIDEO_FREQ, HSW_FREQUENCY(12)); /* Request 600 MHz */ - /* NB: Docs say 1s, and 1000000 - which aren't equivalent */ - I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 100000000 / 128); /* 1 second timeout */ - - /* Docs recommend 900MHz, and 300 MHz respectively */ - I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, - dev_priv->rps.max_delay << 24 | - dev_priv->rps.min_delay << 16); - - I915_WRITE(GEN6_RP_UP_THRESHOLD, 7600000 / 128); /* 76ms busyness per EI, 90% */ - I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 31300000 / 128); /* 313ms busyness per EI, 70%*/ - I915_WRITE(GEN6_RP_UP_EI, 66000); /* 84.48ms, XXX: random? */ - I915_WRITE(GEN6_RP_DOWN_EI, 350000); /* 448ms, XXX: random? */ - - I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); - - /* 5: Enable RPS */ - I915_WRITE(GEN6_RP_CONTROL, - GEN6_RP_MEDIA_TURBO | - GEN6_RP_MEDIA_HW_NORMAL_MODE | - GEN6_RP_MEDIA_IS_GFX | - GEN6_RP_ENABLE | - GEN6_RP_UP_BUSY_AVG | - GEN6_RP_DOWN_IDLE_AVG); - - /* 6: Ring frequency + overclocking (our driver does this later */ - - gen6_set_rps(dev, (I915_READ(GEN6_GT_PERF_STATUS) & 0xff00) >> 8); - - gen6_enable_rps_interrupts(dev); - - gen6_gt_force_wake_put(dev_priv); -} - static void gen6_enable_rps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -3869,10 +3501,7 @@ static void gen6_enable_rps(struct drm_device *dev) /* In units of 50MHz */ dev_priv->rps.hw_max = dev_priv->rps.max_delay = rp_state_cap & 0xff; - dev_priv->rps.min_delay = (rp_state_cap >> 16) & 0xff; - dev_priv->rps.rp1_delay = (rp_state_cap >> 8) & 0xff; - dev_priv->rps.rp0_delay = (rp_state_cap >> 0) & 0xff; - dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay; + dev_priv->rps.min_delay = (rp_state_cap & 0xff0000) >> 16; dev_priv->rps.cur_delay = 0; /* disable the counters and set deterministic thresholds */ @@ -3889,7 +3518,7 @@ static void gen6_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC_SLEEP, 0); I915_WRITE(GEN6_RC1e_THRESHOLD, 1000); - if (IS_IVYBRIDGE(dev)) + if (INTEL_INFO(dev)->gen <= 6 || IS_IVYBRIDGE(dev)) I915_WRITE(GEN6_RC6_THRESHOLD, 125000); else I915_WRITE(GEN6_RC6_THRESHOLD, 50000); @@ -3910,16 +3539,48 @@ static void gen6_enable_rps(struct drm_device *dev) rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; } - intel_print_rc6_info(dev, rc6_mask); + DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", + (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", + (rc6_mask & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", + (rc6_mask & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); I915_WRITE(GEN6_RC_CONTROL, rc6_mask | GEN6_RC_CTL_EI_MODE(1) | GEN6_RC_CTL_HW_ENABLE); - /* Power down if completely idle for over 50ms */ - I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 50000); + if (IS_HASWELL(dev)) { + I915_WRITE(GEN6_RPNSWREQ, + HSW_FREQUENCY(10)); + I915_WRITE(GEN6_RC_VIDEO_FREQ, + HSW_FREQUENCY(12)); + } else { + I915_WRITE(GEN6_RPNSWREQ, + GEN6_FREQUENCY(10) | + GEN6_OFFSET(0) | + GEN6_AGGRESSIVE_TURBO); + I915_WRITE(GEN6_RC_VIDEO_FREQ, + GEN6_FREQUENCY(12)); + } + + I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000); + I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, + dev_priv->rps.max_delay << 24 | + dev_priv->rps.min_delay << 16); + + I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); + I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); + I915_WRITE(GEN6_RP_UP_EI, 66000); + I915_WRITE(GEN6_RP_DOWN_EI, 350000); + I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); + I915_WRITE(GEN6_RP_CONTROL, + GEN6_RP_MEDIA_TURBO | + GEN6_RP_MEDIA_HW_NORMAL_MODE | + GEN6_RP_MEDIA_IS_GFX | + GEN6_RP_ENABLE | + GEN6_RP_UP_BUSY_AVG | + (IS_HASWELL(dev) ? GEN7_RP_DOWN_IDLE_AVG : GEN6_RP_DOWN_IDLE_CONT)); ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0); if (!ret) { @@ -3935,8 +3596,7 @@ static void gen6_enable_rps(struct drm_device *dev) DRM_DEBUG_DRIVER("Failed to set the min frequency\n"); } - dev_priv->rps.power = HIGH_POWER; /* force a reset */ - gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay); + gen6_set_rps(dev_priv->dev, (gt_perf_status & 0xff00) >> 8); gen6_enable_rps_interrupts(dev); @@ -3964,28 +3624,23 @@ void gen6_update_ring_freq(struct drm_device *dev) unsigned int gpu_freq; unsigned int max_ia_freq, min_ring_freq; int scaling_factor = 180; - struct cpufreq_policy *policy; WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); - policy = cpufreq_cpu_get(0); - if (policy) { - max_ia_freq = policy->cpuinfo.max_freq; - cpufreq_cpu_put(policy); - } else { - /* - * Default to measured freq if none found, PCU will ensure we - * don't go over - */ + max_ia_freq = cpufreq_quick_get_max(0); + /* + * Default to measured freq if none found, PCU will ensure we don't go + * over + */ + if (!max_ia_freq) max_ia_freq = tsc_khz; - } /* Convert from kHz to MHz */ max_ia_freq /= 1000; - min_ring_freq = I915_READ(DCLK) & 0xf; - /* convert DDR frequency from units of 266.6MHz to bandwidth */ - min_ring_freq = mult_frac(min_ring_freq, 8, 3); + min_ring_freq = I915_READ(MCHBAR_MIRROR_BASE_SNB + DCLK); + /* convert DDR frequency from units of 133.3MHz to bandwidth */ + min_ring_freq = (2 * 4 * min_ring_freq + 2) / 3; /* * For each potential GPU frequency, load a ring frequency we'd like @@ -3997,11 +3652,8 @@ void gen6_update_ring_freq(struct drm_device *dev) int diff = dev_priv->rps.max_delay - gpu_freq; unsigned int ia_freq = 0, ring_freq = 0; - if (INTEL_INFO(dev)->gen >= 8) { - /* max(2 * GT, DDR). NB: GT is 50MHz units */ - ring_freq = max(min_ring_freq, gpu_freq); - } else if (IS_HASWELL(dev)) { - ring_freq = mult_frac(gpu_freq, 5, 4); + if (IS_HASWELL(dev)) { + ring_freq = (gpu_freq * 5 + 3) / 4; ring_freq = max(min_ring_freq, ring_freq); /* leave ia_freq as the default, chosen by cpufreq */ } else { @@ -4057,6 +3709,24 @@ int valleyview_rps_min_freq(struct drm_i915_private *dev_priv) return vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM) & 0xff; } +static void vlv_rps_timer_work(struct work_struct *work) +{ + drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, + rps.vlv_work.work); + + /* + * Timer fired, we must be idle. Drop to min voltage state. + * Note: we use RPe here since it should match the + * Vmin we were shooting for. That should give us better + * perf when we come back out of RC6 than if we used the + * min freq available. + */ + mutex_lock(&dev_priv->rps.hw_lock); + if (dev_priv->rps.cur_delay > dev_priv->rps.rpe_delay) + valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay); + mutex_unlock(&dev_priv->rps.hw_lock); +} + static void valleyview_setup_pctx(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -4103,14 +3773,13 @@ static void valleyview_enable_rps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_ring_buffer *ring; - u32 gtfifodbg, val, rc6_mode = 0; + u32 gtfifodbg, val; int i; WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); if ((gtfifodbg = I915_READ(GTFIFODBG))) { - DRM_DEBUG_DRIVER("GT fifo had a previous error %x\n", - gtfifodbg); + DRM_ERROR("GT fifo had a previous error %x\n", gtfifodbg); I915_WRITE(GTFIFODBG, gtfifodbg); } @@ -4143,16 +3812,9 @@ static void valleyview_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC6_THRESHOLD, 0xc350); /* allows RC6 residency counter to work */ - I915_WRITE(VLV_COUNTER_CONTROL, - _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH | - VLV_MEDIA_RC6_COUNT_EN | - VLV_RENDER_RC6_COUNT_EN)); - if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE) - rc6_mode = GEN7_RC_CTL_TO_MODE; - - intel_print_rc6_info(dev, rc6_mode); - - I915_WRITE(GEN6_RC_CONTROL, rc6_mode); + I915_WRITE(0x138104, _MASKED_BIT_ENABLE(0x3)); + I915_WRITE(GEN6_RC_CONTROL, + GEN7_RC_CTL_TO_MODE); val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); switch ((val >> 6) & 3) { @@ -4323,8 +3985,6 @@ static void ironlake_enable_rc6(struct drm_device *dev) I915_WRITE(PWRCTXA, i915_gem_obj_ggtt_offset(dev_priv->ips.pwrctx) | PWRCTX_EN); I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); - - intel_print_rc6_info(dev, INTEL_RC6_ENABLE); } static unsigned long intel_pxfreq(u32 vidfreq) @@ -4943,12 +4603,13 @@ void intel_disable_gt_powersave(struct drm_device *dev) } else if (INTEL_INFO(dev)->gen >= 6) { cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work); cancel_work_sync(&dev_priv->rps.work); + if (IS_VALLEYVIEW(dev)) + cancel_delayed_work_sync(&dev_priv->rps.vlv_work); mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev)) valleyview_disable_rps(dev); else gen6_disable_rps(dev); - dev_priv->rps.enabled = false; mutex_unlock(&dev_priv->rps.hw_lock); } } @@ -4964,14 +4625,10 @@ static void intel_gen6_powersave_work(struct work_struct *work) if (IS_VALLEYVIEW(dev)) { valleyview_enable_rps(dev); - } else if (IS_BROADWELL(dev)) { - gen8_enable_rps(dev); - gen6_update_ring_freq(dev); } else { gen6_enable_rps(dev); gen6_update_ring_freq(dev); } - dev_priv->rps.enabled = true; mutex_unlock(&dev_priv->rps.hw_lock); } @@ -5015,7 +4672,7 @@ static void g4x_disable_trickle_feed(struct drm_device *dev) I915_WRITE(DSPCNTR(pipe), I915_READ(DSPCNTR(pipe)) | DISPPLANE_TRICKLE_FEED_DISABLE); - intel_flush_primary_plane(dev_priv, pipe); + intel_flush_display_plane(dev_priv, pipe); } } @@ -5275,50 +4932,6 @@ static void lpt_suspend_hw(struct drm_device *dev) } } -static void gen8_init_clock_gating(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - enum pipe i; - - I915_WRITE(WM3_LP_ILK, 0); - I915_WRITE(WM2_LP_ILK, 0); - I915_WRITE(WM1_LP_ILK, 0); - - /* FIXME(BDW): Check all the w/a, some might only apply to - * pre-production hw. */ - - WARN(!i915_preliminary_hw_support, - "GEN8_CENTROID_PIXEL_OPT_DIS not be needed for production\n"); - I915_WRITE(HALF_SLICE_CHICKEN3, - _MASKED_BIT_ENABLE(GEN8_CENTROID_PIXEL_OPT_DIS)); - I915_WRITE(HALF_SLICE_CHICKEN3, - _MASKED_BIT_ENABLE(GEN8_SAMPLER_POWER_BYPASS_DIS)); - I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_BWGTLB_DISABLE)); - - I915_WRITE(_3D_CHICKEN3, - _3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(2)); - - I915_WRITE(COMMON_SLICE_CHICKEN2, - _MASKED_BIT_ENABLE(GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE)); - - I915_WRITE(GEN7_HALF_SLICE_CHICKEN1, - _MASKED_BIT_ENABLE(GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE)); - - /* WaSwitchSolVfFArbitrationPriority */ - I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); - - /* WaPsrDPAMaskVBlankInSRD */ - I915_WRITE(CHICKEN_PAR1_1, - I915_READ(CHICKEN_PAR1_1) | DPA_MASK_VBLANK_SRD); - - /* WaPsrDPRSUnmaskVBlankInSRD */ - for_each_pipe(i) { - I915_WRITE(CHICKEN_PIPESL_1(i), - I915_READ(CHICKEN_PIPESL_1(i) | - DPRS_MASK_VBLANK_SRD)); - } -} - static void haswell_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -5642,25 +5255,6 @@ void intel_suspend_hw(struct drm_device *dev) lpt_suspend_hw(dev); } -static bool is_always_on_power_domain(struct drm_device *dev, - enum intel_display_power_domain domain) -{ - unsigned long always_on_domains; - - BUG_ON(BIT(domain) & ~POWER_DOMAIN_MASK); - - if (IS_BROADWELL(dev)) { - always_on_domains = BDW_ALWAYS_ON_POWER_DOMAINS; - } else if (IS_HASWELL(dev)) { - always_on_domains = HSW_ALWAYS_ON_POWER_DOMAINS; - } else { - WARN_ON(1); - return true; - } - - return BIT(domain) & always_on_domains; -} - /** * We should only use the power well if we explicitly asked the hardware to * enable it, so check if it's enabled and also check if we've requested it to @@ -5674,11 +5268,23 @@ bool intel_display_power_enabled(struct drm_device *dev, if (!HAS_POWER_WELL(dev)) return true; - if (is_always_on_power_domain(dev, domain)) + switch (domain) { + case POWER_DOMAIN_PIPE_A: + case POWER_DOMAIN_TRANSCODER_EDP: return true; - - return I915_READ(HSW_PWR_WELL_DRIVER) == + case POWER_DOMAIN_PIPE_B: + case POWER_DOMAIN_PIPE_C: + case POWER_DOMAIN_PIPE_A_PANEL_FITTER: + case POWER_DOMAIN_PIPE_B_PANEL_FITTER: + case POWER_DOMAIN_PIPE_C_PANEL_FITTER: + case POWER_DOMAIN_TRANSCODER_A: + case POWER_DOMAIN_TRANSCODER_B: + case POWER_DOMAIN_TRANSCODER_C: + return I915_READ(HSW_PWR_WELL_DRIVER) == (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED); + default: + BUG(); + } } static void __intel_set_power_well(struct drm_device *dev, bool enable) @@ -5722,136 +5328,83 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) spin_lock_irqsave(&dev->vbl_lock, irqflags); for_each_pipe(p) if (p != PIPE_A) - dev->vblank[p].last = 0; + dev->last_vblank[p] = 0; spin_unlock_irqrestore(&dev->vbl_lock, irqflags); } } } -static void __intel_power_well_get(struct drm_device *dev, - struct i915_power_well *power_well) -{ - if (!power_well->count++) - __intel_set_power_well(dev, true); -} - -static void __intel_power_well_put(struct drm_device *dev, - struct i915_power_well *power_well) -{ - WARN_ON(!power_well->count); - if (!--power_well->count && i915_disable_power_well) - __intel_set_power_well(dev, false); -} - -void intel_display_power_get(struct drm_device *dev, - enum intel_display_power_domain domain) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_power_domains *power_domains; - - if (!HAS_POWER_WELL(dev)) - return; - - if (is_always_on_power_domain(dev, domain)) - return; - - power_domains = &dev_priv->power_domains; - - mutex_lock(&power_domains->lock); - __intel_power_well_get(dev, &power_domains->power_wells[0]); - mutex_unlock(&power_domains->lock); -} - -void intel_display_power_put(struct drm_device *dev, - enum intel_display_power_domain domain) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_power_domains *power_domains; - - if (!HAS_POWER_WELL(dev)) - return; - - if (is_always_on_power_domain(dev, domain)) - return; - - power_domains = &dev_priv->power_domains; - - mutex_lock(&power_domains->lock); - __intel_power_well_put(dev, &power_domains->power_wells[0]); - mutex_unlock(&power_domains->lock); -} - -static struct i915_power_domains *hsw_pwr; +static struct i915_power_well *hsw_pwr; /* Display audio driver power well request */ void i915_request_power_well(void) { - struct drm_i915_private *dev_priv; - if (WARN_ON(!hsw_pwr)) return; - dev_priv = container_of(hsw_pwr, struct drm_i915_private, - power_domains); - - mutex_lock(&hsw_pwr->lock); - __intel_power_well_get(dev_priv->dev, &hsw_pwr->power_wells[0]); - mutex_unlock(&hsw_pwr->lock); + spin_lock_irq(&hsw_pwr->lock); + if (!hsw_pwr->count++ && + !hsw_pwr->i915_request) + __intel_set_power_well(hsw_pwr->device, true); + spin_unlock_irq(&hsw_pwr->lock); } EXPORT_SYMBOL_GPL(i915_request_power_well); /* Display audio driver power well release */ void i915_release_power_well(void) { - struct drm_i915_private *dev_priv; - if (WARN_ON(!hsw_pwr)) return; - dev_priv = container_of(hsw_pwr, struct drm_i915_private, - power_domains); - - mutex_lock(&hsw_pwr->lock); - __intel_power_well_put(dev_priv->dev, &hsw_pwr->power_wells[0]); - mutex_unlock(&hsw_pwr->lock); + spin_lock_irq(&hsw_pwr->lock); + WARN_ON(!hsw_pwr->count); + if (!--hsw_pwr->count && + !hsw_pwr->i915_request) + __intel_set_power_well(hsw_pwr->device, false); + spin_unlock_irq(&hsw_pwr->lock); } EXPORT_SYMBOL_GPL(i915_release_power_well); -int intel_power_domains_init(struct drm_device *dev) +int i915_init_power_well(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_power_domains *power_domains = &dev_priv->power_domains; - struct i915_power_well *power_well; - mutex_init(&power_domains->lock); - hsw_pwr = power_domains; + hsw_pwr = &dev_priv->power_well; - power_well = &power_domains->power_wells[0]; - power_well->count = 0; + hsw_pwr->device = dev; + spin_lock_init(&hsw_pwr->lock); + hsw_pwr->count = 0; return 0; } -void intel_power_domains_remove(struct drm_device *dev) +void i915_remove_power_well(struct drm_device *dev) { hsw_pwr = NULL; } -static void intel_power_domains_resume(struct drm_device *dev) +void intel_set_power_well(struct drm_device *dev, bool enable) { struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_power_domains *power_domains = &dev_priv->power_domains; - struct i915_power_well *power_well; + struct i915_power_well *power_well = &dev_priv->power_well; if (!HAS_POWER_WELL(dev)) return; - mutex_lock(&power_domains->lock); + if (!i915_disable_power_well && !enable) + return; - power_well = &power_domains->power_wells[0]; - __intel_set_power_well(dev, power_well->count > 0); + spin_lock_irq(&power_well->lock); + power_well->i915_request = enable; - mutex_unlock(&power_domains->lock); + /* only reject "disable" power well request */ + if (power_well->count && !enable) { + spin_unlock_irq(&power_well->lock); + return; + } + + __intel_set_power_well(dev, enable); + spin_unlock_irq(&power_well->lock); } /* @@ -5860,7 +5413,7 @@ static void intel_power_domains_resume(struct drm_device *dev) * to be enabled, and it will only be disabled if none of the registers is * requesting it to be enabled. */ -void intel_power_domains_init_hw(struct drm_device *dev) +void intel_init_power_well(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -5868,8 +5421,7 @@ void intel_power_domains_init_hw(struct drm_device *dev) return; /* For now, we need the power well to be always enabled. */ - intel_display_set_init_power(dev, true); - intel_power_domains_resume(dev); + intel_set_power_well(dev, true); /* We're taking over the BIOS, so clear any requests made by it since * the driver is in charge now. */ @@ -5973,8 +5525,6 @@ void intel_init_pm(struct drm_device *dev) dev_priv->display.update_wm = NULL; } dev_priv->display.init_clock_gating = haswell_init_clock_gating; - } else if (INTEL_INFO(dev)->gen == 8) { - dev_priv->display.init_clock_gating = gen8_init_clock_gating; } else dev_priv->display.update_wm = NULL; } else if (IS_VALLEYVIEW(dev)) { @@ -6136,4 +5686,7 @@ void intel_pm_init(struct drm_device *dev) INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work, intel_gen6_powersave_work); + + INIT_DELAYED_WORK(&dev_priv->rps.vlv_work, vlv_rps_timer_work); } + diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index b620337..460ee10 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -41,16 +41,6 @@ static inline int ring_space(struct intel_ring_buffer *ring) return space; } -void __intel_ring_advance(struct intel_ring_buffer *ring) -{ - struct drm_i915_private *dev_priv = ring->dev->dev_private; - - ring->tail &= ring->size - 1; - if (dev_priv->gpu_error.stop_rings & intel_ring_flag(ring)) - return; - ring->write_tail(ring, ring->tail); -} - static int gen2_render_ring_flush(struct intel_ring_buffer *ring, u32 invalidate_domains, @@ -360,47 +350,6 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring, return 0; } -static int -gen8_render_ring_flush(struct intel_ring_buffer *ring, - u32 invalidate_domains, u32 flush_domains) -{ - u32 flags = 0; - u32 scratch_addr = ring->scratch.gtt_offset + 128; - int ret; - - flags |= PIPE_CONTROL_CS_STALL; - - if (flush_domains) { - flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; - flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; - } - if (invalidate_domains) { - flags |= PIPE_CONTROL_TLB_INVALIDATE; - flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_QW_WRITE; - flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; - } - - ret = intel_ring_begin(ring, 6); - if (ret) - return ret; - - intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); - intel_ring_emit(ring, flags); - intel_ring_emit(ring, scratch_addr); - intel_ring_emit(ring, 0); - intel_ring_emit(ring, 0); - intel_ring_emit(ring, 0); - intel_ring_advance(ring); - - return 0; - -} - static void ring_write_tail(struct intel_ring_buffer *ring, u32 value) { @@ -436,7 +385,8 @@ static int init_ring_common(struct intel_ring_buffer *ring) int ret = 0; u32 head; - gen6_gt_force_wake_get(dev_priv); + if (HAS_FORCE_WAKE(dev)) + gen6_gt_force_wake_get(dev_priv); if (I915_NEED_GFX_HWS(dev)) intel_ring_setup_status_page(ring); @@ -509,7 +459,8 @@ static int init_ring_common(struct intel_ring_buffer *ring) memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); out: - gen6_gt_force_wake_put(dev_priv); + if (HAS_FORCE_WAKE(dev)) + gen6_gt_force_wake_put(dev_priv); return ret; } @@ -608,8 +559,8 @@ static int init_render_ring(struct intel_ring_buffer *ring) if (INTEL_INFO(dev)->gen >= 6) I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); - if (HAS_L3_DPF(dev)) - I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); + if (HAS_L3_GPU_CACHE(dev)) + I915_WRITE_IMR(ring, ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); return ret; } @@ -642,7 +593,7 @@ update_mboxes(struct intel_ring_buffer *ring, #define MBOX_UPDATE_DWORDS 4 intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); intel_ring_emit(ring, mmio_offset); - intel_ring_emit(ring, ring->outstanding_lazy_seqno); + intel_ring_emit(ring, ring->outstanding_lazy_request); intel_ring_emit(ring, MI_NOOP); } @@ -678,9 +629,9 @@ gen6_add_request(struct intel_ring_buffer *ring) 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, ring->outstanding_lazy_seqno); + intel_ring_emit(ring, ring->outstanding_lazy_request); intel_ring_emit(ring, MI_USER_INTERRUPT); - __intel_ring_advance(ring); + intel_ring_advance(ring); return 0; } @@ -772,7 +723,7 @@ pc_render_add_request(struct intel_ring_buffer *ring) PIPE_CONTROL_WRITE_FLUSH | PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); - intel_ring_emit(ring, ring->outstanding_lazy_seqno); + intel_ring_emit(ring, ring->outstanding_lazy_request); intel_ring_emit(ring, 0); PIPE_CONTROL_FLUSH(ring, scratch_addr); scratch_addr += 128; /* write to separate cachelines */ @@ -791,9 +742,9 @@ pc_render_add_request(struct intel_ring_buffer *ring) PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | PIPE_CONTROL_NOTIFY); intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); - intel_ring_emit(ring, ring->outstanding_lazy_seqno); + intel_ring_emit(ring, ring->outstanding_lazy_request); intel_ring_emit(ring, 0); - __intel_ring_advance(ring); + intel_ring_advance(ring); return 0; } @@ -1012,9 +963,9 @@ i9xx_add_request(struct intel_ring_buffer *ring) 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, ring->outstanding_lazy_seqno); + intel_ring_emit(ring, ring->outstanding_lazy_request); intel_ring_emit(ring, MI_USER_INTERRUPT); - __intel_ring_advance(ring); + intel_ring_advance(ring); return 0; } @@ -1036,10 +987,10 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring) spin_lock_irqsave(&dev_priv->irq_lock, flags); if (ring->irq_refcount++ == 0) { - if (HAS_L3_DPF(dev) && ring->id == RCS) + if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | - GT_PARITY_ERROR(dev))); + GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); else I915_WRITE_IMR(ring, ~ring->irq_enable_mask); ilk_enable_gt_irq(dev_priv, ring->irq_enable_mask); @@ -1058,8 +1009,9 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring) spin_lock_irqsave(&dev_priv->irq_lock, flags); if (--ring->irq_refcount == 0) { - if (HAS_L3_DPF(dev) && ring->id == RCS) - I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); + if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) + I915_WRITE_IMR(ring, + ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); else I915_WRITE_IMR(ring, ~0); ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask); @@ -1107,52 +1059,6 @@ hsw_vebox_put_irq(struct intel_ring_buffer *ring) spin_unlock_irqrestore(&dev_priv->irq_lock, flags); } -static bool -gen8_ring_get_irq(struct intel_ring_buffer *ring) -{ - struct drm_device *dev = ring->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - unsigned long flags; - - if (!dev->irq_enabled) - return false; - - spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (ring->irq_refcount++ == 0) { - if (HAS_L3_DPF(dev) && ring->id == RCS) { - I915_WRITE_IMR(ring, - ~(ring->irq_enable_mask | - GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); - } else { - I915_WRITE_IMR(ring, ~ring->irq_enable_mask); - } - POSTING_READ(RING_IMR(ring->mmio_base)); - } - spin_unlock_irqrestore(&dev_priv->irq_lock, flags); - - return true; -} - -static void -gen8_ring_put_irq(struct intel_ring_buffer *ring) -{ - struct drm_device *dev = ring->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - unsigned long flags; - - spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (--ring->irq_refcount == 0) { - if (HAS_L3_DPF(dev) && ring->id == RCS) { - I915_WRITE_IMR(ring, - ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); - } else { - I915_WRITE_IMR(ring, ~0); - } - POSTING_READ(RING_IMR(ring->mmio_base)); - } - spin_unlock_irqrestore(&dev_priv->irq_lock, flags); -} - static int i965_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 length, @@ -1411,7 +1317,7 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring) /* Disable the ring buffer. The ring must be idle at this point */ dev_priv = ring->dev->dev_private; ret = intel_ring_idle(ring); - if (ret && !i915_reset_in_progress(&dev_priv->gpu_error)) + if (ret) DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", ring->name, ret); @@ -1422,8 +1328,6 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring) i915_gem_object_unpin(ring->obj); drm_gem_object_unreference(&ring->obj->base); ring->obj = NULL; - ring->preallocated_lazy_request = NULL; - ring->outstanding_lazy_seqno = 0; if (ring->cleanup) ring->cleanup(ring); @@ -1510,9 +1414,6 @@ static int ring_wait_for_space(struct intel_ring_buffer *ring, int n) if (ret != -ENOSPC) return ret; - /* force the tail write in case we have been skipping them */ - __intel_ring_advance(ring); - trace_i915_ring_wait_begin(ring); /* With GEM the hangcheck timer should kick us out of the loop, * leaving it early runs the risk of corrupting GEM state (due @@ -1574,7 +1475,7 @@ int intel_ring_idle(struct intel_ring_buffer *ring) int ret; /* We need to add any requests required to flush the objects and ring */ - if (ring->outstanding_lazy_seqno) { + if (ring->outstanding_lazy_request) { ret = i915_add_request(ring, NULL); if (ret) return ret; @@ -1594,20 +1495,10 @@ int intel_ring_idle(struct intel_ring_buffer *ring) static int intel_ring_alloc_seqno(struct intel_ring_buffer *ring) { - if (ring->outstanding_lazy_seqno) + if (ring->outstanding_lazy_request) return 0; - if (ring->preallocated_lazy_request == NULL) { - struct drm_i915_gem_request *request; - - request = kmalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) - return -ENOMEM; - - ring->preallocated_lazy_request = request; - } - - return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno); + return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_request); } static int __intel_ring_begin(struct intel_ring_buffer *ring, @@ -1654,7 +1545,7 @@ void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno) { struct drm_i915_private *dev_priv = ring->dev->dev_private; - BUG_ON(ring->outstanding_lazy_seqno); + BUG_ON(ring->outstanding_lazy_request); if (INTEL_INFO(ring->dev)->gen >= 6) { I915_WRITE(RING_SYNC_0(ring->mmio_base), 0); @@ -1667,6 +1558,17 @@ void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno) ring->hangcheck.seqno = seqno; } +void intel_ring_advance(struct intel_ring_buffer *ring) +{ + struct drm_i915_private *dev_priv = ring->dev->dev_private; + + ring->tail &= ring->size - 1; + if (dev_priv->gpu_error.stop_rings & intel_ring_flag(ring)) + return; + ring->write_tail(ring, ring->tail); +} + + static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring, u32 value) { @@ -1711,8 +1613,6 @@ static int gen6_bsd_ring_flush(struct intel_ring_buffer *ring, return ret; cmd = MI_FLUSH_DW; - if (INTEL_INFO(ring->dev)->gen >= 8) - cmd += 1; /* * Bspec vol 1c.5 - video engine command streamer: * "If ENABLED, all TLBs will be invalidated once the flush @@ -1724,38 +1624,9 @@ static int gen6_bsd_ring_flush(struct intel_ring_buffer *ring, MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; intel_ring_emit(ring, cmd); intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); - if (INTEL_INFO(ring->dev)->gen >= 8) { - intel_ring_emit(ring, 0); /* upper addr */ - intel_ring_emit(ring, 0); /* value */ - } else { - intel_ring_emit(ring, 0); - intel_ring_emit(ring, MI_NOOP); - } - intel_ring_advance(ring); - return 0; -} - -static int -gen8_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, - u32 offset, u32 len, - unsigned flags) -{ - struct drm_i915_private *dev_priv = ring->dev->dev_private; - bool ppgtt = dev_priv->mm.aliasing_ppgtt != NULL && - !(flags & I915_DISPATCH_SECURE); - int ret; - - ret = intel_ring_begin(ring, 4); - if (ret) - return ret; - - /* FIXME(BDW): Address space and security selectors. */ - intel_ring_emit(ring, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8)); - intel_ring_emit(ring, offset); intel_ring_emit(ring, 0); intel_ring_emit(ring, MI_NOOP); intel_ring_advance(ring); - return 0; } @@ -1815,8 +1686,6 @@ static int gen6_ring_flush(struct intel_ring_buffer *ring, return ret; cmd = MI_FLUSH_DW; - if (INTEL_INFO(ring->dev)->gen >= 8) - cmd += 1; /* * Bspec vol 1c.3 - blitter engine command streamer: * "If ENABLED, all TLBs will be invalidated once the flush @@ -1828,13 +1697,8 @@ static int gen6_ring_flush(struct intel_ring_buffer *ring, MI_FLUSH_DW_OP_STOREDW; intel_ring_emit(ring, cmd); intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); - if (INTEL_INFO(ring->dev)->gen >= 8) { - intel_ring_emit(ring, 0); /* upper addr */ - intel_ring_emit(ring, 0); /* value */ - } else { - intel_ring_emit(ring, 0); - intel_ring_emit(ring, MI_NOOP); - } + intel_ring_emit(ring, 0); + intel_ring_emit(ring, MI_NOOP); intel_ring_advance(ring); if (IS_GEN7(dev) && flush) @@ -1857,14 +1721,8 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ring->flush = gen7_render_ring_flush; if (INTEL_INFO(dev)->gen == 6) ring->flush = gen6_render_ring_flush; - if (INTEL_INFO(dev)->gen >= 8) { - ring->flush = gen8_render_ring_flush; - ring->irq_get = gen8_ring_get_irq; - ring->irq_put = gen8_ring_put_irq; - } else { - ring->irq_get = gen6_ring_get_irq; - ring->irq_put = gen6_ring_put_irq; - } + ring->irq_get = gen6_ring_get_irq; + ring->irq_put = gen6_ring_put_irq; ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; ring->get_seqno = gen6_ring_get_seqno; ring->set_seqno = ring_set_seqno; @@ -1906,8 +1764,6 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ring->write_tail = ring_write_tail; if (IS_HASWELL(dev)) ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer; - else if (IS_GEN8(dev)) - ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; else if (INTEL_INFO(dev)->gen >= 6) ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; else if (INTEL_INFO(dev)->gen >= 4) @@ -2021,7 +1877,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) ring->id = VCS; ring->write_tail = ring_write_tail; - if (INTEL_INFO(dev)->gen >= 6) { + if (IS_GEN6(dev) || IS_GEN7(dev)) { ring->mmio_base = GEN6_BSD_RING_BASE; /* gen6 bsd needs a special wa for tail updates */ if (IS_GEN6(dev)) @@ -2030,20 +1886,10 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) ring->add_request = gen6_add_request; ring->get_seqno = gen6_ring_get_seqno; ring->set_seqno = ring_set_seqno; - if (INTEL_INFO(dev)->gen >= 8) { - ring->irq_enable_mask = - GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; - ring->irq_get = gen8_ring_get_irq; - ring->irq_put = gen8_ring_put_irq; - ring->dispatch_execbuffer = - gen8_ring_dispatch_execbuffer; - } else { - ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; - ring->irq_get = gen6_ring_get_irq; - ring->irq_put = gen6_ring_put_irq; - ring->dispatch_execbuffer = - gen6_ring_dispatch_execbuffer; - } + ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; + ring->irq_get = gen6_ring_get_irq; + ring->irq_put = gen6_ring_put_irq; + ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; ring->sync_to = gen6_ring_sync; ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_VR; ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_INVALID; @@ -2089,18 +1935,10 @@ int intel_init_blt_ring_buffer(struct drm_device *dev) ring->add_request = gen6_add_request; ring->get_seqno = gen6_ring_get_seqno; ring->set_seqno = ring_set_seqno; - if (INTEL_INFO(dev)->gen >= 8) { - ring->irq_enable_mask = - GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; - ring->irq_get = gen8_ring_get_irq; - ring->irq_put = gen8_ring_put_irq; - ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; - } else { - ring->irq_enable_mask = GT_BLT_USER_INTERRUPT; - ring->irq_get = gen6_ring_get_irq; - ring->irq_put = gen6_ring_put_irq; - ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; - } + ring->irq_enable_mask = GT_BLT_USER_INTERRUPT; + ring->irq_get = gen6_ring_get_irq; + ring->irq_put = gen6_ring_put_irq; + ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; ring->sync_to = gen6_ring_sync; ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_BR; ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_BV; @@ -2129,19 +1967,10 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev) ring->add_request = gen6_add_request; ring->get_seqno = gen6_ring_get_seqno; ring->set_seqno = ring_set_seqno; - - if (INTEL_INFO(dev)->gen >= 8) { - ring->irq_enable_mask = - GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT; - ring->irq_get = gen8_ring_get_irq; - ring->irq_put = gen8_ring_put_irq; - ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; - } else { - ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; - ring->irq_get = hsw_vebox_get_irq; - ring->irq_put = hsw_vebox_put_irq; - ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; - } + ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; + ring->irq_get = hsw_vebox_get_irq; + ring->irq_put = hsw_vebox_put_irq; + ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; ring->sync_to = gen6_ring_sync; ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_VER; ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_VEV; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 71a73f4..68b1ca974 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -34,7 +34,6 @@ struct intel_hw_status_page { #define I915_WRITE_IMR(ring, val) I915_WRITE(RING_IMR((ring)->mmio_base), val) enum intel_ring_hangcheck_action { - HANGCHECK_IDLE = 0, HANGCHECK_WAIT, HANGCHECK_ACTIVE, HANGCHECK_KICK, @@ -141,8 +140,7 @@ struct intel_ring_buffer { /** * Do we have some not yet emitted requests outstanding? */ - struct drm_i915_gem_request *preallocated_lazy_request; - u32 outstanding_lazy_seqno; + u32 outstanding_lazy_request; bool gpu_caches_dirty; bool fbc_dirty; @@ -239,12 +237,7 @@ static inline void intel_ring_emit(struct intel_ring_buffer *ring, iowrite32(data, ring->virtual_start + ring->tail); ring->tail += 4; } -static inline void intel_ring_advance(struct intel_ring_buffer *ring) -{ - ring->tail &= ring->size - 1; -} -void __intel_ring_advance(struct intel_ring_buffer *ring); - +void intel_ring_advance(struct intel_ring_buffer *ring); int __must_check intel_ring_idle(struct intel_ring_buffer *ring); void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno); int intel_ring_flush_all_caches(struct intel_ring_buffer *ring); @@ -265,8 +258,8 @@ static inline u32 intel_ring_get_tail(struct intel_ring_buffer *ring) static inline u32 intel_ring_get_seqno(struct intel_ring_buffer *ring) { - BUG_ON(ring->outstanding_lazy_seqno == 0); - return ring->outstanding_lazy_seqno; + BUG_ON(ring->outstanding_lazy_request == 0); + return ring->outstanding_lazy_request; } static inline void i915_trace_irq_get(struct intel_ring_buffer *ring, u32 seqno) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index a583e8f..49482fd 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -539,7 +539,7 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo, goto log_fail; while ((status == SDVO_CMD_STATUS_PENDING || - status == SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED) && --retry) { + status == SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED) && --retry) { if (retry < 10) msleep(15); else @@ -1068,7 +1068,7 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_config *pipe_config) { - unsigned dotclock = pipe_config->port_clock; + unsigned dotclock = pipe_config->adjusted_mode.clock; struct dpll *clock = &pipe_config->dpll; /* SDVO TV has fixed PLL values depend on its clock range, @@ -1133,6 +1133,7 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, */ pipe_config->pixel_multiplier = intel_sdvo_get_pixel_multiplier(adjusted_mode); + adjusted_mode->clock *= pipe_config->pixel_multiplier; if (intel_sdvo->color_range_auto) { /* See CEA-861-E - 5.1 Default Encoding Parameters */ @@ -1216,7 +1217,11 @@ static void intel_sdvo_mode_set(struct intel_encoder *intel_encoder) !intel_sdvo_set_tv_format(intel_sdvo)) return; + /* We have tried to get input timing in mode_fixup, and filled into + * adjusted_mode. + */ intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); + input_dtd.part1.clock /= crtc->config.pixel_multiplier; if (intel_sdvo->is_tv || intel_sdvo->is_lvds) input_dtd.part2.sdvo_flags = intel_sdvo->dtd_sdvo_flags; @@ -1325,7 +1330,6 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, struct intel_sdvo *intel_sdvo = to_sdvo(encoder); struct intel_sdvo_dtd dtd; int encoder_pixel_multiplier = 0; - int dotclock; u32 flags = 0, sdvox; u8 val; bool ret; @@ -1364,13 +1368,6 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, >> SDVO_PORT_MULTIPLY_SHIFT) + 1; } - dotclock = pipe_config->port_clock / pipe_config->pixel_multiplier; - - if (HAS_PCH_SPLIT(dev)) - ironlake_check_encoder_dotclock(pipe_config, dotclock); - - pipe_config->adjusted_mode.crtc_clock = dotclock; - /* Cross check the port pixel multiplier with the sdvo encoder state. */ if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_CLOCK_RATE_MULT, &val, 1)) { @@ -1773,9 +1770,6 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) { struct edid *edid; - DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", - connector->base.id, drm_get_connector_name(connector)); - /* set the bus switch and get the modes */ edid = intel_sdvo_get_edid(connector); @@ -1871,9 +1865,6 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector) uint32_t reply = 0, format_map = 0; int i; - DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", - connector->base.id, drm_get_connector_name(connector)); - /* Read the list of supported input resolutions for the selected TV * format. */ @@ -1908,9 +1899,6 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) struct drm_i915_private *dev_priv = connector->dev->dev_private; struct drm_display_mode *newmode; - DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", - connector->base.id, drm_get_connector_name(connector)); - /* * Fetch modes from VBT. For SDVO prefer the VBT mode since some * SDVO->LVDS transcoders can't cope with the EDID mode. @@ -1942,6 +1930,7 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) break; } } + } static int intel_sdvo_get_modes(struct drm_connector *connector) @@ -2009,6 +1998,7 @@ static void intel_sdvo_destroy(struct drm_connector *connector) intel_sdvo_connector->tv_format); intel_sdvo_destroy_enhance_property(connector); + drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); kfree(intel_sdvo_connector); } @@ -2404,9 +2394,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - DRM_DEBUG_KMS("initialising DVI device %d\n", device); - - intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); + intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); if (!intel_sdvo_connector) return false; @@ -2454,9 +2442,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - DRM_DEBUG_KMS("initialising TV type %d\n", type); - - intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); + intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); if (!intel_sdvo_connector) return false; @@ -2481,7 +2467,6 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) return true; err: - drm_sysfs_connector_remove(connector); intel_sdvo_destroy(connector); return false; } @@ -2494,9 +2479,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device) struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - DRM_DEBUG_KMS("initialising analog device %d\n", device); - - intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); + intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); if (!intel_sdvo_connector) return false; @@ -2527,9 +2510,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - DRM_DEBUG_KMS("initialising LVDS device %d\n", device); - - intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); + intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); if (!intel_sdvo_connector) return false; @@ -2553,7 +2534,6 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) return true; err: - drm_sysfs_connector_remove(connector); intel_sdvo_destroy(connector); return false; } @@ -2625,10 +2605,8 @@ static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo) list_for_each_entry_safe(connector, tmp, &dev->mode_config.connector_list, head) { - if (intel_attached_encoder(connector) == &intel_sdvo->base) { - drm_sysfs_connector_remove(connector); + if (intel_attached_encoder(connector) == &intel_sdvo->base) intel_sdvo_destroy(connector); - } } } @@ -2898,7 +2876,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) struct intel_encoder *intel_encoder; struct intel_sdvo *intel_sdvo; int i; - intel_sdvo = kzalloc(sizeof(*intel_sdvo), GFP_KERNEL); + intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL); if (!intel_sdvo) return false; diff --git a/drivers/gpu/drm/i915/intel_sideband.c b/drivers/gpu/drm/i915/intel_sideband.c index 9944d81..9a0e6c5 100644 --- a/drivers/gpu/drm/i915/intel_sideband.c +++ b/drivers/gpu/drm/i915/intel_sideband.c @@ -25,10 +25,7 @@ #include "i915_drv.h" #include "intel_drv.h" -/* - * IOSF sideband, see VLV2_SidebandMsg_HAS.docx and - * VLV_VLV2_PUNIT_HAS_0.8.docx - */ +/* IOSF sideband */ static int vlv_sideband_rw(struct drm_i915_private *dev_priv, u32 devfn, u32 port, u32 opcode, u32 addr, u32 *val) { @@ -104,83 +101,19 @@ u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr) return val; } -u32 vlv_gpio_nc_read(struct drm_i915_private *dev_priv, u32 reg) -{ - u32 val = 0; - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_GPIO_NC, - PUNIT_OPCODE_REG_READ, reg, &val); - return val; -} - -void vlv_gpio_nc_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) -{ - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_GPIO_NC, - PUNIT_OPCODE_REG_WRITE, reg, &val); -} - -u32 vlv_cck_read(struct drm_i915_private *dev_priv, u32 reg) -{ - u32 val = 0; - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_CCK, - PUNIT_OPCODE_REG_READ, reg, &val); - return val; -} - -void vlv_cck_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) -{ - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_CCK, - PUNIT_OPCODE_REG_WRITE, reg, &val); -} - -u32 vlv_ccu_read(struct drm_i915_private *dev_priv, u32 reg) -{ - u32 val = 0; - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_CCU, - PUNIT_OPCODE_REG_READ, reg, &val); - return val; -} - -void vlv_ccu_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) -{ - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_CCU, - PUNIT_OPCODE_REG_WRITE, reg, &val); -} - -u32 vlv_gps_core_read(struct drm_i915_private *dev_priv, u32 reg) -{ - u32 val = 0; - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_GPS_CORE, - PUNIT_OPCODE_REG_READ, reg, &val); - return val; -} - -void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) -{ - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_GPS_CORE, - PUNIT_OPCODE_REG_WRITE, reg, &val); -} - -static u32 vlv_get_phy_port(enum pipe pipe) -{ - u32 port = IOSF_PORT_DPIO; - - WARN_ON ((pipe != PIPE_A) && (pipe != PIPE_B)); - - return port; -} - -u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) +u32 vlv_dpio_read(struct drm_i915_private *dev_priv, int reg) { u32 val = 0; - vlv_sideband_rw(dev_priv, DPIO_DEVFN, vlv_get_phy_port(pipe), + vlv_sideband_rw(dev_priv, DPIO_DEVFN, IOSF_PORT_DPIO, DPIO_OPCODE_REG_READ, reg, &val); + return val; } -void vlv_dpio_write(struct drm_i915_private *dev_priv, enum pipe pipe, int reg, u32 val) +void vlv_dpio_write(struct drm_i915_private *dev_priv, int reg, u32 val) { - vlv_sideband_rw(dev_priv, DPIO_DEVFN, vlv_get_phy_port(pipe), + vlv_sideband_rw(dev_priv, DPIO_DEVFN, IOSF_PORT_DPIO, DPIO_OPCODE_REG_WRITE, reg, &val); } diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index b9fabf8..ad6ec4b 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -260,14 +260,14 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, if (obj->tiling_mode != I915_TILING_NONE) sprctl |= SPRITE_TILED; - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_HASWELL(dev)) sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE; else sprctl |= SPRITE_TRICKLE_FEED_DISABLE; sprctl |= SPRITE_ENABLE; - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_HASWELL(dev)) sprctl |= SPRITE_PIPE_CSC_ENABLE; intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true, @@ -288,7 +288,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, dev_priv->sprite_scaling_enabled |= 1 << pipe; if (!scaling_was_enabled) { - intel_update_watermarks(crtc); + intel_update_watermarks(dev); intel_wait_for_vblank(dev, pipe); } sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; @@ -306,7 +306,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET * register */ - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_HASWELL(dev)) I915_WRITE(SPROFFSET(pipe), (y << 16) | x); else if (obj->tiling_mode != I915_TILING_NONE) I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x); @@ -323,7 +323,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, /* potentially re-enable LP watermarks */ if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled) - intel_update_watermarks(crtc); + intel_update_watermarks(dev); } static void @@ -349,7 +349,7 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) /* potentially re-enable LP watermarks */ if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled) - intel_update_watermarks(crtc); + intel_update_watermarks(dev); } static int @@ -521,28 +521,13 @@ intel_enable_primary(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int reg = DSPCNTR(intel_crtc->plane); - if (intel_crtc->primary_enabled) + if (!intel_crtc->primary_disabled) return; - intel_crtc->primary_enabled = true; + intel_crtc->primary_disabled = false; + intel_update_fbc(dev); I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); - intel_flush_primary_plane(dev_priv, intel_crtc->plane); - - /* - * FIXME IPS should be fine as long as one plane is - * enabled, but in practice it seems to have problems - * when going from primary only to sprite only and vice - * versa. - */ - if (intel_crtc->config.ips_enabled) { - intel_wait_for_vblank(dev, intel_crtc->pipe); - hsw_enable_ips(intel_crtc); - } - - mutex_lock(&dev->struct_mutex); - intel_update_fbc(dev); - mutex_unlock(&dev->struct_mutex); } static void @@ -553,26 +538,13 @@ intel_disable_primary(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int reg = DSPCNTR(intel_crtc->plane); - if (!intel_crtc->primary_enabled) + if (intel_crtc->primary_disabled) return; - intel_crtc->primary_enabled = false; - - mutex_lock(&dev->struct_mutex); - if (dev_priv->fbc.plane == intel_crtc->plane) - intel_disable_fbc(dev); - mutex_unlock(&dev->struct_mutex); - - /* - * FIXME IPS should be fine as long as one plane is - * enabled, but in practice it seems to have problems - * when going from primary only to sprite only and vice - * versa. - */ - hsw_disable_ips(intel_crtc); - I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); - intel_flush_primary_plane(dev_priv, intel_crtc->plane); + + intel_crtc->primary_disabled = true; + intel_update_fbc(dev); } static int @@ -651,12 +623,15 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_w, uint32_t src_h) { struct drm_device *dev = plane->dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane *intel_plane = to_intel_plane(plane); - struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct drm_i915_gem_object *obj = intel_fb->obj; - struct drm_i915_gem_object *old_obj = intel_plane->obj; - int ret; + struct intel_framebuffer *intel_fb; + struct drm_i915_gem_object *obj, *old_obj; + int pipe = intel_plane->pipe; + enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, + pipe); + int ret = 0; bool disable_primary = false; bool visible; int hscale, vscale; @@ -677,24 +652,30 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, .y2 = crtc_y + crtc_h, }; const struct drm_rect clip = { - .x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0, - .y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0, - }; - const struct { - int crtc_x, crtc_y; - unsigned int crtc_w, crtc_h; - uint32_t src_x, src_y, src_w, src_h; - } orig = { - .crtc_x = crtc_x, - .crtc_y = crtc_y, - .crtc_w = crtc_w, - .crtc_h = crtc_h, - .src_x = src_x, - .src_y = src_y, - .src_w = src_w, - .src_h = src_h, + .x2 = crtc->mode.hdisplay, + .y2 = crtc->mode.vdisplay, }; + intel_fb = to_intel_framebuffer(fb); + obj = intel_fb->obj; + + old_obj = intel_plane->obj; + + intel_plane->crtc_x = crtc_x; + intel_plane->crtc_y = crtc_y; + intel_plane->crtc_w = crtc_w; + intel_plane->crtc_h = crtc_h; + intel_plane->src_x = src_x; + intel_plane->src_y = src_y; + intel_plane->src_w = src_w; + intel_plane->src_h = src_h; + + /* Pipe must be running... */ + if (!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE)) { + DRM_DEBUG_KMS("Pipe disabled\n"); + return -EINVAL; + } + /* Don't modify another pipe's plane */ if (intel_plane->pipe != intel_crtc->pipe) { DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n"); @@ -829,7 +810,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, * we can disable the primary and save power. */ disable_primary = drm_rect_equals(&dst, &clip); - WARN_ON(disable_primary && !visible && intel_crtc->active); + WARN_ON(disable_primary && !visible); mutex_lock(&dev->struct_mutex); @@ -839,40 +820,27 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, * the sprite planes only require 128KiB alignment and 32 PTE padding. */ ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); - - mutex_unlock(&dev->struct_mutex); - if (ret) - return ret; - - intel_plane->crtc_x = orig.crtc_x; - intel_plane->crtc_y = orig.crtc_y; - intel_plane->crtc_w = orig.crtc_w; - intel_plane->crtc_h = orig.crtc_h; - intel_plane->src_x = orig.src_x; - intel_plane->src_y = orig.src_y; - intel_plane->src_w = orig.src_w; - intel_plane->src_h = orig.src_h; + goto out_unlock; + intel_plane->obj = obj; - if (intel_crtc->active) { - /* - * Be sure to re-enable the primary before the sprite is no longer - * covering it fully. - */ - if (!disable_primary) - intel_enable_primary(crtc); - - if (visible) - intel_plane->update_plane(plane, crtc, fb, obj, - crtc_x, crtc_y, crtc_w, crtc_h, - src_x, src_y, src_w, src_h); - else - intel_plane->disable_plane(plane, crtc); - - if (disable_primary) - intel_disable_primary(crtc); - } + /* + * Be sure to re-enable the primary before the sprite is no longer + * covering it fully. + */ + if (!disable_primary) + intel_enable_primary(crtc); + + if (visible) + intel_plane->update_plane(plane, crtc, fb, obj, + crtc_x, crtc_y, crtc_w, crtc_h, + src_x, src_y, src_w, src_h); + else + intel_plane->disable_plane(plane, crtc); + + if (disable_primary) + intel_disable_primary(crtc); /* Unpin old obj after new one is active to avoid ugliness */ if (old_obj) { @@ -882,15 +850,17 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, * wait for vblank to avoid ugliness, we only need to * do the pin & ref bookkeeping. */ - if (old_obj != obj && intel_crtc->active) - intel_wait_for_vblank(dev, intel_crtc->pipe); - - mutex_lock(&dev->struct_mutex); + if (old_obj != obj) { + mutex_unlock(&dev->struct_mutex); + intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe); + mutex_lock(&dev->struct_mutex); + } intel_unpin_fb_obj(old_obj); - mutex_unlock(&dev->struct_mutex); } - return 0; +out_unlock: + mutex_unlock(&dev->struct_mutex); + return ret; } static int @@ -898,7 +868,7 @@ intel_disable_plane(struct drm_plane *plane) { struct drm_device *dev = plane->dev; struct intel_plane *intel_plane = to_intel_plane(plane); - struct intel_crtc *intel_crtc; + int ret = 0; if (!plane->fb) return 0; @@ -906,25 +876,21 @@ intel_disable_plane(struct drm_plane *plane) if (WARN_ON(!plane->crtc)) return -EINVAL; - intel_crtc = to_intel_crtc(plane->crtc); + intel_enable_primary(plane->crtc); + intel_plane->disable_plane(plane, plane->crtc); - if (intel_crtc->active) { - intel_enable_primary(plane->crtc); - intel_plane->disable_plane(plane, plane->crtc); - } - - if (intel_plane->obj) { - if (intel_crtc->active) - intel_wait_for_vblank(dev, intel_plane->pipe); + if (!intel_plane->obj) + goto out; - mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(intel_plane->obj); - mutex_unlock(&dev->struct_mutex); + intel_wait_for_vblank(dev, intel_plane->pipe); - intel_plane->obj = NULL; - } + mutex_lock(&dev->struct_mutex); + intel_unpin_fb_obj(intel_plane->obj); + intel_plane->obj = NULL; + mutex_unlock(&dev->struct_mutex); +out: - return 0; + return ret; } static void intel_destroy_plane(struct drm_plane *plane) @@ -955,7 +921,7 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data, obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE); if (!obj) { - ret = -ENOENT; + ret = -EINVAL; goto out_unlock; } @@ -984,7 +950,7 @@ int intel_sprite_get_colorkey(struct drm_device *dev, void *data, obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE); if (!obj) { - ret = -ENOENT; + ret = -EINVAL; goto out_unlock; } @@ -1068,7 +1034,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) if (INTEL_INFO(dev)->gen < 5) return -ENODEV; - intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); + intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL); if (!intel_plane) return -ENOMEM; @@ -1092,7 +1058,6 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) break; case 7: - case 8: if (IS_IVYBRIDGE(dev)) { intel_plane->can_scale = true; intel_plane->max_downscale = 2; diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 22cf0f4..dd6f84b 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -902,13 +902,6 @@ intel_tv_mode_valid(struct drm_connector *connector, } -static void -intel_tv_get_config(struct intel_encoder *encoder, - struct intel_crtc_config *pipe_config) -{ - pipe_config->adjusted_mode.crtc_clock = pipe_config->port_clock; -} - static bool intel_tv_compute_config(struct intel_encoder *encoder, struct intel_crtc_config *pipe_config) @@ -919,7 +912,7 @@ intel_tv_compute_config(struct intel_encoder *encoder, if (!tv_mode) return false; - pipe_config->adjusted_mode.crtc_clock = tv_mode->clock; + pipe_config->adjusted_mode.clock = tv_mode->clock; DRM_DEBUG_KMS("forcing bpc to 8 for TV\n"); pipe_config->pipe_bpp = 8*3; @@ -1051,7 +1044,7 @@ static void intel_tv_mode_set(struct intel_encoder *encoder) tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT; /* Enable two fixes for the chips that need them. */ - if (dev->pdev->device < 0x2772) + if (dev->pci_device < 0x2772) tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX; I915_WRITE(TV_H_CTL_1, hctl1); @@ -1101,7 +1094,7 @@ static void intel_tv_mode_set(struct intel_encoder *encoder) unsigned int xsize, ysize; /* Pipe must be off here */ I915_WRITE(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE); - intel_flush_primary_plane(dev_priv, intel_crtc->plane); + intel_flush_display_plane(dev_priv, intel_crtc->plane); /* Wait for vblank for the disable to take effect */ if (IS_GEN2(dev)) @@ -1130,7 +1123,7 @@ static void intel_tv_mode_set(struct intel_encoder *encoder) I915_WRITE(pipeconf_reg, pipeconf); I915_WRITE(dspcntr_reg, dspcntr); - intel_flush_primary_plane(dev_priv, intel_crtc->plane); + intel_flush_display_plane(dev_priv, intel_crtc->plane); } j = 0; @@ -1440,6 +1433,7 @@ intel_tv_get_modes(struct drm_connector *connector) static void intel_tv_destroy(struct drm_connector *connector) { + drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -1524,7 +1518,7 @@ static const struct drm_encoder_funcs intel_tv_enc_funcs = { static int tv_is_present_in_vbt(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - union child_device_config *p_child; + struct child_device_config *p_child; int i, ret; if (!dev_priv->vbt.child_dev_num) @@ -1536,13 +1530,13 @@ static int tv_is_present_in_vbt(struct drm_device *dev) /* * If the device type is not TV, continue. */ - if (p_child->old.device_type != DEVICE_TYPE_INT_TV && - p_child->old.device_type != DEVICE_TYPE_TV) + if (p_child->device_type != DEVICE_TYPE_INT_TV && + p_child->device_type != DEVICE_TYPE_TV) continue; /* Only when the addin_offset is non-zero, it is regarded * as present. */ - if (p_child->old.addin_offset) { + if (p_child->addin_offset) { ret = 1; break; } @@ -1596,12 +1590,12 @@ intel_tv_init(struct drm_device *dev) (tv_dac_off & TVDAC_STATE_CHG_EN) != 0) return; - intel_tv = kzalloc(sizeof(*intel_tv), GFP_KERNEL); + intel_tv = kzalloc(sizeof(struct intel_tv), GFP_KERNEL); if (!intel_tv) { return; } - intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); + intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); if (!intel_connector) { kfree(intel_tv); return; @@ -1628,7 +1622,6 @@ intel_tv_init(struct drm_device *dev) DRM_MODE_ENCODER_TVDAC); intel_encoder->compute_config = intel_tv_compute_config; - intel_encoder->get_config = intel_tv_get_config; intel_encoder->mode_set = intel_tv_mode_set; intel_encoder->enable = intel_enable_tv; intel_encoder->disable = intel_disable_tv; diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 0b02078..8649f1c 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -93,7 +93,7 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) { u32 forcewake_ack; - if (IS_HASWELL(dev_priv->dev) || IS_GEN8(dev_priv->dev)) + if (IS_HASWELL(dev_priv->dev)) forcewake_ack = FORCEWAKE_ACK_HSW; else forcewake_ack = FORCEWAKE_MT_ACK; @@ -112,8 +112,7 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) DRM_ERROR("Timed out waiting for forcewake to ack request.\n"); /* WaRsForcewakeWaitTC0:ivb,hsw */ - if (INTEL_INFO(dev_priv->dev)->gen < 8) - __gen6_gt_wait_for_thread_c0(dev_priv); + __gen6_gt_wait_for_thread_c0(dev_priv); } static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) @@ -205,74 +204,82 @@ static void vlv_force_wake_put(struct drm_i915_private *dev_priv) gen6_gt_check_fifodbg(dev_priv); } -static void gen6_force_wake_work(struct work_struct *work) +void intel_uncore_early_sanitize(struct drm_device *dev) { - struct drm_i915_private *dev_priv = - container_of(work, typeof(*dev_priv), uncore.force_wake_work.work); - unsigned long irqflags; + struct drm_i915_private *dev_priv = dev->dev_private; - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - if (--dev_priv->uncore.forcewake_count == 0) - dev_priv->uncore.funcs.force_wake_put(dev_priv); - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + if (HAS_FPGA_DBG_UNCLAIMED(dev)) + __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM); } -static void intel_uncore_forcewake_reset(struct drm_device *dev) +void intel_uncore_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; if (IS_VALLEYVIEW(dev)) { - vlv_force_wake_reset(dev_priv); - } else if (INTEL_INFO(dev)->gen >= 6) { - __gen6_gt_force_wake_reset(dev_priv); - if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) - __gen6_gt_force_wake_mt_reset(dev_priv); + dev_priv->uncore.funcs.force_wake_get = vlv_force_wake_get; + dev_priv->uncore.funcs.force_wake_put = vlv_force_wake_put; + } else if (IS_HASWELL(dev)) { + dev_priv->uncore.funcs.force_wake_get = __gen6_gt_force_wake_mt_get; + dev_priv->uncore.funcs.force_wake_put = __gen6_gt_force_wake_mt_put; + } else if (IS_IVYBRIDGE(dev)) { + u32 ecobus; + + /* IVB configs may use multi-threaded forcewake */ + + /* A small trick here - if the bios hasn't configured + * MT forcewake, and if the device is in RC6, then + * force_wake_mt_get will not wake the device and the + * ECOBUS read will return zero. Which will be + * (correctly) interpreted by the test below as MT + * forcewake being disabled. + */ + mutex_lock(&dev->struct_mutex); + __gen6_gt_force_wake_mt_get(dev_priv); + ecobus = __raw_i915_read32(dev_priv, ECOBUS); + __gen6_gt_force_wake_mt_put(dev_priv); + mutex_unlock(&dev->struct_mutex); + + if (ecobus & FORCEWAKE_MT_ENABLE) { + dev_priv->uncore.funcs.force_wake_get = + __gen6_gt_force_wake_mt_get; + dev_priv->uncore.funcs.force_wake_put = + __gen6_gt_force_wake_mt_put; + } else { + DRM_INFO("No MT forcewake available on Ivybridge, this can result in issues\n"); + DRM_INFO("when using vblank-synced partial screen updates.\n"); + dev_priv->uncore.funcs.force_wake_get = + __gen6_gt_force_wake_get; + dev_priv->uncore.funcs.force_wake_put = + __gen6_gt_force_wake_put; + } + } else if (IS_GEN6(dev)) { + dev_priv->uncore.funcs.force_wake_get = + __gen6_gt_force_wake_get; + dev_priv->uncore.funcs.force_wake_put = + __gen6_gt_force_wake_put; } } -void intel_uncore_early_sanitize(struct drm_device *dev) +static void intel_uncore_forcewake_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - if (HAS_FPGA_DBG_UNCLAIMED(dev)) - __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM); - - if (IS_HASWELL(dev) && - (__raw_i915_read32(dev_priv, HSW_EDRAM_PRESENT) == 1)) { - /* The docs do not explain exactly how the calculation can be - * made. It is somewhat guessable, but for now, it's always - * 128MB. - * NB: We can't write IDICR yet because we do not have gt funcs - * set up */ - dev_priv->ellc_size = 128; - DRM_INFO("Found %zuMB of eLLC\n", dev_priv->ellc_size); + if (IS_VALLEYVIEW(dev)) { + vlv_force_wake_reset(dev_priv); + } else if (INTEL_INFO(dev)->gen >= 6) { + __gen6_gt_force_wake_reset(dev_priv); + if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) + __gen6_gt_force_wake_mt_reset(dev_priv); } - - intel_uncore_forcewake_reset(dev); } void intel_uncore_sanitize(struct drm_device *dev) { - struct drm_i915_private *dev_priv = dev->dev_private; - u32 reg_val; - intel_uncore_forcewake_reset(dev); /* BIOS often leaves RC6 enabled, but disable it for hw init */ intel_disable_gt_powersave(dev); - - /* Turn off power gate, require especially for the BIOS less system */ - if (IS_VALLEYVIEW(dev)) { - - mutex_lock(&dev_priv->rps.hw_lock); - reg_val = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS); - - if (reg_val & (RENDER_PWRGT | MEDIA_PWRGT | DISP2D_PWRGT)) - vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, 0x0); - - mutex_unlock(&dev_priv->rps.hw_lock); - - } } /* @@ -285,9 +292,6 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) { unsigned long irqflags; - if (!dev_priv->uncore.funcs.force_wake_get) - return; - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); if (dev_priv->uncore.forcewake_count++ == 0) dev_priv->uncore.funcs.force_wake_get(dev_priv); @@ -301,22 +305,17 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) { unsigned long irqflags; - if (!dev_priv->uncore.funcs.force_wake_put) - return; - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - if (--dev_priv->uncore.forcewake_count == 0) { - dev_priv->uncore.forcewake_count++; - mod_delayed_work(dev_priv->wq, - &dev_priv->uncore.force_wake_work, - 1); - } + if (--dev_priv->uncore.forcewake_count == 0) + dev_priv->uncore.funcs.force_wake_put(dev_priv); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } /* We give fast paths for the really cool registers */ #define NEEDS_FORCE_WAKE(dev_priv, reg) \ - ((reg) < 0x40000 && (reg) != FORCEWAKE) + ((HAS_FORCE_WAKE((dev_priv)->dev)) && \ + ((reg) < 0x40000) && \ + ((reg) != FORCEWAKE)) static void ilk_dummy_write(struct drm_i915_private *dev_priv) @@ -330,7 +329,8 @@ ilk_dummy_write(struct drm_i915_private *dev_priv) static void hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg) { - if (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM) { + if (HAS_FPGA_DBG_UNCLAIMED(dev_priv->dev) && + (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) { DRM_ERROR("Unknown unclaimed register before writing to %x\n", reg); __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM); @@ -340,43 +340,20 @@ hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg) static void hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg) { - if (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM) { + if (HAS_FPGA_DBG_UNCLAIMED(dev_priv->dev) && + (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) { DRM_ERROR("Unclaimed write to %x\n", reg); __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM); } } -#define REG_READ_HEADER(x) \ +#define __i915_read(x) \ +u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg, bool trace) { \ unsigned long irqflags; \ u##x val = 0; \ - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags) - -#define REG_READ_FOOTER \ - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \ - trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \ - return val - -#define __gen4_read(x) \ -static u##x \ -gen4_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ - REG_READ_HEADER(x); \ - val = __raw_i915_read##x(dev_priv, reg); \ - REG_READ_FOOTER; \ -} - -#define __gen5_read(x) \ -static u##x \ -gen5_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ - REG_READ_HEADER(x); \ - ilk_dummy_write(dev_priv); \ - val = __raw_i915_read##x(dev_priv, reg); \ - REG_READ_FOOTER; \ -} - -#define __gen6_read(x) \ -static u##x \ -gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ - REG_READ_HEADER(x); \ + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); \ + if (dev_priv->info->gen == 5) \ + ilk_dummy_write(dev_priv); \ if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ if (dev_priv->uncore.forcewake_count == 0) \ dev_priv->uncore.funcs.force_wake_get(dev_priv); \ @@ -386,73 +363,28 @@ gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ } else { \ val = __raw_i915_read##x(dev_priv, reg); \ } \ - REG_READ_FOOTER; \ -} - -__gen6_read(8) -__gen6_read(16) -__gen6_read(32) -__gen6_read(64) -__gen5_read(8) -__gen5_read(16) -__gen5_read(32) -__gen5_read(64) -__gen4_read(8) -__gen4_read(16) -__gen4_read(32) -__gen4_read(64) - -#undef __gen6_read -#undef __gen5_read -#undef __gen4_read -#undef REG_READ_FOOTER -#undef REG_READ_HEADER - -#define REG_WRITE_HEADER \ - unsigned long irqflags; \ - trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \ - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags) - -#define __gen4_write(x) \ -static void \ -gen4_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ - REG_WRITE_HEADER; \ - __raw_i915_write##x(dev_priv, reg, val); \ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \ + trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \ + return val; \ } -#define __gen5_write(x) \ -static void \ -gen5_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ - REG_WRITE_HEADER; \ - ilk_dummy_write(dev_priv); \ - __raw_i915_write##x(dev_priv, reg, val); \ - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \ -} +__i915_read(8) +__i915_read(16) +__i915_read(32) +__i915_read(64) +#undef __i915_read -#define __gen6_write(x) \ -static void \ -gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ - u32 __fifo_ret = 0; \ - REG_WRITE_HEADER; \ - if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ - __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ - } \ - __raw_i915_write##x(dev_priv, reg, val); \ - if (unlikely(__fifo_ret)) { \ - gen6_gt_check_fifodbg(dev_priv); \ - } \ - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \ -} - -#define __hsw_write(x) \ -static void \ -hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ +#define __i915_write(x) \ +void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val, bool trace) { \ + unsigned long irqflags; \ u32 __fifo_ret = 0; \ - REG_WRITE_HEADER; \ + trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \ + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); \ if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ } \ + if (dev_priv->info->gen == 5) \ + ilk_dummy_write(dev_priv); \ hsw_unclaimed_reg_clear(dev_priv, reg); \ __raw_i915_write##x(dev_priv, reg, val); \ if (unlikely(__fifo_ret)) { \ @@ -461,185 +393,11 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) hsw_unclaimed_reg_check(dev_priv, reg); \ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \ } - -static const u32 gen8_shadowed_regs[] = { - FORCEWAKE_MT, - GEN6_RPNSWREQ, - GEN6_RC_VIDEO_FREQ, - RING_TAIL(RENDER_RING_BASE), - RING_TAIL(GEN6_BSD_RING_BASE), - RING_TAIL(VEBOX_RING_BASE), - RING_TAIL(BLT_RING_BASE), - /* TODO: Other registers are not yet used */ -}; - -static bool is_gen8_shadowed(struct drm_i915_private *dev_priv, u32 reg) -{ - int i; - for (i = 0; i < ARRAY_SIZE(gen8_shadowed_regs); i++) - if (reg == gen8_shadowed_regs[i]) - return true; - - return false; -} - -#define __gen8_write(x) \ -static void \ -gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ - bool __needs_put = !is_gen8_shadowed(dev_priv, reg); \ - REG_WRITE_HEADER; \ - if (__needs_put) { \ - dev_priv->uncore.funcs.force_wake_get(dev_priv); \ - } \ - __raw_i915_write##x(dev_priv, reg, val); \ - if (__needs_put) { \ - dev_priv->uncore.funcs.force_wake_put(dev_priv); \ - } \ - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \ -} - -__gen8_write(8) -__gen8_write(16) -__gen8_write(32) -__gen8_write(64) -__hsw_write(8) -__hsw_write(16) -__hsw_write(32) -__hsw_write(64) -__gen6_write(8) -__gen6_write(16) -__gen6_write(32) -__gen6_write(64) -__gen5_write(8) -__gen5_write(16) -__gen5_write(32) -__gen5_write(64) -__gen4_write(8) -__gen4_write(16) -__gen4_write(32) -__gen4_write(64) - -#undef __gen8_write -#undef __hsw_write -#undef __gen6_write -#undef __gen5_write -#undef __gen4_write -#undef REG_WRITE_HEADER - -void intel_uncore_init(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - INIT_DELAYED_WORK(&dev_priv->uncore.force_wake_work, - gen6_force_wake_work); - - if (IS_VALLEYVIEW(dev)) { - dev_priv->uncore.funcs.force_wake_get = vlv_force_wake_get; - dev_priv->uncore.funcs.force_wake_put = vlv_force_wake_put; - } else if (IS_HASWELL(dev) || IS_GEN8(dev)) { - dev_priv->uncore.funcs.force_wake_get = __gen6_gt_force_wake_mt_get; - dev_priv->uncore.funcs.force_wake_put = __gen6_gt_force_wake_mt_put; - } else if (IS_IVYBRIDGE(dev)) { - u32 ecobus; - - /* IVB configs may use multi-threaded forcewake */ - - /* A small trick here - if the bios hasn't configured - * MT forcewake, and if the device is in RC6, then - * force_wake_mt_get will not wake the device and the - * ECOBUS read will return zero. Which will be - * (correctly) interpreted by the test below as MT - * forcewake being disabled. - */ - mutex_lock(&dev->struct_mutex); - __gen6_gt_force_wake_mt_get(dev_priv); - ecobus = __raw_i915_read32(dev_priv, ECOBUS); - __gen6_gt_force_wake_mt_put(dev_priv); - mutex_unlock(&dev->struct_mutex); - - if (ecobus & FORCEWAKE_MT_ENABLE) { - dev_priv->uncore.funcs.force_wake_get = - __gen6_gt_force_wake_mt_get; - dev_priv->uncore.funcs.force_wake_put = - __gen6_gt_force_wake_mt_put; - } else { - DRM_INFO("No MT forcewake available on Ivybridge, this can result in issues\n"); - DRM_INFO("when using vblank-synced partial screen updates.\n"); - dev_priv->uncore.funcs.force_wake_get = - __gen6_gt_force_wake_get; - dev_priv->uncore.funcs.force_wake_put = - __gen6_gt_force_wake_put; - } - } else if (IS_GEN6(dev)) { - dev_priv->uncore.funcs.force_wake_get = - __gen6_gt_force_wake_get; - dev_priv->uncore.funcs.force_wake_put = - __gen6_gt_force_wake_put; - } - - switch (INTEL_INFO(dev)->gen) { - default: - dev_priv->uncore.funcs.mmio_writeb = gen8_write8; - dev_priv->uncore.funcs.mmio_writew = gen8_write16; - dev_priv->uncore.funcs.mmio_writel = gen8_write32; - dev_priv->uncore.funcs.mmio_writeq = gen8_write64; - dev_priv->uncore.funcs.mmio_readb = gen6_read8; - dev_priv->uncore.funcs.mmio_readw = gen6_read16; - dev_priv->uncore.funcs.mmio_readl = gen6_read32; - dev_priv->uncore.funcs.mmio_readq = gen6_read64; - break; - case 7: - case 6: - if (IS_HASWELL(dev)) { - dev_priv->uncore.funcs.mmio_writeb = hsw_write8; - dev_priv->uncore.funcs.mmio_writew = hsw_write16; - dev_priv->uncore.funcs.mmio_writel = hsw_write32; - dev_priv->uncore.funcs.mmio_writeq = hsw_write64; - } else { - dev_priv->uncore.funcs.mmio_writeb = gen6_write8; - dev_priv->uncore.funcs.mmio_writew = gen6_write16; - dev_priv->uncore.funcs.mmio_writel = gen6_write32; - dev_priv->uncore.funcs.mmio_writeq = gen6_write64; - } - dev_priv->uncore.funcs.mmio_readb = gen6_read8; - dev_priv->uncore.funcs.mmio_readw = gen6_read16; - dev_priv->uncore.funcs.mmio_readl = gen6_read32; - dev_priv->uncore.funcs.mmio_readq = gen6_read64; - break; - case 5: - dev_priv->uncore.funcs.mmio_writeb = gen5_write8; - dev_priv->uncore.funcs.mmio_writew = gen5_write16; - dev_priv->uncore.funcs.mmio_writel = gen5_write32; - dev_priv->uncore.funcs.mmio_writeq = gen5_write64; - dev_priv->uncore.funcs.mmio_readb = gen5_read8; - dev_priv->uncore.funcs.mmio_readw = gen5_read16; - dev_priv->uncore.funcs.mmio_readl = gen5_read32; - dev_priv->uncore.funcs.mmio_readq = gen5_read64; - break; - case 4: - case 3: - case 2: - dev_priv->uncore.funcs.mmio_writeb = gen4_write8; - dev_priv->uncore.funcs.mmio_writew = gen4_write16; - dev_priv->uncore.funcs.mmio_writel = gen4_write32; - dev_priv->uncore.funcs.mmio_writeq = gen4_write64; - dev_priv->uncore.funcs.mmio_readb = gen4_read8; - dev_priv->uncore.funcs.mmio_readw = gen4_read16; - dev_priv->uncore.funcs.mmio_readl = gen4_read32; - dev_priv->uncore.funcs.mmio_readq = gen4_read64; - break; - } -} - -void intel_uncore_fini(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - flush_delayed_work(&dev_priv->uncore.force_wake_work); - - /* Paranoia: make sure we have disabled everything before we exit. */ - intel_uncore_sanitize(dev); -} +__i915_write(8) +__i915_write(16) +__i915_write(32) +__i915_write(64) +#undef __i915_write static const struct register_whitelist { uint64_t offset; @@ -687,6 +445,36 @@ int i915_reg_read_ioctl(struct drm_device *dev, return 0; } +static int i8xx_do_reset(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (IS_I85X(dev)) + return -ENODEV; + + I915_WRITE(D_STATE, I915_READ(D_STATE) | DSTATE_GFX_RESET_I830); + POSTING_READ(D_STATE); + + if (IS_I830(dev) || IS_845G(dev)) { + I915_WRITE(DEBUG_RESET_I830, + DEBUG_RESET_DISPLAY | + DEBUG_RESET_RENDER | + DEBUG_RESET_FULL); + POSTING_READ(DEBUG_RESET_I830); + msleep(1); + + I915_WRITE(DEBUG_RESET_I830, 0); + POSTING_READ(DEBUG_RESET_I830); + } + + msleep(1); + + I915_WRITE(D_STATE, I915_READ(D_STATE) & ~DSTATE_GFX_RESET_I830); + POSTING_READ(D_STATE); + + return 0; +} + static int i965_reset_complete(struct drm_device *dev) { u8 gdrst; @@ -788,6 +576,7 @@ int intel_gpu_reset(struct drm_device *dev) case 6: return gen6_do_reset(dev); case 5: return ironlake_do_reset(dev); case 4: return i965_do_reset(dev); + case 2: return i8xx_do_reset(dev); default: return -ENODEV; } } |