diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-03-25 03:53:42 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-03-25 03:53:42 -0300 |
commit | 03dd4cb26d967f9588437b0fc9cc0e8353322bb7 (patch) | |
tree | fa581f6dc1c0596391690d1f67eceef3af8246dc /drivers/gpu/drm/i915 | |
parent | d4e493caf788ef44982e131ff9c786546904d934 (diff) |
Linux-libre 4.5-gnu
Diffstat (limited to 'drivers/gpu/drm/i915')
78 files changed, 7748 insertions, 5774 deletions
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 44d290ae1..0851de07b 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -77,6 +77,7 @@ i915-y += dvo_ch7017.o \ dvo_tfp410.o \ intel_crt.o \ intel_ddi.o \ + intel_dp_link_training.o \ intel_dp_mst.o \ intel_dp.o \ intel_dsi.o \ diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h index 0e2c1b964..5e6a3013d 100644 --- a/drivers/gpu/drm/i915/dvo.h +++ b/drivers/gpu/drm/i915/dvo.h @@ -32,7 +32,8 @@ struct intel_dvo_device { const char *name; int type; /* DVOA/B/C output register */ - u32 dvo_reg; + i915_reg_t dvo_reg; + i915_reg_t dvo_srcdim_reg; /* GPIO register used for i2c bus to control this device */ u32 gpio; int slave_addr; @@ -128,11 +129,11 @@ struct intel_dvo_dev_ops { void (*dump_regs)(struct intel_dvo_device *dvo); }; -extern struct intel_dvo_dev_ops sil164_ops; -extern struct intel_dvo_dev_ops ch7xxx_ops; -extern struct intel_dvo_dev_ops ivch_ops; -extern struct intel_dvo_dev_ops tfp410_ops; -extern struct intel_dvo_dev_ops ch7017_ops; -extern struct intel_dvo_dev_ops ns2501_ops; +extern const struct intel_dvo_dev_ops sil164_ops; +extern const struct intel_dvo_dev_ops ch7xxx_ops; +extern const struct intel_dvo_dev_ops ivch_ops; +extern const struct intel_dvo_dev_ops tfp410_ops; +extern const struct intel_dvo_dev_ops ch7017_ops; +extern const struct intel_dvo_dev_ops ns2501_ops; #endif /* _INTEL_DVO_H */ diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c index cbb22027a..b3c7c1992 100644 --- a/drivers/gpu/drm/i915/dvo_ch7017.c +++ b/drivers/gpu/drm/i915/dvo_ch7017.c @@ -402,7 +402,7 @@ static void ch7017_destroy(struct intel_dvo_device *dvo) } } -struct intel_dvo_dev_ops ch7017_ops = { +const struct intel_dvo_dev_ops ch7017_ops = { .init = ch7017_init, .detect = ch7017_detect, .mode_valid = ch7017_mode_valid, diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c index 4b4acc1a0..44b3159f2 100644 --- a/drivers/gpu/drm/i915/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c @@ -356,7 +356,7 @@ static void ch7xxx_destroy(struct intel_dvo_device *dvo) } } -struct intel_dvo_dev_ops ch7xxx_ops = { +const struct intel_dvo_dev_ops ch7xxx_ops = { .init = ch7xxx_init, .detect = ch7xxx_detect, .mode_valid = ch7xxx_mode_valid, diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c index ff9f1b077..4950b82f5 100644 --- a/drivers/gpu/drm/i915/dvo_ivch.c +++ b/drivers/gpu/drm/i915/dvo_ivch.c @@ -490,7 +490,7 @@ static void ivch_destroy(struct intel_dvo_device *dvo) } } -struct intel_dvo_dev_ops ivch_ops = { +const struct intel_dvo_dev_ops ivch_ops = { .init = ivch_init, .dpms = ivch_dpms, .get_hw_state = ivch_get_hw_state, diff --git a/drivers/gpu/drm/i915/dvo_ns2501.c b/drivers/gpu/drm/i915/dvo_ns2501.c index 063859fff..2379c33cf 100644 --- a/drivers/gpu/drm/i915/dvo_ns2501.c +++ b/drivers/gpu/drm/i915/dvo_ns2501.c @@ -698,7 +698,7 @@ static void ns2501_destroy(struct intel_dvo_device *dvo) } } -struct intel_dvo_dev_ops ns2501_ops = { +const struct intel_dvo_dev_ops ns2501_ops = { .init = ns2501_init, .detect = ns2501_detect, .mode_valid = ns2501_mode_valid, diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c index 26f13eb63..1c1a0674d 100644 --- a/drivers/gpu/drm/i915/dvo_sil164.c +++ b/drivers/gpu/drm/i915/dvo_sil164.c @@ -267,7 +267,7 @@ static void sil164_destroy(struct intel_dvo_device *dvo) } } -struct intel_dvo_dev_ops sil164_ops = { +const struct intel_dvo_dev_ops sil164_ops = { .init = sil164_init, .detect = sil164_detect, .mode_valid = sil164_mode_valid, diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c index 6f1a0a6d4..31e181da9 100644 --- a/drivers/gpu/drm/i915/dvo_tfp410.c +++ b/drivers/gpu/drm/i915/dvo_tfp410.c @@ -306,7 +306,7 @@ static void tfp410_destroy(struct intel_dvo_device *dvo) } } -struct intel_dvo_dev_ops tfp410_ops = { +const struct intel_dvo_dev_ops tfp410_ops = { .init = tfp410_init, .detect = tfp410_detect, .mode_valid = tfp410_mode_valid, diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index db58c8d66..814d894ed 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -407,14 +407,14 @@ static const struct drm_i915_cmd_table hsw_blt_ring_cmds[] = { * LRI. */ struct drm_i915_reg_descriptor { - u32 addr; + i915_reg_t addr; u32 mask; u32 value; }; /* Convenience macro for adding 32-bit registers. */ -#define REG32(address, ...) \ - { .addr = address, __VA_ARGS__ } +#define REG32(_reg, ...) \ + { .addr = (_reg), __VA_ARGS__ } /* * Convenience macro for adding 64-bit registers. @@ -423,8 +423,13 @@ struct drm_i915_reg_descriptor { * access commands only allow 32-bit accesses. Hence, we have to include * entries for both halves of the 64-bit registers. */ -#define REG64(addr) \ - REG32(addr), REG32(addr + sizeof(u32)) +#define REG64(_reg) \ + { .addr = _reg }, \ + { .addr = _reg ## _UDW } + +#define REG64_IDX(_reg, idx) \ + { .addr = _reg(idx) }, \ + { .addr = _reg ## _UDW(idx) } static const struct drm_i915_reg_descriptor gen7_render_regs[] = { REG64(GPGPU_THREADS_DISPATCHED), @@ -451,14 +456,14 @@ static const struct drm_i915_reg_descriptor gen7_render_regs[] = { REG32(GEN7_GPGPU_DISPATCHDIMX), REG32(GEN7_GPGPU_DISPATCHDIMY), REG32(GEN7_GPGPU_DISPATCHDIMZ), - REG64(GEN7_SO_NUM_PRIMS_WRITTEN(0)), - REG64(GEN7_SO_NUM_PRIMS_WRITTEN(1)), - REG64(GEN7_SO_NUM_PRIMS_WRITTEN(2)), - REG64(GEN7_SO_NUM_PRIMS_WRITTEN(3)), - REG64(GEN7_SO_PRIM_STORAGE_NEEDED(0)), - REG64(GEN7_SO_PRIM_STORAGE_NEEDED(1)), - REG64(GEN7_SO_PRIM_STORAGE_NEEDED(2)), - REG64(GEN7_SO_PRIM_STORAGE_NEEDED(3)), + REG64_IDX(GEN7_SO_NUM_PRIMS_WRITTEN, 0), + REG64_IDX(GEN7_SO_NUM_PRIMS_WRITTEN, 1), + REG64_IDX(GEN7_SO_NUM_PRIMS_WRITTEN, 2), + REG64_IDX(GEN7_SO_NUM_PRIMS_WRITTEN, 3), + REG64_IDX(GEN7_SO_PRIM_STORAGE_NEEDED, 0), + REG64_IDX(GEN7_SO_PRIM_STORAGE_NEEDED, 1), + REG64_IDX(GEN7_SO_PRIM_STORAGE_NEEDED, 2), + REG64_IDX(GEN7_SO_PRIM_STORAGE_NEEDED, 3), REG32(GEN7_SO_WRITE_OFFSET(0)), REG32(GEN7_SO_WRITE_OFFSET(1)), REG32(GEN7_SO_WRITE_OFFSET(2)), @@ -592,7 +597,7 @@ static bool check_sorted(int ring_id, bool ret = true; for (i = 0; i < reg_count; i++) { - u32 curr = reg_table[i].addr; + u32 curr = i915_mmio_reg_offset(reg_table[i].addr); if (curr < previous) { DRM_ERROR("CMD: table not sorted ring=%d entry=%d reg=0x%08X prev=0x%08X\n", @@ -847,7 +852,7 @@ find_reg(const struct drm_i915_reg_descriptor *table, int i; for (i = 0; i < count; i++) { - if (table[i].addr == addr) + if (i915_mmio_reg_offset(table[i].addr) == addr) return &table[i]; } } @@ -1023,7 +1028,7 @@ static bool check_cmd(const struct intel_engine_cs *ring, * to the register. Hence, limit OACONTROL writes to * only MI_LOAD_REGISTER_IMM commands. */ - if (reg_addr == OACONTROL) { + if (reg_addr == i915_mmio_reg_offset(OACONTROL)) { if (desc->cmd.value == MI_LOAD_REGISTER_MEM) { DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n"); return false; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 8aab974b0..cf39ed313 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -825,8 +825,11 @@ static int i915_interrupt_info(struct seq_file *m, void *data) } for_each_pipe(dev_priv, pipe) { - if (!intel_display_power_is_enabled(dev_priv, - POWER_DOMAIN_PIPE(pipe))) { + enum intel_display_power_domain power_domain; + + power_domain = POWER_DOMAIN_PIPE(pipe); + if (!intel_display_power_get_if_enabled(dev_priv, + power_domain)) { seq_printf(m, "Pipe %c power disabled\n", pipe_name(pipe)); continue; @@ -840,6 +843,8 @@ static int i915_interrupt_info(struct seq_file *m, void *data) seq_printf(m, "Pipe %c IER:\t%08x\n", pipe_name(pipe), I915_READ(GEN8_DE_PIPE_IER(pipe))); + + intel_display_power_put(dev_priv, power_domain); } seq_printf(m, "Display Engine port interrupt mask:\t%08x\n", @@ -1142,8 +1147,34 @@ static int i915_frequency_info(struct seq_file *m, void *unused) MEMSTAT_VID_SHIFT); seq_printf(m, "Current P-state: %d\n", (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT); - } else if (IS_GEN6(dev) || (IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) || - IS_BROADWELL(dev) || IS_GEN9(dev)) { + } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + u32 freq_sts; + + mutex_lock(&dev_priv->rps.hw_lock); + freq_sts = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); + seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts); + seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq); + + seq_printf(m, "actual GPU freq: %d MHz\n", + intel_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff)); + + seq_printf(m, "current GPU freq: %d MHz\n", + intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq)); + + seq_printf(m, "max GPU freq: %d MHz\n", + intel_gpu_freq(dev_priv, dev_priv->rps.max_freq)); + + seq_printf(m, "min GPU freq: %d MHz\n", + intel_gpu_freq(dev_priv, dev_priv->rps.min_freq)); + + seq_printf(m, "idle GPU freq: %d MHz\n", + intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq)); + + seq_printf(m, + "efficient (RPe) frequency: %d MHz\n", + intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq)); + mutex_unlock(&dev_priv->rps.hw_lock); + } else if (INTEL_INFO(dev)->gen >= 6) { u32 rp_state_limits; u32 gt_perf_status; u32 rp_state_cap; @@ -1252,18 +1283,21 @@ static int i915_frequency_info(struct seq_file *m, void *unused) max_freq = (IS_BROXTON(dev) ? rp_state_cap >> 0 : rp_state_cap >> 16) & 0xff; - max_freq *= (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1); + max_freq *= (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ? + GEN9_FREQ_SCALER : 1); seq_printf(m, "Lowest (RPN) frequency: %dMHz\n", intel_gpu_freq(dev_priv, max_freq)); max_freq = (rp_state_cap & 0xff00) >> 8; - max_freq *= (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1); + max_freq *= (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ? + GEN9_FREQ_SCALER : 1); seq_printf(m, "Nominal (RP1) frequency: %dMHz\n", intel_gpu_freq(dev_priv, max_freq)); max_freq = (IS_BROXTON(dev) ? rp_state_cap >> 16 : rp_state_cap >> 0) & 0xff; - max_freq *= (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1); + max_freq *= (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ? + GEN9_FREQ_SCALER : 1); seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n", intel_gpu_freq(dev_priv, max_freq)); seq_printf(m, "Max overclocked frequency: %dMHz\n", @@ -1281,33 +1315,6 @@ static int i915_frequency_info(struct seq_file *m, void *unused) seq_printf(m, "efficient (RPe) frequency: %d MHz\n", intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq)); - } else if (IS_VALLEYVIEW(dev)) { - u32 freq_sts; - - mutex_lock(&dev_priv->rps.hw_lock); - freq_sts = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); - seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts); - seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq); - - seq_printf(m, "actual GPU freq: %d MHz\n", - intel_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff)); - - seq_printf(m, "current GPU freq: %d MHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq)); - - seq_printf(m, "max GPU freq: %d MHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.max_freq)); - - seq_printf(m, "min GPU freq: %d MHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.min_freq)); - - seq_printf(m, "idle GPU freq: %d MHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq)); - - seq_printf(m, - "efficient (RPe) frequency: %d MHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq)); - mutex_unlock(&dev_priv->rps.hw_lock); } else { seq_puts(m, "no P-state info available\n"); } @@ -1523,7 +1530,7 @@ static int gen6_drpc_info(struct seq_file *m) seq_printf(m, "RC information accurate: %s\n", yesno(count < 51)); } - gt_core_status = readl(dev_priv->regs + GEN6_GT_CORE_STATUS); + gt_core_status = I915_READ_FW(GEN6_GT_CORE_STATUS); trace_i915_reg_rw(false, GEN6_GT_CORE_STATUS, gt_core_status, 4, true); rpmodectl1 = I915_READ(GEN6_RP_CONTROL); @@ -1599,7 +1606,7 @@ static int i915_drpc_info(struct seq_file *m, void *unused) struct drm_info_node *node = m->private; struct drm_device *dev = node->minor->dev; - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) return vlv_drpc_info(m); else if (INTEL_INFO(dev)->gen >= 6) return gen6_drpc_info(m); @@ -1636,11 +1643,11 @@ static int i915_fbc_status(struct seq_file *m, void *unused) intel_runtime_pm_get(dev_priv); mutex_lock(&dev_priv->fbc.lock); - if (intel_fbc_enabled(dev_priv)) + if (intel_fbc_is_active(dev_priv)) seq_puts(m, "FBC enabled\n"); else seq_printf(m, "FBC disabled: %s\n", - intel_no_fbc_reason_str(dev_priv->fbc.no_fbc_reason)); + dev_priv->fbc.no_fbc_reason); if (INTEL_INFO(dev_priv)->gen >= 7) seq_printf(m, "Compressing: %s\n", @@ -1740,7 +1747,7 @@ static int i915_sr_status(struct seq_file *m, void *unused) sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN; else if (IS_PINEVIEW(dev)) sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN; - else if (IS_VALLEYVIEW(dev)) + else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN; intel_runtime_pm_put(dev_priv); @@ -1801,7 +1808,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) if (ret) goto out; - if (IS_SKYLAKE(dev)) { + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { /* Convert GT frequency to 50 HZ units */ min_gpu_freq = dev_priv->rps.min_freq_softlimit / GEN9_FREQ_SCALER; @@ -1821,7 +1828,8 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) &ia_freq); seq_printf(m, "%d\t\t%d\t\t\t\t%d\n", intel_gpu_freq(dev_priv, (gpu_freq * - (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1))), + (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ? + GEN9_FREQ_SCALER : 1))), ((ia_freq >> 0) & 0xff) * 100, ((ia_freq >> 8) & 0xff) * 100); } @@ -1839,25 +1847,31 @@ static int i915_opregion(struct seq_file *m, void *unused) struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_opregion *opregion = &dev_priv->opregion; - void *data = kmalloc(OPREGION_SIZE, GFP_KERNEL); int ret; - if (data == NULL) - return -ENOMEM; - ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) goto out; - if (opregion->header) { - memcpy(data, opregion->header, OPREGION_SIZE); - seq_write(m, data, OPREGION_SIZE); - } + if (opregion->header) + seq_write(m, opregion->header, OPREGION_SIZE); mutex_unlock(&dev->struct_mutex); out: - kfree(data); + return 0; +} + +static int i915_vbt(struct seq_file *m, void *unused) +{ + struct drm_info_node *node = m->private; + struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_opregion *opregion = &dev_priv->opregion; + + if (opregion->vbt) + seq_write(m, opregion->vbt, opregion->vbt_size); + return 0; } @@ -1865,31 +1879,29 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) { struct drm_info_node *node = m->private; struct drm_device *dev = node->minor->dev; - struct intel_fbdev *ifbdev = NULL; - struct intel_framebuffer *fb; + struct intel_framebuffer *fbdev_fb = NULL; struct drm_framebuffer *drm_fb; #ifdef CONFIG_DRM_FBDEV_EMULATION - struct drm_i915_private *dev_priv = dev->dev_private; - - ifbdev = dev_priv->fbdev; - fb = to_intel_framebuffer(ifbdev->helper.fb); - - seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ", - fb->base.width, - fb->base.height, - fb->base.depth, - fb->base.bits_per_pixel, - fb->base.modifier[0], - atomic_read(&fb->base.refcount.refcount)); - describe_obj(m, fb->obj); - seq_putc(m, '\n'); + if (to_i915(dev)->fbdev) { + fbdev_fb = to_intel_framebuffer(to_i915(dev)->fbdev->helper.fb); + + seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ", + fbdev_fb->base.width, + fbdev_fb->base.height, + fbdev_fb->base.depth, + fbdev_fb->base.bits_per_pixel, + fbdev_fb->base.modifier[0], + atomic_read(&fbdev_fb->base.refcount.refcount)); + describe_obj(m, fbdev_fb->obj); + seq_putc(m, '\n'); + } #endif mutex_lock(&dev->mode_config.fb_lock); drm_for_each_fb(drm_fb, dev) { - fb = to_intel_framebuffer(drm_fb); - if (ifbdev && &fb->base == ifbdev->helper.fb) + struct intel_framebuffer *fb = to_intel_framebuffer(drm_fb); + if (fb == fbdev_fb) continue; seq_printf(m, "user size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ", @@ -2402,6 +2414,12 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data) guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted); seq_printf(m, "\tversion found: %d.%d\n", guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found); + seq_printf(m, "\theader: offset is %d; size = %d\n", + guc_fw->header_offset, guc_fw->header_size); + seq_printf(m, "\tuCode: offset is %d; size = %d\n", + guc_fw->ucode_offset, guc_fw->ucode_size); + seq_printf(m, "\tRSA: offset is %d; size = %d\n", + guc_fw->rsa_offset, guc_fw->rsa_size); tmp = I915_READ(GUC_STATUS); @@ -2461,15 +2479,15 @@ static int i915_guc_info(struct seq_file *m, void *data) if (!HAS_GUC_SCHED(dev_priv->dev)) return 0; + if (mutex_lock_interruptible(&dev->struct_mutex)) + return 0; + /* Take a local copy of the GuC data, so we can dump it at leisure */ - spin_lock(&dev_priv->guc.host2guc_lock); guc = dev_priv->guc; - if (guc.execbuf_client) { - spin_lock(&guc.execbuf_client->wq_lock); + if (guc.execbuf_client) client = *guc.execbuf_client; - spin_unlock(&guc.execbuf_client->wq_lock); - } - spin_unlock(&dev_priv->guc.host2guc_lock); + + mutex_unlock(&dev->struct_mutex); seq_printf(m, "GuC total action count: %llu\n", guc.action_count); seq_printf(m, "GuC action failure count: %u\n", guc.action_fail); @@ -2550,7 +2568,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) yesno(work_busy(&dev_priv->psr.work.work))); if (HAS_DDI(dev)) - enabled = I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE; + enabled = I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE; else { for_each_pipe(dev_priv, pipe) { stat[pipe] = I915_READ(VLV_PSRSTAT(pipe)) & @@ -2570,9 +2588,12 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) } seq_puts(m, "\n"); - /* CHV PSR has no kind of performance counter */ - if (HAS_DDI(dev)) { - psrperf = I915_READ(EDP_PSR_PERF_CNT(dev)) & + /* + * VLV/CHV PSR has no kind of performance counter + * SKL+ Perf counter is reset to 0 everytime DC state is entered + */ + if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + psrperf = I915_READ(EDP_PSR_PERF_CNT) & EDP_PSR_PERF_CNT_MASK; seq_printf(m, "Performance_Counter: %u\n", psrperf); @@ -2673,77 +2694,6 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused) return 0; } -static const char *power_domain_str(enum intel_display_power_domain domain) -{ - switch (domain) { - case POWER_DOMAIN_PIPE_A: - return "PIPE_A"; - case POWER_DOMAIN_PIPE_B: - return "PIPE_B"; - case POWER_DOMAIN_PIPE_C: - return "PIPE_C"; - case POWER_DOMAIN_PIPE_A_PANEL_FITTER: - return "PIPE_A_PANEL_FITTER"; - case POWER_DOMAIN_PIPE_B_PANEL_FITTER: - return "PIPE_B_PANEL_FITTER"; - case POWER_DOMAIN_PIPE_C_PANEL_FITTER: - return "PIPE_C_PANEL_FITTER"; - case POWER_DOMAIN_TRANSCODER_A: - return "TRANSCODER_A"; - case POWER_DOMAIN_TRANSCODER_B: - return "TRANSCODER_B"; - case POWER_DOMAIN_TRANSCODER_C: - return "TRANSCODER_C"; - case POWER_DOMAIN_TRANSCODER_EDP: - return "TRANSCODER_EDP"; - case POWER_DOMAIN_PORT_DDI_A_2_LANES: - return "PORT_DDI_A_2_LANES"; - case POWER_DOMAIN_PORT_DDI_A_4_LANES: - return "PORT_DDI_A_4_LANES"; - case POWER_DOMAIN_PORT_DDI_B_2_LANES: - return "PORT_DDI_B_2_LANES"; - case POWER_DOMAIN_PORT_DDI_B_4_LANES: - return "PORT_DDI_B_4_LANES"; - case POWER_DOMAIN_PORT_DDI_C_2_LANES: - return "PORT_DDI_C_2_LANES"; - case POWER_DOMAIN_PORT_DDI_C_4_LANES: - return "PORT_DDI_C_4_LANES"; - case POWER_DOMAIN_PORT_DDI_D_2_LANES: - return "PORT_DDI_D_2_LANES"; - case POWER_DOMAIN_PORT_DDI_D_4_LANES: - return "PORT_DDI_D_4_LANES"; - case POWER_DOMAIN_PORT_DDI_E_2_LANES: - return "PORT_DDI_E_2_LANES"; - case POWER_DOMAIN_PORT_DSI: - return "PORT_DSI"; - case POWER_DOMAIN_PORT_CRT: - return "PORT_CRT"; - case POWER_DOMAIN_PORT_OTHER: - return "PORT_OTHER"; - case POWER_DOMAIN_VGA: - return "VGA"; - case POWER_DOMAIN_AUDIO: - return "AUDIO"; - case POWER_DOMAIN_PLLS: - return "PLLS"; - case POWER_DOMAIN_AUX_A: - return "AUX_A"; - case POWER_DOMAIN_AUX_B: - return "AUX_B"; - case POWER_DOMAIN_AUX_C: - return "AUX_C"; - case POWER_DOMAIN_AUX_D: - return "AUX_D"; - case POWER_DOMAIN_GMBUS: - return "GMBUS"; - case POWER_DOMAIN_INIT: - return "INIT"; - default: - MISSING_CASE(domain); - return "?"; - } -} - static int i915_power_domain_info(struct seq_file *m, void *unused) { struct drm_info_node *node = m->private; @@ -2769,7 +2719,7 @@ static int i915_power_domain_info(struct seq_file *m, void *unused) continue; seq_printf(m, " %-23s %d\n", - power_domain_str(power_domain), + intel_display_power_domain_str(power_domain), power_domains->domain_use_count[power_domain]); } } @@ -2779,6 +2729,51 @@ static int i915_power_domain_info(struct seq_file *m, void *unused) return 0; } +static int i915_dmc_info(struct seq_file *m, void *unused) +{ + struct drm_info_node *node = m->private; + struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_csr *csr; + + if (!HAS_CSR(dev)) { + seq_puts(m, "not supported\n"); + return 0; + } + + csr = &dev_priv->csr; + + intel_runtime_pm_get(dev_priv); + + seq_printf(m, "fw loaded: %s\n", yesno(csr->dmc_payload != NULL)); + seq_printf(m, "path: %s\n", csr->fw_path); + + if (!csr->dmc_payload) + goto out; + + seq_printf(m, "version: %d.%d\n", CSR_VERSION_MAJOR(csr->version), + CSR_VERSION_MINOR(csr->version)); + + if (IS_SKYLAKE(dev) && csr->version >= CSR_VERSION(1, 6)) { + seq_printf(m, "DC3 -> DC5 count: %d\n", + I915_READ(SKL_CSR_DC3_DC5_COUNT)); + seq_printf(m, "DC5 -> DC6 count: %d\n", + I915_READ(SKL_CSR_DC5_DC6_COUNT)); + } else if (IS_BROXTON(dev) && csr->version >= CSR_VERSION(1, 4)) { + seq_printf(m, "DC3 -> DC5 count: %d\n", + I915_READ(BXT_CSR_DC3_DC5_COUNT)); + } + +out: + seq_printf(m, "program base: 0x%08x\n", I915_READ(CSR_PROGRAM(0))); + seq_printf(m, "ssp base: 0x%08x\n", I915_READ(CSR_SSP_BASE)); + seq_printf(m, "htp: 0x%08x\n", I915_READ(CSR_HTP_SKL)); + + intel_runtime_pm_put(dev_priv); + + return 0; +} + static void intel_seq_print_mode(struct seq_file *m, int tabs, struct drm_display_mode *mode) { @@ -2865,6 +2860,20 @@ static void intel_dp_info(struct seq_file *m, intel_panel_info(m, &intel_connector->panel); } +static void intel_dp_mst_info(struct seq_file *m, + struct intel_connector *intel_connector) +{ + struct intel_encoder *intel_encoder = intel_connector->encoder; + struct intel_dp_mst_encoder *intel_mst = + enc_to_mst(&intel_encoder->base); + struct intel_digital_port *intel_dig_port = intel_mst->primary; + struct intel_dp *intel_dp = &intel_dig_port->dp; + bool has_audio = drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, + intel_connector->port); + + seq_printf(m, "\taudio support: %s\n", yesno(has_audio)); +} + static void intel_hdmi_info(struct seq_file *m, struct intel_connector *intel_connector) { @@ -2908,6 +2917,8 @@ static void intel_connector_info(struct seq_file *m, intel_hdmi_info(m, intel_connector); else if (intel_encoder->type == INTEL_OUTPUT_LVDS) intel_lvds_info(m, intel_connector); + else if (intel_encoder->type == INTEL_OUTPUT_DP_MST) + intel_dp_mst_info(m, intel_connector); } seq_printf(m, "\tmodes:\n"); @@ -2946,6 +2957,107 @@ static bool cursor_position(struct drm_device *dev, int pipe, int *x, int *y) return cursor_active(dev, pipe); } +static const char *plane_type(enum drm_plane_type type) +{ + switch (type) { + case DRM_PLANE_TYPE_OVERLAY: + return "OVL"; + case DRM_PLANE_TYPE_PRIMARY: + return "PRI"; + case DRM_PLANE_TYPE_CURSOR: + return "CUR"; + /* + * Deliberately omitting default: to generate compiler warnings + * when a new drm_plane_type gets added. + */ + } + + return "unknown"; +} + +static const char *plane_rotation(unsigned int rotation) +{ + static char buf[48]; + /* + * According to doc only one DRM_ROTATE_ is allowed but this + * will print them all to visualize if the values are misused + */ + snprintf(buf, sizeof(buf), + "%s%s%s%s%s%s(0x%08x)", + (rotation & BIT(DRM_ROTATE_0)) ? "0 " : "", + (rotation & BIT(DRM_ROTATE_90)) ? "90 " : "", + (rotation & BIT(DRM_ROTATE_180)) ? "180 " : "", + (rotation & BIT(DRM_ROTATE_270)) ? "270 " : "", + (rotation & BIT(DRM_REFLECT_X)) ? "FLIPX " : "", + (rotation & BIT(DRM_REFLECT_Y)) ? "FLIPY " : "", + rotation); + + return buf; +} + +static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc) +{ + struct drm_info_node *node = m->private; + struct drm_device *dev = node->minor->dev; + struct intel_plane *intel_plane; + + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { + struct drm_plane_state *state; + struct drm_plane *plane = &intel_plane->base; + + if (!plane->state) { + seq_puts(m, "plane->state is NULL!\n"); + continue; + } + + state = plane->state; + + seq_printf(m, "\t--Plane id %d: type=%s, crtc_pos=%4dx%4d, crtc_size=%4dx%4d, src_pos=%d.%04ux%d.%04u, src_size=%d.%04ux%d.%04u, format=%s, rotation=%s\n", + plane->base.id, + plane_type(intel_plane->base.type), + state->crtc_x, state->crtc_y, + state->crtc_w, state->crtc_h, + (state->src_x >> 16), + ((state->src_x & 0xffff) * 15625) >> 10, + (state->src_y >> 16), + ((state->src_y & 0xffff) * 15625) >> 10, + (state->src_w >> 16), + ((state->src_w & 0xffff) * 15625) >> 10, + (state->src_h >> 16), + ((state->src_h & 0xffff) * 15625) >> 10, + state->fb ? drm_get_format_name(state->fb->pixel_format) : "N/A", + plane_rotation(state->rotation)); + } +} + +static void intel_scaler_info(struct seq_file *m, struct intel_crtc *intel_crtc) +{ + struct intel_crtc_state *pipe_config; + int num_scalers = intel_crtc->num_scalers; + int i; + + pipe_config = to_intel_crtc_state(intel_crtc->base.state); + + /* Not all platformas have a scaler */ + if (num_scalers) { + seq_printf(m, "\tnum_scalers=%d, scaler_users=%x scaler_id=%d", + num_scalers, + pipe_config->scaler_state.scaler_users, + pipe_config->scaler_state.scaler_id); + + for (i = 0; i < SKL_NUM_SCALERS; i++) { + struct intel_scaler *sc = + &pipe_config->scaler_state.scalers[i]; + + seq_printf(m, ", scalers[%d]: use=%s, mode=%x", + i, yesno(sc->in_use), sc->mode); + } + seq_puts(m, "\n"); + } else { + seq_puts(m, "\tNo scalers available on this platform\n"); + } +} + static int i915_display_info(struct seq_file *m, void *unused) { struct drm_info_node *node = m->private; @@ -2965,10 +3077,12 @@ static int i915_display_info(struct seq_file *m, void *unused) pipe_config = to_intel_crtc_state(crtc->base.state); - seq_printf(m, "CRTC %d: pipe: %c, active=%s (size=%dx%d)\n", + seq_printf(m, "CRTC %d: pipe: %c, active=%s, (size=%dx%d), dither=%s, bpp=%d\n", crtc->base.base.id, pipe_name(crtc->pipe), yesno(pipe_config->base.active), - pipe_config->pipe_src_w, pipe_config->pipe_src_h); + pipe_config->pipe_src_w, pipe_config->pipe_src_h, + yesno(pipe_config->dither), pipe_config->pipe_bpp); + if (pipe_config->base.active) { intel_crtc_info(m, crtc); @@ -2978,6 +3092,8 @@ static int i915_display_info(struct seq_file *m, void *unused) x, y, crtc->base.cursor->state->crtc_w, crtc->base.cursor->state->crtc_h, crtc->cursor_addr, yesno(active)); + intel_scaler_info(m, crtc); + intel_plane_info(m, crtc); } seq_printf(m, "\tunderrun reporting: cpu=%s pch=%s \n", @@ -3112,7 +3228,8 @@ static int i915_wa_registers(struct seq_file *m, void *unused) seq_printf(m, "Workarounds applied: %d\n", dev_priv->workarounds.count); for (i = 0; i < dev_priv->workarounds.count; ++i) { - u32 addr, mask, value, read; + i915_reg_t addr; + u32 mask, value, read; bool ok; addr = dev_priv->workarounds.reg[i].addr; @@ -3121,7 +3238,7 @@ static int i915_wa_registers(struct seq_file *m, void *unused) read = I915_READ(addr); ok = (value & mask) == (read & mask); seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X, read: 0x%08x, status: %s\n", - addr, value, mask, read, ok ? "OK" : "FAIL"); + i915_mmio_reg_offset(addr), value, mask, read, ok ? "OK" : "FAIL"); } intel_runtime_pm_put(dev_priv); @@ -3873,6 +3990,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; struct intel_crtc *crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe)); + enum intel_display_power_domain power_domain; u32 val = 0; /* shut up gcc */ int ret; @@ -3883,7 +4001,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, if (pipe_crc->source && source) return -EINVAL; - if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) { + power_domain = POWER_DOMAIN_PIPE(pipe); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) { DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n"); return -EIO; } @@ -3892,7 +4011,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, 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)) + else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(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); @@ -3900,7 +4019,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, ret = ivb_pipe_crc_ctl_reg(dev, pipe, &source, &val); if (ret != 0) - return ret; + goto out; /* none -> real source transition */ if (source) { @@ -3912,8 +4031,10 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, entries = kcalloc(INTEL_PIPE_CRC_ENTRIES_NR, sizeof(pipe_crc->entries[0]), GFP_KERNEL); - if (!entries) - return -ENOMEM; + if (!entries) { + ret = -ENOMEM; + goto out; + } /* * When IPS gets enabled, the pipe CRC changes. Since IPS gets @@ -3961,7 +4082,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, if (IS_G4X(dev)) g4x_undo_pipe_scramble_reset(dev, pipe); - else if (IS_VALLEYVIEW(dev)) + else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) vlv_undo_pipe_scramble_reset(dev, pipe); else if (IS_HASWELL(dev) && pipe == PIPE_A) hsw_trans_edp_pipe_A_crc_wa(dev, false); @@ -3969,7 +4090,12 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, hsw_enable_ips(crtc); } - return 0; + ret = 0; + +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } /* @@ -4351,7 +4477,8 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[8]) * - WM1+ latency values in 0.5us units * - latencies are in us on gen9/vlv/chv */ - if (INTEL_INFO(dev)->gen >= 9 || IS_VALLEYVIEW(dev)) + if (INTEL_INFO(dev)->gen >= 9 || IS_VALLEYVIEW(dev) || + IS_CHERRYVIEW(dev)) latency *= 10; else if (level > 0) latency *= 5; @@ -5025,7 +5152,7 @@ static void gen9_sseu_device_status(struct drm_device *dev, stat->slice_total++; - if (IS_SKYLAKE(dev)) + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) ss_cnt = INTEL_INFO(dev)->subslice_per_slice; for (ss = 0; ss < ss_max; ss++) { @@ -5225,6 +5352,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_ips_status", i915_ips_status, 0}, {"i915_sr_status", i915_sr_status, 0}, {"i915_opregion", i915_opregion, 0}, + {"i915_vbt", i915_vbt, 0}, {"i915_gem_framebuffer", i915_gem_framebuffer_info, 0}, {"i915_context_status", i915_context_status, 0}, {"i915_dump_lrc", i915_dump_lrc, 0}, @@ -5238,6 +5366,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_energy_uJ", i915_energy_uJ, 0}, {"i915_runtime_pm_status", i915_runtime_pm_status, 0}, {"i915_power_domain_info", i915_power_domain_info, 0}, + {"i915_dmc_info", i915_dmc_info, 0}, {"i915_display_info", i915_display_info, 0}, {"i915_semaphore_status", i915_semaphore_status, 0}, {"i915_shared_dplls_info", i915_shared_dplls_info, 0}, diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 61fcb3b22..d70d96fe5 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -28,7 +28,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include <linux/async.h> #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_helper.h> @@ -170,6 +169,9 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_HAS_RESOURCE_STREAMER: value = HAS_RESOURCE_STREAMER(dev); break; + case I915_PARAM_HAS_EXEC_SOFTPIN: + value = 1; + break; default: DRM_DEBUG("Unknown parameter %d\n", param->param); return -EINVAL; @@ -257,7 +259,7 @@ intel_setup_mchbar(struct drm_device *dev) u32 temp; bool enabled; - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) return; dev_priv->mchbar_need_disable = false; @@ -338,7 +340,7 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_ i915_resume_switcheroo(dev); dev->switch_power_state = DRM_SWITCH_POWER_ON; } else { - pr_err("switched off\n"); + pr_info("switched off\n"); dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; i915_suspend_switcheroo(dev, pmm); dev->switch_power_state = DRM_SWITCH_POWER_OFF; @@ -368,7 +370,7 @@ static int i915_load_modeset_init(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int ret; - ret = intel_parse_bios(dev); + ret = intel_bios_init(dev_priv); if (ret) DRM_INFO("failed to find VBIOS tables\n"); @@ -396,7 +398,9 @@ static int i915_load_modeset_init(struct drm_device *dev) if (ret) goto cleanup_vga_switcheroo; - intel_power_domains_init_hw(dev_priv); + intel_power_domains_init_hw(dev_priv, false); + + intel_csr_ucode_init(dev_priv); ret = intel_irq_install(dev_priv); if (ret) @@ -439,7 +443,7 @@ static int i915_load_modeset_init(struct drm_device *dev) * scanning against hotplug events. Hence do this first and ignore the * tiny window where we will loose hotplug notifactions. */ - async_schedule(intel_fbdev_initial_config, dev_priv); + intel_fbdev_initial_config_async(dev); drm_kms_helper_poll_init(dev); @@ -666,7 +670,8 @@ static void gen9_sseu_info_init(struct drm_device *dev) * supports EU power gating on devices with more than one EU * pair per subslice. */ - info->has_slice_pg = (IS_SKYLAKE(dev) && (info->slice_total > 1)); + info->has_slice_pg = ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) && + (info->slice_total > 1)); info->has_subslice_pg = (IS_BROXTON(dev) && (info->subslice_total > 1)); info->has_eu_pg = (info->eu_per_subslice > 2); } @@ -780,7 +785,7 @@ static void intel_device_info_runtime_init(struct drm_device *dev) info->num_sprites[PIPE_A] = 2; info->num_sprites[PIPE_B] = 2; info->num_sprites[PIPE_C] = 1; - } else if (IS_VALLEYVIEW(dev)) + } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) for_each_pipe(dev_priv, pipe) info->num_sprites[pipe] = 2; else @@ -792,7 +797,7 @@ static void intel_device_info_runtime_init(struct drm_device *dev) info->num_pipes = 0; } else if (info->num_pipes > 0 && (INTEL_INFO(dev)->gen == 7 || INTEL_INFO(dev)->gen == 8) && - !IS_VALLEYVIEW(dev)) { + HAS_PCH_SPLIT(dev)) { u32 fuse_strap = I915_READ(FUSE_STRAP); u32 sfuse_strap = I915_READ(SFUSE_STRAP); @@ -837,9 +842,6 @@ static void intel_device_info_runtime_init(struct drm_device *dev) static void intel_init_dpio(struct drm_i915_private *dev_priv) { - if (!IS_VALLEYVIEW(dev_priv)) - return; - /* * IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C), * CHV x1 PHY (DP/HDMI D) @@ -848,7 +850,7 @@ static void intel_init_dpio(struct drm_i915_private *dev_priv) if (IS_CHERRYVIEW(dev_priv)) { DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2; DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO; - } else { + } else if (IS_VALLEYVIEW(dev_priv)) { DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO; } } @@ -893,11 +895,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) spin_lock_init(&dev_priv->mmio_flip_lock); mutex_init(&dev_priv->sb_lock); mutex_init(&dev_priv->modeset_restore_lock); - mutex_init(&dev_priv->csr_lock); mutex_init(&dev_priv->av_mutex); intel_pm_setup(dev); + intel_runtime_pm_get(dev_priv); + intel_display_crc_init(dev); i915_dump_device_info(dev_priv); @@ -940,9 +943,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_uncore_init(dev); - /* Load CSR Firmware for SKL */ - intel_csr_ucode_init(dev); - ret = i915_gem_gtt_init(dev); if (ret) goto out_freecsr; @@ -1089,6 +1089,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) i915_audio_component_init(dev_priv); + intel_runtime_pm_put(dev_priv); + return 0; out_power_well: @@ -1114,7 +1116,7 @@ out_mtrrfree: out_gtt: i915_global_gtt_cleanup(dev); out_freecsr: - intel_csr_ucode_fini(dev); + intel_csr_ucode_fini(dev_priv); intel_uncore_fini(dev); pci_iounmap(dev->pdev, dev_priv->regs); put_bridge: @@ -1123,6 +1125,9 @@ free_priv: kmem_cache_destroy(dev_priv->requests); kmem_cache_destroy(dev_priv->vmas); kmem_cache_destroy(dev_priv->objects); + + intel_runtime_pm_put(dev_priv); + kfree(dev_priv); return ret; } @@ -1132,6 +1137,8 @@ int i915_driver_unload(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int ret; + intel_fbdev_fini(dev); + i915_audio_component_cleanup(dev_priv); ret = i915_gem_suspend(dev); @@ -1154,8 +1161,6 @@ int i915_driver_unload(struct drm_device *dev) acpi_video_unregister(); - intel_fbdev_fini(dev); - drm_vblank_cleanup(dev); intel_modeset_cleanup(dev); @@ -1197,7 +1202,7 @@ int i915_driver_unload(struct drm_device *dev) intel_fbc_cleanup_cfb(dev_priv); i915_gem_cleanup_stolen(dev); - intel_csr_ucode_fini(dev); + intel_csr_ucode_fini(dev_priv); intel_teardown_mchbar(dev); @@ -1264,8 +1269,6 @@ void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; - if (file_priv && file_priv->bsd_ring) - file_priv->bsd_ring = NULL; kfree(file_priv); } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index a6ad938f4..08854aed3 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -228,161 +228,111 @@ static const struct intel_device_info intel_sandybridge_m_info = { .need_gfx_hws = 1, .has_hotplug = 1, \ .has_fbc = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ - .has_llc = 1 + .has_llc = 1, \ + GEN_DEFAULT_PIPEOFFSETS, \ + IVB_CURSOR_OFFSETS static const struct intel_device_info intel_ivybridge_d_info = { GEN7_FEATURES, .is_ivybridge = 1, - GEN_DEFAULT_PIPEOFFSETS, - IVB_CURSOR_OFFSETS, }; static const struct intel_device_info intel_ivybridge_m_info = { GEN7_FEATURES, .is_ivybridge = 1, .is_mobile = 1, - GEN_DEFAULT_PIPEOFFSETS, - IVB_CURSOR_OFFSETS, }; static const struct intel_device_info intel_ivybridge_q_info = { GEN7_FEATURES, .is_ivybridge = 1, .num_pipes = 0, /* legal, last one wins */ - GEN_DEFAULT_PIPEOFFSETS, - IVB_CURSOR_OFFSETS, }; +#define VLV_FEATURES \ + .gen = 7, .num_pipes = 2, \ + .need_gfx_hws = 1, .has_hotplug = 1, \ + .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ + .display_mmio_offset = VLV_DISPLAY_BASE, \ + GEN_DEFAULT_PIPEOFFSETS, \ + CURSOR_OFFSETS + static const struct intel_device_info intel_valleyview_m_info = { - GEN7_FEATURES, - .is_mobile = 1, - .num_pipes = 2, + VLV_FEATURES, .is_valleyview = 1, - .display_mmio_offset = VLV_DISPLAY_BASE, - .has_fbc = 0, /* legal, last one wins */ - .has_llc = 0, /* legal, last one wins */ - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, + .is_mobile = 1, }; static const struct intel_device_info intel_valleyview_d_info = { - GEN7_FEATURES, - .num_pipes = 2, + VLV_FEATURES, .is_valleyview = 1, - .display_mmio_offset = VLV_DISPLAY_BASE, - .has_fbc = 0, /* legal, last one wins */ - .has_llc = 0, /* legal, last one wins */ - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, }; +#define HSW_FEATURES \ + GEN7_FEATURES, \ + .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, \ + .has_ddi = 1, \ + .has_fpga_dbg = 1 + static const struct intel_device_info intel_haswell_d_info = { - GEN7_FEATURES, + HSW_FEATURES, .is_haswell = 1, - .has_ddi = 1, - .has_fpga_dbg = 1, - .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, - GEN_DEFAULT_PIPEOFFSETS, - IVB_CURSOR_OFFSETS, }; static const struct intel_device_info intel_haswell_m_info = { - GEN7_FEATURES, + HSW_FEATURES, .is_haswell = 1, .is_mobile = 1, - .has_ddi = 1, - .has_fpga_dbg = 1, - .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, - GEN_DEFAULT_PIPEOFFSETS, - IVB_CURSOR_OFFSETS, }; static const struct intel_device_info intel_broadwell_d_info = { - .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, - .has_fpga_dbg = 1, - .has_fbc = 1, - GEN_DEFAULT_PIPEOFFSETS, - IVB_CURSOR_OFFSETS, + HSW_FEATURES, + .gen = 8, }; static const struct intel_device_info intel_broadwell_m_info = { - .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_fpga_dbg = 1, - .has_fbc = 1, - GEN_DEFAULT_PIPEOFFSETS, - IVB_CURSOR_OFFSETS, + HSW_FEATURES, + .gen = 8, .is_mobile = 1, }; static const struct intel_device_info intel_broadwell_gt3d_info = { - .gen = 8, .num_pipes = 3, - .need_gfx_hws = 1, .has_hotplug = 1, + HSW_FEATURES, + .gen = 8, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, - .has_llc = 1, - .has_ddi = 1, - .has_fpga_dbg = 1, - .has_fbc = 1, - GEN_DEFAULT_PIPEOFFSETS, - IVB_CURSOR_OFFSETS, }; static const struct intel_device_info intel_broadwell_gt3m_info = { - .gen = 8, .is_mobile = 1, .num_pipes = 3, - .need_gfx_hws = 1, .has_hotplug = 1, + HSW_FEATURES, + .gen = 8, .is_mobile = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, - .has_llc = 1, - .has_ddi = 1, - .has_fpga_dbg = 1, - .has_fbc = 1, - GEN_DEFAULT_PIPEOFFSETS, - IVB_CURSOR_OFFSETS, }; static const struct intel_device_info intel_cherryview_info = { .gen = 8, .num_pipes = 3, .need_gfx_hws = 1, .has_hotplug = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, - .is_valleyview = 1, + .is_cherryview = 1, .display_mmio_offset = VLV_DISPLAY_BASE, GEN_CHV_PIPEOFFSETS, CURSOR_OFFSETS, }; static const struct intel_device_info intel_skylake_info = { + HSW_FEATURES, .is_skylake = 1, - .gen = 9, .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_fpga_dbg = 1, - .has_fbc = 1, - GEN_DEFAULT_PIPEOFFSETS, - IVB_CURSOR_OFFSETS, + .gen = 9, }; static const struct intel_device_info intel_skylake_gt3_info = { + HSW_FEATURES, .is_skylake = 1, - .gen = 9, .num_pipes = 3, - .need_gfx_hws = 1, .has_hotplug = 1, + .gen = 9, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, - .has_llc = 1, - .has_ddi = 1, - .has_fpga_dbg = 1, - .has_fbc = 1, - GEN_DEFAULT_PIPEOFFSETS, - IVB_CURSOR_OFFSETS, }; static const struct intel_device_info intel_broxton_info = { .is_preliminary = 1, + .is_broxton = 1, .gen = 9, .need_gfx_hws = 1, .has_hotplug = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, @@ -394,50 +344,67 @@ static const struct intel_device_info intel_broxton_info = { IVB_CURSOR_OFFSETS, }; +static const struct intel_device_info intel_kabylake_info = { + HSW_FEATURES, + .is_preliminary = 1, + .is_kabylake = 1, + .gen = 9, +}; + +static const struct intel_device_info intel_kabylake_gt3_info = { + HSW_FEATURES, + .is_preliminary = 1, + .is_kabylake = 1, + .gen = 9, + .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, +}; + /* * Make sure any device matches here are from most specific to most * general. For example, since the Quanta match is based on the subsystem * and subvendor IDs, we need it to come before the more general IVB * PCI ID matches, otherwise we'll use the wrong info struct above. */ -#define INTEL_PCI_IDS \ - INTEL_I830_IDS(&intel_i830_info), \ - INTEL_I845G_IDS(&intel_845g_info), \ - INTEL_I85X_IDS(&intel_i85x_info), \ - INTEL_I865G_IDS(&intel_i865g_info), \ - INTEL_I915G_IDS(&intel_i915g_info), \ - INTEL_I915GM_IDS(&intel_i915gm_info), \ - INTEL_I945G_IDS(&intel_i945g_info), \ - INTEL_I945GM_IDS(&intel_i945gm_info), \ - INTEL_I965G_IDS(&intel_i965g_info), \ - INTEL_G33_IDS(&intel_g33_info), \ - INTEL_I965GM_IDS(&intel_i965gm_info), \ - INTEL_GM45_IDS(&intel_gm45_info), \ - INTEL_G45_IDS(&intel_g45_info), \ - INTEL_PINEVIEW_IDS(&intel_pineview_info), \ - INTEL_IRONLAKE_D_IDS(&intel_ironlake_d_info), \ - INTEL_IRONLAKE_M_IDS(&intel_ironlake_m_info), \ - INTEL_SNB_D_IDS(&intel_sandybridge_d_info), \ - INTEL_SNB_M_IDS(&intel_sandybridge_m_info), \ - INTEL_IVB_Q_IDS(&intel_ivybridge_q_info), /* must be first IVB */ \ - INTEL_IVB_M_IDS(&intel_ivybridge_m_info), \ - INTEL_IVB_D_IDS(&intel_ivybridge_d_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_GT12M_IDS(&intel_broadwell_m_info), \ - INTEL_BDW_GT12D_IDS(&intel_broadwell_d_info), \ - INTEL_BDW_GT3M_IDS(&intel_broadwell_gt3m_info), \ - INTEL_BDW_GT3D_IDS(&intel_broadwell_gt3d_info), \ - INTEL_CHV_IDS(&intel_cherryview_info), \ - INTEL_SKL_GT1_IDS(&intel_skylake_info), \ - INTEL_SKL_GT2_IDS(&intel_skylake_info), \ - INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info), \ - INTEL_BXT_IDS(&intel_broxton_info) - -static const struct pci_device_id pciidlist[] = { /* aka */ - INTEL_PCI_IDS, +static const struct pci_device_id pciidlist[] = { + INTEL_I830_IDS(&intel_i830_info), + INTEL_I845G_IDS(&intel_845g_info), + INTEL_I85X_IDS(&intel_i85x_info), + INTEL_I865G_IDS(&intel_i865g_info), + INTEL_I915G_IDS(&intel_i915g_info), + INTEL_I915GM_IDS(&intel_i915gm_info), + INTEL_I945G_IDS(&intel_i945g_info), + INTEL_I945GM_IDS(&intel_i945gm_info), + INTEL_I965G_IDS(&intel_i965g_info), + INTEL_G33_IDS(&intel_g33_info), + INTEL_I965GM_IDS(&intel_i965gm_info), + INTEL_GM45_IDS(&intel_gm45_info), + INTEL_G45_IDS(&intel_g45_info), + INTEL_PINEVIEW_IDS(&intel_pineview_info), + INTEL_IRONLAKE_D_IDS(&intel_ironlake_d_info), + INTEL_IRONLAKE_M_IDS(&intel_ironlake_m_info), + INTEL_SNB_D_IDS(&intel_sandybridge_d_info), + INTEL_SNB_M_IDS(&intel_sandybridge_m_info), + INTEL_IVB_Q_IDS(&intel_ivybridge_q_info), /* must be first IVB */ + INTEL_IVB_M_IDS(&intel_ivybridge_m_info), + INTEL_IVB_D_IDS(&intel_ivybridge_d_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_GT12M_IDS(&intel_broadwell_m_info), + INTEL_BDW_GT12D_IDS(&intel_broadwell_d_info), + INTEL_BDW_GT3M_IDS(&intel_broadwell_gt3m_info), + INTEL_BDW_GT3D_IDS(&intel_broadwell_gt3d_info), + INTEL_CHV_IDS(&intel_cherryview_info), + INTEL_SKL_GT1_IDS(&intel_skylake_info), + INTEL_SKL_GT2_IDS(&intel_skylake_info), + INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info), + INTEL_SKL_GT4_IDS(&intel_skylake_gt3_info), + INTEL_BXT_IDS(&intel_broxton_info), + INTEL_KBL_GT1_IDS(&intel_kabylake_info), + INTEL_KBL_GT2_IDS(&intel_kabylake_info), + INTEL_KBL_GT3_IDS(&intel_kabylake_gt3_info), + INTEL_KBL_GT4_IDS(&intel_kabylake_gt3_info), {0, 0, 0} }; @@ -463,7 +430,7 @@ static enum intel_pch intel_virt_detect_pch(struct drm_device *dev) } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { ret = PCH_LPT; DRM_DEBUG_KMS("Assuming LynxPoint PCH\n"); - } else if (IS_SKYLAKE(dev)) { + } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { ret = PCH_SPT; DRM_DEBUG_KMS("Assuming SunrisePoint PCH\n"); } @@ -526,11 +493,13 @@ void intel_detect_pch(struct drm_device *dev) } else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_SPT; DRM_DEBUG_KMS("Found SunrisePoint PCH\n"); - WARN_ON(!IS_SKYLAKE(dev)); + WARN_ON(!IS_SKYLAKE(dev) && + !IS_KABYLAKE(dev)); } else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_SPT; DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n"); - WARN_ON(!IS_SKYLAKE(dev)); + WARN_ON(!IS_SKYLAKE(dev) && + !IS_KABYLAKE(dev)); } else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) || ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) && pch->subsystem_vendor == 0x1af4 && @@ -573,47 +542,31 @@ bool i915_semaphore_is_enabled(struct drm_device *dev) return true; } -void i915_firmware_load_error_print(const char *fw_path, int err) -{ - DRM_ERROR("failed to load firmware %s (%d)\n", fw_path, err); - - /* - * If the reason is not known assume -ENOENT since that's the most - * usual failure mode. - */ - if (!err) - err = -ENOENT; - - if (!(IS_BUILTIN(CONFIG_DRM_I915) && err == -ENOENT)) - return; - - DRM_ERROR( - "The driver is built-in, so to load the firmware you need to\n" - "include it either in the kernel (see CONFIG_EXTRA_FIRMWARE) or\n" - "in your initrd/initramfs image.\n"); -} - static void intel_suspend_encoders(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; - struct drm_encoder *encoder; + struct intel_encoder *encoder; drm_modeset_lock_all(dev); - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - struct intel_encoder *intel_encoder = to_intel_encoder(encoder); - - if (intel_encoder->suspend) - intel_encoder->suspend(intel_encoder); - } + for_each_intel_encoder(dev, encoder) + if (encoder->suspend) + encoder->suspend(encoder); drm_modeset_unlock_all(dev); } static int intel_suspend_complete(struct drm_i915_private *dev_priv); static int vlv_resume_prepare(struct drm_i915_private *dev_priv, bool rpm_resume); -static int skl_resume_prepare(struct drm_i915_private *dev_priv); static int bxt_resume_prepare(struct drm_i915_private *dev_priv); +static bool suspend_to_idle(struct drm_i915_private *dev_priv) +{ +#if IS_ENABLED(CONFIG_ACPI_SLEEP) + if (acpi_target_system_state() < ACPI_STATE_S3) + return true; +#endif + return false; +} static int i915_drm_suspend(struct drm_device *dev) { @@ -626,6 +579,8 @@ static int i915_drm_suspend(struct drm_device *dev) dev_priv->modeset_restore = MODESET_SUSPENDED; mutex_unlock(&dev_priv->modeset_restore_lock); + disable_rpm_wakeref_asserts(dev_priv); + /* We do a lot of poking in a lot of registers, make sure they work * properly. */ intel_display_set_init_power(dev_priv, true); @@ -638,7 +593,7 @@ static int i915_drm_suspend(struct drm_device *dev) if (error) { dev_err(&dev->pdev->dev, "GEM idle failed, resume might fail\n"); - return error; + goto out; } intel_guc_suspend(dev); @@ -666,11 +621,7 @@ static int i915_drm_suspend(struct drm_device *dev) i915_save_state(dev); - opregion_target_state = PCI_D3cold; -#if IS_ENABLED(CONFIG_ACPI_SLEEP) - if (acpi_target_system_state() < ACPI_STATE_S3) - opregion_target_state = PCI_D1; -#endif + opregion_target_state = suspend_to_idle(dev_priv) ? PCI_D1 : PCI_D3cold; intel_opregion_notify_adapter(dev, opregion_target_state); intel_uncore_forcewake_reset(dev, false); @@ -682,20 +633,42 @@ static int i915_drm_suspend(struct drm_device *dev) intel_display_set_init_power(dev_priv, false); - return 0; + if (HAS_CSR(dev_priv)) + flush_work(&dev_priv->csr.work); + +out: + enable_rpm_wakeref_asserts(dev_priv); + + return error; } static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation) { struct drm_i915_private *dev_priv = drm_dev->dev_private; + bool fw_csr; int ret; + disable_rpm_wakeref_asserts(dev_priv); + + fw_csr = suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload; + /* + * In case of firmware assisted context save/restore don't manually + * deinit the power domains. This also means the CSR/DMC firmware will + * stay active, it will power down any HW resources as required and + * also enable deeper system power states that would be blocked if the + * firmware was inactive. + */ + if (!fw_csr) + intel_power_domains_suspend(dev_priv); + ret = intel_suspend_complete(dev_priv); if (ret) { DRM_ERROR("Suspend complete failed: %d\n", ret); + if (!fw_csr) + intel_power_domains_init_hw(dev_priv, true); - return ret; + goto out; } pci_disable_device(drm_dev->pdev); @@ -714,7 +687,12 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation) if (!(hibernation && INTEL_INFO(dev_priv)->gen < 6)) pci_set_power_state(drm_dev->pdev, PCI_D3hot); - return 0; + dev_priv->suspended_to_idle = suspend_to_idle(dev_priv); + +out: + enable_rpm_wakeref_asserts(dev_priv); + + return ret; } int i915_suspend_switcheroo(struct drm_device *dev, pm_message_t state) @@ -745,6 +723,8 @@ static int i915_drm_resume(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + disable_rpm_wakeref_asserts(dev_priv); + mutex_lock(&dev->struct_mutex); i915_gem_restore_gtt_mappings(dev); mutex_unlock(&dev->struct_mutex); @@ -781,12 +761,12 @@ static int i915_drm_resume(struct drm_device *dev) dev_priv->display.hpd_irq_setup(dev); spin_unlock_irq(&dev_priv->irq_lock); + intel_dp_mst_resume(dev); + drm_modeset_lock_all(dev); intel_display_resume(dev); drm_modeset_unlock_all(dev); - intel_dp_mst_resume(dev); - /* * ... but also need to make sure that hotplug processing * doesn't cause havoc. Like in the driver load code we don't @@ -809,6 +789,8 @@ static int i915_drm_resume(struct drm_device *dev) drm_kms_helper_poll_enable(dev); + enable_rpm_wakeref_asserts(dev_priv); + return 0; } @@ -826,12 +808,16 @@ static int i915_drm_resume_early(struct drm_device *dev) * FIXME: This should be solved with a special hdmi sink device or * similar so that power domains can be employed. */ - if (pci_enable_device(dev->pdev)) - return -EIO; + if (pci_enable_device(dev->pdev)) { + ret = -EIO; + goto out; + } pci_set_master(dev->pdev); - if (IS_VALLEYVIEW(dev_priv)) + disable_rpm_wakeref_asserts(dev_priv); + + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) ret = vlv_resume_prepare(dev_priv, false); if (ret) DRM_ERROR("Resume prepare failed: %d, continuing anyway\n", @@ -841,13 +827,18 @@ static int i915_drm_resume_early(struct drm_device *dev) if (IS_BROXTON(dev)) ret = bxt_resume_prepare(dev_priv); - else if (IS_SKYLAKE(dev_priv)) - ret = skl_resume_prepare(dev_priv); else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) hsw_disable_pc8(dev_priv); intel_uncore_sanitize(dev); - intel_power_domains_init_hw(dev_priv); + + if (!(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload)) + intel_power_domains_init_hw(dev_priv, true); + +out: + dev_priv->suspended_to_idle = false; + + enable_rpm_wakeref_asserts(dev_priv); return ret; } @@ -1054,15 +1045,6 @@ static int i915_pm_resume(struct device *dev) return i915_drm_resume(drm_dev); } -static int skl_suspend_complete(struct drm_i915_private *dev_priv) -{ - /* Enabling DC6 is not a hard requirement to enter runtime D3 */ - - skl_uninit_cdclk(dev_priv); - - return 0; -} - static int hsw_suspend_complete(struct drm_i915_private *dev_priv) { hsw_enable_pc8(dev_priv); @@ -1102,16 +1084,6 @@ static int bxt_resume_prepare(struct drm_i915_private *dev_priv) return 0; } -static int skl_resume_prepare(struct drm_i915_private *dev_priv) -{ - struct drm_device *dev = dev_priv->dev; - - skl_init_cdclk(dev_priv); - intel_csr_load_program(dev); - - return 0; -} - /* * Save all Gunit registers that may be lost after a D3 and a subsequent * S0i[R123] transition. The list of registers needing a save/restore is @@ -1500,6 +1472,9 @@ static int intel_runtime_suspend(struct device *device) return -EAGAIN; } + + disable_rpm_wakeref_asserts(dev_priv); + /* * We are safe here against re-faults, since the fault handler takes * an RPM reference. @@ -1507,6 +1482,8 @@ static int intel_runtime_suspend(struct device *device) i915_gem_release_all_mmaps(dev_priv); mutex_unlock(&dev->struct_mutex); + cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work); + intel_guc_suspend(dev); intel_suspend_gt_powersave(dev); @@ -1517,11 +1494,15 @@ static int intel_runtime_suspend(struct device *device) DRM_ERROR("Runtime suspend failed, disabling it (%d)\n", ret); intel_runtime_pm_enable_interrupts(dev_priv); + enable_rpm_wakeref_asserts(dev_priv); + return ret; } - cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work); intel_uncore_forcewake_reset(dev, false); + + enable_rpm_wakeref_asserts(dev_priv); + WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count)); dev_priv->pm.suspended = true; /* @@ -1565,6 +1546,9 @@ static int intel_runtime_resume(struct device *device) DRM_DEBUG_KMS("Resuming device\n"); + WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count)); + disable_rpm_wakeref_asserts(dev_priv); + intel_opregion_notify_adapter(dev, PCI_D0); dev_priv->pm.suspended = false; @@ -1575,11 +1559,9 @@ static int intel_runtime_resume(struct device *device) if (IS_BROXTON(dev)) ret = bxt_resume_prepare(dev_priv); - else if (IS_SKYLAKE(dev)) - ret = skl_resume_prepare(dev_priv); else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) hsw_disable_pc8(dev_priv); - else if (IS_VALLEYVIEW(dev_priv)) + else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) ret = vlv_resume_prepare(dev_priv, true); /* @@ -1596,11 +1578,13 @@ static int intel_runtime_resume(struct device *device) * power well, so hpd is reinitialized from there. For * everyone else do it here. */ - if (!IS_VALLEYVIEW(dev_priv)) + if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) intel_hpd_init(dev_priv); intel_enable_gt_powersave(dev); + enable_rpm_wakeref_asserts(dev_priv); + if (ret) DRM_ERROR("Runtime resume failed, disabling it (%d)\n", ret); else @@ -1619,11 +1603,9 @@ static int intel_suspend_complete(struct drm_i915_private *dev_priv) if (IS_BROXTON(dev_priv)) ret = bxt_suspend_complete(dev_priv); - else if (IS_SKYLAKE(dev_priv)) - ret = skl_suspend_complete(dev_priv); else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) ret = hsw_suspend_complete(dev_priv); - else if (IS_VALLEYVIEW(dev_priv)) + else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) ret = vlv_suspend_complete(dev_priv); else ret = 0; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d3ce4da6a..b0847b915 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -33,6 +33,7 @@ #include <uapi/drm/i915_drm.h> #include <uapi/drm/drm_fourcc.h> +#include <drm/drmP.h> #include "i915_reg.h" #include "intel_bios.h" #include "intel_ringbuffer.h" @@ -57,7 +58,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20151010" +#define DRIVER_DATE "20151218" #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */ @@ -180,15 +181,11 @@ enum intel_display_power_domain { POWER_DOMAIN_TRANSCODER_B, POWER_DOMAIN_TRANSCODER_C, POWER_DOMAIN_TRANSCODER_EDP, - POWER_DOMAIN_PORT_DDI_A_2_LANES, - POWER_DOMAIN_PORT_DDI_A_4_LANES, - POWER_DOMAIN_PORT_DDI_B_2_LANES, - POWER_DOMAIN_PORT_DDI_B_4_LANES, - POWER_DOMAIN_PORT_DDI_C_2_LANES, - POWER_DOMAIN_PORT_DDI_C_4_LANES, - POWER_DOMAIN_PORT_DDI_D_2_LANES, - POWER_DOMAIN_PORT_DDI_D_4_LANES, - POWER_DOMAIN_PORT_DDI_E_2_LANES, + POWER_DOMAIN_PORT_DDI_A_LANES, + POWER_DOMAIN_PORT_DDI_B_LANES, + POWER_DOMAIN_PORT_DDI_C_LANES, + POWER_DOMAIN_PORT_DDI_D_LANES, + POWER_DOMAIN_PORT_DDI_E_LANES, POWER_DOMAIN_PORT_DSI, POWER_DOMAIN_PORT_CRT, POWER_DOMAIN_PORT_OTHER, @@ -200,6 +197,7 @@ enum intel_display_power_domain { POWER_DOMAIN_AUX_C, POWER_DOMAIN_AUX_D, POWER_DOMAIN_GMBUS, + POWER_DOMAIN_MODESET, POWER_DOMAIN_INIT, POWER_DOMAIN_NUM, @@ -289,7 +287,7 @@ struct i915_hotplug { list_for_each_entry(intel_plane, \ &(dev)->mode_config.plane_list, \ base.head) \ - if ((intel_plane)->pipe == (intel_crtc)->pipe) + for_each_if ((intel_plane)->pipe == (intel_crtc)->pipe) #define for_each_intel_crtc(dev, intel_crtc) \ list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) @@ -306,15 +304,15 @@ struct i915_hotplug { #define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \ list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \ - if ((intel_encoder)->base.crtc == (__crtc)) + for_each_if ((intel_encoder)->base.crtc == (__crtc)) #define for_each_connector_on_encoder(dev, __encoder, intel_connector) \ list_for_each_entry((intel_connector), &(dev)->mode_config.connector_list, base.head) \ - if ((intel_connector)->base.encoder == (__encoder)) + for_each_if ((intel_connector)->base.encoder == (__encoder)) #define for_each_power_domain(domain, mask) \ for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \ - if ((1 << (domain)) & (mask)) + for_each_if ((1 << (domain)) & (mask)) struct drm_i915_private; struct i915_mm_struct; @@ -460,7 +458,9 @@ struct intel_opregion { u32 swsci_gbda_sub_functions; u32 swsci_sbcb_sub_functions; struct opregion_asle *asle; - void *vbt; + void *rvda; + const void *vbt; + u32 vbt_size; u32 *lid_state; struct work_struct asle_work; }; @@ -631,11 +631,9 @@ struct drm_i915_display_funcs { int target, int refclk, struct dpll *match_clock, struct dpll *best_clock); + int (*compute_pipe_wm)(struct intel_crtc *crtc, + struct drm_atomic_state *state); void (*update_wm)(struct drm_crtc *crtc); - void (*update_sprite_wm)(struct drm_plane *plane, - struct drm_crtc *crtc, - uint32_t sprite_width, uint32_t sprite_height, - int pixel_size, bool enable, bool scaled); int (*modeset_calc_cdclk)(struct drm_atomic_state *state); void (*modeset_commit_cdclk)(struct drm_atomic_state *state); /* Returns the active state of the crtc, and if the crtc is active, @@ -693,18 +691,18 @@ struct intel_uncore_funcs { void (*force_wake_put)(struct drm_i915_private *dev_priv, enum forcewake_domains domains); - 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); + uint8_t (*mmio_readb)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace); + uint16_t (*mmio_readw)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace); + uint32_t (*mmio_readl)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace); + uint64_t (*mmio_readq)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace); - void (*mmio_writeb)(struct drm_i915_private *dev_priv, off_t offset, + void (*mmio_writeb)(struct drm_i915_private *dev_priv, i915_reg_t r, uint8_t val, bool trace); - void (*mmio_writew)(struct drm_i915_private *dev_priv, off_t offset, + void (*mmio_writew)(struct drm_i915_private *dev_priv, i915_reg_t r, uint16_t val, bool trace); - void (*mmio_writel)(struct drm_i915_private *dev_priv, off_t offset, + void (*mmio_writel)(struct drm_i915_private *dev_priv, i915_reg_t r, uint32_t val, bool trace); - void (*mmio_writeq)(struct drm_i915_private *dev_priv, off_t offset, + void (*mmio_writeq)(struct drm_i915_private *dev_priv, i915_reg_t r, uint64_t val, bool trace); }; @@ -721,11 +719,11 @@ struct intel_uncore { enum forcewake_domain_id id; unsigned wake_count; struct timer_list timer; - u32 reg_set; + i915_reg_t reg_set; u32 val_set; u32 val_clear; - u32 reg_ack; - u32 reg_post; + i915_reg_t reg_ack; + i915_reg_t reg_post; u32 val_reset; } fw_domain[FW_DOMAIN_ID_COUNT]; }; @@ -735,25 +733,25 @@ struct intel_uncore { for ((i__) = 0, (domain__) = &(dev_priv__)->uncore.fw_domain[0]; \ (i__) < FW_DOMAIN_ID_COUNT; \ (i__)++, (domain__) = &(dev_priv__)->uncore.fw_domain[i__]) \ - if (((mask__) & (dev_priv__)->uncore.fw_domains) & (1 << (i__))) + for_each_if (((mask__) & (dev_priv__)->uncore.fw_domains) & (1 << (i__))) #define for_each_fw_domain(domain__, dev_priv__, i__) \ for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__) -enum csr_state { - FW_UNINITIALIZED = 0, - FW_LOADED, - FW_FAILED -}; +#define CSR_VERSION(major, minor) ((major) << 16 | (minor)) +#define CSR_VERSION_MAJOR(version) ((version) >> 16) +#define CSR_VERSION_MINOR(version) ((version) & 0xffff) struct intel_csr { + struct work_struct work; const char *fw_path; uint32_t *dmc_payload; uint32_t dmc_fw_size; + uint32_t version; uint32_t mmio_count; - uint32_t mmioaddr[8]; + i915_reg_t mmioaddr[8]; uint32_t mmiodata[8]; - enum csr_state state; + uint32_t dc_state; }; #define DEV_INFO_FOR_EACH_FLAG(func, sep) \ @@ -769,8 +767,11 @@ struct intel_csr { func(is_crestline) sep \ func(is_ivybridge) sep \ func(is_valleyview) sep \ + func(is_cherryview) sep \ func(is_haswell) sep \ func(is_skylake) sep \ + func(is_broxton) sep \ + func(is_kabylake) sep \ func(is_preliminary) sep \ func(has_fbc) sep \ func(has_pipe_cxsr) sep \ @@ -906,7 +907,6 @@ struct i915_fbc { /* This is always the inner lock when overlapping with struct_mutex and * it's the outer lock when overlapping with stolen_lock. */ struct mutex lock; - unsigned long uncompressed_size; unsigned threshold; unsigned int fb_id; unsigned int possible_framebuffer_bits; @@ -919,38 +919,21 @@ struct i915_fbc { bool false_color; - /* Tracks whether the HW is actually enabled, not whether the feature is - * possible. */ bool enabled; + bool active; struct intel_fbc_work { - struct delayed_work work; - struct intel_crtc *crtc; + bool scheduled; + struct work_struct work; struct drm_framebuffer *fb; - } *fbc_work; - - enum no_fbc_reason { - FBC_OK, /* FBC is enabled */ - FBC_UNSUPPORTED, /* FBC is not supported by this chipset */ - FBC_NO_OUTPUT, /* no outputs enabled to compress */ - FBC_STOLEN_TOO_SMALL, /* not enough space for buffers */ - FBC_UNSUPPORTED_MODE, /* interlace or doublescanned mode */ - FBC_MODE_TOO_LARGE, /* mode too large for compression */ - FBC_BAD_PLANE, /* fbc not supported on plane */ - FBC_NOT_TILED, /* buffer not tiled */ - FBC_MULTIPLE_PIPES, /* more than one pipe active */ - FBC_MODULE_PARAM, - FBC_CHIP_DEFAULT, /* disabled by default on this chip */ - FBC_ROTATION, /* rotation is not supported */ - FBC_IN_DBG_MASTER, /* kernel debugger is active */ - FBC_BAD_STRIDE, /* stride is not supported */ - FBC_PIXEL_RATE, /* pixel rate is too big */ - FBC_PIXEL_FORMAT /* pixel format is invalid */ - } no_fbc_reason; - - bool (*fbc_enabled)(struct drm_i915_private *dev_priv); - void (*enable_fbc)(struct intel_crtc *crtc); - void (*disable_fbc)(struct drm_i915_private *dev_priv); + unsigned long enable_jiffies; + } work; + + const char *no_fbc_reason; + + bool (*is_active)(struct drm_i915_private *dev_priv); + void (*activate)(struct intel_crtc *crtc); + void (*deactivate)(struct drm_i915_private *dev_priv); }; /** @@ -1020,7 +1003,7 @@ struct intel_gmbus { struct i2c_adapter adapter; u32 force_bit; u32 reg0; - u32 gpio_reg; + i915_reg_t gpio_reg; struct i2c_algo_bit_data bit_algo; struct drm_i915_private *dev_priv; }; @@ -1623,6 +1606,8 @@ struct skl_wm_level { * For more, read the Documentation/power/runtime_pm.txt. */ struct i915_runtime_pm { + atomic_t wakeref_count; + atomic_t atomic_seq; bool suspended; bool irqs_enabled; }; @@ -1669,7 +1654,7 @@ struct i915_frontbuffer_tracking { }; struct i915_wa_reg { - u32 addr; + i915_reg_t addr; u32 value; /* bitmask representing WA bits */ u32 mask; @@ -1698,6 +1683,13 @@ struct i915_execbuffer_params { struct drm_i915_gem_request *request; }; +/* used in computing the new watermarks state */ +struct intel_wm_config { + unsigned int num_pipes_active; + bool sprites_enabled; + bool sprites_scaled; +}; + struct drm_i915_private { struct drm_device *dev; struct kmem_cache *objects; @@ -1718,9 +1710,6 @@ struct drm_i915_private { struct intel_csr csr; - /* Display CSR-related protection */ - struct mutex csr_lock; - struct intel_gmbus gmbus[GMBUS_NUM_PINS]; /** gmbus_mutex protects against concurrent usage of the single hw gmbus @@ -1735,6 +1724,8 @@ struct drm_i915_private { /* MMIO base address for MIPI regs */ uint32_t mipi_mmio_base; + uint32_t psr_mmio_base; + wait_queue_head_t gmbus_wait_queue; struct pci_dev *bridge_dev; @@ -1900,6 +1891,7 @@ struct drm_i915_private { u32 chv_phy_control; u32 suspend_count; + bool suspended_to_idle; struct i915_suspend_saved_registers regfile; struct vlv_s0ix_state vlv_s0ix_state; @@ -1922,6 +1914,9 @@ struct drm_i915_private { */ uint16_t skl_latency[8]; + /* Committed wm config */ + struct intel_wm_config config; + /* * The skl_wm_values structure is a bit too big for stack * allocation, so we keep the staging struct where we store @@ -1956,6 +1951,8 @@ struct drm_i915_private { /* perform PHY state sanity checks? */ bool chv_phy_assert[2]; + struct intel_encoder *dig_port_map[I915_MAX_PORTS]; + /* * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place. @@ -1980,7 +1977,7 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) /* Iterate over initialised rings */ #define for_each_ring(ring__, dev_priv__, i__) \ for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \ - if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))) + for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))) enum hdmi_force_audio { HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */ @@ -1992,6 +1989,9 @@ enum hdmi_force_audio { #define I915_GTT_OFFSET_NONE ((u32)-1) struct drm_i915_gem_object_ops { + unsigned int flags; +#define I915_GEM_OBJECT_HAS_STRUCT_PAGE 0x1 + /* Interface between the GEM object and its backing storage. * get_pages() is called once prior to the use of the associated set * of pages before to binding them into the GTT, and put_pages() is @@ -2007,6 +2007,7 @@ struct drm_i915_gem_object_ops { */ int (*get_pages)(struct drm_i915_gem_object *); void (*put_pages)(struct drm_i915_gem_object *); + int (*dmabuf_export)(struct drm_i915_gem_object *); void (*release)(struct drm_i915_gem_object *); }; @@ -2445,6 +2446,15 @@ struct drm_i915_cmd_table { #define INTEL_DEVID(p) (INTEL_INFO(p)->device_id) #define INTEL_REVID(p) (__I915__(p)->dev->pdev->revision) +#define REVID_FOREVER 0xff +/* + * Return true if revision is in range [since,until] inclusive. + * + * Use 0 for open-ended since, and REVID_FOREVER for open-ended until. + */ +#define IS_REVID(p, since, until) \ + (INTEL_REVID(p) >= (since) && INTEL_REVID(p) <= (until)) + #define IS_I830(dev) (INTEL_DEVID(dev) == 0x3577) #define IS_845G(dev) (INTEL_DEVID(dev) == 0x2562) #define IS_I85X(dev) (INTEL_INFO(dev)->is_i85x) @@ -2467,11 +2477,12 @@ struct drm_i915_cmd_table { INTEL_DEVID(dev) == 0x0152 || \ INTEL_DEVID(dev) == 0x015a) #define IS_VALLEYVIEW(dev) (INTEL_INFO(dev)->is_valleyview) -#define IS_CHERRYVIEW(dev) (INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev)) +#define IS_CHERRYVIEW(dev) (INTEL_INFO(dev)->is_cherryview) #define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell) -#define IS_BROADWELL(dev) (!INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev)) +#define IS_BROADWELL(dev) (!INTEL_INFO(dev)->is_cherryview && IS_GEN8(dev)) #define IS_SKYLAKE(dev) (INTEL_INFO(dev)->is_skylake) -#define IS_BROXTON(dev) (!INTEL_INFO(dev)->is_skylake && IS_GEN9(dev)) +#define IS_BROXTON(dev) (INTEL_INFO(dev)->is_broxton) +#define IS_KABYLAKE(dev) (INTEL_INFO(dev)->is_kabylake) #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) #define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \ (INTEL_DEVID(dev) & 0xFF00) == 0x0C00) @@ -2499,6 +2510,14 @@ struct drm_i915_cmd_table { #define IS_SKL_ULX(dev) (INTEL_DEVID(dev) == 0x190E || \ INTEL_DEVID(dev) == 0x1915 || \ INTEL_DEVID(dev) == 0x191E) +#define IS_KBL_ULT(dev) (INTEL_DEVID(dev) == 0x5906 || \ + INTEL_DEVID(dev) == 0x5913 || \ + INTEL_DEVID(dev) == 0x5916 || \ + INTEL_DEVID(dev) == 0x5921 || \ + INTEL_DEVID(dev) == 0x5926) +#define IS_KBL_ULX(dev) (INTEL_DEVID(dev) == 0x590E || \ + INTEL_DEVID(dev) == 0x5915 || \ + INTEL_DEVID(dev) == 0x591E) #define IS_SKL_GT3(dev) (IS_SKYLAKE(dev) && \ (INTEL_DEVID(dev) & 0x00F0) == 0x0020) #define IS_SKL_GT4(dev) (IS_SKYLAKE(dev) && \ @@ -2506,16 +2525,21 @@ struct drm_i915_cmd_table { #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) -#define SKL_REVID_A0 (0x0) -#define SKL_REVID_B0 (0x1) -#define SKL_REVID_C0 (0x2) -#define SKL_REVID_D0 (0x3) -#define SKL_REVID_E0 (0x4) -#define SKL_REVID_F0 (0x5) +#define SKL_REVID_A0 0x0 +#define SKL_REVID_B0 0x1 +#define SKL_REVID_C0 0x2 +#define SKL_REVID_D0 0x3 +#define SKL_REVID_E0 0x4 +#define SKL_REVID_F0 0x5 + +#define IS_SKL_REVID(p, since, until) (IS_SKYLAKE(p) && IS_REVID(p, since, until)) -#define BXT_REVID_A0 (0x0) -#define BXT_REVID_B0 (0x3) -#define BXT_REVID_C0 (0x9) +#define BXT_REVID_A0 0x0 +#define BXT_REVID_A1 0x1 +#define BXT_REVID_B0 0x3 +#define BXT_REVID_C0 0x9 + +#define IS_BXT_REVID(p, since, until) (IS_BROXTON(p) && IS_REVID(p, since, until)) /* * The genX designation typically refers to the render engine, so render @@ -2587,23 +2611,25 @@ struct drm_i915_cmd_table { #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) #define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev) || \ IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || \ - IS_SKYLAKE(dev)) + IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) #define HAS_RUNTIME_PM(dev) (IS_GEN6(dev) || IS_HASWELL(dev) || \ IS_BROADWELL(dev) || IS_VALLEYVIEW(dev) || \ - IS_SKYLAKE(dev)) + IS_CHERRYVIEW(dev) || IS_SKYLAKE(dev) || \ + IS_KABYLAKE(dev)) #define HAS_RC6(dev) (INTEL_INFO(dev)->gen >= 6) #define HAS_RC6p(dev) (INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev)) #define HAS_CSR(dev) (IS_GEN9(dev)) -#define HAS_GUC_UCODE(dev) (IS_GEN9(dev)) -#define HAS_GUC_SCHED(dev) (IS_GEN9(dev)) +#define HAS_GUC_UCODE(dev) (IS_GEN9(dev) && !IS_KABYLAKE(dev)) +#define HAS_GUC_SCHED(dev) (IS_GEN9(dev) && !IS_KABYLAKE(dev)) #define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \ INTEL_INFO(dev)->gen >= 8) #define HAS_CORE_RING_FREQ(dev) (INTEL_INFO(dev)->gen >= 6 && \ - !IS_VALLEYVIEW(dev) && !IS_BROXTON(dev)) + !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && \ + !IS_BROXTON(dev)) #define INTEL_PCH_DEVICE_ID_MASK 0xff00 #define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00 @@ -2620,12 +2646,14 @@ struct drm_i915_cmd_table { #define HAS_PCH_SPT(dev) (INTEL_PCH_TYPE(dev) == PCH_SPT) #define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT) #define HAS_PCH_LPT_LP(dev) (__I915__(dev)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) +#define HAS_PCH_LPT_H(dev) (__I915__(dev)->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) #define HAS_PCH_NOP(dev) (INTEL_PCH_TYPE(dev) == PCH_NOP) #define HAS_PCH_SPLIT(dev) (INTEL_PCH_TYPE(dev) != PCH_NONE) -#define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->gen < 5 || IS_VALLEYVIEW(dev)) +#define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->gen < 5 || \ + IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) /* DPF == dynamic parity feature */ #define HAS_L3_DPF(dev) (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) @@ -2651,6 +2679,7 @@ struct i915_params { int panel_use_ssc; int vbt_sdvo_panel_type; int enable_rc6; + int enable_dc; int enable_fbc; int enable_ppgtt; int enable_execlists; @@ -2699,7 +2728,6 @@ extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv); extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv); extern void i915_update_gfx_val(struct drm_i915_private *dev_priv); int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on); -void i915_firmware_load_error_print(const char *fw_path, int err); /* intel_hotplug.c */ void intel_hpd_irq_handler(struct drm_device *dev, u32 pin_mask, u32 long_mask); @@ -2756,17 +2784,47 @@ void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv); void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv, uint32_t mask, uint32_t bits); -void -ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask); -void -ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask); +void ilk_update_display_irq(struct drm_i915_private *dev_priv, + uint32_t interrupt_mask, + uint32_t enabled_irq_mask); +static inline void +ilk_enable_display_irq(struct drm_i915_private *dev_priv, uint32_t bits) +{ + ilk_update_display_irq(dev_priv, bits, bits); +} +static inline void +ilk_disable_display_irq(struct drm_i915_private *dev_priv, uint32_t bits) +{ + ilk_update_display_irq(dev_priv, bits, 0); +} +void bdw_update_pipe_irq(struct drm_i915_private *dev_priv, + enum pipe pipe, + uint32_t interrupt_mask, + uint32_t enabled_irq_mask); +static inline void bdw_enable_pipe_irq(struct drm_i915_private *dev_priv, + enum pipe pipe, uint32_t bits) +{ + bdw_update_pipe_irq(dev_priv, pipe, bits, bits); +} +static inline void bdw_disable_pipe_irq(struct drm_i915_private *dev_priv, + enum pipe pipe, uint32_t bits) +{ + bdw_update_pipe_irq(dev_priv, pipe, bits, 0); +} void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, uint32_t interrupt_mask, uint32_t enabled_irq_mask); -#define ibx_enable_display_interrupt(dev_priv, bits) \ - ibx_display_interrupt_update((dev_priv), (bits), (bits)) -#define ibx_disable_display_interrupt(dev_priv, bits) \ - ibx_display_interrupt_update((dev_priv), (bits), 0) +static inline void +ibx_enable_display_interrupt(struct drm_i915_private *dev_priv, uint32_t bits) +{ + ibx_display_interrupt_update(dev_priv, bits, bits); +} +static inline void +ibx_disable_display_interrupt(struct drm_i915_private *dev_priv, uint32_t bits) +{ + ibx_display_interrupt_update(dev_priv, bits, 0); +} + /* i915_gem.c */ int i915_gem_create_ioctl(struct drm_device *dev, void *data, @@ -2835,6 +2893,7 @@ void i915_gem_vma_destroy(struct i915_vma *vma); #define PIN_UPDATE (1<<5) #define PIN_ZONE_4G (1<<6) #define PIN_HIGH (1<<7) +#define PIN_OFFSET_FIXED (1<<8) #define PIN_OFFSET_MASK (~4095) int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj, @@ -2870,6 +2929,9 @@ static inline int __sg_page_count(struct scatterlist *sg) return sg->length >> PAGE_SHIFT; } +struct page * +i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n); + static inline struct page * i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n) { @@ -3009,8 +3071,6 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write); int __must_check i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, u32 alignment, - struct intel_engine_cs *pipelined, - struct drm_i915_gem_request **pipelined_request, const struct i915_ggtt_view *view); void i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj, const struct i915_ggtt_view *view); @@ -3185,6 +3245,7 @@ int __must_check i915_gem_evict_something(struct drm_device *dev, unsigned long start, unsigned long end, unsigned flags); +int __must_check i915_gem_evict_for_vma(struct i915_vma *target); int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle); /* belongs in i915_gem_gtt.h */ @@ -3313,6 +3374,10 @@ static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter) } extern void intel_i2c_reset(struct drm_device *dev); +/* intel_bios.c */ +int intel_bios_init(struct drm_i915_private *dev_priv); +bool intel_bios_is_valid_vbt(const void *buf, size_t size); + /* intel_opregion.c */ #ifdef CONFIG_ACPI extern int intel_opregion_setup(struct drm_device *dev); @@ -3365,7 +3430,6 @@ extern void intel_set_rps(struct drm_device *dev, u8 val); extern void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable); extern void intel_detect_pch(struct drm_device *dev); -extern int intel_trans_dp_port_sel(struct drm_crtc *crtc); extern int intel_enable_rc6(const struct drm_device *dev); extern bool i915_semaphore_is_enabled(struct drm_device *dev); @@ -3448,6 +3512,32 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val); #define POSTING_READ(reg) (void)I915_READ_NOTRACE(reg) #define POSTING_READ16(reg) (void)I915_READ16_NOTRACE(reg) +#define __raw_read(x, s) \ +static inline uint##x##_t __raw_i915_read##x(struct drm_i915_private *dev_priv, \ + i915_reg_t reg) \ +{ \ + return read##s(dev_priv->regs + i915_mmio_reg_offset(reg)); \ +} + +#define __raw_write(x, s) \ +static inline void __raw_i915_write##x(struct drm_i915_private *dev_priv, \ + i915_reg_t reg, uint##x##_t val) \ +{ \ + write##s(val, dev_priv->regs + i915_mmio_reg_offset(reg)); \ +} +__raw_read(8, b) +__raw_read(16, w) +__raw_read(32, l) +__raw_read(64, q) + +__raw_write(8, b) +__raw_write(16, w) +__raw_write(32, l) +__raw_write(64, q) + +#undef __raw_read +#undef __raw_write + /* These are untraced mmio-accessors that are only valid to be used inside * criticial sections inside IRQ handlers where forcewake is explicitly * controlled. @@ -3455,8 +3545,8 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val); * Note: Should only be used between intel_uncore_forcewake_irqlock() and * intel_uncore_forcewake_irqunlock(). */ -#define I915_READ_FW(reg__) readl(dev_priv->regs + (reg__)) -#define I915_WRITE_FW(reg__, val__) writel(val__, dev_priv->regs + (reg__)) +#define I915_READ_FW(reg__) __raw_i915_read32(dev_priv, (reg__)) +#define I915_WRITE_FW(reg__, val__) __raw_i915_write32(dev_priv, (reg__), (val__)) #define POSTING_READ_FW(reg__) (void)I915_READ_FW(reg__) /* "Broadcast RGB" property */ @@ -3464,9 +3554,9 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val); #define INTEL_BROADCAST_RGB_FULL 1 #define INTEL_BROADCAST_RGB_LIMITED 2 -static inline uint32_t i915_vgacntrl_reg(struct drm_device *dev) +static inline i915_reg_t i915_vgacntrl_reg(struct drm_device *dev) { - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) return VLV_VGACNTRL; else if (INTEL_INFO(dev)->gen >= 5) return CPU_VGACNTRL; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f56af0aaa..bb44bad15 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2797,6 +2797,8 @@ static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv, static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv, struct intel_engine_cs *ring) { + struct intel_ringbuffer *buffer; + while (!list_empty(&ring->active_list)) { struct drm_i915_gem_object *obj; @@ -2812,18 +2814,16 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv, * are the ones that keep the context and ringbuffer backing objects * pinned in place. */ - while (!list_empty(&ring->execlist_queue)) { - struct drm_i915_gem_request *submit_req; - submit_req = list_first_entry(&ring->execlist_queue, - struct drm_i915_gem_request, - execlist_link); - list_del(&submit_req->execlist_link); + if (i915.enable_execlists) { + spin_lock_irq(&ring->execlist_lock); - if (submit_req->ctx != ring->default_context) - intel_lr_context_unpin(submit_req); + /* list_splice_tail_init checks for empty lists */ + list_splice_tail_init(&ring->execlist_queue, + &ring->execlist_retired_req_list); - i915_gem_request_unreference(submit_req); + spin_unlock_irq(&ring->execlist_lock); + intel_execlists_retire_requests(ring); } /* @@ -2842,6 +2842,18 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv, i915_gem_request_retire(request); } + + /* Having flushed all requests from all queues, we know that all + * ringbuffers must now be empty. However, since we do not reclaim + * all space when retiring the request (to prevent HEADs colliding + * with rapid ringbuffer wraparound) the amount of available space + * upon reset is less than when we start. Do one more pass over + * all the ringbuffers to reset last_retired_head. + */ + list_for_each_entry(buffer, &ring->buffers, link) { + buffer->last_retired_head = buffer->tail; + intel_ring_update_space(buffer); + } } void i915_gem_reset(struct drm_device *dev) @@ -2982,6 +2994,10 @@ i915_gem_idle_work_handler(struct work_struct *work) if (!list_empty(&ring->request_list)) return; + /* we probably should sync with hangcheck here, using cancel_work_sync. + * Also locking seems to be fubar here, ring->request_list is protected + * by dev->struct_mutex. */ + intel_mark_idle(dev); if (mutex_trylock(&dev->struct_mutex)) { @@ -3106,7 +3122,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) if (ret == 0) ret = __i915_wait_request(req[i], reset_counter, true, args->timeout_ns > 0 ? &args->timeout_ns : NULL, - file->driver_priv); + to_rps_client(file)); i915_gem_request_unreference__unlocked(req[i]); } return ret; @@ -3472,7 +3488,7 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, if (flags & PIN_MAPPABLE) end = min_t(u64, end, dev_priv->gtt.mappable_end); if (flags & PIN_ZONE_4G) - end = min_t(u64, end, (1ULL << 32)); + end = min_t(u64, end, (1ULL << 32) - PAGE_SIZE); if (alignment == 0) alignment = flags & PIN_MAPPABLE ? fence_alignment : @@ -3509,30 +3525,50 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, if (IS_ERR(vma)) goto err_unpin; - if (flags & PIN_HIGH) { - search_flag = DRM_MM_SEARCH_BELOW; - alloc_flag = DRM_MM_CREATE_TOP; + if (flags & PIN_OFFSET_FIXED) { + uint64_t offset = flags & PIN_OFFSET_MASK; + + if (offset & (alignment - 1) || offset + size > end) { + ret = -EINVAL; + goto err_free_vma; + } + vma->node.start = offset; + vma->node.size = size; + vma->node.color = obj->cache_level; + ret = drm_mm_reserve_node(&vm->mm, &vma->node); + if (ret) { + ret = i915_gem_evict_for_vma(vma); + if (ret == 0) + ret = drm_mm_reserve_node(&vm->mm, &vma->node); + } + if (ret) + goto err_free_vma; } else { - search_flag = DRM_MM_SEARCH_DEFAULT; - alloc_flag = DRM_MM_CREATE_DEFAULT; - } + if (flags & PIN_HIGH) { + search_flag = DRM_MM_SEARCH_BELOW; + alloc_flag = DRM_MM_CREATE_TOP; + } else { + search_flag = DRM_MM_SEARCH_DEFAULT; + alloc_flag = DRM_MM_CREATE_DEFAULT; + } search_free: - ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node, - size, alignment, - obj->cache_level, - start, end, - search_flag, - alloc_flag); - if (ret) { - ret = i915_gem_evict_something(dev, vm, size, alignment, - obj->cache_level, - start, end, - flags); - if (ret == 0) - goto search_free; + ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node, + size, alignment, + obj->cache_level, + start, end, + search_flag, + alloc_flag); + if (ret) { + ret = i915_gem_evict_something(dev, vm, size, alignment, + obj->cache_level, + start, end, + flags); + if (ret == 0) + goto search_free; - goto err_free_vma; + goto err_free_vma; + } } if (WARN_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level))) { ret = -EINVAL; @@ -3886,7 +3922,7 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data, * cacheline, whereas normally such cachelines would get * invalidated. */ - if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) + if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) return -ENODEV; level = I915_CACHE_LLC; @@ -3929,17 +3965,11 @@ rpm_put: int i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, u32 alignment, - struct intel_engine_cs *pipelined, - struct drm_i915_gem_request **pipelined_request, const struct i915_ggtt_view *view) { u32 old_read_domains, old_write_domain; int ret; - ret = i915_gem_object_sync(obj, pipelined, pipelined_request); - if (ret) - return ret; - /* Mark the pin_display early so that we account for the * display coherency whilst setting up the cache domains. */ @@ -4129,6 +4159,10 @@ i915_vma_misplaced(struct i915_vma *vma, uint32_t alignment, uint64_t flags) vma->node.start < (flags & PIN_OFFSET_MASK)) return true; + if (flags & PIN_OFFSET_FIXED && + vma->node.start != (flags & PIN_OFFSET_MASK)) + return true; + return false; } @@ -4391,6 +4425,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj, } static const struct drm_i915_gem_object_ops i915_gem_object_ops = { + .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE, .get_pages = i915_gem_object_get_pages_gtt, .put_pages = i915_gem_object_put_pages_gtt, }; @@ -4541,10 +4576,8 @@ struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj, { struct i915_vma *vma; list_for_each_entry(vma, &obj->vma_list, vma_link) { - if (i915_is_ggtt(vma->vm) && - vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL) - continue; - if (vma->vm == vm) + if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL && + vma->vm == vm) return vma; } return NULL; @@ -4633,7 +4666,6 @@ int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice) struct intel_engine_cs *ring = req->ring; struct drm_device *dev = ring->dev; struct drm_i915_private *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; @@ -4649,10 +4681,10 @@ int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice) * here because no other code should access these registers other than * at initialization time. */ - for (i = 0; i < GEN7_L3LOG_SIZE; i += 4) { + for (i = 0; i < GEN7_L3LOG_SIZE / 4; i++) { intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit(ring, reg_base + i); - intel_ring_emit(ring, remap_info[i/4]); + intel_ring_emit_reg(ring, GEN7_L3LOG(slice, i)); + intel_ring_emit(ring, remap_info[i]); } intel_ring_advance(ring); @@ -4820,18 +4852,9 @@ i915_gem_init_hw(struct drm_device *dev) if (HAS_GUC_UCODE(dev)) { ret = intel_guc_ucode_load(dev); if (ret) { - /* - * If we got an error and GuC submission is enabled, map - * the error to -EIO so the GPU will be declared wedged. - * OTOH, if we didn't intend to use the GuC anyway, just - * discard the error and carry on. - */ - DRM_ERROR("Failed to initialize GuC, error %d%s\n", ret, - i915.enable_guc_submission ? "" : - " (ignored)"); - ret = i915.enable_guc_submission ? -EIO : 0; - if (ret) - goto out; + DRM_ERROR("Failed to initialize GuC, error %d\n", ret); + ret = -EIO; + goto out; } } @@ -4894,14 +4917,6 @@ int i915_gem_init(struct drm_device *dev) mutex_lock(&dev->struct_mutex); - if (IS_VALLEYVIEW(dev)) { - /* VLVA0 (potential hack), BIOS isn't actually waking us */ - I915_WRITE(VLV_GTLC_WAKE_CTRL, VLV_GTLC_ALLOWWAKEREQ); - if (wait_for((I915_READ(VLV_GTLC_PW_STATUS) & - VLV_GTLC_ALLOWWAKEACK), 10)) - DRM_DEBUG_DRIVER("allow wake ack timed out\n"); - } - if (!i915.enable_execlists) { dev_priv->gt.execbuf_submit = i915_gem_ringbuffer_submission; dev_priv->gt.init_rings = i915_gem_init_rings; @@ -5019,7 +5034,7 @@ i915_gem_load(struct drm_device *dev) dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL; - if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev)) + if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) dev_priv->num_fence_regs = 32; else if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) dev_priv->num_fence_regs = 16; @@ -5240,6 +5255,21 @@ bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj) return false; } +/* Like i915_gem_object_get_page(), but mark the returned page dirty */ +struct page * +i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n) +{ + struct page *page; + + /* Only default objects have per-page dirty tracking */ + if (WARN_ON((obj->ops->flags & I915_GEM_OBJECT_HAS_STRUCT_PAGE) == 0)) + return NULL; + + page = i915_gem_object_get_page(obj, n); + set_page_dirty(page); + return page; +} + /* Allocate a new GEM object and fill it with the supplied data */ struct drm_i915_gem_object * i915_gem_object_create_from_data(struct drm_device *dev, @@ -5265,6 +5295,7 @@ i915_gem_object_create_from_data(struct drm_device *dev, i915_gem_object_pin_pages(obj); sg = obj->pages; bytes = sg_copy_from_buffer(sg->sgl, sg->nents, (void *)data, size); + obj->dirty = 1; /* Backing store is now out of date */ i915_gem_object_unpin_pages(obj); if (WARN_ON(bytes != size)) { diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 0433d25f9..c25083c78 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -189,8 +189,15 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size) * shouldn't touch the cache level, especially as that * would make the object snooped which might have a * negative performance impact. + * + * Snooping is required on non-llc platforms in execlist + * mode, but since all GGTT accesses use PAT entry 0 we + * get snooping anyway regardless of cache_level. + * + * This is only applicable for Ivy Bridge devices since + * later platforms don't have L3 control bits in the PTE. */ - if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev)) { + if (IS_IVYBRIDGE(dev)) { ret = i915_gem_object_set_cache_level(obj, I915_CACHE_L3_LLC); /* Failure shouldn't ever happen this early */ if (WARN_ON(ret)) { @@ -558,7 +565,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) if (signaller == ring) continue; - intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base)); + intel_ring_emit_reg(ring, RING_PSMI_CTL(signaller->mmio_base)); intel_ring_emit(ring, _MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE)); } } @@ -583,7 +590,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) if (signaller == ring) continue; - intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base)); + intel_ring_emit_reg(ring, RING_PSMI_CTL(signaller->mmio_base)); intel_ring_emit(ring, _MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE)); } } @@ -927,6 +934,14 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data, case I915_CONTEXT_PARAM_NO_ZEROMAP: args->value = ctx->flags & CONTEXT_NO_ZEROMAP; break; + case I915_CONTEXT_PARAM_GTT_SIZE: + if (ctx->ppgtt) + args->value = ctx->ppgtt->base.total; + else if (to_i915(dev)->mm.aliasing_ppgtt) + args->value = to_i915(dev)->mm.aliasing_ppgtt->base.total; + else + args->value = to_i915(dev)->gtt.base.total; + break; default: ret = -EINVAL; break; diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index d71a133ce..07c6e4d32 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -199,6 +199,45 @@ found: return ret; } +int +i915_gem_evict_for_vma(struct i915_vma *target) +{ + struct drm_mm_node *node, *next; + + list_for_each_entry_safe(node, next, + &target->vm->mm.head_node.node_list, + node_list) { + struct i915_vma *vma; + int ret; + + if (node->start + node->size <= target->node.start) + continue; + if (node->start >= target->node.start + target->node.size) + break; + + vma = container_of(node, typeof(*vma), node); + + if (vma->pin_count) { + if (!vma->exec_entry || (vma->pin_count > 1)) + /* Object is pinned for some other use */ + return -EBUSY; + + /* We need to evict a buffer in the same batch */ + if (vma->exec_entry->flags & EXEC_OBJECT_PINNED) + /* Overlapping fixed objects in the same batch */ + return -EINVAL; + + return -ENOSPC; + } + + ret = i915_vma_unbind(vma); + if (ret) + return ret; + } + + return 0; +} + /** * i915_gem_evict_vm - Evict all idle vmas from a vm * @vm: Address space to cleanse diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 6ed7d63a0..dccb51736 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -249,6 +249,31 @@ static inline int use_cpu_reloc(struct drm_i915_gem_object *obj) obj->cache_level != I915_CACHE_NONE); } +/* Used to convert any address to canonical form. + * Starting from gen8, some commands (e.g. STATE_BASE_ADDRESS, + * MI_LOAD_REGISTER_MEM and others, see Broadwell PRM Vol2a) require the + * addresses to be in a canonical form: + * "GraphicsAddress[63:48] are ignored by the HW and assumed to be in correct + * canonical form [63:48] == [47]." + */ +#define GEN8_HIGH_ADDRESS_BIT 47 +static inline uint64_t gen8_canonical_addr(uint64_t address) +{ + return sign_extend64(address, GEN8_HIGH_ADDRESS_BIT); +} + +static inline uint64_t gen8_noncanonical_addr(uint64_t address) +{ + return address & ((1ULL << (GEN8_HIGH_ADDRESS_BIT + 1)) - 1); +} + +static inline uint64_t +relocation_target(struct drm_i915_gem_relocation_entry *reloc, + uint64_t target_offset) +{ + return gen8_canonical_addr((int)reloc->delta + target_offset); +} + static int relocate_entry_cpu(struct drm_i915_gem_object *obj, struct drm_i915_gem_relocation_entry *reloc, @@ -256,7 +281,7 @@ relocate_entry_cpu(struct drm_i915_gem_object *obj, { struct drm_device *dev = obj->base.dev; uint32_t page_offset = offset_in_page(reloc->offset); - uint64_t delta = reloc->delta + target_offset; + uint64_t delta = relocation_target(reloc, target_offset); char *vaddr; int ret; @@ -264,7 +289,7 @@ relocate_entry_cpu(struct drm_i915_gem_object *obj, if (ret) return ret; - vaddr = kmap_atomic(i915_gem_object_get_page(obj, + vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj, reloc->offset >> PAGE_SHIFT)); *(uint32_t *)(vaddr + page_offset) = lower_32_bits(delta); @@ -273,7 +298,7 @@ relocate_entry_cpu(struct drm_i915_gem_object *obj, if (page_offset == 0) { kunmap_atomic(vaddr); - vaddr = kmap_atomic(i915_gem_object_get_page(obj, + vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj, (reloc->offset + sizeof(uint32_t)) >> PAGE_SHIFT)); } @@ -292,7 +317,7 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj, { struct drm_device *dev = obj->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - uint64_t delta = reloc->delta + target_offset; + uint64_t delta = relocation_target(reloc, target_offset); uint64_t offset; void __iomem *reloc_page; int ret; @@ -347,7 +372,7 @@ relocate_entry_clflush(struct drm_i915_gem_object *obj, { struct drm_device *dev = obj->base.dev; uint32_t page_offset = offset_in_page(reloc->offset); - uint64_t delta = (int)reloc->delta + target_offset; + uint64_t delta = relocation_target(reloc, target_offset); char *vaddr; int ret; @@ -355,7 +380,7 @@ relocate_entry_clflush(struct drm_i915_gem_object *obj, if (ret) return ret; - vaddr = kmap_atomic(i915_gem_object_get_page(obj, + vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj, reloc->offset >> PAGE_SHIFT)); clflush_write32(vaddr + page_offset, lower_32_bits(delta)); @@ -364,7 +389,7 @@ relocate_entry_clflush(struct drm_i915_gem_object *obj, if (page_offset == 0) { kunmap_atomic(vaddr); - vaddr = kmap_atomic(i915_gem_object_get_page(obj, + vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj, (reloc->offset + sizeof(uint32_t)) >> PAGE_SHIFT)); } @@ -395,7 +420,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, target_i915_obj = target_vma->obj; target_obj = &target_vma->obj->base; - target_offset = target_vma->node.start; + target_offset = gen8_canonical_addr(target_vma->node.start); /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and * pipe_control writes because the gpu doesn't properly redirect them @@ -599,6 +624,8 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, flags |= PIN_GLOBAL | PIN_MAPPABLE; if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS) flags |= BATCH_OFFSET_BIAS | PIN_OFFSET_BIAS; + if (entry->flags & EXEC_OBJECT_PINNED) + flags |= entry->offset | PIN_OFFSET_FIXED; if ((flags & PIN_MAPPABLE) == 0) flags |= PIN_HIGH; } @@ -670,6 +697,10 @@ eb_vma_misplaced(struct i915_vma *vma) vma->node.start & (entry->alignment - 1)) return true; + if (entry->flags & EXEC_OBJECT_PINNED && + vma->node.start != entry->offset) + return true; + if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS && vma->node.start < BATCH_OFFSET_BIAS) return true; @@ -695,6 +726,7 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring, struct i915_vma *vma; struct i915_address_space *vm; struct list_head ordered_vmas; + struct list_head pinned_vmas; bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; int retry; @@ -703,6 +735,7 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring, vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm; INIT_LIST_HEAD(&ordered_vmas); + INIT_LIST_HEAD(&pinned_vmas); while (!list_empty(vmas)) { struct drm_i915_gem_exec_object2 *entry; bool need_fence, need_mappable; @@ -721,7 +754,9 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring, obj->tiling_mode != I915_TILING_NONE; need_mappable = need_fence || need_reloc_mappable(vma); - if (need_mappable) { + if (entry->flags & EXEC_OBJECT_PINNED) + list_move_tail(&vma->exec_list, &pinned_vmas); + else if (need_mappable) { entry->flags |= __EXEC_OBJECT_NEEDS_MAP; list_move(&vma->exec_list, &ordered_vmas); } else @@ -731,6 +766,7 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring, obj->base.pending_write_domain = 0; } list_splice(&ordered_vmas, vmas); + list_splice(&pinned_vmas, vmas); /* Attempt to pin all of the buffers into the GTT. * This is done in 3 phases: @@ -983,6 +1019,21 @@ validate_exec_list(struct drm_device *dev, if (exec[i].flags & invalid_flags) return -EINVAL; + /* Offset can be used as input (EXEC_OBJECT_PINNED), reject + * any non-page-aligned or non-canonical addresses. + */ + if (exec[i].flags & EXEC_OBJECT_PINNED) { + if (exec[i].offset != + gen8_canonical_addr(exec[i].offset & PAGE_MASK)) + return -EINVAL; + + /* From drm_mm perspective address space is continuous, + * so from this point we're always using non-canonical + * form internally. + */ + exec[i].offset = gen8_noncanonical_addr(exec[i].offset); + } + if (exec[i].alignment && !is_power_of_2(exec[i].alignment)) return -EINVAL; @@ -1114,7 +1165,7 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev, for (i = 0; i < 4; i++) { intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit(ring, GEN7_SO_WRITE_OFFSET(i)); + intel_ring_emit_reg(ring, GEN7_SO_WRITE_OFFSET(i)); intel_ring_emit(ring, 0); } @@ -1241,7 +1292,7 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params, intel_ring_emit(ring, MI_NOOP); intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit(ring, INSTPM); + intel_ring_emit_reg(ring, INSTPM); intel_ring_emit(ring, instp_mask << 16 | instp_mode); intel_ring_advance(ring); @@ -1317,7 +1368,8 @@ eb_get_batch(struct eb_vmas *eb) * Note that actual hangs have only been observed on gen7, but for * paranoia do it everywhere. */ - vma->exec_entry->flags |= __EXEC_OBJECT_NEEDS_BIAS; + if ((vma->exec_entry->flags & EXEC_OBJECT_PINNED) == 0) + vma->exec_entry->flags |= __EXEC_OBJECT_NEEDS_BIAS; return vma->obj; } @@ -1675,6 +1727,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, /* Copy the new buffer offsets back to the user's exec list. */ for (i = 0; i < args->buffer_count; i++) { + exec2_list[i].offset = + gen8_canonical_addr(exec2_list[i].offset); ret = __copy_to_user(&user_exec_list[i].offset, &exec2_list[i].offset, sizeof(user_exec_list[i].offset)); @@ -1740,6 +1794,8 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data, int i; for (i = 0; i < args->buffer_count; i++) { + exec2_list[i].offset = + gen8_canonical_addr(exec2_list[i].offset); ret = __copy_to_user(&user_exec_list[i].offset, &exec2_list[i].offset, sizeof(user_exec_list[i].offset)); diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence.c index f010391b8..598198543 100644 --- a/drivers/gpu/drm/i915/i915_gem_fence.c +++ b/drivers/gpu/drm/i915/i915_gem_fence.c @@ -59,7 +59,7 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg, struct drm_i915_gem_object *obj) { struct drm_i915_private *dev_priv = dev->dev_private; - int fence_reg_lo, fence_reg_hi; + i915_reg_t fence_reg_lo, fence_reg_hi; int fence_pitch_shift; if (INTEL_INFO(dev)->gen >= 6) { diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 86c750045..56f4f2e58 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -24,6 +24,7 @@ */ #include <linux/seq_file.h> +#include <linux/stop_machine.h> #include <drm/drmP.h> #include <drm/i915_drm.h> #include "i915_drv.h" @@ -104,9 +105,11 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt) { bool has_aliasing_ppgtt; bool has_full_ppgtt; + bool has_full_48bit_ppgtt; has_aliasing_ppgtt = INTEL_INFO(dev)->gen >= 6; has_full_ppgtt = INTEL_INFO(dev)->gen >= 7; + has_full_48bit_ppgtt = IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9; if (intel_vgpu_active(dev)) has_full_ppgtt = false; /* emulation is too hard */ @@ -125,6 +128,9 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt) if (enable_ppgtt == 2 && has_full_ppgtt) return 2; + if (enable_ppgtt == 3 && has_full_48bit_ppgtt) + return 3; + #ifdef CONFIG_INTEL_IOMMU /* Disable ppgtt on SNB if VT-d is on. */ if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) { @@ -134,14 +140,13 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt) #endif /* Early VLV doesn't have this */ - if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && - dev->pdev->revision < 0xb) { + if (IS_VALLEYVIEW(dev) && dev->pdev->revision < 0xb) { DRM_DEBUG_DRIVER("disabling PPGTT on pre-B3 step VLV\n"); return 0; } if (INTEL_INFO(dev)->gen >= 8 && i915.enable_execlists) - return 2; + return has_full_48bit_ppgtt ? 3 : 2; else return has_aliasing_ppgtt ? 1 : 0; } @@ -661,10 +666,10 @@ static int gen8_write_pdp(struct drm_i915_gem_request *req, return ret; intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit(ring, GEN8_RING_PDP_UDW(ring, entry)); + intel_ring_emit_reg(ring, GEN8_RING_PDP_UDW(ring, entry)); intel_ring_emit(ring, upper_32_bits(addr)); intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit(ring, GEN8_RING_PDP_LDW(ring, entry)); + intel_ring_emit_reg(ring, GEN8_RING_PDP_LDW(ring, entry)); intel_ring_emit(ring, lower_32_bits(addr)); intel_ring_advance(ring); @@ -764,10 +769,10 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm, gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length, scratch_pte); } else { - uint64_t templ4, pml4e; + uint64_t pml4e; struct i915_page_directory_pointer *pdp; - gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, templ4, pml4e) { + gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) { gen8_ppgtt_clear_pte_range(vm, pdp, start, length, scratch_pte); } @@ -833,10 +838,10 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm, cache_level); } else { struct i915_page_directory_pointer *pdp; - uint64_t templ4, pml4e; + uint64_t pml4e; uint64_t length = (uint64_t)pages->orig_nents << PAGE_SHIFT; - gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, templ4, pml4e) { + gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) { gen8_ppgtt_insert_pte_entries(vm, pdp, &sg_iter, start, cache_level); } @@ -904,14 +909,13 @@ static int gen8_ppgtt_notify_vgt(struct i915_hw_ppgtt *ppgtt, bool create) enum vgt_g2v_type msg; struct drm_device *dev = ppgtt->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - unsigned int offset = vgtif_reg(pdp0_lo); int i; if (USES_FULL_48BIT_PPGTT(dev)) { u64 daddr = px_dma(&ppgtt->pml4); - I915_WRITE(offset, lower_32_bits(daddr)); - I915_WRITE(offset + 4, upper_32_bits(daddr)); + I915_WRITE(vgtif_reg(pdp[0].lo), lower_32_bits(daddr)); + I915_WRITE(vgtif_reg(pdp[0].hi), upper_32_bits(daddr)); msg = (create ? VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE : VGT_G2V_PPGTT_L4_PAGE_TABLE_DESTROY); @@ -919,10 +923,8 @@ static int gen8_ppgtt_notify_vgt(struct i915_hw_ppgtt *ppgtt, bool create) for (i = 0; i < GEN8_LEGACY_PDPES; i++) { u64 daddr = i915_page_dir_dma_addr(ppgtt, i); - I915_WRITE(offset, lower_32_bits(daddr)); - I915_WRITE(offset + 4, upper_32_bits(daddr)); - - offset += 8; + I915_WRITE(vgtif_reg(pdp[i].lo), lower_32_bits(daddr)); + I915_WRITE(vgtif_reg(pdp[i].hi), upper_32_bits(daddr)); } msg = (create ? VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE : @@ -1017,10 +1019,9 @@ static int gen8_ppgtt_alloc_pagetabs(struct i915_address_space *vm, { struct drm_device *dev = vm->dev; struct i915_page_table *pt; - uint64_t temp; uint32_t pde; - gen8_for_each_pde(pt, pd, start, length, temp, pde) { + gen8_for_each_pde(pt, pd, start, length, pde) { /* Don't reallocate page tables */ if (test_bit(pde, pd->used_pdes)) { /* Scratch is never allocated this way */ @@ -1079,13 +1080,12 @@ gen8_ppgtt_alloc_page_directories(struct i915_address_space *vm, { struct drm_device *dev = vm->dev; struct i915_page_directory *pd; - uint64_t temp; uint32_t pdpe; uint32_t pdpes = I915_PDPES_PER_PDP(dev); WARN_ON(!bitmap_empty(new_pds, pdpes)); - gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) { + gen8_for_each_pdpe(pd, pdp, start, length, pdpe) { if (test_bit(pdpe, pdp->used_pdpes)) continue; @@ -1133,12 +1133,11 @@ gen8_ppgtt_alloc_page_dirpointers(struct i915_address_space *vm, { struct drm_device *dev = vm->dev; struct i915_page_directory_pointer *pdp; - uint64_t temp; uint32_t pml4e; WARN_ON(!bitmap_empty(new_pdps, GEN8_PML4ES_PER_PML4)); - gen8_for_each_pml4e(pdp, pml4, start, length, temp, pml4e) { + gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) { if (!test_bit(pml4e, pml4->used_pml4es)) { pdp = alloc_pdp(dev); if (IS_ERR(pdp)) @@ -1222,7 +1221,6 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm, struct i915_page_directory *pd; const uint64_t orig_start = start; const uint64_t orig_length = length; - uint64_t temp; uint32_t pdpe; uint32_t pdpes = I915_PDPES_PER_PDP(dev); int ret; @@ -1249,7 +1247,7 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm, } /* For every page directory referenced, allocate page tables */ - gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) { + gen8_for_each_pdpe(pd, pdp, start, length, pdpe) { ret = gen8_ppgtt_alloc_pagetabs(vm, pd, start, length, new_page_tables + pdpe * BITS_TO_LONGS(I915_PDES)); if (ret) @@ -1261,7 +1259,7 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm, /* Allocations have completed successfully, so set the bitmaps, and do * the mappings. */ - gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) { + gen8_for_each_pdpe(pd, pdp, start, length, pdpe) { gen8_pde_t *const page_directory = kmap_px(pd); struct i915_page_table *pt; uint64_t pd_len = length; @@ -1271,7 +1269,7 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm, /* Every pd should be allocated, we just did that above. */ WARN_ON(!pd); - gen8_for_each_pde(pt, pd, pd_start, pd_len, temp, pde) { + gen8_for_each_pde(pt, pd, pd_start, pd_len, pde) { /* Same reasoning as pd */ WARN_ON(!pt); WARN_ON(!pd_len); @@ -1308,6 +1306,8 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm, err_out: while (pdpe--) { + unsigned long temp; + for_each_set_bit(temp, new_page_tables + pdpe * BITS_TO_LONGS(I915_PDES), I915_PDES) free_pt(dev, pdp->page_directory[pdpe]->page_table[temp]); @@ -1330,7 +1330,7 @@ static int gen8_alloc_va_range_4lvl(struct i915_address_space *vm, struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); struct i915_page_directory_pointer *pdp; - uint64_t temp, pml4e; + uint64_t pml4e; int ret = 0; /* Do the pml4 allocations first, so we don't need to track the newly @@ -1349,7 +1349,7 @@ static int gen8_alloc_va_range_4lvl(struct i915_address_space *vm, "The allocation has spanned more than 512GB. " "It is highly likely this is incorrect."); - gen8_for_each_pml4e(pdp, pml4, start, length, temp, pml4e) { + gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) { WARN_ON(!pdp); ret = gen8_alloc_va_range_3lvl(vm, pdp, start, length); @@ -1389,10 +1389,9 @@ static void gen8_dump_pdp(struct i915_page_directory_pointer *pdp, struct seq_file *m) { struct i915_page_directory *pd; - uint64_t temp; uint32_t pdpe; - gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) { + gen8_for_each_pdpe(pd, pdp, start, length, pdpe) { struct i915_page_table *pt; uint64_t pd_len = length; uint64_t pd_start = start; @@ -1402,7 +1401,7 @@ static void gen8_dump_pdp(struct i915_page_directory_pointer *pdp, continue; seq_printf(m, "\tPDPE #%d\n", pdpe); - gen8_for_each_pde(pt, pd, pd_start, pd_len, temp, pde) { + gen8_for_each_pde(pt, pd, pd_start, pd_len, pde) { uint32_t pte; gen8_pte_t *pt_vaddr; @@ -1452,11 +1451,11 @@ static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) if (!USES_FULL_48BIT_PPGTT(vm->dev)) { gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m); } else { - uint64_t templ4, pml4e; + uint64_t pml4e; struct i915_pml4 *pml4 = &ppgtt->pml4; struct i915_page_directory_pointer *pdp; - gen8_for_each_pml4e(pdp, pml4, start, length, templ4, pml4e) { + gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) { if (!test_bit(pml4e, pml4->used_pml4es)) continue; @@ -1662,9 +1661,9 @@ static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt, return ret; intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2)); - intel_ring_emit(ring, RING_PP_DIR_DCLV(ring)); + intel_ring_emit_reg(ring, RING_PP_DIR_DCLV(ring)); intel_ring_emit(ring, PP_DIR_DCLV_2G); - intel_ring_emit(ring, RING_PP_DIR_BASE(ring)); + intel_ring_emit_reg(ring, RING_PP_DIR_BASE(ring)); intel_ring_emit(ring, get_pd_offset(ppgtt)); intel_ring_emit(ring, MI_NOOP); intel_ring_advance(ring); @@ -1699,9 +1698,9 @@ static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt, return ret; intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2)); - intel_ring_emit(ring, RING_PP_DIR_DCLV(ring)); + intel_ring_emit_reg(ring, RING_PP_DIR_DCLV(ring)); intel_ring_emit(ring, PP_DIR_DCLV_2G); - intel_ring_emit(ring, RING_PP_DIR_BASE(ring)); + intel_ring_emit_reg(ring, RING_PP_DIR_BASE(ring)); intel_ring_emit(ring, get_pd_offset(ppgtt)); intel_ring_emit(ring, MI_NOOP); intel_ring_advance(ring); @@ -2352,6 +2351,9 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, int i = 0; struct sg_page_iter sg_iter; dma_addr_t addr = 0; /* shut up gcc */ + int rpm_atomic_seq; + + rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) { addr = sg_dma_address(sg_iter.sg) + @@ -2378,6 +2380,34 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, */ I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); POSTING_READ(GFX_FLSH_CNTL_GEN6); + + assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); +} + +struct insert_entries { + struct i915_address_space *vm; + struct sg_table *st; + uint64_t start; + enum i915_cache_level level; + u32 flags; +}; + +static int gen8_ggtt_insert_entries__cb(void *_arg) +{ + struct insert_entries *arg = _arg; + gen8_ggtt_insert_entries(arg->vm, arg->st, + arg->start, arg->level, arg->flags); + return 0; +} + +static void gen8_ggtt_insert_entries__BKL(struct i915_address_space *vm, + struct sg_table *st, + uint64_t start, + enum i915_cache_level level, + u32 flags) +{ + struct insert_entries arg = { vm, st, start, level, flags }; + stop_machine(gen8_ggtt_insert_entries__cb, &arg, NULL); } /* @@ -2398,6 +2428,9 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, int i = 0; struct sg_page_iter sg_iter; dma_addr_t addr = 0; + int rpm_atomic_seq; + + rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) { addr = sg_page_iter_dma_address(&sg_iter); @@ -2422,6 +2455,8 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, */ I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); POSTING_READ(GFX_FLSH_CNTL_GEN6); + + assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); } static void gen8_ggtt_clear_range(struct i915_address_space *vm, @@ -2436,6 +2471,9 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, (gen8_pte_t __iomem *) dev_priv->gtt.gsm + first_entry; const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry; int i; + int rpm_atomic_seq; + + rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); if (WARN(num_entries > max_entries, "First entry = %d; Num entries = %d (max=%d)\n", @@ -2448,6 +2486,8 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, for (i = 0; i < num_entries; i++) gen8_set_pte(>t_base[i], scratch_pte); readl(gtt_base); + + assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); } static void gen6_ggtt_clear_range(struct i915_address_space *vm, @@ -2462,6 +2502,9 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, (gen6_pte_t __iomem *) dev_priv->gtt.gsm + first_entry; const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry; int i; + int rpm_atomic_seq; + + rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); if (WARN(num_entries > max_entries, "First entry = %d; Num entries = %d (max=%d)\n", @@ -2474,6 +2517,8 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, for (i = 0; i < num_entries; i++) iowrite32(scratch_pte, >t_base[i]); readl(gtt_base); + + assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); } static void i915_ggtt_insert_entries(struct i915_address_space *vm, @@ -2481,11 +2526,17 @@ static void i915_ggtt_insert_entries(struct i915_address_space *vm, uint64_t start, enum i915_cache_level cache_level, u32 unused) { + struct drm_i915_private *dev_priv = vm->dev->dev_private; unsigned int flags = (cache_level == I915_CACHE_NONE) ? AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY; + int rpm_atomic_seq; + + rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); intel_gtt_insert_sg_entries(pages, start >> PAGE_SHIFT, flags); + assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); + } static void i915_ggtt_clear_range(struct i915_address_space *vm, @@ -2493,9 +2544,16 @@ static void i915_ggtt_clear_range(struct i915_address_space *vm, uint64_t length, bool unused) { + struct drm_i915_private *dev_priv = vm->dev->dev_private; unsigned first_entry = start >> PAGE_SHIFT; unsigned num_entries = length >> PAGE_SHIFT; + int rpm_atomic_seq; + + rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); + intel_gtt_clear_range(first_entry, num_entries); + + assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); } static int ggtt_bind_vma(struct i915_vma *vma, @@ -2996,6 +3054,9 @@ static int gen8_gmch_probe(struct drm_device *dev, dev_priv->gtt.base.bind_vma = ggtt_bind_vma; dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma; + if (IS_CHERRYVIEW(dev_priv)) + dev_priv->gtt.base.insert_entries = gen8_ggtt_insert_entries__BKL; + return ret; } @@ -3303,7 +3364,7 @@ static struct sg_table * intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, struct drm_i915_gem_object *obj) { - struct intel_rotation_info *rot_info = &ggtt_view->rotation_info; + struct intel_rotation_info *rot_info = &ggtt_view->params.rotation_info; unsigned int size_pages = rot_info->size >> PAGE_SHIFT; unsigned int size_pages_uv; struct sg_page_iter sg_iter; @@ -3535,7 +3596,7 @@ i915_ggtt_view_size(struct drm_i915_gem_object *obj, if (view->type == I915_GGTT_VIEW_NORMAL) { return obj->base.size; } else if (view->type == I915_GGTT_VIEW_ROTATED) { - return view->rotation_info.size; + return view->params.rotation_info.size; } else if (view->type == I915_GGTT_VIEW_PARTIAL) { return view->params.partial.size << PAGE_SHIFT; } else { diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index a216397ea..b448ad832 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -156,13 +156,10 @@ struct i915_ggtt_view { u64 offset; unsigned int size; } partial; + struct intel_rotation_info rotation_info; } params; struct sg_table *pages; - - union { - struct intel_rotation_info rotation_info; - }; }; extern const struct i915_ggtt_view i915_ggtt_view_normal; @@ -458,32 +455,29 @@ static inline uint32_t gen6_pde_index(uint32_t addr) * between from start until start + length. On gen8+ it simply iterates * over every page directory entry in a page directory. */ -#define gen8_for_each_pde(pt, pd, start, length, temp, iter) \ - for (iter = gen8_pde_index(start); \ - length > 0 && iter < I915_PDES ? \ - (pt = (pd)->page_table[iter]), 1 : 0; \ - iter++, \ - temp = ALIGN(start+1, 1 << GEN8_PDE_SHIFT) - start, \ - temp = min(temp, length), \ - start += temp, length -= temp) - -#define gen8_for_each_pdpe(pd, pdp, start, length, temp, iter) \ - for (iter = gen8_pdpe_index(start); \ - length > 0 && (iter < I915_PDPES_PER_PDP(dev)) ? \ - (pd = (pdp)->page_directory[iter]), 1 : 0; \ - iter++, \ - temp = ALIGN(start+1, 1 << GEN8_PDPE_SHIFT) - start, \ - temp = min(temp, length), \ - start += temp, length -= temp) - -#define gen8_for_each_pml4e(pdp, pml4, start, length, temp, iter) \ - for (iter = gen8_pml4e_index(start); \ - length > 0 && iter < GEN8_PML4ES_PER_PML4 ? \ - (pdp = (pml4)->pdps[iter]), 1 : 0; \ - iter++, \ - temp = ALIGN(start+1, 1ULL << GEN8_PML4E_SHIFT) - start, \ - temp = min(temp, length), \ - start += temp, length -= temp) +#define gen8_for_each_pde(pt, pd, start, length, iter) \ + for (iter = gen8_pde_index(start); \ + length > 0 && iter < I915_PDES && \ + (pt = (pd)->page_table[iter], true); \ + ({ u64 temp = ALIGN(start+1, 1 << GEN8_PDE_SHIFT); \ + temp = min(temp - start, length); \ + start += temp, length -= temp; }), ++iter) + +#define gen8_for_each_pdpe(pd, pdp, start, length, iter) \ + for (iter = gen8_pdpe_index(start); \ + length > 0 && iter < I915_PDPES_PER_PDP(dev) && \ + (pd = (pdp)->page_directory[iter], true); \ + ({ u64 temp = ALIGN(start+1, 1 << GEN8_PDPE_SHIFT); \ + temp = min(temp - start, length); \ + start += temp, length -= temp; }), ++iter) + +#define gen8_for_each_pml4e(pdp, pml4, start, length, iter) \ + for (iter = gen8_pml4e_index(start); \ + length > 0 && iter < GEN8_PML4ES_PER_PML4 && \ + (pdp = (pml4)->pdps[iter], true); \ + ({ u64 temp = ALIGN(start+1, 1ULL << GEN8_PML4E_SHIFT); \ + temp = min(temp - start, length); \ + start += temp, length -= temp; }), ++iter) static inline uint32_t gen8_pte_index(uint64_t address) { @@ -556,7 +550,7 @@ i915_ggtt_view_equal(const struct i915_ggtt_view *a, if (a->type != b->type) return false; - if (a->type == I915_GGTT_VIEW_PARTIAL) + if (a->type != I915_GGTT_VIEW_NORMAL) return !memcmp(&a->params, &b->params, sizeof(a->params)); return true; } diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index 5026a6267..fc7e6d5c6 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -103,7 +103,7 @@ static int render_state_setup(struct render_state *so) if (ret) return ret; - page = sg_page(so->obj->pages->sgl); + page = i915_gem_object_get_dirty_page(so->obj, 0); d = kmap(page); while (i < rodata->batch_items) { diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 87e919a06..3476877fc 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -433,7 +433,8 @@ int i915_gem_init_stolen(struct drm_device *dev) &reserved_size); break; default: - if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv)) + if (IS_BROADWELL(dev_priv) || + IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev)) bdw_get_stolen_reserved(dev_priv, &reserved_base, &reserved_size); else diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 8a6717cc2..7410f6c96 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -176,6 +176,8 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, return -EINVAL; } + intel_runtime_pm_get(dev_priv); + mutex_lock(&dev->struct_mutex); if (obj->pin_display || obj->framebuffer_references) { ret = -EBUSY; @@ -269,6 +271,8 @@ err: drm_gem_object_unreference(&obj->base); mutex_unlock(&dev->struct_mutex); + intel_runtime_pm_put(dev_priv); + return ret; } diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 19fb0bddc..59e45b3a6 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -789,9 +789,10 @@ i915_gem_userptr_dmabuf_export(struct drm_i915_gem_object *obj) } static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = { - .dmabuf_export = i915_gem_userptr_dmabuf_export, + .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE, .get_pages = i915_gem_userptr_get_pages, .put_pages = i915_gem_userptr_put_pages, + .dmabuf_export = i915_gem_userptr_dmabuf_export, .release = i915_gem_userptr_release, }; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 2f04e4f2f..06ca40827 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -366,6 +366,17 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, err_printf(m, "Suspend count: %u\n", error->suspend_count); err_printf(m, "PCI ID: 0x%04x\n", dev->pdev->device); err_printf(m, "IOMMU enabled?: %d\n", error->iommu); + + if (HAS_CSR(dev)) { + struct intel_csr *csr = &dev_priv->csr; + + err_printf(m, "DMC loaded: %s\n", + yesno(csr->dmc_payload != NULL)); + err_printf(m, "DMC fw version: %d.%d\n", + CSR_VERSION_MAJOR(csr->version), + CSR_VERSION_MINOR(csr->version)); + } + err_printf(m, "EIR: 0x%08x\n", error->eir); err_printf(m, "IER: 0x%08x\n", error->ier); if (INTEL_INFO(dev)->gen >= 8) { @@ -862,7 +873,7 @@ static void i915_record_ring_state(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; if (INTEL_INFO(dev)->gen >= 6) { - ering->rc_psmi = I915_READ(ring->mmio_base + 0x50); + ering->rc_psmi = I915_READ(RING_PSMI_CTL(ring->mmio_base)); ering->fault_reg = I915_READ(RING_FAULT_REG(ring)); if (INTEL_INFO(dev)->gen >= 8) gen8_record_semaphore_state(dev_priv, error, ring, ering); @@ -899,7 +910,7 @@ static void i915_record_ring_state(struct drm_device *dev, ering->ctl = I915_READ_CTL(ring); if (I915_NEED_GFX_HWS(dev)) { - int mmio; + i915_reg_t mmio; if (IS_GEN7(dev)) { switch (ring->id) { @@ -1071,6 +1082,25 @@ static void i915_gem_record_rings(struct drm_device *dev, list_for_each_entry(request, &ring->request_list, list) { struct drm_i915_error_request *erq; + if (count >= error->ring[i].num_requests) { + /* + * If the ring request list was changed in + * between the point where the error request + * list was created and dimensioned and this + * point then just exit early to avoid crashes. + * + * We don't need to communicate that the + * request list changed state during error + * state capture and that the error state is + * slightly incorrect as a consequence since we + * are typically only interested in the request + * list state at the point of error state + * capture, not in any changes happening during + * the capture. + */ + break; + } + erq = &error->ring[i].requests[count++]; erq->seqno = request->seqno; erq->jiffies = request->emitted_jiffies; @@ -1181,7 +1211,7 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, if (IS_VALLEYVIEW(dev)) { error->gtier[0] = I915_READ(GTIER); error->ier = I915_READ(VLV_IER); - error->forcewake = I915_READ(FORCEWAKE_VLV); + error->forcewake = I915_READ_FW(FORCEWAKE_VLV); } if (IS_GEN7(dev)) @@ -1193,14 +1223,14 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, } if (IS_GEN6(dev)) { - error->forcewake = I915_READ(FORCEWAKE); + error->forcewake = I915_READ_FW(FORCEWAKE); error->gab_ctl = I915_READ(GAB_CTL); error->gfx_mode = I915_READ(GFX_MODE); } /* 2: Registers which belong to multiple generations */ if (INTEL_INFO(dev)->gen >= 7) - error->forcewake = I915_READ(FORCEWAKE_MT); + error->forcewake = I915_READ_FW(FORCEWAKE_MT); if (INTEL_INFO(dev)->gen >= 6) { error->derrmr = I915_READ(DERRMR); diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h index c4cb1c0c4..685c7991e 100644 --- a/drivers/gpu/drm/i915/i915_guc_reg.h +++ b/drivers/gpu/drm/i915/i915_guc_reg.h @@ -26,7 +26,7 @@ /* Definitions of GuC H/W registers, bits, etc */ -#define GUC_STATUS 0xc000 +#define GUC_STATUS _MMIO(0xc000) #define GS_BOOTROM_SHIFT 1 #define GS_BOOTROM_MASK (0x7F << GS_BOOTROM_SHIFT) #define GS_BOOTROM_RSA_FAILED (0x50 << GS_BOOTROM_SHIFT) @@ -39,40 +39,41 @@ #define GS_MIA_MASK (0x07 << GS_MIA_SHIFT) #define GS_MIA_CORE_STATE (1 << GS_MIA_SHIFT) -#define SOFT_SCRATCH(n) (0xc180 + ((n) * 4)) +#define SOFT_SCRATCH(n) _MMIO(0xc180 + (n) * 4) -#define UOS_RSA_SCRATCH(i) (0xc200 + (i) * 4) -#define DMA_ADDR_0_LOW 0xc300 -#define DMA_ADDR_0_HIGH 0xc304 -#define DMA_ADDR_1_LOW 0xc308 -#define DMA_ADDR_1_HIGH 0xc30c +#define UOS_RSA_SCRATCH(i) _MMIO(0xc200 + (i) * 4) +#define UOS_RSA_SCRATCH_MAX_COUNT 64 +#define DMA_ADDR_0_LOW _MMIO(0xc300) +#define DMA_ADDR_0_HIGH _MMIO(0xc304) +#define DMA_ADDR_1_LOW _MMIO(0xc308) +#define DMA_ADDR_1_HIGH _MMIO(0xc30c) #define DMA_ADDRESS_SPACE_WOPCM (7 << 16) #define DMA_ADDRESS_SPACE_GTT (8 << 16) -#define DMA_COPY_SIZE 0xc310 -#define DMA_CTRL 0xc314 +#define DMA_COPY_SIZE _MMIO(0xc310) +#define DMA_CTRL _MMIO(0xc314) #define UOS_MOVE (1<<4) #define START_DMA (1<<0) -#define DMA_GUC_WOPCM_OFFSET 0xc340 +#define DMA_GUC_WOPCM_OFFSET _MMIO(0xc340) #define GUC_WOPCM_OFFSET_VALUE 0x80000 /* 512KB */ -#define GUC_MAX_IDLE_COUNT 0xC3E4 +#define GUC_MAX_IDLE_COUNT _MMIO(0xC3E4) -#define GUC_WOPCM_SIZE 0xc050 +#define GUC_WOPCM_SIZE _MMIO(0xc050) #define GUC_WOPCM_SIZE_VALUE (0x80 << 12) /* 512KB */ /* GuC addresses below GUC_WOPCM_TOP don't map through the GTT */ #define GUC_WOPCM_TOP (GUC_WOPCM_SIZE_VALUE) -#define GEN8_GT_PM_CONFIG 0x138140 -#define GEN9LP_GT_PM_CONFIG 0x138140 -#define GEN9_GT_PM_CONFIG 0x13816c +#define GEN8_GT_PM_CONFIG _MMIO(0x138140) +#define GEN9LP_GT_PM_CONFIG _MMIO(0x138140) +#define GEN9_GT_PM_CONFIG _MMIO(0x13816c) #define GT_DOORBELL_ENABLE (1<<0) -#define GEN8_GTCR 0x4274 +#define GEN8_GTCR _MMIO(0x4274) #define GEN8_GTCR_INVALIDATE (1<<0) -#define GUC_ARAT_C6DIS 0xA178 +#define GUC_ARAT_C6DIS _MMIO(0xA178) -#define GUC_SHIM_CONTROL 0xc064 +#define GUC_SHIM_CONTROL _MMIO(0xc064) #define GUC_DISABLE_SRAM_INIT_TO_ZEROES (1<<0) #define GUC_ENABLE_READ_CACHE_LOGIC (1<<1) #define GUC_ENABLE_MIA_CACHING (1<<2) @@ -89,21 +90,21 @@ GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA | \ GUC_ENABLE_MIA_CLOCK_GATING) -#define HOST2GUC_INTERRUPT 0xc4c8 +#define HOST2GUC_INTERRUPT _MMIO(0xc4c8) #define HOST2GUC_TRIGGER (1<<0) #define DRBMISC1 0x1984 #define DOORBELL_ENABLE (1<<0) -#define GEN8_DRBREGL(x) (0x1000 + (x) * 8) +#define GEN8_DRBREGL(x) _MMIO(0x1000 + (x) * 8) #define GEN8_DRB_VALID (1<<0) -#define GEN8_DRBREGU(x) (GEN8_DRBREGL(x) + 4) +#define GEN8_DRBREGU(x) _MMIO(0x1000 + (x) * 8 + 4) -#define DE_GUCRMR 0x44054 +#define DE_GUCRMR _MMIO(0x44054) -#define GUC_BCS_RCS_IER 0xC550 -#define GUC_VCS2_VCS1_IER 0xC554 -#define GUC_WD_VECS_IER 0xC558 -#define GUC_PM_P24C_IER 0xC55C +#define GUC_BCS_RCS_IER _MMIO(0xC550) +#define GUC_VCS2_VCS1_IER _MMIO(0xC554) +#define GUC_WD_VECS_IER _MMIO(0xC558) +#define GUC_PM_P24C_IER _MMIO(0xC55C) #endif diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 036b42bae..05aa7e61c 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -27,7 +27,7 @@ #include "intel_guc.h" /** - * DOC: GuC Client + * DOC: GuC-based command submission * * i915_guc_client: * We use the term client to avoid confusion with contexts. A i915_guc_client is @@ -86,7 +86,6 @@ static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len) return -EINVAL; intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); - spin_lock(&dev_priv->guc.host2guc_lock); dev_priv->guc.action_count += 1; dev_priv->guc.action_cmd = data[0]; @@ -119,7 +118,6 @@ static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len) } dev_priv->guc.action_status = status; - spin_unlock(&dev_priv->guc.host2guc_lock); intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); return ret; @@ -161,9 +159,9 @@ static int host2guc_sample_forcewake(struct intel_guc *guc, data[0] = HOST2GUC_ACTION_SAMPLE_FORCEWAKE; /* WaRsDisableCoarsePowerGating:skl,bxt */ if (!intel_enable_rc6(dev_priv->dev) || - (IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) || - (IS_SKL_GT3(dev) && (INTEL_REVID(dev) <= SKL_REVID_E0)) || - (IS_SKL_GT4(dev) && (INTEL_REVID(dev) <= SKL_REVID_E0))) + IS_BXT_REVID(dev, 0, BXT_REVID_A1) || + (IS_SKL_GT3(dev) && IS_SKL_REVID(dev, 0, SKL_REVID_E0)) || + (IS_SKL_GT4(dev) && IS_SKL_REVID(dev, 0, SKL_REVID_E0))) data[1] = 0; else /* bit 0 and 1 are for Render and Media domain separately */ @@ -258,7 +256,7 @@ static void guc_disable_doorbell(struct intel_guc *guc, struct drm_i915_private *dev_priv = guc_to_i915(guc); struct guc_doorbell_info *doorbell; void *base; - int drbreg = GEN8_DRBREGL(client->doorbell_id); + i915_reg_t drbreg = GEN8_DRBREGL(client->doorbell_id); int value; base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0)); @@ -292,16 +290,12 @@ static uint32_t select_doorbell_cacheline(struct intel_guc *guc) const uint32_t cacheline_size = cache_line_size(); uint32_t offset; - spin_lock(&guc->host2guc_lock); - /* Doorbell uses a single cache line within a page */ offset = offset_in_page(guc->db_cacheline); /* Moving to next cache line to reduce contention */ guc->db_cacheline += cacheline_size; - spin_unlock(&guc->host2guc_lock); - DRM_DEBUG_DRIVER("selected doorbell cacheline 0x%x, next 0x%x, linesize %u\n", offset, guc->db_cacheline, cacheline_size); @@ -322,13 +316,11 @@ static uint16_t assign_doorbell(struct intel_guc *guc, uint32_t priority) const uint16_t end = start + half; uint16_t id; - spin_lock(&guc->host2guc_lock); id = find_next_zero_bit(guc->doorbell_bitmap, end, start); if (id == end) id = GUC_INVALID_DOORBELL_ID; else bitmap_set(guc->doorbell_bitmap, id, 1); - spin_unlock(&guc->host2guc_lock); DRM_DEBUG_DRIVER("assigned %s priority doorbell id 0x%x\n", hi_pri ? "high" : "normal", id); @@ -338,9 +330,7 @@ static uint16_t assign_doorbell(struct intel_guc *guc, uint32_t priority) static void release_doorbell(struct intel_guc *guc, uint16_t id) { - spin_lock(&guc->host2guc_lock); bitmap_clear(guc->doorbell_bitmap, id, 1); - spin_unlock(&guc->host2guc_lock); } /* @@ -487,16 +477,13 @@ static int guc_get_workqueue_space(struct i915_guc_client *gc, u32 *offset) struct guc_process_desc *desc; void *base; u32 size = sizeof(struct guc_wq_item); - int ret = 0, timeout_counter = 200; + int ret = -ETIMEDOUT, timeout_counter = 200; base = kmap_atomic(i915_gem_object_get_page(gc->client_obj, 0)); desc = base + gc->proc_desc_offset; while (timeout_counter-- > 0) { - ret = wait_for_atomic(CIRC_SPACE(gc->wq_tail, desc->head, - gc->wq_size) >= size, 1); - - if (!ret) { + if (CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size) >= size) { *offset = gc->wq_tail; /* advance the tail for next workqueue item */ @@ -505,7 +492,11 @@ static int guc_get_workqueue_space(struct i915_guc_client *gc, u32 *offset) /* this will break the loop */ timeout_counter = 0; + ret = 0; } + + if (timeout_counter) + usleep_range(1000, 2000); }; kunmap_atomic(base); @@ -577,7 +568,7 @@ static void lr_context_update(struct drm_i915_gem_request *rq) WARN_ON(!i915_gem_obj_is_pinned(ctx_obj)); WARN_ON(!i915_gem_obj_is_pinned(rb_obj)); - page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); + page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN); reg_state = kmap_atomic(page); reg_state[CTX_RING_BUFFER_START+1] = i915_gem_obj_ggtt_offset(rb_obj); @@ -588,8 +579,7 @@ static void lr_context_update(struct drm_i915_gem_request *rq) /** * i915_guc_submit() - Submit commands through GuC * @client: the guc client where commands will go through - * @ctx: LRC where commands come from - * @ring: HW engine that will excute the commands + * @rq: request associated with the commands * * Return: 0 if succeed */ @@ -598,15 +588,12 @@ int i915_guc_submit(struct i915_guc_client *client, { struct intel_guc *guc = client->guc; enum intel_ring_id ring_id = rq->ring->id; - unsigned long flags; int q_ret, b_ret; /* Need this because of the deferred pin ctx and ring */ /* Shall we move this right after ring is pinned? */ lr_context_update(rq); - spin_lock_irqsave(&client->wq_lock, flags); - q_ret = guc_add_workqueue_item(client, rq); if (q_ret == 0) b_ret = guc_ring_doorbell(client); @@ -621,12 +608,8 @@ int i915_guc_submit(struct i915_guc_client *client, } else { client->retcode = 0; } - spin_unlock_irqrestore(&client->wq_lock, flags); - - spin_lock(&guc->host2guc_lock); guc->submissions[ring_id] += 1; guc->last_seqno[ring_id] = rq->seqno; - spin_unlock(&guc->host2guc_lock); return q_ret; } @@ -678,7 +661,7 @@ static struct drm_i915_gem_object *gem_allocate_guc_obj(struct drm_device *dev, /** * gem_release_guc_obj() - Release gem object allocated for GuC usage * @obj: gem obj to be released - */ + */ static void gem_release_guc_obj(struct drm_i915_gem_object *obj) { if (!obj) @@ -731,7 +714,8 @@ static void guc_client_free(struct drm_device *dev, * The kernel client to replace ExecList submission is created with * NORMAL priority. Priority of a client for scheduler can be HIGH, * while a preemption context can use CRITICAL. - * @ctx the context to own the client (we use the default render context) + * @ctx: the context that owns the client (we use the default render + * context) * * Return: An i915_guc_client object if success. */ @@ -768,7 +752,6 @@ static struct i915_guc_client *guc_client_alloc(struct drm_device *dev, client->client_obj = obj; client->wq_offset = GUC_DB_SIZE; client->wq_size = GUC_WQ_SIZE; - spin_lock_init(&client->wq_lock); client->doorbell_offset = select_doorbell_cacheline(guc); @@ -871,8 +854,6 @@ int i915_guc_submission_init(struct drm_device *dev) if (!guc->ctx_pool_obj) return -ENOMEM; - spin_lock_init(&dev_priv->guc.host2guc_lock); - ida_init(&guc->ctx_ids); guc_create_log(guc); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 0f42a2782..fa8afa786 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -139,7 +139,8 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = { /* * We should clear IMR at preinstall/uninstall, and just check at postinstall. */ -static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv, u32 reg) +static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv, + i915_reg_t reg) { u32 val = I915_READ(reg); @@ -147,7 +148,7 @@ static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv, u32 reg) return; WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n", - reg, val); + i915_mmio_reg_offset(reg), val); I915_WRITE(reg, 0xffffffff); POSTING_READ(reg); I915_WRITE(reg, 0xffffffff); @@ -214,9 +215,9 @@ void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv, * @interrupt_mask: mask of interrupt bits to update * @enabled_irq_mask: mask of interrupt bits to enable */ -static void ilk_update_display_irq(struct drm_i915_private *dev_priv, - uint32_t interrupt_mask, - uint32_t enabled_irq_mask) +void ilk_update_display_irq(struct drm_i915_private *dev_priv, + uint32_t interrupt_mask, + uint32_t enabled_irq_mask) { uint32_t new_val; @@ -238,18 +239,6 @@ static void ilk_update_display_irq(struct drm_i915_private *dev_priv, } } -void -ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask) -{ - ilk_update_display_irq(dev_priv, mask, mask); -} - -void -ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask) -{ - ilk_update_display_irq(dev_priv, mask, 0); -} - /** * ilk_update_gt_irq - update GTIMR * @dev_priv: driver private @@ -283,27 +272,27 @@ void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask) ilk_update_gt_irq(dev_priv, mask, 0); } -static u32 gen6_pm_iir(struct drm_i915_private *dev_priv) +static i915_reg_t gen6_pm_iir(struct drm_i915_private *dev_priv) { return INTEL_INFO(dev_priv)->gen >= 8 ? GEN8_GT_IIR(2) : GEN6_PMIIR; } -static u32 gen6_pm_imr(struct drm_i915_private *dev_priv) +static i915_reg_t gen6_pm_imr(struct drm_i915_private *dev_priv) { return INTEL_INFO(dev_priv)->gen >= 8 ? GEN8_GT_IMR(2) : GEN6_PMIMR; } -static u32 gen6_pm_ier(struct drm_i915_private *dev_priv) +static i915_reg_t gen6_pm_ier(struct drm_i915_private *dev_priv) { return INTEL_INFO(dev_priv)->gen >= 8 ? GEN8_GT_IER(2) : GEN6_PMIER; } /** - * snb_update_pm_irq - update GEN6_PMIMR - * @dev_priv: driver private - * @interrupt_mask: mask of interrupt bits to update - * @enabled_irq_mask: mask of interrupt bits to enable - */ + * snb_update_pm_irq - update GEN6_PMIMR + * @dev_priv: driver private + * @interrupt_mask: mask of interrupt bits to update + * @enabled_irq_mask: mask of interrupt bits to enable + */ static void snb_update_pm_irq(struct drm_i915_private *dev_priv, uint32_t interrupt_mask, uint32_t enabled_irq_mask) @@ -350,7 +339,7 @@ void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask) void gen6_reset_rps_interrupts(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t reg = gen6_pm_iir(dev_priv); + i915_reg_t reg = gen6_pm_iir(dev_priv); spin_lock_irq(&dev_priv->irq_lock); I915_WRITE(reg, dev_priv->pm_rps_events); @@ -417,11 +406,11 @@ void gen6_disable_rps_interrupts(struct drm_device *dev) } /** - * bdw_update_port_irq - update DE port interrupt - * @dev_priv: driver private - * @interrupt_mask: mask of interrupt bits to update - * @enabled_irq_mask: mask of interrupt bits to enable - */ + * bdw_update_port_irq - update DE port interrupt + * @dev_priv: driver private + * @interrupt_mask: mask of interrupt bits to update + * @enabled_irq_mask: mask of interrupt bits to enable + */ static void bdw_update_port_irq(struct drm_i915_private *dev_priv, uint32_t interrupt_mask, uint32_t enabled_irq_mask) @@ -449,6 +438,38 @@ static void bdw_update_port_irq(struct drm_i915_private *dev_priv, } /** + * bdw_update_pipe_irq - update DE pipe interrupt + * @dev_priv: driver private + * @pipe: pipe whose interrupt to update + * @interrupt_mask: mask of interrupt bits to update + * @enabled_irq_mask: mask of interrupt bits to enable + */ +void bdw_update_pipe_irq(struct drm_i915_private *dev_priv, + enum pipe pipe, + uint32_t interrupt_mask, + uint32_t enabled_irq_mask) +{ + uint32_t new_val; + + assert_spin_locked(&dev_priv->irq_lock); + + WARN_ON(enabled_irq_mask & ~interrupt_mask); + + if (WARN_ON(!intel_irqs_enabled(dev_priv))) + return; + + new_val = dev_priv->de_irq_mask[pipe]; + new_val &= ~interrupt_mask; + new_val |= (~enabled_irq_mask & interrupt_mask); + + if (new_val != dev_priv->de_irq_mask[pipe]) { + dev_priv->de_irq_mask[pipe] = new_val; + 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 * @interrupt_mask: mask of interrupt bits to update @@ -477,7 +498,7 @@ static void __i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, u32 enable_mask, u32 status_mask) { - u32 reg = PIPESTAT(pipe); + i915_reg_t reg = PIPESTAT(pipe); u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK; assert_spin_locked(&dev_priv->irq_lock); @@ -504,7 +525,7 @@ static void __i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, u32 enable_mask, u32 status_mask) { - u32 reg = PIPESTAT(pipe); + i915_reg_t reg = PIPESTAT(pipe); u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK; assert_spin_locked(&dev_priv->irq_lock); @@ -560,7 +581,7 @@ i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, { u32 enable_mask; - if (IS_VALLEYVIEW(dev_priv->dev)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) enable_mask = vlv_get_pipestat_enable_mask(dev_priv->dev, status_mask); else @@ -574,7 +595,7 @@ i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, { u32 enable_mask; - if (IS_VALLEYVIEW(dev_priv->dev)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) enable_mask = vlv_get_pipestat_enable_mask(dev_priv->dev, status_mask); else @@ -665,8 +686,7 @@ static u32 i8xx_get_vblank_counter(struct drm_device *dev, unsigned int pipe) static u32 i915_get_vblank_counter(struct drm_device *dev, unsigned int pipe) { struct drm_i915_private *dev_priv = dev->dev_private; - unsigned long high_frame; - unsigned long low_frame; + i915_reg_t high_frame, low_frame; u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal; struct intel_crtc *intel_crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); @@ -717,9 +737,7 @@ static u32 g4x_get_vblank_counter(struct drm_device *dev, unsigned int pipe) return I915_READ(PIPE_FRMCOUNT_G4X(pipe)); } -/* 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__)) - +/* I915_READ_FW, only for fast reads of display block, no need for forcewake etc. */ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; @@ -733,9 +751,9 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) vtotal /= 2; if (IS_GEN2(dev)) - position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN2; + position = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN2; else - position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3; + position = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN3; /* * On HSW, the DSL reg (0x70000) appears to return 0 if we @@ -827,7 +845,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, * 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_FW(PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; /* convert to pixel counts */ vbl_start *= htotal; @@ -1085,6 +1103,14 @@ static void gen6_pm_rps_work(struct work_struct *work) spin_unlock_irq(&dev_priv->irq_lock); return; } + + /* + * The RPS work is synced during runtime suspend, we don't require a + * wakeref. TODO: instead of disabling the asserts make sure that we + * always hold an RPM reference while the work is running. + */ + DISABLE_RPM_WAKEREF_ASSERTS(dev_priv); + pm_iir = dev_priv->rps.pm_iir; dev_priv->rps.pm_iir = 0; /* Make sure not to corrupt PMIMR state used by ringbuffer on GEN6 */ @@ -1097,7 +1123,7 @@ static void gen6_pm_rps_work(struct work_struct *work) WARN_ON(pm_iir & ~dev_priv->pm_rps_events); if ((pm_iir & dev_priv->pm_rps_events) == 0 && !client_boost) - return; + goto out; mutex_lock(&dev_priv->rps.hw_lock); @@ -1152,6 +1178,8 @@ static void gen6_pm_rps_work(struct work_struct *work) intel_set_rps(dev_priv->dev, new_delay); mutex_unlock(&dev_priv->rps.hw_lock); +out: + ENABLE_RPM_WAKEREF_ASSERTS(dev_priv); } @@ -1188,7 +1216,7 @@ static void ivybridge_parity_work(struct work_struct *work) POSTING_READ(GEN7_MISCCPCTL); while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) { - u32 reg; + i915_reg_t reg; slice--; if (WARN_ON_ONCE(slice >= NUM_L3_SLICES(dev_priv->dev))) @@ -1196,7 +1224,7 @@ static void ivybridge_parity_work(struct work_struct *work) dev_priv->l3_parity.which_slice &= ~(1<<slice); - reg = GEN7_L3CDERRST1 + (slice * 0x200); + reg = GEN7_L3CDERRST1(slice); error_status = I915_READ(reg); row = GEN7_PARITY_ERROR_ROW(error_status); @@ -1290,70 +1318,69 @@ static void snb_gt_irq_handler(struct drm_device *dev, ivybridge_parity_error_irq_handler(dev, gt_iir); } +static __always_inline void +gen8_cs_irq_handler(struct intel_engine_cs *ring, u32 iir, int test_shift) +{ + if (iir & (GT_RENDER_USER_INTERRUPT << test_shift)) + notify_ring(ring); + if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift)) + intel_lrc_irq_handler(ring); +} + static irqreturn_t gen8_gt_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) { irqreturn_t ret = IRQ_NONE; if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { - u32 tmp = I915_READ_FW(GEN8_GT_IIR(0)); - if (tmp) { - I915_WRITE_FW(GEN8_GT_IIR(0), tmp); + u32 iir = I915_READ_FW(GEN8_GT_IIR(0)); + if (iir) { + I915_WRITE_FW(GEN8_GT_IIR(0), iir); ret = IRQ_HANDLED; - if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT)) - intel_lrc_irq_handler(&dev_priv->ring[RCS]); - if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT)) - notify_ring(&dev_priv->ring[RCS]); + gen8_cs_irq_handler(&dev_priv->ring[RCS], + iir, GEN8_RCS_IRQ_SHIFT); - if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT)) - intel_lrc_irq_handler(&dev_priv->ring[BCS]); - if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT)) - notify_ring(&dev_priv->ring[BCS]); + gen8_cs_irq_handler(&dev_priv->ring[BCS], + iir, GEN8_BCS_IRQ_SHIFT); } else DRM_ERROR("The master control interrupt lied (GT0)!\n"); } if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) { - u32 tmp = I915_READ_FW(GEN8_GT_IIR(1)); - if (tmp) { - I915_WRITE_FW(GEN8_GT_IIR(1), tmp); + u32 iir = I915_READ_FW(GEN8_GT_IIR(1)); + if (iir) { + I915_WRITE_FW(GEN8_GT_IIR(1), iir); ret = IRQ_HANDLED; - if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT)) - intel_lrc_irq_handler(&dev_priv->ring[VCS]); - if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT)) - notify_ring(&dev_priv->ring[VCS]); + gen8_cs_irq_handler(&dev_priv->ring[VCS], + iir, GEN8_VCS1_IRQ_SHIFT); - if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS2_IRQ_SHIFT)) - intel_lrc_irq_handler(&dev_priv->ring[VCS2]); - if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT)) - notify_ring(&dev_priv->ring[VCS2]); + gen8_cs_irq_handler(&dev_priv->ring[VCS2], + iir, GEN8_VCS2_IRQ_SHIFT); } else DRM_ERROR("The master control interrupt lied (GT1)!\n"); } if (master_ctl & GEN8_GT_VECS_IRQ) { - u32 tmp = I915_READ_FW(GEN8_GT_IIR(3)); - if (tmp) { - I915_WRITE_FW(GEN8_GT_IIR(3), tmp); + u32 iir = I915_READ_FW(GEN8_GT_IIR(3)); + if (iir) { + I915_WRITE_FW(GEN8_GT_IIR(3), iir); ret = IRQ_HANDLED; - if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT)) - intel_lrc_irq_handler(&dev_priv->ring[VECS]); - if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT)) - notify_ring(&dev_priv->ring[VECS]); + gen8_cs_irq_handler(&dev_priv->ring[VECS], + iir, GEN8_VECS_IRQ_SHIFT); } else DRM_ERROR("The master control interrupt lied (GT3)!\n"); } if (master_ctl & GEN8_GT_PM_IRQ) { - u32 tmp = I915_READ_FW(GEN8_GT_IIR(2)); - if (tmp & dev_priv->pm_rps_events) { + u32 iir = I915_READ_FW(GEN8_GT_IIR(2)); + if (iir & dev_priv->pm_rps_events) { I915_WRITE_FW(GEN8_GT_IIR(2), - tmp & dev_priv->pm_rps_events); + iir & dev_priv->pm_rps_events); ret = IRQ_HANDLED; - gen6_rps_irq_handler(dev_priv, tmp); + gen6_rps_irq_handler(dev_priv, iir); } else DRM_ERROR("The master control interrupt lied (PM)!\n"); } @@ -1625,7 +1652,7 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir) spin_lock(&dev_priv->irq_lock); for_each_pipe(dev_priv, pipe) { - int reg; + i915_reg_t reg; u32 mask, iir_bit = 0; /* @@ -1706,7 +1733,7 @@ static void i9xx_hpd_irq_handler(struct drm_device *dev) */ POSTING_READ(PORT_HOTPLUG_STAT); - if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) { + if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X; if (hotplug_trigger) { @@ -1741,6 +1768,9 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; + /* IRQs are synced during runtime_suspend, we don't require a wakeref */ + disable_rpm_wakeref_asserts(dev_priv); + while (true) { /* Find, clear, then process each source of interrupt */ @@ -1775,6 +1805,8 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) } out: + enable_rpm_wakeref_asserts(dev_priv); + return ret; } @@ -1788,6 +1820,9 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; + /* IRQs are synced during runtime_suspend, we don't require a wakeref */ + disable_rpm_wakeref_asserts(dev_priv); + for (;;) { master_ctl = I915_READ(GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL; iir = I915_READ(VLV_IIR); @@ -1818,6 +1853,8 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) POSTING_READ(GEN8_MASTER_IRQ); } + enable_rpm_wakeref_asserts(dev_priv); + return ret; } @@ -1827,8 +1864,24 @@ static void ibx_hpd_irq_handler(struct drm_device *dev, u32 hotplug_trigger, struct drm_i915_private *dev_priv = to_i915(dev); u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; + /* + * Somehow the PCH doesn't seem to really ack the interrupt to the CPU + * unless we touch the hotplug register, even if hotplug_trigger is + * zero. Not acking leads to "The master control interrupt lied (SDE)!" + * errors. + */ dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG); + if (!hotplug_trigger) { + u32 mask = PORTA_HOTPLUG_STATUS_MASK | + PORTD_HOTPLUG_STATUS_MASK | + PORTC_HOTPLUG_STATUS_MASK | + PORTB_HOTPLUG_STATUS_MASK; + dig_hotplug_reg &= ~mask; + } + I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg); + if (!hotplug_trigger) + return; intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger, dig_hotplug_reg, hpd, @@ -1843,8 +1896,7 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir) int pipe; u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK; - if (hotplug_trigger) - ibx_hpd_irq_handler(dev, hotplug_trigger, hpd_ibx); + ibx_hpd_irq_handler(dev, hotplug_trigger, hpd_ibx); if (pch_iir & SDE_AUDIO_POWER_MASK) { int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >> @@ -1937,8 +1989,7 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) int pipe; u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT; - if (hotplug_trigger) - ibx_hpd_irq_handler(dev, hotplug_trigger, hpd_cpt); + ibx_hpd_irq_handler(dev, hotplug_trigger, hpd_cpt); if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) { int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >> @@ -2134,6 +2185,9 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; + /* IRQs are synced during runtime_suspend, we don't require a wakeref */ + disable_rpm_wakeref_asserts(dev_priv); + /* We get interrupts on unclaimed registers, so check for this before we * do any I915_{READ,WRITE}. */ intel_uncore_check_errors(dev); @@ -2192,6 +2246,9 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) POSTING_READ(SDEIER); } + /* IRQs are synced during runtime_suspend, we don't require a wakeref */ + enable_rpm_wakeref_asserts(dev_priv); + return ret; } @@ -2224,6 +2281,9 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; + /* IRQs are synced during runtime_suspend, we don't require a wakeref */ + disable_rpm_wakeref_asserts(dev_priv); + if (INTEL_INFO(dev_priv)->gen >= 9) aux_mask |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C | GEN9_AUX_CHANNEL_D; @@ -2231,7 +2291,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) master_ctl = I915_READ_FW(GEN8_MASTER_IRQ); master_ctl &= ~GEN8_MASTER_IRQ_CONTROL; if (!master_ctl) - return IRQ_NONE; + goto out; I915_WRITE_FW(GEN8_MASTER_IRQ, 0); @@ -2366,6 +2426,9 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); POSTING_READ_FW(GEN8_MASTER_IRQ); +out: + enable_rpm_wakeref_asserts(dev_priv); + return ret; } @@ -2648,7 +2711,7 @@ static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe) DE_PIPE_VBLANK(pipe); spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - ironlake_enable_display_irq(dev_priv, bit); + ilk_enable_display_irq(dev_priv, bit); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); return 0; @@ -2673,10 +2736,9 @@ static int gen8_enable_vblank(struct drm_device *dev, unsigned int pipe) unsigned long irqflags; 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)); + bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); + return 0; } @@ -2703,7 +2765,7 @@ static void ironlake_disable_vblank(struct drm_device *dev, unsigned int pipe) DE_PIPE_VBLANK(pipe); spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - ironlake_disable_display_irq(dev_priv, bit); + ilk_disable_display_irq(dev_priv, bit); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } @@ -2724,9 +2786,7 @@ static void gen8_disable_vblank(struct drm_device *dev, unsigned int pipe) unsigned long irqflags; 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)); + bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } @@ -2965,6 +3025,13 @@ static void i915_hangcheck_elapsed(struct work_struct *work) if (!i915.enable_hangcheck) return; + /* + * The hangcheck work is synced during runtime suspend, we don't + * require a wakeref. TODO: instead of disabling the asserts make + * sure that we hold a reference when this work is running. + */ + DISABLE_RPM_WAKEREF_ASSERTS(dev_priv); + for_each_ring(ring, dev_priv, i) { u64 acthd; u32 seqno; @@ -3056,13 +3123,18 @@ static void i915_hangcheck_elapsed(struct work_struct *work) } } - if (rings_hung) - return i915_handle_error(dev, true, "Ring hung"); + if (rings_hung) { + i915_handle_error(dev, true, "Ring hung"); + goto out; + } if (busy_count) /* Reset timer case chip hangs without another request * being added */ i915_queue_hangcheck(dev); + +out: + ENABLE_RPM_WAKEREF_ASSERTS(dev_priv); } void i915_queue_hangcheck(struct drm_device *dev) @@ -3455,7 +3527,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev) * setup is guaranteed to run in single-threaded context. But we * need it to make the assert_spin_locked happy. */ spin_lock_irq(&dev_priv->irq_lock); - ironlake_enable_display_irq(dev_priv, DE_PCU_EVENT); + ilk_enable_display_irq(dev_priv, DE_PCU_EVENT); spin_unlock_irq(&dev_priv->irq_lock); } @@ -3854,13 +3926,18 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) u16 flip_mask = I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT; + irqreturn_t ret; if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; + /* IRQs are synced during runtime_suspend, we don't require a wakeref */ + disable_rpm_wakeref_asserts(dev_priv); + + ret = IRQ_NONE; iir = I915_READ16(IIR); if (iir == 0) - return IRQ_NONE; + goto out; while (iir & ~flip_mask) { /* Can't rely on pipestat interrupt bit in iir as it might @@ -3873,7 +3950,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); for_each_pipe(dev_priv, pipe) { - int reg = PIPESTAT(pipe); + i915_reg_t reg = PIPESTAT(pipe); pipe_stats[pipe] = I915_READ(reg); /* @@ -3909,8 +3986,12 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) iir = new_iir; } + ret = IRQ_HANDLED; + +out: + enable_rpm_wakeref_asserts(dev_priv); - return IRQ_HANDLED; + return ret; } static void i8xx_irq_uninstall(struct drm_device * dev) @@ -4039,6 +4120,9 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; + /* IRQs are synced during runtime_suspend, we don't require a wakeref */ + disable_rpm_wakeref_asserts(dev_priv); + iir = I915_READ(IIR); do { bool irq_received = (iir & ~flip_mask) != 0; @@ -4054,7 +4138,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); for_each_pipe(dev_priv, pipe) { - int reg = PIPESTAT(pipe); + i915_reg_t reg = PIPESTAT(pipe); pipe_stats[pipe] = I915_READ(reg); /* Clear the PIPE*STAT regs before the IIR */ @@ -4121,6 +4205,8 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) iir = new_iir; } while (iir & ~flip_mask); + enable_rpm_wakeref_asserts(dev_priv); + return ret; } @@ -4260,6 +4346,9 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; + /* IRQs are synced during runtime_suspend, we don't require a wakeref */ + disable_rpm_wakeref_asserts(dev_priv); + iir = I915_READ(IIR); for (;;) { @@ -4276,7 +4365,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); for_each_pipe(dev_priv, pipe) { - int reg = PIPESTAT(pipe); + i915_reg_t reg = PIPESTAT(pipe); pipe_stats[pipe] = I915_READ(reg); /* @@ -4345,6 +4434,8 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) iir = new_iir; } + enable_rpm_wakeref_asserts(dev_priv); + return ret; } @@ -4388,7 +4479,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv) INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work); /* Let's track the enabled rps events */ - if (IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) + if (IS_VALLEYVIEW(dev_priv)) /* WaGsvRC0ResidencyMethod:vlv */ dev_priv->pm_rps_events = GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED; else diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 4be13a5eb..835d6099c 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -32,6 +32,7 @@ struct i915_params i915 __read_mostly = { .panel_use_ssc = -1, .vbt_sdvo_panel_type = -1, .enable_rc6 = -1, + .enable_dc = -1, .enable_fbc = -1, .enable_execlists = -1, .enable_hangcheck = true, @@ -80,6 +81,11 @@ MODULE_PARM_DESC(enable_rc6, "For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. " "default: -1 (use per-chip default)"); +module_param_named_unsafe(enable_dc, i915.enable_dc, int, 0400); +MODULE_PARM_DESC(enable_dc, + "Enable power-saving display C-states. " + "(-1=auto [default]; 0=disable; 1=up to DC5; 2=up to DC6)"); + module_param_named_unsafe(enable_fbc, i915.enable_fbc, int, 0600); MODULE_PARM_DESC(enable_fbc, "Enable frame buffer compression for power savings " @@ -112,7 +118,7 @@ MODULE_PARM_DESC(enable_hangcheck, module_param_named_unsafe(enable_ppgtt, i915.enable_ppgtt, int, 0400); MODULE_PARM_DESC(enable_ppgtt, "Override PPGTT usage. " - "(-1=auto [default], 0=disabled, 1=aliasing, 2=full)"); + "(-1=auto [default], 0=disabled, 1=aliasing, 2=full, 3=full with extended address space)"); module_param_named_unsafe(enable_execlists, i915.enable_execlists, int, 0400); MODULE_PARM_DESC(enable_execlists, @@ -126,7 +132,7 @@ module_param_named_unsafe(preliminary_hw_support, i915.preliminary_hw_support, i MODULE_PARM_DESC(preliminary_hw_support, "Enable preliminary hardware support."); -module_param_named_unsafe(disable_power_well, i915.disable_power_well, int, 0600); +module_param_named_unsafe(disable_power_well, i915.disable_power_well, int, 0400); MODULE_PARM_DESC(disable_power_well, "Disable display power wells when possible " "(-1=auto [default], 0=power wells always on, 1=power wells disabled when possible)"); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index bc7b8faba..489772871 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -25,14 +25,43 @@ #ifndef _I915_REG_H_ #define _I915_REG_H_ +typedef struct { + uint32_t reg; +} i915_reg_t; + +#define _MMIO(r) ((const i915_reg_t){ .reg = (r) }) + +#define INVALID_MMIO_REG _MMIO(0) + +static inline uint32_t i915_mmio_reg_offset(i915_reg_t reg) +{ + return reg.reg; +} + +static inline bool i915_mmio_reg_equal(i915_reg_t a, i915_reg_t b) +{ + return i915_mmio_reg_offset(a) == i915_mmio_reg_offset(b); +} + +static inline bool i915_mmio_reg_valid(i915_reg_t reg) +{ + return !i915_mmio_reg_equal(reg, INVALID_MMIO_REG); +} + #define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) +#define _MMIO_PIPE(pipe, a, b) _MMIO(_PIPE(pipe, a, b)) #define _PLANE(plane, a, b) _PIPE(plane, a, b) -#define _TRANSCODER(tran, a, b) ((a) + (tran)*((b)-(a))) +#define _MMIO_PLANE(plane, a, b) _MMIO_PIPE(plane, a, b) +#define _TRANS(tran, a, b) ((a) + (tran)*((b)-(a))) +#define _MMIO_TRANS(tran, a, b) _MMIO(_TRANS(tran, a, b)) #define _PORT(port, a, b) ((a) + (port)*((b)-(a))) +#define _MMIO_PORT(port, a, b) _MMIO(_PORT(port, a, b)) #define _PIPE3(pipe, a, b, c) ((pipe) == PIPE_A ? (a) : \ (pipe) == PIPE_B ? (b) : (c)) +#define _MMIO_PIPE3(pipe, a, b, c) _MMIO(_PIPE3(pipe, a, b, c)) #define _PORT3(port, a, b, c) ((port) == PORT_A ? (a) : \ (port) == PORT_B ? (b) : (c)) +#define _MMIO_PORT3(pipe, a, b, c) _MMIO(_PORT3(pipe, a, b, c)) #define _MASKED_FIELD(mask, value) ({ \ if (__builtin_constant_p(mask)) \ @@ -105,14 +134,14 @@ #define GRDOM_RESET_STATUS (1<<1) #define GRDOM_RESET_ENABLE (1<<0) -#define ILK_GDSR (MCHBAR_MIRROR_BASE + 0x2ca4) +#define ILK_GDSR _MMIO(MCHBAR_MIRROR_BASE + 0x2ca4) #define ILK_GRDOM_FULL (0<<1) #define ILK_GRDOM_RENDER (1<<1) #define ILK_GRDOM_MEDIA (3<<1) #define ILK_GRDOM_MASK (3<<1) #define ILK_GRDOM_RESET_ENABLE (1<<0) -#define GEN6_MBCUNIT_SNPCR 0x900c /* for LLC config */ +#define GEN6_MBCUNIT_SNPCR _MMIO(0x900c) /* for LLC config */ #define GEN6_MBC_SNPCR_SHIFT 21 #define GEN6_MBC_SNPCR_MASK (3<<21) #define GEN6_MBC_SNPCR_MAX (0<<21) @@ -120,31 +149,31 @@ #define GEN6_MBC_SNPCR_LOW (2<<21) #define GEN6_MBC_SNPCR_MIN (3<<21) /* only 1/16th of the cache is shared */ -#define VLV_G3DCTL 0x9024 -#define VLV_GSCKGCTL 0x9028 +#define VLV_G3DCTL _MMIO(0x9024) +#define VLV_GSCKGCTL _MMIO(0x9028) -#define GEN6_MBCTL 0x0907c +#define GEN6_MBCTL _MMIO(0x0907c) #define GEN6_MBCTL_ENABLE_BOOT_FETCH (1 << 4) #define GEN6_MBCTL_CTX_FETCH_NEEDED (1 << 3) #define GEN6_MBCTL_BME_UPDATE_ENABLE (1 << 2) #define GEN6_MBCTL_MAE_UPDATE_ENABLE (1 << 1) #define GEN6_MBCTL_BOOT_FETCH_MECH (1 << 0) -#define GEN6_GDRST 0x941c +#define GEN6_GDRST _MMIO(0x941c) #define GEN6_GRDOM_FULL (1 << 0) #define GEN6_GRDOM_RENDER (1 << 1) #define GEN6_GRDOM_MEDIA (1 << 2) #define GEN6_GRDOM_BLT (1 << 3) -#define RING_PP_DIR_BASE(ring) ((ring)->mmio_base+0x228) -#define RING_PP_DIR_BASE_READ(ring) ((ring)->mmio_base+0x518) -#define RING_PP_DIR_DCLV(ring) ((ring)->mmio_base+0x220) +#define RING_PP_DIR_BASE(ring) _MMIO((ring)->mmio_base+0x228) +#define RING_PP_DIR_BASE_READ(ring) _MMIO((ring)->mmio_base+0x518) +#define RING_PP_DIR_DCLV(ring) _MMIO((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 GEN8_RING_PDP_UDW(ring, n) _MMIO((ring)->mmio_base+0x270 + (n) * 8 + 4) +#define GEN8_RING_PDP_LDW(ring, n) _MMIO((ring)->mmio_base+0x270 + (n) * 8) -#define GEN8_R_PWR_CLK_STATE 0x20C8 +#define GEN8_R_PWR_CLK_STATE _MMIO(0x20C8) #define GEN8_RPCS_ENABLE (1 << 31) #define GEN8_RPCS_S_CNT_ENABLE (1 << 18) #define GEN8_RPCS_S_CNT_SHIFT 15 @@ -157,7 +186,7 @@ #define GEN8_RPCS_EU_MIN_SHIFT 0 #define GEN8_RPCS_EU_MIN_MASK (0xf << GEN8_RPCS_EU_MIN_SHIFT) -#define GAM_ECOCHK 0x4090 +#define GAM_ECOCHK _MMIO(0x4090) #define BDW_DISABLE_HDC_INVALIDATION (1<<25) #define ECOCHK_SNB_BIT (1<<10) #define ECOCHK_DIS_TLB (1<<8) @@ -170,15 +199,15 @@ #define ECOCHK_PPGTT_WT_HSW (0x2<<3) #define ECOCHK_PPGTT_WB_HSW (0x3<<3) -#define GAC_ECO_BITS 0x14090 +#define GAC_ECO_BITS _MMIO(0x14090) #define ECOBITS_SNB_BIT (1<<13) #define ECOBITS_PPGTT_CACHE64B (3<<8) #define ECOBITS_PPGTT_CACHE4B (0<<8) -#define GAB_CTL 0x24000 +#define GAB_CTL _MMIO(0x24000) #define GAB_CTL_CONT_AFTER_PAGEFAULT (1<<8) -#define GEN6_STOLEN_RESERVED 0x1082C0 +#define GEN6_STOLEN_RESERVED _MMIO(0x1082C0) #define GEN6_STOLEN_RESERVED_ADDR_MASK (0xFFF << 20) #define GEN7_STOLEN_RESERVED_ADDR_MASK (0x3FFF << 18) #define GEN6_STOLEN_RESERVED_SIZE_MASK (3 << 4) @@ -200,6 +229,7 @@ #define VGA_ST01_MDA 0x3ba #define VGA_ST01_CGA 0x3da +#define _VGA_MSR_WRITE _MMIO(0x3c2) #define VGA_MSR_WRITE 0x3c2 #define VGA_MSR_READ 0x3cc #define VGA_MSR_MEM_EN (1<<1) @@ -377,10 +407,12 @@ #define MI_BATCH_BUFFER_START_GEN8 MI_INSTR(0x31, 1) #define MI_BATCH_RESOURCE_STREAMER (1<<10) -#define MI_PREDICATE_SRC0 (0x2400) -#define MI_PREDICATE_SRC1 (0x2408) +#define MI_PREDICATE_SRC0 _MMIO(0x2400) +#define MI_PREDICATE_SRC0_UDW _MMIO(0x2400 + 4) +#define MI_PREDICATE_SRC1 _MMIO(0x2408) +#define MI_PREDICATE_SRC1_UDW _MMIO(0x2408 + 4) -#define MI_PREDICATE_RESULT_2 (0x2214) +#define MI_PREDICATE_RESULT_2 _MMIO(0x2214) #define LOWER_SLICE_ENABLED (1<<0) #define LOWER_SLICE_DISABLED (0<<0) @@ -509,49 +541,61 @@ /* * Registers used only by the command parser */ -#define BCS_SWCTRL 0x22200 - -#define GPGPU_THREADS_DISPATCHED 0x2290 -#define HS_INVOCATION_COUNT 0x2300 -#define DS_INVOCATION_COUNT 0x2308 -#define IA_VERTICES_COUNT 0x2310 -#define IA_PRIMITIVES_COUNT 0x2318 -#define VS_INVOCATION_COUNT 0x2320 -#define GS_INVOCATION_COUNT 0x2328 -#define GS_PRIMITIVES_COUNT 0x2330 -#define CL_INVOCATION_COUNT 0x2338 -#define CL_PRIMITIVES_COUNT 0x2340 -#define PS_INVOCATION_COUNT 0x2348 -#define PS_DEPTH_COUNT 0x2350 +#define BCS_SWCTRL _MMIO(0x22200) + +#define GPGPU_THREADS_DISPATCHED _MMIO(0x2290) +#define GPGPU_THREADS_DISPATCHED_UDW _MMIO(0x2290 + 4) +#define HS_INVOCATION_COUNT _MMIO(0x2300) +#define HS_INVOCATION_COUNT_UDW _MMIO(0x2300 + 4) +#define DS_INVOCATION_COUNT _MMIO(0x2308) +#define DS_INVOCATION_COUNT_UDW _MMIO(0x2308 + 4) +#define IA_VERTICES_COUNT _MMIO(0x2310) +#define IA_VERTICES_COUNT_UDW _MMIO(0x2310 + 4) +#define IA_PRIMITIVES_COUNT _MMIO(0x2318) +#define IA_PRIMITIVES_COUNT_UDW _MMIO(0x2318 + 4) +#define VS_INVOCATION_COUNT _MMIO(0x2320) +#define VS_INVOCATION_COUNT_UDW _MMIO(0x2320 + 4) +#define GS_INVOCATION_COUNT _MMIO(0x2328) +#define GS_INVOCATION_COUNT_UDW _MMIO(0x2328 + 4) +#define GS_PRIMITIVES_COUNT _MMIO(0x2330) +#define GS_PRIMITIVES_COUNT_UDW _MMIO(0x2330 + 4) +#define CL_INVOCATION_COUNT _MMIO(0x2338) +#define CL_INVOCATION_COUNT_UDW _MMIO(0x2338 + 4) +#define CL_PRIMITIVES_COUNT _MMIO(0x2340) +#define CL_PRIMITIVES_COUNT_UDW _MMIO(0x2340 + 4) +#define PS_INVOCATION_COUNT _MMIO(0x2348) +#define PS_INVOCATION_COUNT_UDW _MMIO(0x2348 + 4) +#define PS_DEPTH_COUNT _MMIO(0x2350) +#define PS_DEPTH_COUNT_UDW _MMIO(0x2350 + 4) /* There are the 4 64-bit counter registers, one for each stream output */ -#define GEN7_SO_NUM_PRIMS_WRITTEN(n) (0x5200 + (n) * 8) +#define GEN7_SO_NUM_PRIMS_WRITTEN(n) _MMIO(0x5200 + (n) * 8) +#define GEN7_SO_NUM_PRIMS_WRITTEN_UDW(n) _MMIO(0x5200 + (n) * 8 + 4) -#define GEN7_SO_PRIM_STORAGE_NEEDED(n) (0x5240 + (n) * 8) +#define GEN7_SO_PRIM_STORAGE_NEEDED(n) _MMIO(0x5240 + (n) * 8) +#define GEN7_SO_PRIM_STORAGE_NEEDED_UDW(n) _MMIO(0x5240 + (n) * 8 + 4) -#define GEN7_3DPRIM_END_OFFSET 0x2420 -#define GEN7_3DPRIM_START_VERTEX 0x2430 -#define GEN7_3DPRIM_VERTEX_COUNT 0x2434 -#define GEN7_3DPRIM_INSTANCE_COUNT 0x2438 -#define GEN7_3DPRIM_START_INSTANCE 0x243C -#define GEN7_3DPRIM_BASE_VERTEX 0x2440 +#define GEN7_3DPRIM_END_OFFSET _MMIO(0x2420) +#define GEN7_3DPRIM_START_VERTEX _MMIO(0x2430) +#define GEN7_3DPRIM_VERTEX_COUNT _MMIO(0x2434) +#define GEN7_3DPRIM_INSTANCE_COUNT _MMIO(0x2438) +#define GEN7_3DPRIM_START_INSTANCE _MMIO(0x243C) +#define GEN7_3DPRIM_BASE_VERTEX _MMIO(0x2440) -#define GEN7_GPGPU_DISPATCHDIMX 0x2500 -#define GEN7_GPGPU_DISPATCHDIMY 0x2504 -#define GEN7_GPGPU_DISPATCHDIMZ 0x2508 +#define GEN7_GPGPU_DISPATCHDIMX _MMIO(0x2500) +#define GEN7_GPGPU_DISPATCHDIMY _MMIO(0x2504) +#define GEN7_GPGPU_DISPATCHDIMZ _MMIO(0x2508) -#define OACONTROL 0x2360 +#define OACONTROL _MMIO(0x2360) #define _GEN7_PIPEA_DE_LOAD_SL 0x70068 #define _GEN7_PIPEB_DE_LOAD_SL 0x71068 -#define GEN7_PIPE_DE_LOAD_SL(pipe) _PIPE(pipe, \ - _GEN7_PIPEA_DE_LOAD_SL, \ - _GEN7_PIPEB_DE_LOAD_SL) +#define GEN7_PIPE_DE_LOAD_SL(pipe) _MMIO_PIPE(pipe, _GEN7_PIPEA_DE_LOAD_SL, _GEN7_PIPEB_DE_LOAD_SL) /* * Reset registers */ -#define DEBUG_RESET_I830 0x6070 +#define DEBUG_RESET_I830 _MMIO(0x6070) #define DEBUG_RESET_FULL (1<<7) #define DEBUG_RESET_RENDER (1<<8) #define DEBUG_RESET_DISPLAY (1<<9) @@ -559,7 +603,7 @@ /* * IOSF sideband */ -#define VLV_IOSF_DOORBELL_REQ (VLV_DISPLAY_BASE + 0x2100) +#define VLV_IOSF_DOORBELL_REQ _MMIO(VLV_DISPLAY_BASE + 0x2100) #define IOSF_DEVFN_SHIFT 24 #define IOSF_OPCODE_SHIFT 16 #define IOSF_PORT_SHIFT 8 @@ -576,8 +620,8 @@ #define IOSF_PORT_CCU 0xA9 #define IOSF_PORT_GPS_CORE 0x48 #define IOSF_PORT_FLISDSI 0x1B -#define VLV_IOSF_DATA (VLV_DISPLAY_BASE + 0x2104) -#define VLV_IOSF_ADDR (VLV_DISPLAY_BASE + 0x2108) +#define VLV_IOSF_DATA _MMIO(VLV_DISPLAY_BASE + 0x2104) +#define VLV_IOSF_ADDR _MMIO(VLV_DISPLAY_BASE + 0x2108) /* See configdb bunit SB addr map */ #define BUNIT_REG_BISOC 0x11 @@ -609,6 +653,7 @@ /* See the PUNIT HAS v0.8 for the below bits */ enum punit_power_well { + /* These numbers are fixed and must match the position of the pw bits */ PUNIT_POWER_WELL_RENDER = 0, PUNIT_POWER_WELL_MEDIA = 1, PUNIT_POWER_WELL_DISP2D = 3, @@ -621,10 +666,12 @@ enum punit_power_well { PUNIT_POWER_WELL_DPIO_RX1 = 11, PUNIT_POWER_WELL_DPIO_CMN_D = 12, - PUNIT_POWER_WELL_NUM, + /* Not actual bit groups. Used as IDs for lookup_power_well() */ + PUNIT_POWER_WELL_ALWAYS_ON, }; enum skl_disp_power_wells { + /* These numbers are fixed and must match the position of the pw bits */ SKL_DISP_PW_MISC_IO, SKL_DISP_PW_DDI_A_E, SKL_DISP_PW_DDI_B, @@ -632,6 +679,10 @@ enum skl_disp_power_wells { SKL_DISP_PW_DDI_D, SKL_DISP_PW_1 = 14, SKL_DISP_PW_2, + + /* Not actual bit groups. Used as IDs for lookup_power_well() */ + SKL_DISP_PW_ALWAYS_ON, + SKL_DISP_PW_DC_OFF, }; #define SKL_POWER_WELL_STATE(pw) (1 << ((pw) * 2)) @@ -804,35 +855,35 @@ enum skl_disp_power_wells { * * Note: DDI0 is digital port B, DD1 is digital port C, and DDI2 is * digital port D (CHV) or port A (BXT). - */ -/* - * Dual channel PHY (VLV/CHV/BXT) - * --------------------------------- - * | CH0 | CH1 | - * | CMN/PLL/REF | CMN/PLL/REF | - * |---------------|---------------| Display PHY - * | PCS01 | PCS23 | PCS01 | PCS23 | - * |-------|-------|-------|-------| - * |TX0|TX1|TX2|TX3|TX0|TX1|TX2|TX3| - * --------------------------------- - * | DDI0 | DDI1 | DP/HDMI ports - * --------------------------------- * - * Single channel PHY (CHV/BXT) - * ----------------- - * | CH0 | - * | CMN/PLL/REF | - * |---------------| Display PHY - * | PCS01 | PCS23 | - * |-------|-------| - * |TX0|TX1|TX2|TX3| - * ----------------- - * | DDI2 | DP/HDMI port - * ----------------- + * + * Dual channel PHY (VLV/CHV/BXT) + * --------------------------------- + * | CH0 | CH1 | + * | CMN/PLL/REF | CMN/PLL/REF | + * |---------------|---------------| Display PHY + * | PCS01 | PCS23 | PCS01 | PCS23 | + * |-------|-------|-------|-------| + * |TX0|TX1|TX2|TX3|TX0|TX1|TX2|TX3| + * --------------------------------- + * | DDI0 | DDI1 | DP/HDMI ports + * --------------------------------- + * + * Single channel PHY (CHV/BXT) + * ----------------- + * | CH0 | + * | CMN/PLL/REF | + * |---------------| Display PHY + * | PCS01 | PCS23 | + * |-------|-------| + * |TX0|TX1|TX2|TX3| + * ----------------- + * | DDI2 | DP/HDMI port + * ----------------- */ #define DPIO_DEVFN 0 -#define DPIO_CTL (VLV_DISPLAY_BASE + 0x2110) +#define DPIO_CTL _MMIO(VLV_DISPLAY_BASE + 0x2110) #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) @@ -1185,9 +1236,9 @@ enum skl_disp_power_wells { #define DPIO_UPAR_SHIFT 30 /* BXT PHY registers */ -#define _BXT_PHY(phy, a, b) _PIPE((phy), (a), (b)) +#define _BXT_PHY(phy, a, b) _MMIO_PIPE((phy), (a), (b)) -#define BXT_P_CR_GT_DISP_PWRON 0x138090 +#define BXT_P_CR_GT_DISP_PWRON _MMIO(0x138090) #define GT_DISPLAY_POWER_ON(phy) (1 << (phy)) #define _PHY_CTL_FAMILY_EDP 0x64C80 @@ -1203,7 +1254,7 @@ enum skl_disp_power_wells { #define PORT_PLL_ENABLE (1 << 31) #define PORT_PLL_LOCK (1 << 30) #define PORT_PLL_REF_SEL (1 << 27) -#define BXT_PORT_PLL_ENABLE(port) _PORT(port, _PORT_PLL_A, _PORT_PLL_B) +#define BXT_PORT_PLL_ENABLE(port) _MMIO_PORT(port, _PORT_PLL_A, _PORT_PLL_B) #define _PORT_PLL_EBB_0_A 0x162034 #define _PORT_PLL_EBB_0_B 0x6C034 @@ -1214,7 +1265,7 @@ enum skl_disp_power_wells { #define PORT_PLL_P2_SHIFT 8 #define PORT_PLL_P2_MASK (0x1f << PORT_PLL_P2_SHIFT) #define PORT_PLL_P2(x) ((x) << PORT_PLL_P2_SHIFT) -#define BXT_PORT_PLL_EBB_0(port) _PORT3(port, _PORT_PLL_EBB_0_A, \ +#define BXT_PORT_PLL_EBB_0(port) _MMIO_PORT3(port, _PORT_PLL_EBB_0_A, \ _PORT_PLL_EBB_0_B, \ _PORT_PLL_EBB_0_C) @@ -1223,7 +1274,7 @@ enum skl_disp_power_wells { #define _PORT_PLL_EBB_4_C 0x6C344 #define PORT_PLL_10BIT_CLK_ENABLE (1 << 13) #define PORT_PLL_RECALIBRATE (1 << 14) -#define BXT_PORT_PLL_EBB_4(port) _PORT3(port, _PORT_PLL_EBB_4_A, \ +#define BXT_PORT_PLL_EBB_4(port) _MMIO_PORT3(port, _PORT_PLL_EBB_4_A, \ _PORT_PLL_EBB_4_B, \ _PORT_PLL_EBB_4_C) @@ -1259,7 +1310,7 @@ enum skl_disp_power_wells { #define _PORT_PLL_BASE(port) _PORT3(port, _PORT_PLL_0_A, \ _PORT_PLL_0_B, \ _PORT_PLL_0_C) -#define BXT_PORT_PLL(port, idx) (_PORT_PLL_BASE(port) + (idx) * 4) +#define BXT_PORT_PLL(port, idx) _MMIO(_PORT_PLL_BASE(port) + (idx) * 4) /* BXT PHY common lane registers */ #define _PORT_CL1CM_DW0_A 0x162000 @@ -1297,7 +1348,7 @@ enum skl_disp_power_wells { _PORT_CL1CM_DW30_A) /* Defined for PHY0 only */ -#define BXT_PORT_CL2CM_DW6_BC 0x6C358 +#define BXT_PORT_CL2CM_DW6_BC _MMIO(0x6C358) #define DW6_OLDO_DYN_PWR_DOWN_EN (1 << 28) /* BXT PHY Ref registers */ @@ -1337,10 +1388,10 @@ enum skl_disp_power_wells { #define _PORT_PCS_DW10_GRP_A 0x162C28 #define _PORT_PCS_DW10_GRP_B 0x6CC28 #define _PORT_PCS_DW10_GRP_C 0x6CE28 -#define BXT_PORT_PCS_DW10_LN01(port) _PORT3(port, _PORT_PCS_DW10_LN01_A, \ +#define BXT_PORT_PCS_DW10_LN01(port) _MMIO_PORT3(port, _PORT_PCS_DW10_LN01_A, \ _PORT_PCS_DW10_LN01_B, \ _PORT_PCS_DW10_LN01_C) -#define BXT_PORT_PCS_DW10_GRP(port) _PORT3(port, _PORT_PCS_DW10_GRP_A, \ +#define BXT_PORT_PCS_DW10_GRP(port) _MMIO_PORT3(port, _PORT_PCS_DW10_GRP_A, \ _PORT_PCS_DW10_GRP_B, \ _PORT_PCS_DW10_GRP_C) #define TX2_SWING_CALC_INIT (1 << 31) @@ -1357,13 +1408,13 @@ enum skl_disp_power_wells { #define _PORT_PCS_DW12_GRP_C 0x6CE30 #define LANESTAGGER_STRAP_OVRD (1 << 6) #define LANE_STAGGER_MASK 0x1F -#define BXT_PORT_PCS_DW12_LN01(port) _PORT3(port, _PORT_PCS_DW12_LN01_A, \ +#define BXT_PORT_PCS_DW12_LN01(port) _MMIO_PORT3(port, _PORT_PCS_DW12_LN01_A, \ _PORT_PCS_DW12_LN01_B, \ _PORT_PCS_DW12_LN01_C) -#define BXT_PORT_PCS_DW12_LN23(port) _PORT3(port, _PORT_PCS_DW12_LN23_A, \ +#define BXT_PORT_PCS_DW12_LN23(port) _MMIO_PORT3(port, _PORT_PCS_DW12_LN23_A, \ _PORT_PCS_DW12_LN23_B, \ _PORT_PCS_DW12_LN23_C) -#define BXT_PORT_PCS_DW12_GRP(port) _PORT3(port, _PORT_PCS_DW12_GRP_A, \ +#define BXT_PORT_PCS_DW12_GRP(port) _MMIO_PORT3(port, _PORT_PCS_DW12_GRP_A, \ _PORT_PCS_DW12_GRP_B, \ _PORT_PCS_DW12_GRP_C) @@ -1377,10 +1428,10 @@ enum skl_disp_power_wells { #define _PORT_TX_DW2_GRP_A 0x162D08 #define _PORT_TX_DW2_GRP_B 0x6CD08 #define _PORT_TX_DW2_GRP_C 0x6CF08 -#define BXT_PORT_TX_DW2_GRP(port) _PORT3(port, _PORT_TX_DW2_GRP_A, \ +#define BXT_PORT_TX_DW2_GRP(port) _MMIO_PORT3(port, _PORT_TX_DW2_GRP_A, \ _PORT_TX_DW2_GRP_B, \ _PORT_TX_DW2_GRP_C) -#define BXT_PORT_TX_DW2_LN0(port) _PORT3(port, _PORT_TX_DW2_LN0_A, \ +#define BXT_PORT_TX_DW2_LN0(port) _MMIO_PORT3(port, _PORT_TX_DW2_LN0_A, \ _PORT_TX_DW2_LN0_B, \ _PORT_TX_DW2_LN0_C) #define MARGIN_000_SHIFT 16 @@ -1394,10 +1445,10 @@ enum skl_disp_power_wells { #define _PORT_TX_DW3_GRP_A 0x162D0C #define _PORT_TX_DW3_GRP_B 0x6CD0C #define _PORT_TX_DW3_GRP_C 0x6CF0C -#define BXT_PORT_TX_DW3_GRP(port) _PORT3(port, _PORT_TX_DW3_GRP_A, \ +#define BXT_PORT_TX_DW3_GRP(port) _MMIO_PORT3(port, _PORT_TX_DW3_GRP_A, \ _PORT_TX_DW3_GRP_B, \ _PORT_TX_DW3_GRP_C) -#define BXT_PORT_TX_DW3_LN0(port) _PORT3(port, _PORT_TX_DW3_LN0_A, \ +#define BXT_PORT_TX_DW3_LN0(port) _MMIO_PORT3(port, _PORT_TX_DW3_LN0_A, \ _PORT_TX_DW3_LN0_B, \ _PORT_TX_DW3_LN0_C) #define SCALE_DCOMP_METHOD (1 << 26) @@ -1409,10 +1460,10 @@ enum skl_disp_power_wells { #define _PORT_TX_DW4_GRP_A 0x162D10 #define _PORT_TX_DW4_GRP_B 0x6CD10 #define _PORT_TX_DW4_GRP_C 0x6CF10 -#define BXT_PORT_TX_DW4_LN0(port) _PORT3(port, _PORT_TX_DW4_LN0_A, \ +#define BXT_PORT_TX_DW4_LN0(port) _MMIO_PORT3(port, _PORT_TX_DW4_LN0_A, \ _PORT_TX_DW4_LN0_B, \ _PORT_TX_DW4_LN0_C) -#define BXT_PORT_TX_DW4_GRP(port) _PORT3(port, _PORT_TX_DW4_GRP_A, \ +#define BXT_PORT_TX_DW4_GRP(port) _MMIO_PORT3(port, _PORT_TX_DW4_GRP_A, \ _PORT_TX_DW4_GRP_B, \ _PORT_TX_DW4_GRP_C) #define DEEMPH_SHIFT 24 @@ -1423,17 +1474,17 @@ enum skl_disp_power_wells { #define _PORT_TX_DW14_LN0_C 0x6C938 #define LATENCY_OPTIM_SHIFT 30 #define LATENCY_OPTIM (1 << LATENCY_OPTIM_SHIFT) -#define BXT_PORT_TX_DW14_LN(port, lane) (_PORT3((port), _PORT_TX_DW14_LN0_A, \ +#define BXT_PORT_TX_DW14_LN(port, lane) _MMIO(_PORT3((port), _PORT_TX_DW14_LN0_A, \ _PORT_TX_DW14_LN0_B, \ _PORT_TX_DW14_LN0_C) + \ _BXT_LANE_OFFSET(lane)) /* UAIMI scratch pad register 1 */ -#define UAIMI_SPR1 0x4F074 +#define UAIMI_SPR1 _MMIO(0x4F074) /* SKL VccIO mask */ #define SKL_VCCIO_MASK 0x1 /* SKL balance leg register */ -#define DISPIO_CR_TX_BMU_CR0 0x6C00C +#define DISPIO_CR_TX_BMU_CR0 _MMIO(0x6C00C) /* I_boost values */ #define BALANCE_LEG_SHIFT(port) (8+3*(port)) #define BALANCE_LEG_MASK(port) (7<<(8+3*(port))) @@ -1450,7 +1501,7 @@ enum skl_disp_power_wells { * [0-15] @ 0x100000 gen6,vlv,chv * [0-31] @ 0x100000 gen7+ */ -#define FENCE_REG(i) (0x2000 + (((i) & 8) << 9) + ((i) & 7) * 4) +#define FENCE_REG(i) _MMIO(0x2000 + (((i) & 8) << 9) + ((i) & 7) * 4) #define I830_FENCE_START_MASK 0x07f80000 #define I830_FENCE_TILING_Y_SHIFT 12 #define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) @@ -1463,21 +1514,21 @@ enum skl_disp_power_wells { #define I915_FENCE_START_MASK 0x0ff00000 #define I915_FENCE_SIZE_BITS(size) ((ffs((size) >> 20) - 1) << 8) -#define FENCE_REG_965_LO(i) (0x03000 + (i) * 8) -#define FENCE_REG_965_HI(i) (0x03000 + (i) * 8 + 4) +#define FENCE_REG_965_LO(i) _MMIO(0x03000 + (i) * 8) +#define FENCE_REG_965_HI(i) _MMIO(0x03000 + (i) * 8 + 4) #define I965_FENCE_PITCH_SHIFT 2 #define I965_FENCE_TILING_Y_SHIFT 1 #define I965_FENCE_REG_VALID (1<<0) #define I965_FENCE_MAX_PITCH_VAL 0x0400 -#define FENCE_REG_GEN6_LO(i) (0x100000 + (i) * 8) -#define FENCE_REG_GEN6_HI(i) (0x100000 + (i) * 8 + 4) +#define FENCE_REG_GEN6_LO(i) _MMIO(0x100000 + (i) * 8) +#define FENCE_REG_GEN6_HI(i) _MMIO(0x100000 + (i) * 8 + 4) #define GEN6_FENCE_PITCH_SHIFT 32 #define GEN7_FENCE_MAX_PITCH_VAL 0x0800 /* control register for cpu gtt access */ -#define TILECTL 0x101000 +#define TILECTL _MMIO(0x101000) #define TILECTL_SWZCTL (1 << 0) #define TILECTL_TLBPF (1 << 1) #define TILECTL_TLB_PREFETCH_DIS (1 << 2) @@ -1486,30 +1537,30 @@ enum skl_disp_power_wells { /* * Instruction and interrupt control regs */ -#define PGTBL_CTL 0x02020 +#define PGTBL_CTL _MMIO(0x02020) #define PGTBL_ADDRESS_LO_MASK 0xfffff000 /* bits [31:12] */ #define PGTBL_ADDRESS_HI_MASK 0x000000f0 /* bits [35:32] (gen4) */ -#define PGTBL_ER 0x02024 -#define PRB0_BASE (0x2030-0x30) -#define PRB1_BASE (0x2040-0x30) /* 830,gen3 */ -#define PRB2_BASE (0x2050-0x30) /* gen3 */ -#define SRB0_BASE (0x2100-0x30) /* gen2 */ -#define SRB1_BASE (0x2110-0x30) /* gen2 */ -#define SRB2_BASE (0x2120-0x30) /* 830 */ -#define SRB3_BASE (0x2130-0x30) /* 830 */ +#define PGTBL_ER _MMIO(0x02024) +#define PRB0_BASE (0x2030-0x30) +#define PRB1_BASE (0x2040-0x30) /* 830,gen3 */ +#define PRB2_BASE (0x2050-0x30) /* gen3 */ +#define SRB0_BASE (0x2100-0x30) /* gen2 */ +#define SRB1_BASE (0x2110-0x30) /* gen2 */ +#define SRB2_BASE (0x2120-0x30) /* 830 */ +#define SRB3_BASE (0x2130-0x30) /* 830 */ #define RENDER_RING_BASE 0x02000 #define BSD_RING_BASE 0x04000 #define GEN6_BSD_RING_BASE 0x12000 #define GEN8_BSD2_RING_BASE 0x1c000 #define VEBOX_RING_BASE 0x1a000 #define BLT_RING_BASE 0x22000 -#define RING_TAIL(base) ((base)+0x30) -#define RING_HEAD(base) ((base)+0x34) -#define RING_START(base) ((base)+0x38) -#define RING_CTL(base) ((base)+0x3c) -#define RING_SYNC_0(base) ((base)+0x40) -#define RING_SYNC_1(base) ((base)+0x44) -#define RING_SYNC_2(base) ((base)+0x48) +#define RING_TAIL(base) _MMIO((base)+0x30) +#define RING_HEAD(base) _MMIO((base)+0x34) +#define RING_START(base) _MMIO((base)+0x38) +#define RING_CTL(base) _MMIO((base)+0x3c) +#define RING_SYNC_0(base) _MMIO((base)+0x40) +#define RING_SYNC_1(base) _MMIO((base)+0x44) +#define RING_SYNC_2(base) _MMIO((base)+0x48) #define GEN6_RVSYNC (RING_SYNC_0(RENDER_RING_BASE)) #define GEN6_RBSYNC (RING_SYNC_1(RENDER_RING_BASE)) #define GEN6_RVESYNC (RING_SYNC_2(RENDER_RING_BASE)) @@ -1522,51 +1573,52 @@ enum skl_disp_power_wells { #define GEN6_VEBSYNC (RING_SYNC_0(VEBOX_RING_BASE)) #define GEN6_VERSYNC (RING_SYNC_1(VEBOX_RING_BASE)) #define GEN6_VEVSYNC (RING_SYNC_2(VEBOX_RING_BASE)) -#define GEN6_NOSYNC 0 -#define RING_PSMI_CTL(base) ((base)+0x50) -#define RING_MAX_IDLE(base) ((base)+0x54) -#define RING_HWS_PGA(base) ((base)+0x80) -#define RING_HWS_PGA_GEN6(base) ((base)+0x2080) -#define RING_RESET_CTL(base) ((base)+0xd0) +#define GEN6_NOSYNC INVALID_MMIO_REG +#define RING_PSMI_CTL(base) _MMIO((base)+0x50) +#define RING_MAX_IDLE(base) _MMIO((base)+0x54) +#define RING_HWS_PGA(base) _MMIO((base)+0x80) +#define RING_HWS_PGA_GEN6(base) _MMIO((base)+0x2080) +#define RING_RESET_CTL(base) _MMIO((base)+0xd0) #define RESET_CTL_REQUEST_RESET (1 << 0) #define RESET_CTL_READY_TO_RESET (1 << 1) -#define HSW_GTT_CACHE_EN 0x4024 +#define HSW_GTT_CACHE_EN _MMIO(0x4024) #define GTT_CACHE_EN_ALL 0xF0007FFF -#define GEN7_WR_WATERMARK 0x4028 -#define GEN7_GFX_PRIO_CTRL 0x402C -#define ARB_MODE 0x4030 +#define GEN7_WR_WATERMARK _MMIO(0x4028) +#define GEN7_GFX_PRIO_CTRL _MMIO(0x402C) +#define ARB_MODE _MMIO(0x4030) #define ARB_MODE_SWIZZLE_SNB (1<<4) #define ARB_MODE_SWIZZLE_IVB (1<<5) -#define GEN7_GFX_PEND_TLB0 0x4034 -#define GEN7_GFX_PEND_TLB1 0x4038 +#define GEN7_GFX_PEND_TLB0 _MMIO(0x4034) +#define GEN7_GFX_PEND_TLB1 _MMIO(0x4038) /* L3, CVS, ZTLB, RCC, CASC LRA min, max values */ -#define GEN7_LRA_LIMITS(i) (0x403C + (i) * 4) +#define GEN7_LRA_LIMITS(i) _MMIO(0x403C + (i) * 4) #define GEN7_LRA_LIMITS_REG_NUM 13 -#define GEN7_MEDIA_MAX_REQ_COUNT 0x4070 -#define GEN7_GFX_MAX_REQ_COUNT 0x4074 +#define GEN7_MEDIA_MAX_REQ_COUNT _MMIO(0x4070) +#define GEN7_GFX_MAX_REQ_COUNT _MMIO(0x4074) -#define GAMTARBMODE 0x04a08 +#define GAMTARBMODE _MMIO(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 RENDER_HWS_PGA_GEN7 _MMIO(0x04080) +#define RING_FAULT_REG(ring) _MMIO(0x4094 + 0x100*(ring)->id) #define RING_FAULT_GTTSEL_MASK (1<<11) #define RING_FAULT_SRCID(x) (((x) >> 3) & 0xff) #define RING_FAULT_FAULT_TYPE(x) (((x) >> 1) & 0x3) #define RING_FAULT_VALID (1<<0) -#define DONE_REG 0x40b0 -#define GEN8_PRIVATE_PAT_LO 0x40e0 -#define GEN8_PRIVATE_PAT_HI (0x40e0 + 4) -#define BSD_HWS_PGA_GEN7 (0x04180) -#define BLT_HWS_PGA_GEN7 (0x04280) -#define VEBOX_HWS_PGA_GEN7 (0x04380) -#define RING_ACTHD(base) ((base)+0x74) -#define RING_ACTHD_UDW(base) ((base)+0x5c) -#define RING_NOPID(base) ((base)+0x94) -#define RING_IMR(base) ((base)+0xa8) -#define RING_HWSTAM(base) ((base)+0x98) -#define RING_TIMESTAMP(base) ((base)+0x358) +#define DONE_REG _MMIO(0x40b0) +#define GEN8_PRIVATE_PAT_LO _MMIO(0x40e0) +#define GEN8_PRIVATE_PAT_HI _MMIO(0x40e0 + 4) +#define BSD_HWS_PGA_GEN7 _MMIO(0x04180) +#define BLT_HWS_PGA_GEN7 _MMIO(0x04280) +#define VEBOX_HWS_PGA_GEN7 _MMIO(0x04380) +#define RING_ACTHD(base) _MMIO((base)+0x74) +#define RING_ACTHD_UDW(base) _MMIO((base)+0x5c) +#define RING_NOPID(base) _MMIO((base)+0x94) +#define RING_IMR(base) _MMIO((base)+0xa8) +#define RING_HWSTAM(base) _MMIO((base)+0x98) +#define RING_TIMESTAMP(base) _MMIO((base)+0x358) +#define RING_TIMESTAMP_UDW(base) _MMIO((base)+0x358 + 4) #define TAIL_ADDR 0x001FFFF8 #define HEAD_WRAP_COUNT 0xFFE00000 #define HEAD_WRAP_ONE 0x00200000 @@ -1583,57 +1635,65 @@ enum skl_disp_power_wells { #define RING_WAIT (1<<11) /* gen3+, PRBx_CTL */ #define RING_WAIT_SEMAPHORE (1<<10) /* gen6+ */ -#define GEN7_TLB_RD_ADDR 0x4700 +#define GEN7_TLB_RD_ADDR _MMIO(0x4700) #if 0 -#define PRB0_TAIL 0x02030 -#define PRB0_HEAD 0x02034 -#define PRB0_START 0x02038 -#define PRB0_CTL 0x0203c -#define PRB1_TAIL 0x02040 /* 915+ only */ -#define PRB1_HEAD 0x02044 /* 915+ only */ -#define PRB1_START 0x02048 /* 915+ only */ -#define PRB1_CTL 0x0204c /* 915+ only */ +#define PRB0_TAIL _MMIO(0x2030) +#define PRB0_HEAD _MMIO(0x2034) +#define PRB0_START _MMIO(0x2038) +#define PRB0_CTL _MMIO(0x203c) +#define PRB1_TAIL _MMIO(0x2040) /* 915+ only */ +#define PRB1_HEAD _MMIO(0x2044) /* 915+ only */ +#define PRB1_START _MMIO(0x2048) /* 915+ only */ +#define PRB1_CTL _MMIO(0x204c) /* 915+ only */ #endif -#define IPEIR_I965 0x02064 -#define IPEHR_I965 0x02068 -#define GEN7_SC_INSTDONE 0x07100 -#define GEN7_SAMPLER_INSTDONE 0x0e160 -#define GEN7_ROW_INSTDONE 0x0e164 +#define IPEIR_I965 _MMIO(0x2064) +#define IPEHR_I965 _MMIO(0x2068) +#define GEN7_SC_INSTDONE _MMIO(0x7100) +#define GEN7_SAMPLER_INSTDONE _MMIO(0xe160) +#define GEN7_ROW_INSTDONE _MMIO(0xe164) #define I915_NUM_INSTDONE_REG 4 -#define RING_IPEIR(base) ((base)+0x64) -#define RING_IPEHR(base) ((base)+0x68) +#define RING_IPEIR(base) _MMIO((base)+0x64) +#define RING_IPEHR(base) _MMIO((base)+0x68) /* * On GEN4, only the render ring INSTDONE exists and has a different * layout than the GEN7+ version. * The GEN2 counterpart of this register is GEN2_INSTDONE. */ -#define RING_INSTDONE(base) ((base)+0x6c) -#define RING_INSTPS(base) ((base)+0x70) -#define RING_DMA_FADD(base) ((base)+0x78) -#define RING_DMA_FADD_UDW(base) ((base)+0x60) /* gen8+ */ -#define RING_INSTPM(base) ((base)+0xc0) -#define RING_MI_MODE(base) ((base)+0x9c) -#define INSTPS 0x02070 /* 965+ only */ -#define GEN4_INSTDONE1 0x0207c /* 965+ only, aka INSTDONE_2 on SNB */ -#define ACTHD_I965 0x02074 -#define HWS_PGA 0x02080 +#define RING_INSTDONE(base) _MMIO((base)+0x6c) +#define RING_INSTPS(base) _MMIO((base)+0x70) +#define RING_DMA_FADD(base) _MMIO((base)+0x78) +#define RING_DMA_FADD_UDW(base) _MMIO((base)+0x60) /* gen8+ */ +#define RING_INSTPM(base) _MMIO((base)+0xc0) +#define RING_MI_MODE(base) _MMIO((base)+0x9c) +#define INSTPS _MMIO(0x2070) /* 965+ only */ +#define GEN4_INSTDONE1 _MMIO(0x207c) /* 965+ only, aka INSTDONE_2 on SNB */ +#define ACTHD_I965 _MMIO(0x2074) +#define HWS_PGA _MMIO(0x2080) #define HWS_ADDRESS_MASK 0xfffff000 #define HWS_START_ADDRESS_SHIFT 4 -#define PWRCTXA 0x2088 /* 965GM+ only */ +#define PWRCTXA _MMIO(0x2088) /* 965GM+ only */ #define PWRCTX_EN (1<<0) -#define IPEIR 0x02088 -#define IPEHR 0x0208c -#define GEN2_INSTDONE 0x02090 -#define NOPID 0x02094 -#define HWSTAM 0x02098 -#define DMA_FADD_I8XX 0x020d0 -#define RING_BBSTATE(base) ((base)+0x110) -#define RING_BBADDR(base) ((base)+0x140) -#define RING_BBADDR_UDW(base) ((base)+0x168) /* gen8+ */ - -#define ERROR_GEN6 0x040a0 -#define GEN7_ERR_INT 0x44040 +#define IPEIR _MMIO(0x2088) +#define IPEHR _MMIO(0x208c) +#define GEN2_INSTDONE _MMIO(0x2090) +#define NOPID _MMIO(0x2094) +#define HWSTAM _MMIO(0x2098) +#define DMA_FADD_I8XX _MMIO(0x20d0) +#define RING_BBSTATE(base) _MMIO((base)+0x110) +#define RING_BB_PPGTT (1 << 5) +#define RING_SBBADDR(base) _MMIO((base)+0x114) /* hsw+ */ +#define RING_SBBSTATE(base) _MMIO((base)+0x118) /* hsw+ */ +#define RING_SBBADDR_UDW(base) _MMIO((base)+0x11c) /* gen8+ */ +#define RING_BBADDR(base) _MMIO((base)+0x140) +#define RING_BBADDR_UDW(base) _MMIO((base)+0x168) /* gen8+ */ +#define RING_BB_PER_CTX_PTR(base) _MMIO((base)+0x1c0) /* gen8+ */ +#define RING_INDIRECT_CTX(base) _MMIO((base)+0x1c4) /* gen8+ */ +#define RING_INDIRECT_CTX_OFFSET(base) _MMIO((base)+0x1c8) /* gen8+ */ +#define RING_CTX_TIMESTAMP(base) _MMIO((base)+0x3a8) /* gen8+ */ + +#define ERROR_GEN6 _MMIO(0x40a0) +#define GEN7_ERR_INT _MMIO(0x44040) #define ERR_INT_POISON (1<<31) #define ERR_INT_MMIO_UNCLAIMED (1<<13) #define ERR_INT_PIPE_CRC_DONE_C (1<<8) @@ -1645,13 +1705,13 @@ enum skl_disp_power_wells { #define ERR_INT_FIFO_UNDERRUN_A (1<<0) #define ERR_INT_FIFO_UNDERRUN(pipe) (1<<((pipe)*3)) -#define GEN8_FAULT_TLB_DATA0 0x04b10 -#define GEN8_FAULT_TLB_DATA1 0x04b14 +#define GEN8_FAULT_TLB_DATA0 _MMIO(0x4b10) +#define GEN8_FAULT_TLB_DATA1 _MMIO(0x4b14) -#define FPGA_DBG 0x42300 +#define FPGA_DBG _MMIO(0x42300) #define FPGA_DBG_RM_NOCLAIM (1<<31) -#define DERRMR 0x44050 +#define DERRMR _MMIO(0x44050) /* Note that HBLANK events are reserved on bdw+ */ #define DERRMR_PIPEA_SCANLINE (1<<0) #define DERRMR_PIPEA_PRI_FLIP_DONE (1<<1) @@ -1675,29 +1735,29 @@ enum skl_disp_power_wells { * for various sorts of correct behavior. The top 16 bits of each are * the enables for writing to the corresponding low bit. */ -#define _3D_CHICKEN 0x02084 +#define _3D_CHICKEN _MMIO(0x2084) #define _3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB (1 << 10) -#define _3D_CHICKEN2 0x0208c +#define _3D_CHICKEN2 _MMIO(0x208c) /* Disables pipelining of read flushes past the SF-WIZ interface. * Required on all Ironlake steppings according to the B-Spec, but the * particular danger of not doing so is not specified. */ # define _3D_CHICKEN2_WM_READ_PIPELINED (1 << 14) -#define _3D_CHICKEN3 0x02090 +#define _3D_CHICKEN3 _MMIO(0x2090) #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) /* gen8+ */ #define _3D_CHICKEN3_SF_DISABLE_PIPELINED_ATTR_FETCH (1 << 1) /* gen6 */ -#define MI_MODE 0x0209c +#define MI_MODE _MMIO(0x209c) # define VS_TIMER_DISPATCH (1 << 6) # define MI_FLUSH_ENABLE (1 << 12) # define ASYNC_FLIP_PERF_DISABLE (1 << 14) # define MODE_IDLE (1 << 9) # define STOP_RING (1 << 8) -#define GEN6_GT_MODE 0x20d0 -#define GEN7_GT_MODE 0x7008 +#define GEN6_GT_MODE _MMIO(0x20d0) +#define GEN7_GT_MODE _MMIO(0x7008) #define GEN6_WIZ_HASHING(hi, lo) (((hi) << 9) | ((lo) << 7)) #define GEN6_WIZ_HASHING_8x8 GEN6_WIZ_HASHING(0, 0) #define GEN6_WIZ_HASHING_8x4 GEN6_WIZ_HASHING(0, 1) @@ -1707,9 +1767,9 @@ enum skl_disp_power_wells { #define GEN9_IZ_HASHING_MASK(slice) (0x3 << ((slice) * 2)) #define GEN9_IZ_HASHING(slice, val) ((val) << ((slice) * 2)) -#define GFX_MODE 0x02520 -#define GFX_MODE_GEN7 0x0229c -#define RING_MODE_GEN7(ring) ((ring)->mmio_base+0x29c) +#define GFX_MODE _MMIO(0x2520) +#define GFX_MODE_GEN7 _MMIO(0x229c) +#define RING_MODE_GEN7(ring) _MMIO((ring)->mmio_base+0x29c) #define GFX_RUN_LIST_ENABLE (1<<15) #define GFX_INTERRUPT_STEERING (1<<14) #define GFX_TLB_INVALIDATE_EXPLICIT (1<<13) @@ -1727,36 +1787,36 @@ enum skl_disp_power_wells { #define VLV_DISPLAY_BASE 0x180000 #define VLV_MIPI_BASE VLV_DISPLAY_BASE -#define VLV_GU_CTL0 (VLV_DISPLAY_BASE + 0x2030) -#define VLV_GU_CTL1 (VLV_DISPLAY_BASE + 0x2034) -#define SCPD0 0x0209c /* 915+ only */ -#define IER 0x020a0 -#define IIR 0x020a4 -#define IMR 0x020a8 -#define ISR 0x020ac -#define VLV_GUNIT_CLOCK_GATE (VLV_DISPLAY_BASE + 0x2060) +#define VLV_GU_CTL0 _MMIO(VLV_DISPLAY_BASE + 0x2030) +#define VLV_GU_CTL1 _MMIO(VLV_DISPLAY_BASE + 0x2034) +#define SCPD0 _MMIO(0x209c) /* 915+ only */ +#define IER _MMIO(0x20a0) +#define IIR _MMIO(0x20a4) +#define IMR _MMIO(0x20a8) +#define ISR _MMIO(0x20ac) +#define VLV_GUNIT_CLOCK_GATE _MMIO(VLV_DISPLAY_BASE + 0x2060) #define GINT_DIS (1<<22) #define GCFG_DIS (1<<8) -#define VLV_GUNIT_CLOCK_GATE2 (VLV_DISPLAY_BASE + 0x2064) -#define VLV_IIR_RW (VLV_DISPLAY_BASE + 0x2084) -#define VLV_IER (VLV_DISPLAY_BASE + 0x20a0) -#define VLV_IIR (VLV_DISPLAY_BASE + 0x20a4) -#define VLV_IMR (VLV_DISPLAY_BASE + 0x20a8) -#define VLV_ISR (VLV_DISPLAY_BASE + 0x20ac) -#define VLV_PCBR (VLV_DISPLAY_BASE + 0x2120) +#define VLV_GUNIT_CLOCK_GATE2 _MMIO(VLV_DISPLAY_BASE + 0x2064) +#define VLV_IIR_RW _MMIO(VLV_DISPLAY_BASE + 0x2084) +#define VLV_IER _MMIO(VLV_DISPLAY_BASE + 0x20a0) +#define VLV_IIR _MMIO(VLV_DISPLAY_BASE + 0x20a4) +#define VLV_IMR _MMIO(VLV_DISPLAY_BASE + 0x20a8) +#define VLV_ISR _MMIO(VLV_DISPLAY_BASE + 0x20ac) +#define VLV_PCBR _MMIO(VLV_DISPLAY_BASE + 0x2120) #define VLV_PCBR_ADDR_SHIFT 12 #define DISPLAY_PLANE_FLIP_PENDING(plane) (1<<(11-(plane))) /* A and B only */ -#define EIR 0x020b0 -#define EMR 0x020b4 -#define ESR 0x020b8 +#define EIR _MMIO(0x20b0) +#define EMR _MMIO(0x20b4) +#define ESR _MMIO(0x20b8) #define GM45_ERROR_PAGE_TABLE (1<<5) #define GM45_ERROR_MEM_PRIV (1<<4) #define I915_ERROR_PAGE_TABLE (1<<4) #define GM45_ERROR_CP_PRIV (1<<3) #define I915_ERROR_MEMORY_REFRESH (1<<1) #define I915_ERROR_INSTRUCTION (1<<0) -#define INSTPM 0x020c0 +#define INSTPM _MMIO(0x20c0) #define INSTPM_SELF_EN (1<<12) /* 915GM only */ #define INSTPM_AGPBUSY_INT_EN (1<<11) /* gen3: when disabled, pending interrupts will not assert AGPBUSY# and will only @@ -1764,14 +1824,14 @@ enum skl_disp_power_wells { #define INSTPM_FORCE_ORDERING (1<<7) /* GEN6+ */ #define INSTPM_TLB_INVALIDATE (1<<9) #define INSTPM_SYNC_FLUSH (1<<5) -#define ACTHD 0x020c8 -#define MEM_MODE 0x020cc +#define ACTHD _MMIO(0x20c8) +#define MEM_MODE _MMIO(0x20cc) #define MEM_DISPLAY_B_TRICKLE_FEED_DISABLE (1<<3) /* 830 only */ #define MEM_DISPLAY_A_TRICKLE_FEED_DISABLE (1<<2) /* 830/845 only */ #define MEM_DISPLAY_TRICKLE_FEED_DISABLE (1<<2) /* 85x only */ -#define FW_BLC 0x020d8 -#define FW_BLC2 0x020dc -#define FW_BLC_SELF 0x020e0 /* 915+ only */ +#define FW_BLC _MMIO(0x20d8) +#define FW_BLC2 _MMIO(0x20dc) +#define FW_BLC_SELF _MMIO(0x20e0) /* 915+ only */ #define FW_BLC_SELF_EN_MASK (1<<31) #define FW_BLC_SELF_FIFO_MASK (1<<16) /* 945 only */ #define FW_BLC_SELF_EN (1<<15) /* 945 only */ @@ -1779,7 +1839,7 @@ enum skl_disp_power_wells { #define MM_FIFO_WATERMARK 0x0001F000 #define LM_BURST_LENGTH 0x00000700 #define LM_FIFO_WATERMARK 0x0000001F -#define MI_ARB_STATE 0x020e4 /* 915+ only */ +#define MI_ARB_STATE _MMIO(0x20e4) /* 915+ only */ /* Make render/texture TLB fetches lower priorty than associated data * fetches. This is not turned on by default @@ -1843,11 +1903,11 @@ enum skl_disp_power_wells { #define MI_ARB_DISPLAY_PRIORITY_A_B (0 << 0) /* display A > display B */ #define MI_ARB_DISPLAY_PRIORITY_B_A (1 << 0) /* display B > display A */ -#define MI_STATE 0x020e4 /* gen2 only */ +#define MI_STATE _MMIO(0x20e4) /* gen2 only */ #define MI_AGPBUSY_INT_EN (1 << 1) /* 85x only */ #define MI_AGPBUSY_830_MODE (1 << 0) /* 85x only */ -#define CACHE_MODE_0 0x02120 /* 915+ only */ +#define CACHE_MODE_0 _MMIO(0x2120) /* 915+ only */ #define CM0_PIPELINED_RENDER_FLUSH_DISABLE (1<<8) #define CM0_IZ_OPT_DISABLE (1<<6) #define CM0_ZR_OPT_DISABLE (1<<5) @@ -1856,32 +1916,32 @@ enum skl_disp_power_wells { #define CM0_COLOR_EVICT_DISABLE (1<<3) #define CM0_DEPTH_WRITE_DISABLE (1<<1) #define CM0_RC_OP_FLUSH_DISABLE (1<<0) -#define GFX_FLSH_CNTL 0x02170 /* 915+ only */ -#define GFX_FLSH_CNTL_GEN6 0x101008 +#define GFX_FLSH_CNTL _MMIO(0x2170) /* 915+ only */ +#define GFX_FLSH_CNTL_GEN6 _MMIO(0x101008) #define GFX_FLSH_CNTL_EN (1<<0) -#define ECOSKPD 0x021d0 +#define ECOSKPD _MMIO(0x21d0) #define ECO_GATING_CX_ONLY (1<<3) #define ECO_FLIP_DONE (1<<0) -#define CACHE_MODE_0_GEN7 0x7000 /* IVB+ */ +#define CACHE_MODE_0_GEN7 _MMIO(0x7000) /* IVB+ */ #define RC_OP_FLUSH_ENABLE (1<<0) #define HIZ_RAW_STALL_OPT_DISABLE (1<<2) -#define CACHE_MODE_1 0x7004 /* IVB+ */ +#define CACHE_MODE_1 _MMIO(0x7004) /* IVB+ */ #define PIXEL_SUBSPAN_COLLECT_OPT_DISABLE (1<<6) #define GEN8_4x4_STC_OPTIMIZATION_DISABLE (1<<6) #define GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE (1<<1) -#define GEN6_BLITTER_ECOSKPD 0x221d0 +#define GEN6_BLITTER_ECOSKPD _MMIO(0x221d0) #define GEN6_BLITTER_LOCK_SHIFT 16 #define GEN6_BLITTER_FBC_NOTIFY (1<<3) -#define GEN6_RC_SLEEP_PSMI_CONTROL 0x2050 +#define GEN6_RC_SLEEP_PSMI_CONTROL _MMIO(0x2050) #define GEN6_PSMI_SLEEP_MSG_DISABLE (1 << 0) #define GEN8_RC_SEMA_IDLE_MSG_DISABLE (1 << 12) #define GEN8_FF_DOP_CLOCK_GATE_DISABLE (1<<10) /* Fuse readout registers for GT */ -#define CHV_FUSE_GT (VLV_DISPLAY_BASE + 0x2168) +#define CHV_FUSE_GT _MMIO(VLV_DISPLAY_BASE + 0x2168) #define CHV_FGT_DISABLE_SS0 (1 << 10) #define CHV_FGT_DISABLE_SS1 (1 << 11) #define CHV_FGT_EU_DIS_SS0_R0_SHIFT 16 @@ -1893,7 +1953,7 @@ enum skl_disp_power_wells { #define CHV_FGT_EU_DIS_SS1_R1_SHIFT 28 #define CHV_FGT_EU_DIS_SS1_R1_MASK (0xf << CHV_FGT_EU_DIS_SS1_R1_SHIFT) -#define GEN8_FUSE2 0x9120 +#define GEN8_FUSE2 _MMIO(0x9120) #define GEN8_F2_SS_DIS_SHIFT 21 #define GEN8_F2_SS_DIS_MASK (0x7 << GEN8_F2_SS_DIS_SHIFT) #define GEN8_F2_S_ENA_SHIFT 25 @@ -1902,22 +1962,22 @@ enum skl_disp_power_wells { #define GEN9_F2_SS_DIS_SHIFT 20 #define GEN9_F2_SS_DIS_MASK (0xf << GEN9_F2_SS_DIS_SHIFT) -#define GEN8_EU_DISABLE0 0x9134 +#define GEN8_EU_DISABLE0 _MMIO(0x9134) #define GEN8_EU_DIS0_S0_MASK 0xffffff #define GEN8_EU_DIS0_S1_SHIFT 24 #define GEN8_EU_DIS0_S1_MASK (0xff << GEN8_EU_DIS0_S1_SHIFT) -#define GEN8_EU_DISABLE1 0x9138 +#define GEN8_EU_DISABLE1 _MMIO(0x9138) #define GEN8_EU_DIS1_S1_MASK 0xffff #define GEN8_EU_DIS1_S2_SHIFT 16 #define GEN8_EU_DIS1_S2_MASK (0xffff << GEN8_EU_DIS1_S2_SHIFT) -#define GEN8_EU_DISABLE2 0x913c +#define GEN8_EU_DISABLE2 _MMIO(0x913c) #define GEN8_EU_DIS2_S2_MASK 0xff -#define GEN9_EU_DISABLE(slice) (0x9134 + (slice)*0x4) +#define GEN9_EU_DISABLE(slice) _MMIO(0x9134 + (slice)*0x4) -#define GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050 +#define GEN6_BSD_SLEEP_PSMI_CONTROL _MMIO(0x12050) #define GEN6_BSD_SLEEP_MSG_DISABLE (1 << 0) #define GEN6_BSD_SLEEP_FLUSH_DISABLE (1 << 2) #define GEN6_BSD_SLEEP_INDICATOR (1 << 3) @@ -1995,9 +2055,9 @@ enum skl_disp_power_wells { #define I915_ASLE_INTERRUPT (1<<0) #define I915_BSD_USER_INTERRUPT (1<<25) -#define GEN6_BSD_RNCID 0x12198 +#define GEN6_BSD_RNCID _MMIO(0x12198) -#define GEN7_FF_THREAD_MODE 0x20a0 +#define GEN7_FF_THREAD_MODE _MMIO(0x20a0) #define GEN7_FF_SCHED_MASK 0x0077070 #define GEN8_FF_DS_REF_CNT_FFME (1 << 19) #define GEN7_FF_TS_SCHED_HS1 (0x5<<16) @@ -2018,9 +2078,9 @@ enum skl_disp_power_wells { * Framebuffer compression (915+ only) */ -#define FBC_CFB_BASE 0x03200 /* 4k page aligned */ -#define FBC_LL_BASE 0x03204 /* 4k page aligned */ -#define FBC_CONTROL 0x03208 +#define FBC_CFB_BASE _MMIO(0x3200) /* 4k page aligned */ +#define FBC_LL_BASE _MMIO(0x3204) /* 4k page aligned */ +#define FBC_CONTROL _MMIO(0x3208) #define FBC_CTL_EN (1<<31) #define FBC_CTL_PERIODIC (1<<30) #define FBC_CTL_INTERVAL_SHIFT (16) @@ -2028,14 +2088,14 @@ enum skl_disp_power_wells { #define FBC_CTL_C3_IDLE (1<<13) #define FBC_CTL_STRIDE_SHIFT (5) #define FBC_CTL_FENCENO_SHIFT (0) -#define FBC_COMMAND 0x0320c +#define FBC_COMMAND _MMIO(0x320c) #define FBC_CMD_COMPRESS (1<<0) -#define FBC_STATUS 0x03210 +#define FBC_STATUS _MMIO(0x3210) #define FBC_STAT_COMPRESSING (1<<31) #define FBC_STAT_COMPRESSED (1<<30) #define FBC_STAT_MODIFIED (1<<29) #define FBC_STAT_CURRENT_LINE_SHIFT (0) -#define FBC_CONTROL2 0x03214 +#define FBC_CONTROL2 _MMIO(0x3214) #define FBC_CTL_FENCE_DBL (0<<4) #define FBC_CTL_IDLE_IMM (0<<2) #define FBC_CTL_IDLE_FULL (1<<2) @@ -2043,17 +2103,17 @@ enum skl_disp_power_wells { #define FBC_CTL_IDLE_DEBUG (3<<2) #define FBC_CTL_CPU_FENCE (1<<1) #define FBC_CTL_PLANE(plane) ((plane)<<0) -#define FBC_FENCE_OFF 0x03218 /* BSpec typo has 321Bh */ -#define FBC_TAG(i) (0x03300 + (i) * 4) +#define FBC_FENCE_OFF _MMIO(0x3218) /* BSpec typo has 321Bh */ +#define FBC_TAG(i) _MMIO(0x3300 + (i) * 4) -#define FBC_STATUS2 0x43214 +#define FBC_STATUS2 _MMIO(0x43214) #define FBC_COMPRESSION_MASK 0x7ff #define FBC_LL_SIZE (1536) /* Framebuffer compression for GM45+ */ -#define DPFC_CB_BASE 0x3200 -#define DPFC_CONTROL 0x3208 +#define DPFC_CB_BASE _MMIO(0x3200) +#define DPFC_CONTROL _MMIO(0x3208) #define DPFC_CTL_EN (1<<31) #define DPFC_CTL_PLANE(plane) ((plane)<<30) #define IVB_DPFC_CTL_PLANE(plane) ((plane)<<29) @@ -2064,37 +2124,37 @@ enum skl_disp_power_wells { #define DPFC_CTL_LIMIT_1X (0<<6) #define DPFC_CTL_LIMIT_2X (1<<6) #define DPFC_CTL_LIMIT_4X (2<<6) -#define DPFC_RECOMP_CTL 0x320c +#define DPFC_RECOMP_CTL _MMIO(0x320c) #define DPFC_RECOMP_STALL_EN (1<<27) #define DPFC_RECOMP_STALL_WM_SHIFT (16) #define DPFC_RECOMP_STALL_WM_MASK (0x07ff0000) #define DPFC_RECOMP_TIMER_COUNT_SHIFT (0) #define DPFC_RECOMP_TIMER_COUNT_MASK (0x0000003f) -#define DPFC_STATUS 0x3210 +#define DPFC_STATUS _MMIO(0x3210) #define DPFC_INVAL_SEG_SHIFT (16) #define DPFC_INVAL_SEG_MASK (0x07ff0000) #define DPFC_COMP_SEG_SHIFT (0) #define DPFC_COMP_SEG_MASK (0x000003ff) -#define DPFC_STATUS2 0x3214 -#define DPFC_FENCE_YOFF 0x3218 -#define DPFC_CHICKEN 0x3224 +#define DPFC_STATUS2 _MMIO(0x3214) +#define DPFC_FENCE_YOFF _MMIO(0x3218) +#define DPFC_CHICKEN _MMIO(0x3224) #define DPFC_HT_MODIFY (1<<31) /* Framebuffer compression for Ironlake */ -#define ILK_DPFC_CB_BASE 0x43200 -#define ILK_DPFC_CONTROL 0x43208 +#define ILK_DPFC_CB_BASE _MMIO(0x43200) +#define ILK_DPFC_CONTROL _MMIO(0x43208) #define FBC_CTL_FALSE_COLOR (1<<10) /* The bit 28-8 is reserved */ #define DPFC_RESERVED (0x1FFFFF00) -#define ILK_DPFC_RECOMP_CTL 0x4320c -#define ILK_DPFC_STATUS 0x43210 -#define ILK_DPFC_FENCE_YOFF 0x43218 -#define ILK_DPFC_CHICKEN 0x43224 -#define ILK_FBC_RT_BASE 0x2128 +#define ILK_DPFC_RECOMP_CTL _MMIO(0x4320c) +#define ILK_DPFC_STATUS _MMIO(0x43210) +#define ILK_DPFC_FENCE_YOFF _MMIO(0x43218) +#define ILK_DPFC_CHICKEN _MMIO(0x43224) +#define ILK_FBC_RT_BASE _MMIO(0x2128) #define ILK_FBC_RT_VALID (1<<0) #define SNB_FBC_FRONT_BUFFER (1<<1) -#define ILK_DISPLAY_CHICKEN1 0x42000 +#define ILK_DISPLAY_CHICKEN1 _MMIO(0x42000) #define ILK_FBCQ_DIS (1<<22) #define ILK_PABSTRETCH_DIS (1<<21) @@ -2104,31 +2164,31 @@ enum skl_disp_power_wells { * * The following two registers are of type GTTMMADR */ -#define SNB_DPFC_CTL_SA 0x100100 +#define SNB_DPFC_CTL_SA _MMIO(0x100100) #define SNB_CPU_FENCE_ENABLE (1<<29) -#define DPFC_CPU_FENCE_OFFSET 0x100104 +#define DPFC_CPU_FENCE_OFFSET _MMIO(0x100104) /* Framebuffer compression for Ivybridge */ -#define IVB_FBC_RT_BASE 0x7020 +#define IVB_FBC_RT_BASE _MMIO(0x7020) -#define IPS_CTL 0x43408 +#define IPS_CTL _MMIO(0x43408) #define IPS_ENABLE (1 << 31) -#define MSG_FBC_REND_STATE 0x50380 +#define MSG_FBC_REND_STATE _MMIO(0x50380) #define FBC_REND_NUKE (1<<2) #define FBC_REND_CACHE_CLEAN (1<<1) /* * GPIO regs */ -#define GPIOA 0x5010 -#define GPIOB 0x5014 -#define GPIOC 0x5018 -#define GPIOD 0x501c -#define GPIOE 0x5020 -#define GPIOF 0x5024 -#define GPIOG 0x5028 -#define GPIOH 0x502c +#define GPIOA _MMIO(0x5010) +#define GPIOB _MMIO(0x5014) +#define GPIOC _MMIO(0x5018) +#define GPIOD _MMIO(0x501c) +#define GPIOE _MMIO(0x5020) +#define GPIOF _MMIO(0x5024) +#define GPIOG _MMIO(0x5028) +#define GPIOH _MMIO(0x502c) # define GPIO_CLOCK_DIR_MASK (1 << 0) # define GPIO_CLOCK_DIR_IN (0 << 1) # define GPIO_CLOCK_DIR_OUT (1 << 1) @@ -2144,7 +2204,7 @@ enum skl_disp_power_wells { # define GPIO_DATA_VAL_IN (1 << 12) # define GPIO_DATA_PULLUP_DISABLE (1 << 13) -#define GMBUS0 (dev_priv->gpio_mmio_base + 0x5100) /* clock/port select */ +#define GMBUS0 _MMIO(dev_priv->gpio_mmio_base + 0x5100) /* clock/port select */ #define GMBUS_RATE_100KHZ (0<<8) #define GMBUS_RATE_50KHZ (1<<8) #define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */ @@ -2163,7 +2223,7 @@ enum skl_disp_power_wells { #define GMBUS_PIN_2_BXT 2 #define GMBUS_PIN_3_BXT 3 #define GMBUS_NUM_PINS 7 /* including 0 */ -#define GMBUS1 (dev_priv->gpio_mmio_base + 0x5104) /* command/status */ +#define GMBUS1 _MMIO(dev_priv->gpio_mmio_base + 0x5104) /* command/status */ #define GMBUS_SW_CLR_INT (1<<31) #define GMBUS_SW_RDY (1<<30) #define GMBUS_ENT (1<<29) /* enable timeout */ @@ -2177,7 +2237,7 @@ enum skl_disp_power_wells { #define GMBUS_SLAVE_ADDR_SHIFT 1 #define GMBUS_SLAVE_READ (1<<0) #define GMBUS_SLAVE_WRITE (0<<0) -#define GMBUS2 (dev_priv->gpio_mmio_base + 0x5108) /* status */ +#define GMBUS2 _MMIO(dev_priv->gpio_mmio_base + 0x5108) /* status */ #define GMBUS_INUSE (1<<15) #define GMBUS_HW_WAIT_PHASE (1<<14) #define GMBUS_STALL_TIMEOUT (1<<13) @@ -2185,14 +2245,14 @@ enum skl_disp_power_wells { #define GMBUS_HW_RDY (1<<11) #define GMBUS_SATOER (1<<10) #define GMBUS_ACTIVE (1<<9) -#define GMBUS3 (dev_priv->gpio_mmio_base + 0x510c) /* data buffer bytes 3-0 */ -#define GMBUS4 (dev_priv->gpio_mmio_base + 0x5110) /* interrupt mask (Pineview+) */ +#define GMBUS3 _MMIO(dev_priv->gpio_mmio_base + 0x510c) /* data buffer bytes 3-0 */ +#define GMBUS4 _MMIO(dev_priv->gpio_mmio_base + 0x5110) /* interrupt mask (Pineview+) */ #define GMBUS_SLAVE_TIMEOUT_EN (1<<4) #define GMBUS_NAK_EN (1<<3) #define GMBUS_IDLE_EN (1<<2) #define GMBUS_HW_WAIT_EN (1<<1) #define GMBUS_HW_RDY_EN (1<<0) -#define GMBUS5 (dev_priv->gpio_mmio_base + 0x5120) /* byte index */ +#define GMBUS5 _MMIO(dev_priv->gpio_mmio_base + 0x5120) /* byte index */ #define GMBUS_2BYTE_INDEX_EN (1<<31) /* @@ -2201,11 +2261,11 @@ enum skl_disp_power_wells { #define _DPLL_A (dev_priv->info.display_mmio_offset + 0x6014) #define _DPLL_B (dev_priv->info.display_mmio_offset + 0x6018) #define _CHV_DPLL_C (dev_priv->info.display_mmio_offset + 0x6030) -#define DPLL(pipe) _PIPE3((pipe), _DPLL_A, _DPLL_B, _CHV_DPLL_C) +#define DPLL(pipe) _MMIO_PIPE3((pipe), _DPLL_A, _DPLL_B, _CHV_DPLL_C) -#define VGA0 0x6000 -#define VGA1 0x6004 -#define VGA_PD 0x6010 +#define VGA0 _MMIO(0x6000) +#define VGA1 _MMIO(0x6004) +#define VGA_PD _MMIO(0x6010) #define VGA0_PD_P2_DIV_4 (1 << 7) #define VGA0_PD_P1_DIV_2 (1 << 5) #define VGA0_PD_P1_SHIFT 0 @@ -2241,9 +2301,9 @@ enum skl_disp_power_wells { #define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 /* Additional CHV pll/phy registers */ -#define DPIO_PHY_STATUS (VLV_DISPLAY_BASE + 0x6240) +#define DPIO_PHY_STATUS _MMIO(VLV_DISPLAY_BASE + 0x6240) #define DPLL_PORTD_READY_MASK (0xf) -#define DISPLAY_PHY_CONTROL (VLV_DISPLAY_BASE + 0x60100) +#define DISPLAY_PHY_CONTROL _MMIO(VLV_DISPLAY_BASE + 0x60100) #define PHY_CH_POWER_DOWN_OVRD_EN(phy, ch) (1 << (2*(phy)+(ch)+27)) #define PHY_LDO_DELAY_0NS 0x0 #define PHY_LDO_DELAY_200NS 0x1 @@ -2254,7 +2314,7 @@ enum skl_disp_power_wells { #define PHY_CH_DEEP_PSR 0x7 #define PHY_CH_POWER_MODE(mode, phy, ch) ((mode) << (6*(phy)+3*(ch)+2)) #define PHY_COM_LANE_RESET_DEASSERT(phy) (1 << (phy)) -#define DISPLAY_PHY_STATUS (VLV_DISPLAY_BASE + 0x60104) +#define DISPLAY_PHY_STATUS _MMIO(VLV_DISPLAY_BASE + 0x60104) #define PHY_POWERGOOD(phy) (((phy) == DPIO_PHY0) ? (1<<31) : (1<<30)) #define PHY_STATUS_CMN_LDO(phy, ch) (1 << (6-(6*(phy)+3*(ch)))) #define PHY_STATUS_SPLINE_LDO(phy, ch, spline) (1 << (8-(6*(phy)+3*(ch)+(spline)))) @@ -2300,7 +2360,7 @@ enum skl_disp_power_wells { #define _DPLL_A_MD (dev_priv->info.display_mmio_offset + 0x601c) #define _DPLL_B_MD (dev_priv->info.display_mmio_offset + 0x6020) #define _CHV_DPLL_C_MD (dev_priv->info.display_mmio_offset + 0x603c) -#define DPLL_MD(pipe) _PIPE3((pipe), _DPLL_A_MD, _DPLL_B_MD, _CHV_DPLL_C_MD) +#define DPLL_MD(pipe) _MMIO_PIPE3((pipe), _DPLL_A_MD, _DPLL_B_MD, _CHV_DPLL_C_MD) /* * UDI pixel divider, controlling how many pixels are stuffed into a packet. @@ -2339,12 +2399,12 @@ enum skl_disp_power_wells { #define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f #define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 -#define _FPA0 0x06040 -#define _FPA1 0x06044 -#define _FPB0 0x06048 -#define _FPB1 0x0604c -#define FP0(pipe) _PIPE(pipe, _FPA0, _FPB0) -#define FP1(pipe) _PIPE(pipe, _FPA1, _FPB1) +#define _FPA0 0x6040 +#define _FPA1 0x6044 +#define _FPB0 0x6048 +#define _FPB1 0x604c +#define FP0(pipe) _MMIO_PIPE(pipe, _FPA0, _FPB0) +#define FP1(pipe) _MMIO_PIPE(pipe, _FPA1, _FPB1) #define FP_N_DIV_MASK 0x003f0000 #define FP_N_PINEVIEW_DIV_MASK 0x00ff0000 #define FP_N_DIV_SHIFT 16 @@ -2353,7 +2413,7 @@ enum skl_disp_power_wells { #define FP_M2_DIV_MASK 0x0000003f #define FP_M2_PINEVIEW_DIV_MASK 0x000000ff #define FP_M2_DIV_SHIFT 0 -#define DPLL_TEST 0x606c +#define DPLL_TEST _MMIO(0x606c) #define DPLLB_TEST_SDVO_DIV_1 (0 << 22) #define DPLLB_TEST_SDVO_DIV_2 (1 << 22) #define DPLLB_TEST_SDVO_DIV_4 (2 << 22) @@ -2364,12 +2424,12 @@ enum skl_disp_power_wells { #define DPLLA_TEST_N_BYPASS (1 << 3) #define DPLLA_TEST_M_BYPASS (1 << 2) #define DPLLA_INPUT_BUFFER_ENABLE (1 << 0) -#define D_STATE 0x6104 +#define D_STATE _MMIO(0x6104) #define DSTATE_GFX_RESET_I830 (1<<6) #define DSTATE_PLL_D3_OFF (1<<3) #define DSTATE_GFX_CLOCK_GATING (1<<1) #define DSTATE_DOT_CLOCK_GATING (1<<0) -#define DSPCLK_GATE_D (dev_priv->info.display_mmio_offset + 0x6200) +#define DSPCLK_GATE_D _MMIO(dev_priv->info.display_mmio_offset + 0x6200) # define DPUNIT_B_CLOCK_GATE_DISABLE (1 << 30) /* 965 */ # define VSUNIT_CLOCK_GATE_DISABLE (1 << 29) /* 965 */ # define VRHUNIT_CLOCK_GATE_DISABLE (1 << 28) /* 965 */ @@ -2408,7 +2468,7 @@ enum skl_disp_power_wells { # define ZVUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 830 */ # define OVLUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 845,865 */ -#define RENCLK_GATE_D1 0x6204 +#define RENCLK_GATE_D1 _MMIO(0x6204) # define BLITTER_CLOCK_GATE_DISABLE (1 << 13) /* 945GM only */ # define MPEG_CLOCK_GATE_DISABLE (1 << 12) /* 945GM only */ # define PC_FE_CLOCK_GATE_DISABLE (1 << 11) @@ -2472,35 +2532,35 @@ enum skl_disp_power_wells { # define I965_FT_CLOCK_GATE_DISABLE (1 << 1) # define I965_DM_CLOCK_GATE_DISABLE (1 << 0) -#define RENCLK_GATE_D2 0x6208 +#define RENCLK_GATE_D2 _MMIO(0x6208) #define VF_UNIT_CLOCK_GATE_DISABLE (1 << 9) #define GS_UNIT_CLOCK_GATE_DISABLE (1 << 7) #define CL_UNIT_CLOCK_GATE_DISABLE (1 << 6) -#define VDECCLK_GATE_D 0x620C /* g4x only */ +#define VDECCLK_GATE_D _MMIO(0x620C) /* g4x only */ #define VCP_UNIT_CLOCK_GATE_DISABLE (1 << 4) -#define RAMCLK_GATE_D 0x6210 /* CRL only */ -#define DEUC 0x6214 /* CRL only */ +#define RAMCLK_GATE_D _MMIO(0x6210) /* CRL only */ +#define DEUC _MMIO(0x6214) /* CRL only */ -#define FW_BLC_SELF_VLV (VLV_DISPLAY_BASE + 0x6500) +#define FW_BLC_SELF_VLV _MMIO(VLV_DISPLAY_BASE + 0x6500) #define FW_CSPWRDWNEN (1<<15) -#define MI_ARB_VLV (VLV_DISPLAY_BASE + 0x6504) +#define MI_ARB_VLV _MMIO(VLV_DISPLAY_BASE + 0x6504) -#define CZCLK_CDCLK_FREQ_RATIO (VLV_DISPLAY_BASE + 0x6508) +#define CZCLK_CDCLK_FREQ_RATIO _MMIO(VLV_DISPLAY_BASE + 0x6508) #define CDCLK_FREQ_SHIFT 4 #define CDCLK_FREQ_MASK (0x1f << CDCLK_FREQ_SHIFT) #define CZCLK_FREQ_MASK 0xf -#define GCI_CONTROL (VLV_DISPLAY_BASE + 0x650C) +#define GCI_CONTROL _MMIO(VLV_DISPLAY_BASE + 0x650C) #define PFI_CREDIT_63 (9 << 28) /* chv only */ #define PFI_CREDIT_31 (8 << 28) /* chv only */ #define PFI_CREDIT(x) (((x) - 8) << 28) /* 8-15 */ #define PFI_CREDIT_RESEND (1 << 27) #define VGA_FAST_MODE_DISABLE (1 << 14) -#define GMBUSFREQ_VLV (VLV_DISPLAY_BASE + 0x6510) +#define GMBUSFREQ_VLV _MMIO(VLV_DISPLAY_BASE + 0x6510) /* * Palette regs @@ -2508,8 +2568,8 @@ enum skl_disp_power_wells { #define PALETTE_A_OFFSET 0xa000 #define PALETTE_B_OFFSET 0xa800 #define CHV_PALETTE_C_OFFSET 0xc000 -#define PALETTE(pipe, i) (dev_priv->info.palette_offsets[pipe] + \ - dev_priv->info.display_mmio_offset + (i) * 4) +#define PALETTE(pipe, i) _MMIO(dev_priv->info.palette_offsets[pipe] + \ + dev_priv->info.display_mmio_offset + (i) * 4) /* MCH MMIO space */ @@ -2527,37 +2587,37 @@ enum skl_disp_power_wells { #define MCHBAR_MIRROR_BASE_SNB 0x140000 -#define CTG_STOLEN_RESERVED (MCHBAR_MIRROR_BASE + 0x34) -#define ELK_STOLEN_RESERVED (MCHBAR_MIRROR_BASE + 0x48) +#define CTG_STOLEN_RESERVED _MMIO(MCHBAR_MIRROR_BASE + 0x34) +#define ELK_STOLEN_RESERVED _MMIO(MCHBAR_MIRROR_BASE + 0x48) #define G4X_STOLEN_RESERVED_ADDR1_MASK (0xFFFF << 16) #define G4X_STOLEN_RESERVED_ADDR2_MASK (0xFFF << 4) /* Memory controller frequency in MCHBAR for Haswell (possible SNB+) */ -#define DCLK (MCHBAR_MIRROR_BASE_SNB + 0x5e04) +#define DCLK _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5e04) /* 915-945 and GM965 MCH register controlling DRAM channel access */ -#define DCC 0x10200 +#define DCC _MMIO(MCHBAR_MIRROR_BASE + 0x200) #define DCC_ADDRESSING_MODE_SINGLE_CHANNEL (0 << 0) #define DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC (1 << 0) #define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED (2 << 0) #define DCC_ADDRESSING_MODE_MASK (3 << 0) #define DCC_CHANNEL_XOR_DISABLE (1 << 10) #define DCC_CHANNEL_XOR_BIT_17 (1 << 9) -#define DCC2 0x10204 +#define DCC2 _MMIO(MCHBAR_MIRROR_BASE + 0x204) #define DCC2_MODIFIED_ENHANCED_DISABLE (1 << 20) /* Pineview MCH register contains DDR3 setting */ -#define CSHRDDR3CTL 0x101a8 +#define CSHRDDR3CTL _MMIO(MCHBAR_MIRROR_BASE + 0x1a8) #define CSHRDDR3CTL_DDR3 (1 << 2) /* 965 MCH register controlling DRAM channel configuration */ -#define C0DRB3 0x10206 -#define C1DRB3 0x10606 +#define C0DRB3 _MMIO(MCHBAR_MIRROR_BASE + 0x206) +#define C1DRB3 _MMIO(MCHBAR_MIRROR_BASE + 0x606) /* snb MCH registers for reading the DRAM channel configuration */ -#define MAD_DIMM_C0 (MCHBAR_MIRROR_BASE_SNB + 0x5004) -#define MAD_DIMM_C1 (MCHBAR_MIRROR_BASE_SNB + 0x5008) -#define MAD_DIMM_C2 (MCHBAR_MIRROR_BASE_SNB + 0x500C) +#define MAD_DIMM_C0 _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5004) +#define MAD_DIMM_C1 _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5008) +#define MAD_DIMM_C2 _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x500C) #define MAD_DIMM_ECC_MASK (0x3 << 24) #define MAD_DIMM_ECC_OFF (0x0 << 24) #define MAD_DIMM_ECC_IO_ON_LOGIC_OFF (0x1 << 24) @@ -2577,14 +2637,14 @@ enum skl_disp_power_wells { #define MAD_DIMM_A_SIZE_MASK (0xff << MAD_DIMM_A_SIZE_SHIFT) /* snb MCH registers for priority tuning */ -#define MCH_SSKPD (MCHBAR_MIRROR_BASE_SNB + 0x5d10) +#define MCH_SSKPD _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5d10) #define MCH_SSKPD_WM0_MASK 0x3f #define MCH_SSKPD_WM0_VAL 0xc -#define MCH_SECP_NRG_STTS (MCHBAR_MIRROR_BASE_SNB + 0x592c) +#define MCH_SECP_NRG_STTS _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x592c) /* Clocking configuration register */ -#define CLKCFG 0x10c00 +#define CLKCFG _MMIO(MCHBAR_MIRROR_BASE + 0xc00) #define CLKCFG_FSB_400 (5 << 0) /* hrawclk 100 */ #define CLKCFG_FSB_533 (1 << 0) /* hrawclk 133 */ #define CLKCFG_FSB_667 (3 << 0) /* hrawclk 166 */ @@ -2600,26 +2660,26 @@ enum skl_disp_power_wells { #define CLKCFG_MEM_800 (3 << 4) #define CLKCFG_MEM_MASK (7 << 4) -#define HPLLVCO (MCHBAR_MIRROR_BASE + 0xc38) -#define HPLLVCO_MOBILE (MCHBAR_MIRROR_BASE + 0xc0f) +#define HPLLVCO _MMIO(MCHBAR_MIRROR_BASE + 0xc38) +#define HPLLVCO_MOBILE _MMIO(MCHBAR_MIRROR_BASE + 0xc0f) -#define TSC1 0x11001 +#define TSC1 _MMIO(0x11001) #define TSE (1<<0) -#define TR1 0x11006 -#define TSFS 0x11020 +#define TR1 _MMIO(0x11006) +#define TSFS _MMIO(0x11020) #define TSFS_SLOPE_MASK 0x0000ff00 #define TSFS_SLOPE_SHIFT 8 #define TSFS_INTR_MASK 0x000000ff -#define CRSTANDVID 0x11100 -#define PXVFREQ(i) (0x11110 + (i) * 4) /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */ +#define CRSTANDVID _MMIO(0x11100) +#define PXVFREQ(fstart) _MMIO(0x11110 + (fstart) * 4) /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */ #define PXVFREQ_PX_MASK 0x7f000000 #define PXVFREQ_PX_SHIFT 24 -#define VIDFREQ_BASE 0x11110 -#define VIDFREQ1 0x11110 /* VIDFREQ1-4 (0x1111c) (Cantiga) */ -#define VIDFREQ2 0x11114 -#define VIDFREQ3 0x11118 -#define VIDFREQ4 0x1111c +#define VIDFREQ_BASE _MMIO(0x11110) +#define VIDFREQ1 _MMIO(0x11110) /* VIDFREQ1-4 (0x1111c) (Cantiga) */ +#define VIDFREQ2 _MMIO(0x11114) +#define VIDFREQ3 _MMIO(0x11118) +#define VIDFREQ4 _MMIO(0x1111c) #define VIDFREQ_P0_MASK 0x1f000000 #define VIDFREQ_P0_SHIFT 24 #define VIDFREQ_P0_CSCLK_MASK 0x00f00000 @@ -2631,8 +2691,8 @@ enum skl_disp_power_wells { #define VIDFREQ_P1_CSCLK_MASK 0x000000f0 #define VIDFREQ_P1_CSCLK_SHIFT 4 #define VIDFREQ_P1_CRCLK_MASK 0x0000000f -#define INTTOEXT_BASE_ILK 0x11300 -#define INTTOEXT_BASE 0x11120 /* INTTOEXT1-8 (0x1113c) */ +#define INTTOEXT_BASE_ILK _MMIO(0x11300) +#define INTTOEXT_BASE _MMIO(0x11120) /* INTTOEXT1-8 (0x1113c) */ #define INTTOEXT_MAP3_SHIFT 24 #define INTTOEXT_MAP3_MASK (0x1f << INTTOEXT_MAP3_SHIFT) #define INTTOEXT_MAP2_SHIFT 16 @@ -2641,7 +2701,7 @@ enum skl_disp_power_wells { #define INTTOEXT_MAP1_MASK (0x1f << INTTOEXT_MAP1_SHIFT) #define INTTOEXT_MAP0_SHIFT 0 #define INTTOEXT_MAP0_MASK (0x1f << INTTOEXT_MAP0_SHIFT) -#define MEMSWCTL 0x11170 /* Ironlake only */ +#define MEMSWCTL _MMIO(0x11170) /* Ironlake only */ #define MEMCTL_CMD_MASK 0xe000 #define MEMCTL_CMD_SHIFT 13 #define MEMCTL_CMD_RCLK_OFF 0 @@ -2656,8 +2716,8 @@ enum skl_disp_power_wells { #define MEMCTL_FREQ_SHIFT 8 #define MEMCTL_SFCAVM (1<<7) #define MEMCTL_TGT_VID_MASK 0x007f -#define MEMIHYST 0x1117c -#define MEMINTREN 0x11180 /* 16 bits */ +#define MEMIHYST _MMIO(0x1117c) +#define MEMINTREN _MMIO(0x11180) /* 16 bits */ #define MEMINT_RSEXIT_EN (1<<8) #define MEMINT_CX_SUPR_EN (1<<7) #define MEMINT_CONT_BUSY_EN (1<<6) @@ -2667,7 +2727,7 @@ enum skl_disp_power_wells { #define MEMINT_UP_EVAL_EN (1<<2) #define MEMINT_DOWN_EVAL_EN (1<<1) #define MEMINT_SW_CMD_EN (1<<0) -#define MEMINTRSTR 0x11182 /* 16 bits */ +#define MEMINTRSTR _MMIO(0x11182) /* 16 bits */ #define MEM_RSEXIT_MASK 0xc000 #define MEM_RSEXIT_SHIFT 14 #define MEM_CONT_BUSY_MASK 0x3000 @@ -2687,7 +2747,7 @@ enum skl_disp_power_wells { #define MEM_INT_STEER_CMR 1 #define MEM_INT_STEER_SMI 2 #define MEM_INT_STEER_SCI 3 -#define MEMINTRSTS 0x11184 +#define MEMINTRSTS _MMIO(0x11184) #define MEMINT_RSEXIT (1<<7) #define MEMINT_CONT_BUSY (1<<6) #define MEMINT_AVG_BUSY (1<<5) @@ -2696,7 +2756,7 @@ enum skl_disp_power_wells { #define MEMINT_UP_EVAL (1<<2) #define MEMINT_DOWN_EVAL (1<<1) #define MEMINT_SW_CMD (1<<0) -#define MEMMODECTL 0x11190 +#define MEMMODECTL _MMIO(0x11190) #define MEMMODE_BOOST_EN (1<<31) #define MEMMODE_BOOST_FREQ_MASK 0x0f000000 /* jitter for boost, 0-15 */ #define MEMMODE_BOOST_FREQ_SHIFT 24 @@ -2713,8 +2773,8 @@ enum skl_disp_power_wells { #define MEMMODE_FMAX_MASK 0x000000f0 /* max jitter, 0-15 */ #define MEMMODE_FMAX_SHIFT 4 #define MEMMODE_FMIN_MASK 0x0000000f /* min jitter, 0-15 */ -#define RCBMAXAVG 0x1119c -#define MEMSWCTL2 0x1119e /* Cantiga only */ +#define RCBMAXAVG _MMIO(0x1119c) +#define MEMSWCTL2 _MMIO(0x1119e) /* Cantiga only */ #define SWMEMCMD_RENDER_OFF (0 << 13) #define SWMEMCMD_RENDER_ON (1 << 13) #define SWMEMCMD_SWFREQ (2 << 13) @@ -2726,11 +2786,11 @@ enum skl_disp_power_wells { #define SWFREQ_MASK 0x0380 /* P0-7 */ #define SWFREQ_SHIFT 7 #define TARVID_MASK 0x001f -#define MEMSTAT_CTG 0x111a0 -#define RCBMINAVG 0x111a0 -#define RCUPEI 0x111b0 -#define RCDNEI 0x111b4 -#define RSTDBYCTL 0x111b8 +#define MEMSTAT_CTG _MMIO(0x111a0) +#define RCBMINAVG _MMIO(0x111a0) +#define RCUPEI _MMIO(0x111b0) +#define RCDNEI _MMIO(0x111b4) +#define RSTDBYCTL _MMIO(0x111b8) #define RS1EN (1<<31) #define RS2EN (1<<30) #define RS3EN (1<<29) @@ -2774,10 +2834,10 @@ enum skl_disp_power_wells { #define RS_CSTATE_C367_RS2 (3<<4) #define REDSAVES (1<<3) /* no context save if was idle during rs0 */ #define REDRESTORES (1<<2) /* no restore if was idle during rs0 */ -#define VIDCTL 0x111c0 -#define VIDSTS 0x111c8 -#define VIDSTART 0x111cc /* 8 bits */ -#define MEMSTAT_ILK 0x111f8 +#define VIDCTL _MMIO(0x111c0) +#define VIDSTS _MMIO(0x111c8) +#define VIDSTART _MMIO(0x111cc) /* 8 bits */ +#define MEMSTAT_ILK _MMIO(0x111f8) #define MEMSTAT_VID_MASK 0x7f00 #define MEMSTAT_VID_SHIFT 8 #define MEMSTAT_PSTATE_MASK 0x00f8 @@ -2788,55 +2848,55 @@ enum skl_disp_power_wells { #define MEMSTAT_SRC_CTL_TRB 1 #define MEMSTAT_SRC_CTL_THM 2 #define MEMSTAT_SRC_CTL_STDBY 3 -#define RCPREVBSYTUPAVG 0x113b8 -#define RCPREVBSYTDNAVG 0x113bc -#define PMMISC 0x11214 +#define RCPREVBSYTUPAVG _MMIO(0x113b8) +#define RCPREVBSYTDNAVG _MMIO(0x113bc) +#define PMMISC _MMIO(0x11214) #define MCPPCE_EN (1<<0) /* enable PM_MSG from PCH->MPC */ -#define SDEW 0x1124c -#define CSIEW0 0x11250 -#define CSIEW1 0x11254 -#define CSIEW2 0x11258 -#define PEW(i) (0x1125c + (i) * 4) /* 5 registers */ -#define DEW(i) (0x11270 + (i) * 4) /* 3 registers */ -#define MCHAFE 0x112c0 -#define CSIEC 0x112e0 -#define DMIEC 0x112e4 -#define DDREC 0x112e8 -#define PEG0EC 0x112ec -#define PEG1EC 0x112f0 -#define GFXEC 0x112f4 -#define RPPREVBSYTUPAVG 0x113b8 -#define RPPREVBSYTDNAVG 0x113bc -#define ECR 0x11600 +#define SDEW _MMIO(0x1124c) +#define CSIEW0 _MMIO(0x11250) +#define CSIEW1 _MMIO(0x11254) +#define CSIEW2 _MMIO(0x11258) +#define PEW(i) _MMIO(0x1125c + (i) * 4) /* 5 registers */ +#define DEW(i) _MMIO(0x11270 + (i) * 4) /* 3 registers */ +#define MCHAFE _MMIO(0x112c0) +#define CSIEC _MMIO(0x112e0) +#define DMIEC _MMIO(0x112e4) +#define DDREC _MMIO(0x112e8) +#define PEG0EC _MMIO(0x112ec) +#define PEG1EC _MMIO(0x112f0) +#define GFXEC _MMIO(0x112f4) +#define RPPREVBSYTUPAVG _MMIO(0x113b8) +#define RPPREVBSYTDNAVG _MMIO(0x113bc) +#define ECR _MMIO(0x11600) #define ECR_GPFE (1<<31) #define ECR_IMONE (1<<30) #define ECR_CAP_MASK 0x0000001f /* Event range, 0-31 */ -#define OGW0 0x11608 -#define OGW1 0x1160c -#define EG0 0x11610 -#define EG1 0x11614 -#define EG2 0x11618 -#define EG3 0x1161c -#define EG4 0x11620 -#define EG5 0x11624 -#define EG6 0x11628 -#define EG7 0x1162c -#define PXW(i) (0x11664 + (i) * 4) /* 4 registers */ -#define PXWL(i) (0x11680 + (i) * 4) /* 8 registers */ -#define LCFUSE02 0x116c0 +#define OGW0 _MMIO(0x11608) +#define OGW1 _MMIO(0x1160c) +#define EG0 _MMIO(0x11610) +#define EG1 _MMIO(0x11614) +#define EG2 _MMIO(0x11618) +#define EG3 _MMIO(0x1161c) +#define EG4 _MMIO(0x11620) +#define EG5 _MMIO(0x11624) +#define EG6 _MMIO(0x11628) +#define EG7 _MMIO(0x1162c) +#define PXW(i) _MMIO(0x11664 + (i) * 4) /* 4 registers */ +#define PXWL(i) _MMIO(0x11680 + (i) * 8) /* 8 registers */ +#define LCFUSE02 _MMIO(0x116c0) #define LCFUSE_HIV_MASK 0x000000ff -#define CSIPLL0 0x12c10 -#define DDRMPLL1 0X12c20 -#define PEG_BAND_GAP_DATA 0x14d68 +#define CSIPLL0 _MMIO(0x12c10) +#define DDRMPLL1 _MMIO(0X12c20) +#define PEG_BAND_GAP_DATA _MMIO(0x14d68) -#define GEN6_GT_THREAD_STATUS_REG 0x13805c +#define GEN6_GT_THREAD_STATUS_REG _MMIO(0x13805c) #define GEN6_GT_THREAD_STATUS_CORE_MASK 0x7 -#define GEN6_GT_PERF_STATUS (MCHBAR_MIRROR_BASE_SNB + 0x5948) -#define BXT_GT_PERF_STATUS (MCHBAR_MIRROR_BASE_SNB + 0x7070) -#define GEN6_RP_STATE_LIMITS (MCHBAR_MIRROR_BASE_SNB + 0x5994) -#define GEN6_RP_STATE_CAP (MCHBAR_MIRROR_BASE_SNB + 0x5998) -#define BXT_RP_STATE_CAP 0x138170 +#define GEN6_GT_PERF_STATUS _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5948) +#define BXT_GT_PERF_STATUS _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x7070) +#define GEN6_RP_STATE_LIMITS _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5994) +#define GEN6_RP_STATE_CAP _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5998) +#define BXT_RP_STATE_CAP _MMIO(0x138170) #define INTERVAL_1_28_US(us) (((us) * 100) >> 7) #define INTERVAL_1_33_US(us) (((us) * 3) >> 2) @@ -2850,7 +2910,7 @@ enum skl_disp_power_wells { /* * Logical Context regs */ -#define CCID 0x2180 +#define CCID _MMIO(0x2180) #define CCID_EN (1<<0) /* * Notes on SNB/IVB/VLV context size: @@ -2865,7 +2925,7 @@ enum skl_disp_power_wells { * - GT1 size just indicates how much of render context * doesn't need saving on GT1 */ -#define CXT_SIZE 0x21a0 +#define CXT_SIZE _MMIO(0x21a0) #define GEN6_CXT_POWER_SIZE(cxt_reg) (((cxt_reg) >> 24) & 0x3f) #define GEN6_CXT_RING_SIZE(cxt_reg) (((cxt_reg) >> 18) & 0x3f) #define GEN6_CXT_RENDER_SIZE(cxt_reg) (((cxt_reg) >> 12) & 0x3f) @@ -2874,7 +2934,7 @@ enum skl_disp_power_wells { #define GEN6_CXT_TOTAL_SIZE(cxt_reg) (GEN6_CXT_RING_SIZE(cxt_reg) + \ GEN6_CXT_EXTENDED_SIZE(cxt_reg) + \ GEN6_CXT_PIPELINE_SIZE(cxt_reg)) -#define GEN7_CXT_SIZE 0x21a8 +#define GEN7_CXT_SIZE _MMIO(0x21a8) #define GEN7_CXT_POWER_SIZE(ctx_reg) (((ctx_reg) >> 25) & 0x7f) #define GEN7_CXT_RING_SIZE(ctx_reg) (((ctx_reg) >> 22) & 0x7) #define GEN7_CXT_RENDER_SIZE(ctx_reg) (((ctx_reg) >> 16) & 0x3f) @@ -2894,23 +2954,30 @@ enum skl_disp_power_wells { /* Same as Haswell, but 72064 bytes now. */ #define GEN8_CXT_TOTAL_SIZE (18 * PAGE_SIZE) -#define CHV_CLK_CTL1 0x101100 -#define VLV_CLK_CTL2 0x101104 +#define CHV_CLK_CTL1 _MMIO(0x101100) +#define VLV_CLK_CTL2 _MMIO(0x101104) #define CLK_CTL2_CZCOUNT_30NS_SHIFT 28 /* * Overlay regs */ -#define OVADD 0x30000 -#define DOVSTA 0x30008 +#define OVADD _MMIO(0x30000) +#define DOVSTA _MMIO(0x30008) #define OC_BUF (0x3<<20) -#define OGAMC5 0x30010 -#define OGAMC4 0x30014 -#define OGAMC3 0x30018 -#define OGAMC2 0x3001c -#define OGAMC1 0x30020 -#define OGAMC0 0x30024 +#define OGAMC5 _MMIO(0x30010) +#define OGAMC4 _MMIO(0x30014) +#define OGAMC3 _MMIO(0x30018) +#define OGAMC2 _MMIO(0x3001c) +#define OGAMC1 _MMIO(0x30020) +#define OGAMC0 _MMIO(0x30024) + +/* + * GEN9 clock gating regs + */ +#define GEN9_CLKGATE_DIS_0 _MMIO(0x46530) +#define PWM2_GATING_DIS (1 << 14) +#define PWM1_GATING_DIS (1 << 13) /* * Display engine regs @@ -2970,28 +3037,18 @@ enum skl_disp_power_wells { #define _PIPE_CRC_RES_4_B_IVB 0x61070 #define _PIPE_CRC_RES_5_B_IVB 0x61074 -#define PIPE_CRC_CTL(pipe) _TRANSCODER2(pipe, _PIPE_CRC_CTL_A) -#define PIPE_CRC_RES_1_IVB(pipe) \ - _TRANSCODER2(pipe, _PIPE_CRC_RES_1_A_IVB) -#define PIPE_CRC_RES_2_IVB(pipe) \ - _TRANSCODER2(pipe, _PIPE_CRC_RES_2_A_IVB) -#define PIPE_CRC_RES_3_IVB(pipe) \ - _TRANSCODER2(pipe, _PIPE_CRC_RES_3_A_IVB) -#define PIPE_CRC_RES_4_IVB(pipe) \ - _TRANSCODER2(pipe, _PIPE_CRC_RES_4_A_IVB) -#define PIPE_CRC_RES_5_IVB(pipe) \ - _TRANSCODER2(pipe, _PIPE_CRC_RES_5_A_IVB) - -#define PIPE_CRC_RES_RED(pipe) \ - _TRANSCODER2(pipe, _PIPE_CRC_RES_RED_A) -#define PIPE_CRC_RES_GREEN(pipe) \ - _TRANSCODER2(pipe, _PIPE_CRC_RES_GREEN_A) -#define PIPE_CRC_RES_BLUE(pipe) \ - _TRANSCODER2(pipe, _PIPE_CRC_RES_BLUE_A) -#define PIPE_CRC_RES_RES1_I915(pipe) \ - _TRANSCODER2(pipe, _PIPE_CRC_RES_RES1_A_I915) -#define PIPE_CRC_RES_RES2_G4X(pipe) \ - _TRANSCODER2(pipe, _PIPE_CRC_RES_RES2_A_G4X) +#define PIPE_CRC_CTL(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_CTL_A) +#define PIPE_CRC_RES_1_IVB(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_1_A_IVB) +#define PIPE_CRC_RES_2_IVB(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_2_A_IVB) +#define PIPE_CRC_RES_3_IVB(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_3_A_IVB) +#define PIPE_CRC_RES_4_IVB(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_4_A_IVB) +#define PIPE_CRC_RES_5_IVB(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_5_A_IVB) + +#define PIPE_CRC_RES_RED(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_RED_A) +#define PIPE_CRC_RES_GREEN(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_GREEN_A) +#define PIPE_CRC_RES_BLUE(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_BLUE_A) +#define PIPE_CRC_RES_RES1_I915(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_RES1_A_I915) +#define PIPE_CRC_RES_RES2_G4X(pipe) _MMIO_TRANS2(pipe, _PIPE_CRC_RES_RES2_A_G4X) /* Pipe A timing regs */ #define _HTOTAL_A 0x60000 @@ -3023,20 +3080,20 @@ enum skl_disp_power_wells { #define CHV_TRANSCODER_C_OFFSET 0x63000 #define TRANSCODER_EDP_OFFSET 0x6f000 -#define _TRANSCODER2(pipe, reg) (dev_priv->info.trans_offsets[(pipe)] - \ +#define _MMIO_TRANS2(pipe, reg) _MMIO(dev_priv->info.trans_offsets[(pipe)] - \ dev_priv->info.trans_offsets[TRANSCODER_A] + (reg) + \ dev_priv->info.display_mmio_offset) -#define HTOTAL(trans) _TRANSCODER2(trans, _HTOTAL_A) -#define HBLANK(trans) _TRANSCODER2(trans, _HBLANK_A) -#define HSYNC(trans) _TRANSCODER2(trans, _HSYNC_A) -#define VTOTAL(trans) _TRANSCODER2(trans, _VTOTAL_A) -#define VBLANK(trans) _TRANSCODER2(trans, _VBLANK_A) -#define VSYNC(trans) _TRANSCODER2(trans, _VSYNC_A) -#define BCLRPAT(trans) _TRANSCODER2(trans, _BCLRPAT_A) -#define VSYNCSHIFT(trans) _TRANSCODER2(trans, _VSYNCSHIFT_A) -#define PIPESRC(trans) _TRANSCODER2(trans, _PIPEASRC) -#define PIPE_MULT(trans) _TRANSCODER2(trans, _PIPE_MULT_A) +#define HTOTAL(trans) _MMIO_TRANS2(trans, _HTOTAL_A) +#define HBLANK(trans) _MMIO_TRANS2(trans, _HBLANK_A) +#define HSYNC(trans) _MMIO_TRANS2(trans, _HSYNC_A) +#define VTOTAL(trans) _MMIO_TRANS2(trans, _VTOTAL_A) +#define VBLANK(trans) _MMIO_TRANS2(trans, _VBLANK_A) +#define VSYNC(trans) _MMIO_TRANS2(trans, _VSYNC_A) +#define BCLRPAT(trans) _MMIO_TRANS2(trans, _BCLRPAT_A) +#define VSYNCSHIFT(trans) _MMIO_TRANS2(trans, _VSYNCSHIFT_A) +#define PIPESRC(trans) _MMIO_TRANS2(trans, _PIPEASRC) +#define PIPE_MULT(trans) _MMIO_TRANS2(trans, _PIPE_MULT_A) /* VLV eDP PSR registers */ #define _PSRCTLA (VLV_DISPLAY_BASE + 0x60090) @@ -3052,14 +3109,14 @@ enum skl_disp_power_wells { #define VLV_EDP_PSR_DBL_FRAME (1<<10) #define VLV_EDP_PSR_FRAME_COUNT_MASK (0xff<<16) #define VLV_EDP_PSR_IDLE_FRAME_SHIFT 16 -#define VLV_PSRCTL(pipe) _PIPE(pipe, _PSRCTLA, _PSRCTLB) +#define VLV_PSRCTL(pipe) _MMIO_PIPE(pipe, _PSRCTLA, _PSRCTLB) #define _VSCSDPA (VLV_DISPLAY_BASE + 0x600a0) #define _VSCSDPB (VLV_DISPLAY_BASE + 0x610a0) #define VLV_EDP_PSR_SDP_FREQ_MASK (3<<30) #define VLV_EDP_PSR_SDP_FREQ_ONCE (1<<31) #define VLV_EDP_PSR_SDP_FREQ_EVFRAME (1<<30) -#define VLV_VSCSDP(pipe) _PIPE(pipe, _VSCSDPA, _VSCSDPB) +#define VLV_VSCSDP(pipe) _MMIO_PIPE(pipe, _VSCSDPA, _VSCSDPB) #define _PSRSTATA (VLV_DISPLAY_BASE + 0x60094) #define _PSRSTATB (VLV_DISPLAY_BASE + 0x61094) @@ -3072,11 +3129,12 @@ enum skl_disp_power_wells { #define VLV_EDP_PSR_ACTIVE_SF_UPDATE (4<<0) #define VLV_EDP_PSR_EXIT (5<<0) #define VLV_EDP_PSR_IN_TRANS (1<<7) -#define VLV_PSRSTAT(pipe) _PIPE(pipe, _PSRSTATA, _PSRSTATB) +#define VLV_PSRSTAT(pipe) _MMIO_PIPE(pipe, _PSRSTATA, _PSRSTATB) /* HSW+ eDP PSR registers */ -#define EDP_PSR_BASE(dev) (IS_HASWELL(dev) ? 0x64800 : 0x6f800) -#define EDP_PSR_CTL(dev) (EDP_PSR_BASE(dev) + 0) +#define HSW_EDP_PSR_BASE 0x64800 +#define BDW_EDP_PSR_BASE 0x6f800 +#define EDP_PSR_CTL _MMIO(dev_priv->psr_mmio_base + 0) #define EDP_PSR_ENABLE (1<<31) #define BDW_PSR_SINGLE_FRAME (1<<30) #define EDP_PSR_LINK_STANDBY (1<<27) @@ -3099,14 +3157,10 @@ enum skl_disp_power_wells { #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_DATA2(dev) (EDP_PSR_BASE(dev) + 0x18) -#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_CTL _MMIO(dev_priv->psr_mmio_base + 0x10) +#define EDP_PSR_AUX_DATA(i) _MMIO(dev_priv->psr_mmio_base + 0x14 + (i) * 4) /* 5 registers */ -#define EDP_PSR_STATUS_CTL(dev) (EDP_PSR_BASE(dev) + 0x40) +#define EDP_PSR_STATUS_CTL _MMIO(dev_priv->psr_mmio_base + 0x40) #define EDP_PSR_STATUS_STATE_MASK (7<<29) #define EDP_PSR_STATUS_STATE_IDLE (0<<29) #define EDP_PSR_STATUS_STATE_SRDONACK (1<<29) @@ -3130,15 +3184,15 @@ enum skl_disp_power_wells { #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 _MMIO(dev_priv->psr_mmio_base + 0x44) #define EDP_PSR_PERF_CNT_MASK 0xffffff -#define EDP_PSR_DEBUG_CTL(dev) (EDP_PSR_BASE(dev) + 0x60) +#define EDP_PSR_DEBUG_CTL _MMIO(dev_priv->psr_mmio_base + 0x60) #define EDP_PSR_DEBUG_MASK_LPSP (1<<27) #define EDP_PSR_DEBUG_MASK_MEMUP (1<<26) #define EDP_PSR_DEBUG_MASK_HPD (1<<25) -#define EDP_PSR2_CTL 0x6f900 +#define EDP_PSR2_CTL _MMIO(0x6f900) #define EDP_PSR2_ENABLE (1<<31) #define EDP_SU_TRACK_ENABLE (1<<30) #define EDP_MAX_SU_DISABLE_TIME(t) ((t)<<20) @@ -3153,9 +3207,9 @@ enum skl_disp_power_wells { #define EDP_PSR2_IDLE_MASK 0xf /* VGA port control */ -#define ADPA 0x61100 -#define PCH_ADPA 0xe1100 -#define VLV_ADPA (VLV_DISPLAY_BASE + ADPA) +#define ADPA _MMIO(0x61100) +#define PCH_ADPA _MMIO(0xe1100) +#define VLV_ADPA _MMIO(VLV_DISPLAY_BASE + 0x61100) #define ADPA_DAC_ENABLE (1<<31) #define ADPA_DAC_DISABLE 0 @@ -3201,7 +3255,7 @@ enum skl_disp_power_wells { /* Hotplug control (945+ only) */ -#define PORT_HOTPLUG_EN (dev_priv->info.display_mmio_offset + 0x61110) +#define PORT_HOTPLUG_EN _MMIO(dev_priv->info.display_mmio_offset + 0x61110) #define PORTB_HOTPLUG_INT_EN (1 << 29) #define PORTC_HOTPLUG_INT_EN (1 << 28) #define PORTD_HOTPLUG_INT_EN (1 << 27) @@ -3231,21 +3285,22 @@ enum skl_disp_power_wells { #define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2) #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) -#define PORT_HOTPLUG_STAT (dev_priv->info.display_mmio_offset + 0x61114) +#define PORT_HOTPLUG_STAT _MMIO(dev_priv->info.display_mmio_offset + 0x61114) /* - * HDMI/DP bits are gen4+ + * HDMI/DP bits are g4x+ * * WARNING: Bspec for hpd status bits on gen4 seems to be completely confused. * Please check the detailed lore in the commit message for for experimental * evidence. */ -#define PORTD_HOTPLUG_LIVE_STATUS_G4X (1 << 29) +/* Bspec says GM45 should match G4X/VLV/CHV, but reality disagrees */ +#define PORTD_HOTPLUG_LIVE_STATUS_GM45 (1 << 29) +#define PORTC_HOTPLUG_LIVE_STATUS_GM45 (1 << 28) +#define PORTB_HOTPLUG_LIVE_STATUS_GM45 (1 << 27) +/* G4X/VLV/CHV DP/HDMI bits again match Bspec */ +#define PORTD_HOTPLUG_LIVE_STATUS_G4X (1 << 27) #define PORTC_HOTPLUG_LIVE_STATUS_G4X (1 << 28) -#define PORTB_HOTPLUG_LIVE_STATUS_G4X (1 << 27) -/* VLV DP/HDMI bits again match Bspec */ -#define PORTD_HOTPLUG_LIVE_STATUS_VLV (1 << 27) -#define PORTC_HOTPLUG_LIVE_STATUS_VLV (1 << 28) -#define PORTB_HOTPLUG_LIVE_STATUS_VLV (1 << 29) +#define PORTB_HOTPLUG_LIVE_STATUS_G4X (1 << 29) #define PORTD_HOTPLUG_INT_STATUS (3 << 21) #define PORTD_HOTPLUG_INT_LONG_PULSE (2 << 21) #define PORTD_HOTPLUG_INT_SHORT_PULSE (1 << 21) @@ -3296,21 +3351,23 @@ enum skl_disp_power_wells { /* SDVO and HDMI port control. * The same register may be used for SDVO or HDMI */ -#define GEN3_SDVOB 0x61140 -#define GEN3_SDVOC 0x61160 +#define _GEN3_SDVOB 0x61140 +#define _GEN3_SDVOC 0x61160 +#define GEN3_SDVOB _MMIO(_GEN3_SDVOB) +#define GEN3_SDVOC _MMIO(_GEN3_SDVOC) #define GEN4_HDMIB GEN3_SDVOB #define GEN4_HDMIC GEN3_SDVOC -#define VLV_HDMIB (VLV_DISPLAY_BASE + GEN4_HDMIB) -#define VLV_HDMIC (VLV_DISPLAY_BASE + GEN4_HDMIC) -#define CHV_HDMID (VLV_DISPLAY_BASE + 0x6116C) -#define PCH_SDVOB 0xe1140 +#define VLV_HDMIB _MMIO(VLV_DISPLAY_BASE + 0x61140) +#define VLV_HDMIC _MMIO(VLV_DISPLAY_BASE + 0x61160) +#define CHV_HDMID _MMIO(VLV_DISPLAY_BASE + 0x6116C) +#define PCH_SDVOB _MMIO(0xe1140) #define PCH_HDMIB PCH_SDVOB -#define PCH_HDMIC 0xe1150 -#define PCH_HDMID 0xe1160 +#define PCH_HDMIC _MMIO(0xe1150) +#define PCH_HDMID _MMIO(0xe1160) -#define PORT_DFT_I9XX 0x61150 +#define PORT_DFT_I9XX _MMIO(0x61150) #define DC_BALANCE_RESET (1 << 25) -#define PORT_DFT2_G4X (dev_priv->info.display_mmio_offset + 0x61154) +#define PORT_DFT2_G4X _MMIO(dev_priv->info.display_mmio_offset + 0x61154) #define DC_BALANCE_RESET_VLV (1 << 31) #define PIPE_SCRAMBLE_RESET_MASK ((1 << 14) | (0x3 << 0)) #define PIPE_C_SCRAMBLE_RESET (1 << 14) /* chv */ @@ -3370,9 +3427,12 @@ enum skl_disp_power_wells { /* DVO port control */ -#define DVOA 0x61120 -#define DVOB 0x61140 -#define DVOC 0x61160 +#define _DVOA 0x61120 +#define DVOA _MMIO(_DVOA) +#define _DVOB 0x61140 +#define DVOB _MMIO(_DVOB) +#define _DVOC 0x61160 +#define DVOC _MMIO(_DVOC) #define DVO_ENABLE (1 << 31) #define DVO_PIPE_B_SELECT (1 << 30) #define DVO_PIPE_STALL_UNUSED (0 << 28) @@ -3397,14 +3457,14 @@ enum skl_disp_power_wells { #define DVO_OUTPUT_CSTATE_PIXELS (1 << 1) /* SDG only */ #define DVO_OUTPUT_SOURCE_SIZE_PIXELS (1 << 0) /* SDG only */ #define DVO_PRESERVE_MASK (0x7<<24) -#define DVOA_SRCDIM 0x61124 -#define DVOB_SRCDIM 0x61144 -#define DVOC_SRCDIM 0x61164 +#define DVOA_SRCDIM _MMIO(0x61124) +#define DVOB_SRCDIM _MMIO(0x61144) +#define DVOC_SRCDIM _MMIO(0x61164) #define DVO_SRCDIM_HORIZONTAL_SHIFT 12 #define DVO_SRCDIM_VERTICAL_SHIFT 0 /* LVDS port control */ -#define LVDS 0x61180 +#define LVDS _MMIO(0x61180) /* * Enables the LVDS port. This bit must be set before DPLLs are enabled, as * the DPLL semantics change when the LVDS is assigned to that pipe. @@ -3454,13 +3514,13 @@ enum skl_disp_power_wells { #define LVDS_B0B3_POWER_UP (3 << 2) /* Video Data Island Packet control */ -#define VIDEO_DIP_DATA 0x61178 +#define VIDEO_DIP_DATA _MMIO(0x61178) /* Read the description of VIDEO_DIP_DATA (before Haswell) or VIDEO_DIP_ECC * (Haswell and newer) to see which VIDEO_DIP_DATA byte corresponds to each byte * of the infoframe structure specified by CEA-861. */ #define VIDEO_DIP_DATA_SIZE 32 #define VIDEO_DIP_VSC_DATA_SIZE 36 -#define VIDEO_DIP_CTL 0x61170 +#define VIDEO_DIP_CTL _MMIO(0x61170) /* Pre HSW: */ #define VIDEO_DIP_ENABLE (1 << 31) #define VIDEO_DIP_PORT(port) ((port) << 29) @@ -3487,7 +3547,7 @@ enum skl_disp_power_wells { #define VIDEO_DIP_ENABLE_SPD_HSW (1 << 0) /* Panel power sequencing */ -#define PP_STATUS 0x61200 +#define PP_STATUS _MMIO(0x61200) #define PP_ON (1 << 31) /* * Indicates that all dependencies of the panel are on: @@ -3513,14 +3573,14 @@ enum skl_disp_power_wells { #define PP_SEQUENCE_STATE_ON_S1_2 (0xa << 0) #define PP_SEQUENCE_STATE_ON_S1_3 (0xb << 0) #define PP_SEQUENCE_STATE_RESET (0xf << 0) -#define PP_CONTROL 0x61204 +#define PP_CONTROL _MMIO(0x61204) #define POWER_TARGET_ON (1 << 0) -#define PP_ON_DELAYS 0x61208 -#define PP_OFF_DELAYS 0x6120c -#define PP_DIVISOR 0x61210 +#define PP_ON_DELAYS _MMIO(0x61208) +#define PP_OFF_DELAYS _MMIO(0x6120c) +#define PP_DIVISOR _MMIO(0x61210) /* Panel fitting */ -#define PFIT_CONTROL (dev_priv->info.display_mmio_offset + 0x61230) +#define PFIT_CONTROL _MMIO(dev_priv->info.display_mmio_offset + 0x61230) #define PFIT_ENABLE (1 << 31) #define PFIT_PIPE_MASK (3 << 29) #define PFIT_PIPE_SHIFT 29 @@ -3538,7 +3598,7 @@ enum skl_disp_power_wells { #define PFIT_SCALING_PROGRAMMED (1 << 26) #define PFIT_SCALING_PILLAR (2 << 26) #define PFIT_SCALING_LETTER (3 << 26) -#define PFIT_PGM_RATIOS (dev_priv->info.display_mmio_offset + 0x61234) +#define PFIT_PGM_RATIOS _MMIO(dev_priv->info.display_mmio_offset + 0x61234) /* Pre-965 */ #define PFIT_VERT_SCALE_SHIFT 20 #define PFIT_VERT_SCALE_MASK 0xfff00000 @@ -3550,25 +3610,25 @@ enum skl_disp_power_wells { #define PFIT_HORIZ_SCALE_SHIFT_965 0 #define PFIT_HORIZ_SCALE_MASK_965 0x00001fff -#define PFIT_AUTO_RATIOS (dev_priv->info.display_mmio_offset + 0x61238) +#define PFIT_AUTO_RATIOS _MMIO(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_CTL2(pipe) _MMIO_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_PWM_CTL(pipe) _MMIO_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) +#define VLV_BLC_HIST_CTL(pipe) _MMIO_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 BLC_PWM_CTL2 _MMIO(dev_priv->info.display_mmio_offset + 0x61250) /* 965+ only */ #define BLM_PWM_ENABLE (1 << 31) #define BLM_COMBINATION_MODE (1 << 30) /* gen4 only */ #define BLM_PIPE_SELECT (1 << 29) @@ -3591,7 +3651,7 @@ enum skl_disp_power_wells { #define BLM_PHASE_IN_COUNT_MASK (0xff << 8) #define BLM_PHASE_IN_INCR_SHIFT (0) #define BLM_PHASE_IN_INCR_MASK (0xff << 0) -#define BLC_PWM_CTL (dev_priv->info.display_mmio_offset + 0x61254) +#define BLC_PWM_CTL _MMIO(dev_priv->info.display_mmio_offset + 0x61254) /* * This is the most significant 15 bits of the number of backlight cycles in a * complete cycle of the modulated backlight control. @@ -3613,25 +3673,25 @@ enum skl_disp_power_wells { #define BACKLIGHT_DUTY_CYCLE_MASK_PNV (0xfffe) #define BLM_POLARITY_PNV (1 << 0) /* pnv only */ -#define BLC_HIST_CTL (dev_priv->info.display_mmio_offset + 0x61260) +#define BLC_HIST_CTL _MMIO(dev_priv->info.display_mmio_offset + 0x61260) #define BLM_HISTOGRAM_ENABLE (1 << 31) /* New registers for PCH-split platforms. Safe where new bits show up, the * register layout machtes with gen4 BLC_PWM_CTL[12]. */ -#define BLC_PWM_CPU_CTL2 0x48250 -#define BLC_PWM_CPU_CTL 0x48254 +#define BLC_PWM_CPU_CTL2 _MMIO(0x48250) +#define BLC_PWM_CPU_CTL _MMIO(0x48254) -#define HSW_BLC_PWM2_CTL 0x48350 +#define HSW_BLC_PWM2_CTL _MMIO(0x48350) /* PCH CTL1 is totally different, all but the below bits are reserved. CTL2 is * like the normal CTL from gen4 and earlier. Hooray for confusing naming. */ -#define BLC_PWM_PCH_CTL1 0xc8250 +#define BLC_PWM_PCH_CTL1 _MMIO(0xc8250) #define BLM_PCH_PWM_ENABLE (1 << 31) #define BLM_PCH_OVERRIDE_ENABLE (1 << 30) #define BLM_PCH_POLARITY (1 << 29) -#define BLC_PWM_PCH_CTL2 0xc8254 +#define BLC_PWM_PCH_CTL2 _MMIO(0xc8254) -#define UTIL_PIN_CTL 0x48400 +#define UTIL_PIN_CTL _MMIO(0x48400) #define UTIL_PIN_ENABLE (1 << 31) #define UTIL_PIN_PIPE(x) ((x) << 29) @@ -3651,18 +3711,18 @@ enum skl_disp_power_wells { #define _BXT_BLC_PWM_FREQ2 0xC8354 #define _BXT_BLC_PWM_DUTY2 0xC8358 -#define BXT_BLC_PWM_CTL(controller) _PIPE(controller, \ +#define BXT_BLC_PWM_CTL(controller) _MMIO_PIPE(controller, \ _BXT_BLC_PWM_CTL1, _BXT_BLC_PWM_CTL2) -#define BXT_BLC_PWM_FREQ(controller) _PIPE(controller, \ +#define BXT_BLC_PWM_FREQ(controller) _MMIO_PIPE(controller, \ _BXT_BLC_PWM_FREQ1, _BXT_BLC_PWM_FREQ2) -#define BXT_BLC_PWM_DUTY(controller) _PIPE(controller, \ +#define BXT_BLC_PWM_DUTY(controller) _MMIO_PIPE(controller, \ _BXT_BLC_PWM_DUTY1, _BXT_BLC_PWM_DUTY2) -#define PCH_GTC_CTL 0xe7000 +#define PCH_GTC_CTL _MMIO(0xe7000) #define PCH_GTC_ENABLE (1 << 31) /* TV port control */ -#define TV_CTL 0x68000 +#define TV_CTL _MMIO(0x68000) /* Enables the TV encoder */ # define TV_ENC_ENABLE (1 << 31) /* Sources the TV encoder input from pipe B instead of A. */ @@ -3729,7 +3789,7 @@ enum skl_disp_power_wells { # define TV_TEST_MODE_MONITOR_DETECT (7 << 0) # define TV_TEST_MODE_MASK (7 << 0) -#define TV_DAC 0x68004 +#define TV_DAC _MMIO(0x68004) # define TV_DAC_SAVE 0x00ffff00 /* * Reports that DAC state change logic has reported change (RO). @@ -3780,13 +3840,13 @@ enum skl_disp_power_wells { * where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with * -1 (0x3) being the only legal negative value. */ -#define TV_CSC_Y 0x68010 +#define TV_CSC_Y _MMIO(0x68010) # define TV_RY_MASK 0x07ff0000 # define TV_RY_SHIFT 16 # define TV_GY_MASK 0x00000fff # define TV_GY_SHIFT 0 -#define TV_CSC_Y2 0x68014 +#define TV_CSC_Y2 _MMIO(0x68014) # define TV_BY_MASK 0x07ff0000 # define TV_BY_SHIFT 16 /* @@ -3797,13 +3857,13 @@ enum skl_disp_power_wells { # define TV_AY_MASK 0x000003ff # define TV_AY_SHIFT 0 -#define TV_CSC_U 0x68018 +#define TV_CSC_U _MMIO(0x68018) # define TV_RU_MASK 0x07ff0000 # define TV_RU_SHIFT 16 # define TV_GU_MASK 0x000007ff # define TV_GU_SHIFT 0 -#define TV_CSC_U2 0x6801c +#define TV_CSC_U2 _MMIO(0x6801c) # define TV_BU_MASK 0x07ff0000 # define TV_BU_SHIFT 16 /* @@ -3814,13 +3874,13 @@ enum skl_disp_power_wells { # define TV_AU_MASK 0x000003ff # define TV_AU_SHIFT 0 -#define TV_CSC_V 0x68020 +#define TV_CSC_V _MMIO(0x68020) # define TV_RV_MASK 0x0fff0000 # define TV_RV_SHIFT 16 # define TV_GV_MASK 0x000007ff # define TV_GV_SHIFT 0 -#define TV_CSC_V2 0x68024 +#define TV_CSC_V2 _MMIO(0x68024) # define TV_BV_MASK 0x07ff0000 # define TV_BV_SHIFT 16 /* @@ -3831,7 +3891,7 @@ enum skl_disp_power_wells { # define TV_AV_MASK 0x000007ff # define TV_AV_SHIFT 0 -#define TV_CLR_KNOBS 0x68028 +#define TV_CLR_KNOBS _MMIO(0x68028) /* 2s-complement brightness adjustment */ # define TV_BRIGHTNESS_MASK 0xff000000 # define TV_BRIGHTNESS_SHIFT 24 @@ -3845,7 +3905,7 @@ enum skl_disp_power_wells { # define TV_HUE_MASK 0x000000ff # define TV_HUE_SHIFT 0 -#define TV_CLR_LEVEL 0x6802c +#define TV_CLR_LEVEL _MMIO(0x6802c) /* Controls the DAC level for black */ # define TV_BLACK_LEVEL_MASK 0x01ff0000 # define TV_BLACK_LEVEL_SHIFT 16 @@ -3853,7 +3913,7 @@ enum skl_disp_power_wells { # define TV_BLANK_LEVEL_MASK 0x000001ff # define TV_BLANK_LEVEL_SHIFT 0 -#define TV_H_CTL_1 0x68030 +#define TV_H_CTL_1 _MMIO(0x68030) /* Number of pixels in the hsync. */ # define TV_HSYNC_END_MASK 0x1fff0000 # define TV_HSYNC_END_SHIFT 16 @@ -3861,7 +3921,7 @@ enum skl_disp_power_wells { # define TV_HTOTAL_MASK 0x00001fff # define TV_HTOTAL_SHIFT 0 -#define TV_H_CTL_2 0x68034 +#define TV_H_CTL_2 _MMIO(0x68034) /* Enables the colorburst (needed for non-component color) */ # define TV_BURST_ENA (1 << 31) /* Offset of the colorburst from the start of hsync, in pixels minus one. */ @@ -3871,7 +3931,7 @@ enum skl_disp_power_wells { # define TV_HBURST_LEN_SHIFT 0 # define TV_HBURST_LEN_MASK 0x0001fff -#define TV_H_CTL_3 0x68038 +#define TV_H_CTL_3 _MMIO(0x68038) /* End of hblank, measured in pixels minus one from start of hsync */ # define TV_HBLANK_END_SHIFT 16 # define TV_HBLANK_END_MASK 0x1fff0000 @@ -3879,7 +3939,7 @@ enum skl_disp_power_wells { # define TV_HBLANK_START_SHIFT 0 # define TV_HBLANK_START_MASK 0x0001fff -#define TV_V_CTL_1 0x6803c +#define TV_V_CTL_1 _MMIO(0x6803c) /* XXX */ # define TV_NBR_END_SHIFT 16 # define TV_NBR_END_MASK 0x07ff0000 @@ -3890,7 +3950,7 @@ enum skl_disp_power_wells { # define TV_VI_END_F2_SHIFT 0 # define TV_VI_END_F2_MASK 0x0000003f -#define TV_V_CTL_2 0x68040 +#define TV_V_CTL_2 _MMIO(0x68040) /* Length of vsync, in half lines */ # define TV_VSYNC_LEN_MASK 0x07ff0000 # define TV_VSYNC_LEN_SHIFT 16 @@ -3906,7 +3966,7 @@ enum skl_disp_power_wells { # define TV_VSYNC_START_F2_MASK 0x0000007f # define TV_VSYNC_START_F2_SHIFT 0 -#define TV_V_CTL_3 0x68044 +#define TV_V_CTL_3 _MMIO(0x68044) /* Enables generation of the equalization signal */ # define TV_EQUAL_ENA (1 << 31) /* Length of vsync, in half lines */ @@ -3924,7 +3984,7 @@ enum skl_disp_power_wells { # define TV_VEQ_START_F2_MASK 0x000007f # define TV_VEQ_START_F2_SHIFT 0 -#define TV_V_CTL_4 0x68048 +#define TV_V_CTL_4 _MMIO(0x68048) /* * Offset to start of vertical colorburst, measured in one less than the * number of lines from vertical start. @@ -3938,7 +3998,7 @@ enum skl_disp_power_wells { # define TV_VBURST_END_F1_MASK 0x000000ff # define TV_VBURST_END_F1_SHIFT 0 -#define TV_V_CTL_5 0x6804c +#define TV_V_CTL_5 _MMIO(0x6804c) /* * Offset to start of vertical colorburst, measured in one less than the * number of lines from vertical start. @@ -3952,7 +4012,7 @@ enum skl_disp_power_wells { # define TV_VBURST_END_F2_MASK 0x000000ff # define TV_VBURST_END_F2_SHIFT 0 -#define TV_V_CTL_6 0x68050 +#define TV_V_CTL_6 _MMIO(0x68050) /* * Offset to start of vertical colorburst, measured in one less than the * number of lines from vertical start. @@ -3966,7 +4026,7 @@ enum skl_disp_power_wells { # define TV_VBURST_END_F3_MASK 0x000000ff # define TV_VBURST_END_F3_SHIFT 0 -#define TV_V_CTL_7 0x68054 +#define TV_V_CTL_7 _MMIO(0x68054) /* * Offset to start of vertical colorburst, measured in one less than the * number of lines from vertical start. @@ -3980,7 +4040,7 @@ enum skl_disp_power_wells { # define TV_VBURST_END_F4_MASK 0x000000ff # define TV_VBURST_END_F4_SHIFT 0 -#define TV_SC_CTL_1 0x68060 +#define TV_SC_CTL_1 _MMIO(0x68060) /* Turns on the first subcarrier phase generation DDA */ # define TV_SC_DDA1_EN (1 << 31) /* Turns on the first subcarrier phase generation DDA */ @@ -4002,7 +4062,7 @@ enum skl_disp_power_wells { # define TV_SCDDA1_INC_MASK 0x00000fff # define TV_SCDDA1_INC_SHIFT 0 -#define TV_SC_CTL_2 0x68064 +#define TV_SC_CTL_2 _MMIO(0x68064) /* Sets the rollover for the second subcarrier phase generation DDA */ # define TV_SCDDA2_SIZE_MASK 0x7fff0000 # define TV_SCDDA2_SIZE_SHIFT 16 @@ -4010,7 +4070,7 @@ enum skl_disp_power_wells { # define TV_SCDDA2_INC_MASK 0x00007fff # define TV_SCDDA2_INC_SHIFT 0 -#define TV_SC_CTL_3 0x68068 +#define TV_SC_CTL_3 _MMIO(0x68068) /* Sets the rollover for the third subcarrier phase generation DDA */ # define TV_SCDDA3_SIZE_MASK 0x7fff0000 # define TV_SCDDA3_SIZE_SHIFT 16 @@ -4018,7 +4078,7 @@ enum skl_disp_power_wells { # define TV_SCDDA3_INC_MASK 0x00007fff # define TV_SCDDA3_INC_SHIFT 0 -#define TV_WIN_POS 0x68070 +#define TV_WIN_POS _MMIO(0x68070) /* X coordinate of the display from the start of horizontal active */ # define TV_XPOS_MASK 0x1fff0000 # define TV_XPOS_SHIFT 16 @@ -4026,7 +4086,7 @@ enum skl_disp_power_wells { # define TV_YPOS_MASK 0x00000fff # define TV_YPOS_SHIFT 0 -#define TV_WIN_SIZE 0x68074 +#define TV_WIN_SIZE _MMIO(0x68074) /* Horizontal size of the display window, measured in pixels*/ # define TV_XSIZE_MASK 0x1fff0000 # define TV_XSIZE_SHIFT 16 @@ -4038,7 +4098,7 @@ enum skl_disp_power_wells { # define TV_YSIZE_MASK 0x00000fff # define TV_YSIZE_SHIFT 0 -#define TV_FILTER_CTL_1 0x68080 +#define TV_FILTER_CTL_1 _MMIO(0x68080) /* * Enables automatic scaling calculation. * @@ -4071,7 +4131,7 @@ enum skl_disp_power_wells { # define TV_HSCALE_FRAC_MASK 0x00003fff # define TV_HSCALE_FRAC_SHIFT 0 -#define TV_FILTER_CTL_2 0x68084 +#define TV_FILTER_CTL_2 _MMIO(0x68084) /* * Sets the integer part of the 3.15 fixed-point vertical scaling factor. * @@ -4087,7 +4147,7 @@ enum skl_disp_power_wells { # define TV_VSCALE_FRAC_MASK 0x00007fff # define TV_VSCALE_FRAC_SHIFT 0 -#define TV_FILTER_CTL_3 0x68088 +#define TV_FILTER_CTL_3 _MMIO(0x68088) /* * Sets the integer part of the 3.15 fixed-point vertical scaling factor. * @@ -4107,7 +4167,7 @@ enum skl_disp_power_wells { # define TV_VSCALE_IP_FRAC_MASK 0x00007fff # define TV_VSCALE_IP_FRAC_SHIFT 0 -#define TV_CC_CONTROL 0x68090 +#define TV_CC_CONTROL _MMIO(0x68090) # define TV_CC_ENABLE (1 << 31) /* * Specifies which field to send the CC data in. @@ -4123,7 +4183,7 @@ enum skl_disp_power_wells { # define TV_CC_LINE_MASK 0x0000003f # define TV_CC_LINE_SHIFT 0 -#define TV_CC_DATA 0x68094 +#define TV_CC_DATA _MMIO(0x68094) # define TV_CC_RDY (1 << 31) /* Second word of CC data to be transmitted. */ # define TV_CC_DATA_2_MASK 0x007f0000 @@ -4132,20 +4192,20 @@ enum skl_disp_power_wells { # define TV_CC_DATA_1_MASK 0x0000007f # define TV_CC_DATA_1_SHIFT 0 -#define TV_H_LUMA(i) (0x68100 + (i) * 4) /* 60 registers */ -#define TV_H_CHROMA(i) (0x68200 + (i) * 4) /* 60 registers */ -#define TV_V_LUMA(i) (0x68300 + (i) * 4) /* 43 registers */ -#define TV_V_CHROMA(i) (0x68400 + (i) * 4) /* 43 registers */ +#define TV_H_LUMA(i) _MMIO(0x68100 + (i) * 4) /* 60 registers */ +#define TV_H_CHROMA(i) _MMIO(0x68200 + (i) * 4) /* 60 registers */ +#define TV_V_LUMA(i) _MMIO(0x68300 + (i) * 4) /* 43 registers */ +#define TV_V_CHROMA(i) _MMIO(0x68400 + (i) * 4) /* 43 registers */ /* Display Port */ -#define DP_A 0x64000 /* eDP */ -#define DP_B 0x64100 -#define DP_C 0x64200 -#define DP_D 0x64300 +#define DP_A _MMIO(0x64000) /* eDP */ +#define DP_B _MMIO(0x64100) +#define DP_C _MMIO(0x64200) +#define DP_D _MMIO(0x64300) -#define VLV_DP_B (VLV_DISPLAY_BASE + DP_B) -#define VLV_DP_C (VLV_DISPLAY_BASE + DP_C) -#define CHV_DP_D (VLV_DISPLAY_BASE + DP_D) +#define VLV_DP_B _MMIO(VLV_DISPLAY_BASE + 0x64100) +#define VLV_DP_C _MMIO(VLV_DISPLAY_BASE + 0x64200) +#define CHV_DP_D _MMIO(VLV_DISPLAY_BASE + 0x64300) #define DP_PORT_EN (1 << 31) #define DP_PIPEB_SELECT (1 << 30) @@ -4199,7 +4259,7 @@ enum skl_disp_power_wells { /* eDP */ #define DP_PLL_FREQ_270MHZ (0 << 16) -#define DP_PLL_FREQ_160MHZ (1 << 16) +#define DP_PLL_FREQ_162MHZ (1 << 16) #define DP_PLL_FREQ_MASK (3 << 16) /* locked once port is enabled */ @@ -4232,33 +4292,36 @@ enum skl_disp_power_wells { * is 20 bytes in each direction, hence the 5 fixed * data registers */ -#define DPA_AUX_CH_CTL 0x64010 -#define DPA_AUX_CH_DATA1 0x64014 -#define DPA_AUX_CH_DATA2 0x64018 -#define DPA_AUX_CH_DATA3 0x6401c -#define DPA_AUX_CH_DATA4 0x64020 -#define DPA_AUX_CH_DATA5 0x64024 - -#define DPB_AUX_CH_CTL 0x64110 -#define DPB_AUX_CH_DATA1 0x64114 -#define DPB_AUX_CH_DATA2 0x64118 -#define DPB_AUX_CH_DATA3 0x6411c -#define DPB_AUX_CH_DATA4 0x64120 -#define DPB_AUX_CH_DATA5 0x64124 - -#define DPC_AUX_CH_CTL 0x64210 -#define DPC_AUX_CH_DATA1 0x64214 -#define DPC_AUX_CH_DATA2 0x64218 -#define DPC_AUX_CH_DATA3 0x6421c -#define DPC_AUX_CH_DATA4 0x64220 -#define DPC_AUX_CH_DATA5 0x64224 - -#define DPD_AUX_CH_CTL 0x64310 -#define DPD_AUX_CH_DATA1 0x64314 -#define DPD_AUX_CH_DATA2 0x64318 -#define DPD_AUX_CH_DATA3 0x6431c -#define DPD_AUX_CH_DATA4 0x64320 -#define DPD_AUX_CH_DATA5 0x64324 +#define _DPA_AUX_CH_CTL (dev_priv->info.display_mmio_offset + 0x64010) +#define _DPA_AUX_CH_DATA1 (dev_priv->info.display_mmio_offset + 0x64014) +#define _DPA_AUX_CH_DATA2 (dev_priv->info.display_mmio_offset + 0x64018) +#define _DPA_AUX_CH_DATA3 (dev_priv->info.display_mmio_offset + 0x6401c) +#define _DPA_AUX_CH_DATA4 (dev_priv->info.display_mmio_offset + 0x64020) +#define _DPA_AUX_CH_DATA5 (dev_priv->info.display_mmio_offset + 0x64024) + +#define _DPB_AUX_CH_CTL (dev_priv->info.display_mmio_offset + 0x64110) +#define _DPB_AUX_CH_DATA1 (dev_priv->info.display_mmio_offset + 0x64114) +#define _DPB_AUX_CH_DATA2 (dev_priv->info.display_mmio_offset + 0x64118) +#define _DPB_AUX_CH_DATA3 (dev_priv->info.display_mmio_offset + 0x6411c) +#define _DPB_AUX_CH_DATA4 (dev_priv->info.display_mmio_offset + 0x64120) +#define _DPB_AUX_CH_DATA5 (dev_priv->info.display_mmio_offset + 0x64124) + +#define _DPC_AUX_CH_CTL (dev_priv->info.display_mmio_offset + 0x64210) +#define _DPC_AUX_CH_DATA1 (dev_priv->info.display_mmio_offset + 0x64214) +#define _DPC_AUX_CH_DATA2 (dev_priv->info.display_mmio_offset + 0x64218) +#define _DPC_AUX_CH_DATA3 (dev_priv->info.display_mmio_offset + 0x6421c) +#define _DPC_AUX_CH_DATA4 (dev_priv->info.display_mmio_offset + 0x64220) +#define _DPC_AUX_CH_DATA5 (dev_priv->info.display_mmio_offset + 0x64224) + +#define _DPD_AUX_CH_CTL (dev_priv->info.display_mmio_offset + 0x64310) +#define _DPD_AUX_CH_DATA1 (dev_priv->info.display_mmio_offset + 0x64314) +#define _DPD_AUX_CH_DATA2 (dev_priv->info.display_mmio_offset + 0x64318) +#define _DPD_AUX_CH_DATA3 (dev_priv->info.display_mmio_offset + 0x6431c) +#define _DPD_AUX_CH_DATA4 (dev_priv->info.display_mmio_offset + 0x64320) +#define _DPD_AUX_CH_DATA5 (dev_priv->info.display_mmio_offset + 0x64324) + +#define DP_AUX_CH_CTL(port) _MMIO_PORT(port, _DPA_AUX_CH_CTL, _DPB_AUX_CH_CTL) +#define DP_AUX_CH_DATA(port, i) _MMIO(_PORT(port, _DPA_AUX_CH_DATA1, _DPB_AUX_CH_DATA1) + (i) * 4) /* 5 registers */ #define DP_AUX_CH_CTL_SEND_BUSY (1 << 31) #define DP_AUX_CH_CTL_DONE (1 << 30) @@ -4335,10 +4398,10 @@ enum skl_disp_power_wells { #define _PIPEB_LINK_N_G4X 0x71064 #define PIPEA_DP_LINK_N_MASK (0xffffff) -#define PIPE_DATA_M_G4X(pipe) _PIPE(pipe, _PIPEA_DATA_M_G4X, _PIPEB_DATA_M_G4X) -#define PIPE_DATA_N_G4X(pipe) _PIPE(pipe, _PIPEA_DATA_N_G4X, _PIPEB_DATA_N_G4X) -#define PIPE_LINK_M_G4X(pipe) _PIPE(pipe, _PIPEA_LINK_M_G4X, _PIPEB_LINK_M_G4X) -#define PIPE_LINK_N_G4X(pipe) _PIPE(pipe, _PIPEA_LINK_N_G4X, _PIPEB_LINK_N_G4X) +#define PIPE_DATA_M_G4X(pipe) _MMIO_PIPE(pipe, _PIPEA_DATA_M_G4X, _PIPEB_DATA_M_G4X) +#define PIPE_DATA_N_G4X(pipe) _MMIO_PIPE(pipe, _PIPEA_DATA_N_G4X, _PIPEB_DATA_N_G4X) +#define PIPE_LINK_M_G4X(pipe) _MMIO_PIPE(pipe, _PIPEA_LINK_M_G4X, _PIPEB_LINK_M_G4X) +#define PIPE_LINK_N_G4X(pipe) _MMIO_PIPE(pipe, _PIPEA_LINK_N_G4X, _PIPEB_LINK_N_G4X) /* Display & cursor control */ @@ -4454,15 +4517,15 @@ enum skl_disp_power_wells { */ #define PIPE_EDP_OFFSET 0x7f000 -#define _PIPE2(pipe, reg) (dev_priv->info.pipe_offsets[pipe] - \ +#define _MMIO_PIPE2(pipe, reg) _MMIO(dev_priv->info.pipe_offsets[pipe] - \ dev_priv->info.pipe_offsets[PIPE_A] + (reg) + \ dev_priv->info.display_mmio_offset) -#define PIPECONF(pipe) _PIPE2(pipe, _PIPEACONF) -#define PIPEDSL(pipe) _PIPE2(pipe, _PIPEADSL) -#define PIPEFRAME(pipe) _PIPE2(pipe, _PIPEAFRAMEHIGH) -#define PIPEFRAMEPIXEL(pipe) _PIPE2(pipe, _PIPEAFRAMEPIXEL) -#define PIPESTAT(pipe) _PIPE2(pipe, _PIPEASTAT) +#define PIPECONF(pipe) _MMIO_PIPE2(pipe, _PIPEACONF) +#define PIPEDSL(pipe) _MMIO_PIPE2(pipe, _PIPEADSL) +#define PIPEFRAME(pipe) _MMIO_PIPE2(pipe, _PIPEAFRAMEHIGH) +#define PIPEFRAMEPIXEL(pipe) _MMIO_PIPE2(pipe, _PIPEAFRAMEPIXEL) +#define PIPESTAT(pipe) _MMIO_PIPE2(pipe, _PIPEASTAT) #define _PIPE_MISC_A 0x70030 #define _PIPE_MISC_B 0x71030 @@ -4474,9 +4537,9 @@ enum skl_disp_power_wells { #define PIPEMISC_DITHER_ENABLE (1<<4) #define PIPEMISC_DITHER_TYPE_MASK (3<<2) #define PIPEMISC_DITHER_TYPE_SP (0<<2) -#define PIPEMISC(pipe) _PIPE2(pipe, _PIPE_MISC_A) +#define PIPEMISC(pipe) _MMIO_PIPE2(pipe, _PIPE_MISC_A) -#define VLV_DPFLIPSTAT (VLV_DISPLAY_BASE + 0x70028) +#define VLV_DPFLIPSTAT _MMIO(VLV_DISPLAY_BASE + 0x70028) #define PIPEB_LINE_COMPARE_INT_EN (1<<29) #define PIPEB_HLINE_INT_EN (1<<28) #define PIPEB_VBLANK_INT_EN (1<<27) @@ -4497,7 +4560,7 @@ enum skl_disp_power_wells { #define SPRITEE_FLIPDONE_INT_EN (1<<9) #define PLANEC_FLIPDONE_INT_EN (1<<8) -#define DPINVGTT (VLV_DISPLAY_BASE + 0x7002c) /* VLV/CHV only */ +#define DPINVGTT _MMIO(VLV_DISPLAY_BASE + 0x7002c) /* VLV/CHV only */ #define SPRITEF_INVALID_GTT_INT_EN (1<<27) #define SPRITEE_INVALID_GTT_INT_EN (1<<26) #define PLANEC_INVALID_GTT_INT_EN (1<<25) @@ -4527,7 +4590,7 @@ enum skl_disp_power_wells { #define DPINVGTT_STATUS_MASK 0xff #define DPINVGTT_STATUS_MASK_CHV 0xfff -#define DSPARB (dev_priv->info.display_mmio_offset + 0x70030) +#define DSPARB _MMIO(dev_priv->info.display_mmio_offset + 0x70030) #define DSPARB_CSTART_MASK (0x7f << 7) #define DSPARB_CSTART_SHIFT 7 #define DSPARB_BSTART_MASK (0x7f) @@ -4542,7 +4605,7 @@ enum skl_disp_power_wells { #define DSPARB_SPRITEC_MASK_VLV (0xff << 16) #define DSPARB_SPRITED_SHIFT_VLV 24 #define DSPARB_SPRITED_MASK_VLV (0xff << 24) -#define DSPARB2 (VLV_DISPLAY_BASE + 0x70060) /* vlv/chv */ +#define DSPARB2 _MMIO(VLV_DISPLAY_BASE + 0x70060) /* vlv/chv */ #define DSPARB_SPRITEA_HI_SHIFT_VLV 0 #define DSPARB_SPRITEA_HI_MASK_VLV (0x1 << 0) #define DSPARB_SPRITEB_HI_SHIFT_VLV 4 @@ -4555,14 +4618,14 @@ enum skl_disp_power_wells { #define DSPARB_SPRITEE_HI_MASK_VLV (0x1 << 16) #define DSPARB_SPRITEF_HI_SHIFT_VLV 20 #define DSPARB_SPRITEF_HI_MASK_VLV (0x1 << 20) -#define DSPARB3 (VLV_DISPLAY_BASE + 0x7006c) /* chv */ +#define DSPARB3 _MMIO(VLV_DISPLAY_BASE + 0x7006c) /* chv */ #define DSPARB_SPRITEE_SHIFT_VLV 0 #define DSPARB_SPRITEE_MASK_VLV (0xff << 0) #define DSPARB_SPRITEF_SHIFT_VLV 8 #define DSPARB_SPRITEF_MASK_VLV (0xff << 8) /* pnv/gen4/g4x/vlv/chv */ -#define DSPFW1 (dev_priv->info.display_mmio_offset + 0x70034) +#define DSPFW1 _MMIO(dev_priv->info.display_mmio_offset + 0x70034) #define DSPFW_SR_SHIFT 23 #define DSPFW_SR_MASK (0x1ff<<23) #define DSPFW_CURSORB_SHIFT 16 @@ -4573,7 +4636,7 @@ enum skl_disp_power_wells { #define DSPFW_PLANEA_SHIFT 0 #define DSPFW_PLANEA_MASK (0x7f<<0) #define DSPFW_PLANEA_MASK_VLV (0xff<<0) /* vlv/chv */ -#define DSPFW2 (dev_priv->info.display_mmio_offset + 0x70038) +#define DSPFW2 _MMIO(dev_priv->info.display_mmio_offset + 0x70038) #define DSPFW_FBC_SR_EN (1<<31) /* g4x */ #define DSPFW_FBC_SR_SHIFT 28 #define DSPFW_FBC_SR_MASK (0x7<<28) /* g4x */ @@ -4589,7 +4652,7 @@ enum skl_disp_power_wells { #define DSPFW_SPRITEA_SHIFT 0 #define DSPFW_SPRITEA_MASK (0x7f<<0) /* g4x */ #define DSPFW_SPRITEA_MASK_VLV (0xff<<0) /* vlv/chv */ -#define DSPFW3 (dev_priv->info.display_mmio_offset + 0x7003c) +#define DSPFW3 _MMIO(dev_priv->info.display_mmio_offset + 0x7003c) #define DSPFW_HPLL_SR_EN (1<<31) #define PINEVIEW_SELF_REFRESH_EN (1<<30) #define DSPFW_CURSOR_SR_SHIFT 24 @@ -4600,14 +4663,14 @@ enum skl_disp_power_wells { #define DSPFW_HPLL_SR_MASK (0x1ff<<0) /* vlv/chv */ -#define DSPFW4 (VLV_DISPLAY_BASE + 0x70070) +#define DSPFW4 _MMIO(VLV_DISPLAY_BASE + 0x70070) #define DSPFW_SPRITEB_WM1_SHIFT 16 #define DSPFW_SPRITEB_WM1_MASK (0xff<<16) #define DSPFW_CURSORA_WM1_SHIFT 8 #define DSPFW_CURSORA_WM1_MASK (0x3f<<8) #define DSPFW_SPRITEA_WM1_SHIFT 0 #define DSPFW_SPRITEA_WM1_MASK (0xff<<0) -#define DSPFW5 (VLV_DISPLAY_BASE + 0x70074) +#define DSPFW5 _MMIO(VLV_DISPLAY_BASE + 0x70074) #define DSPFW_PLANEB_WM1_SHIFT 24 #define DSPFW_PLANEB_WM1_MASK (0xff<<24) #define DSPFW_PLANEA_WM1_SHIFT 16 @@ -4616,11 +4679,11 @@ enum skl_disp_power_wells { #define DSPFW_CURSORB_WM1_MASK (0x3f<<8) #define DSPFW_CURSOR_SR_WM1_SHIFT 0 #define DSPFW_CURSOR_SR_WM1_MASK (0x3f<<0) -#define DSPFW6 (VLV_DISPLAY_BASE + 0x70078) +#define DSPFW6 _MMIO(VLV_DISPLAY_BASE + 0x70078) #define DSPFW_SR_WM1_SHIFT 0 #define DSPFW_SR_WM1_MASK (0x1ff<<0) -#define DSPFW7 (VLV_DISPLAY_BASE + 0x7007c) -#define DSPFW7_CHV (VLV_DISPLAY_BASE + 0x700b4) /* wtf #1? */ +#define DSPFW7 _MMIO(VLV_DISPLAY_BASE + 0x7007c) +#define DSPFW7_CHV _MMIO(VLV_DISPLAY_BASE + 0x700b4) /* wtf #1? */ #define DSPFW_SPRITED_WM1_SHIFT 24 #define DSPFW_SPRITED_WM1_MASK (0xff<<24) #define DSPFW_SPRITED_SHIFT 16 @@ -4629,7 +4692,7 @@ enum skl_disp_power_wells { #define DSPFW_SPRITEC_WM1_MASK (0xff<<8) #define DSPFW_SPRITEC_SHIFT 0 #define DSPFW_SPRITEC_MASK_VLV (0xff<<0) -#define DSPFW8_CHV (VLV_DISPLAY_BASE + 0x700b8) +#define DSPFW8_CHV _MMIO(VLV_DISPLAY_BASE + 0x700b8) #define DSPFW_SPRITEF_WM1_SHIFT 24 #define DSPFW_SPRITEF_WM1_MASK (0xff<<24) #define DSPFW_SPRITEF_SHIFT 16 @@ -4638,7 +4701,7 @@ enum skl_disp_power_wells { #define DSPFW_SPRITEE_WM1_MASK (0xff<<8) #define DSPFW_SPRITEE_SHIFT 0 #define DSPFW_SPRITEE_MASK_VLV (0xff<<0) -#define DSPFW9_CHV (VLV_DISPLAY_BASE + 0x7007c) /* wtf #2? */ +#define DSPFW9_CHV _MMIO(VLV_DISPLAY_BASE + 0x7007c) /* wtf #2? */ #define DSPFW_PLANEC_WM1_SHIFT 24 #define DSPFW_PLANEC_WM1_MASK (0xff<<24) #define DSPFW_PLANEC_SHIFT 16 @@ -4649,7 +4712,7 @@ enum skl_disp_power_wells { #define DSPFW_CURSORC_MASK (0x3f<<0) /* vlv/chv high order bits */ -#define DSPHOWM (VLV_DISPLAY_BASE + 0x70064) +#define DSPHOWM _MMIO(VLV_DISPLAY_BASE + 0x70064) #define DSPFW_SR_HI_SHIFT 24 #define DSPFW_SR_HI_MASK (3<<24) /* 2 bits for chv, 1 for vlv */ #define DSPFW_SPRITEF_HI_SHIFT 23 @@ -4670,7 +4733,7 @@ enum skl_disp_power_wells { #define DSPFW_SPRITEA_HI_MASK (1<<4) #define DSPFW_PLANEA_HI_SHIFT 0 #define DSPFW_PLANEA_HI_MASK (1<<0) -#define DSPHOWM1 (VLV_DISPLAY_BASE + 0x70068) +#define DSPHOWM1 _MMIO(VLV_DISPLAY_BASE + 0x70068) #define DSPFW_SR_WM1_HI_SHIFT 24 #define DSPFW_SR_WM1_HI_MASK (3<<24) /* 2 bits for chv, 1 for vlv */ #define DSPFW_SPRITEF_WM1_HI_SHIFT 23 @@ -4693,7 +4756,7 @@ enum skl_disp_power_wells { #define DSPFW_PLANEA_WM1_HI_MASK (1<<0) /* drain latency register values*/ -#define VLV_DDL(pipe) (VLV_DISPLAY_BASE + 0x70050 + 4 * (pipe)) +#define VLV_DDL(pipe) _MMIO(VLV_DISPLAY_BASE + 0x70050 + 4 * (pipe)) #define DDL_CURSOR_SHIFT 24 #define DDL_SPRITE_SHIFT(sprite) (8+8*(sprite)) #define DDL_PLANE_SHIFT 0 @@ -4701,7 +4764,7 @@ enum skl_disp_power_wells { #define DDL_PRECISION_LOW (0<<7) #define DRAIN_LATENCY_MASK 0x7f -#define CBR1_VLV (VLV_DISPLAY_BASE + 0x70400) +#define CBR1_VLV _MMIO(VLV_DISPLAY_BASE + 0x70400) #define CBR_PND_DEADLINE_DISABLE (1<<31) #define CBR_PWM_CLOCK_MUX_SELECT (1<<30) @@ -4739,51 +4802,51 @@ enum skl_disp_power_wells { #define I965_CURSOR_DFT_WM 8 /* Watermark register definitions for SKL */ -#define CUR_WM_A_0 0x70140 -#define CUR_WM_B_0 0x71140 -#define PLANE_WM_1_A_0 0x70240 -#define PLANE_WM_1_B_0 0x71240 -#define PLANE_WM_2_A_0 0x70340 -#define PLANE_WM_2_B_0 0x71340 -#define PLANE_WM_TRANS_1_A_0 0x70268 -#define PLANE_WM_TRANS_1_B_0 0x71268 -#define PLANE_WM_TRANS_2_A_0 0x70368 -#define PLANE_WM_TRANS_2_B_0 0x71368 -#define CUR_WM_TRANS_A_0 0x70168 -#define CUR_WM_TRANS_B_0 0x71168 +#define _CUR_WM_A_0 0x70140 +#define _CUR_WM_B_0 0x71140 +#define _PLANE_WM_1_A_0 0x70240 +#define _PLANE_WM_1_B_0 0x71240 +#define _PLANE_WM_2_A_0 0x70340 +#define _PLANE_WM_2_B_0 0x71340 +#define _PLANE_WM_TRANS_1_A_0 0x70268 +#define _PLANE_WM_TRANS_1_B_0 0x71268 +#define _PLANE_WM_TRANS_2_A_0 0x70368 +#define _PLANE_WM_TRANS_2_B_0 0x71368 +#define _CUR_WM_TRANS_A_0 0x70168 +#define _CUR_WM_TRANS_B_0 0x71168 #define PLANE_WM_EN (1 << 31) #define PLANE_WM_LINES_SHIFT 14 #define PLANE_WM_LINES_MASK 0x1f #define PLANE_WM_BLOCKS_MASK 0x3ff -#define CUR_WM_0(pipe) _PIPE(pipe, CUR_WM_A_0, CUR_WM_B_0) -#define CUR_WM(pipe, level) (CUR_WM_0(pipe) + ((4) * (level))) -#define CUR_WM_TRANS(pipe) _PIPE(pipe, CUR_WM_TRANS_A_0, CUR_WM_TRANS_B_0) +#define _CUR_WM_0(pipe) _PIPE(pipe, _CUR_WM_A_0, _CUR_WM_B_0) +#define CUR_WM(pipe, level) _MMIO(_CUR_WM_0(pipe) + ((4) * (level))) +#define CUR_WM_TRANS(pipe) _MMIO_PIPE(pipe, _CUR_WM_TRANS_A_0, _CUR_WM_TRANS_B_0) -#define _PLANE_WM_1(pipe) _PIPE(pipe, PLANE_WM_1_A_0, PLANE_WM_1_B_0) -#define _PLANE_WM_2(pipe) _PIPE(pipe, PLANE_WM_2_A_0, PLANE_WM_2_B_0) +#define _PLANE_WM_1(pipe) _PIPE(pipe, _PLANE_WM_1_A_0, _PLANE_WM_1_B_0) +#define _PLANE_WM_2(pipe) _PIPE(pipe, _PLANE_WM_2_A_0, _PLANE_WM_2_B_0) #define _PLANE_WM_BASE(pipe, plane) \ _PLANE(plane, _PLANE_WM_1(pipe), _PLANE_WM_2(pipe)) #define PLANE_WM(pipe, plane, level) \ - (_PLANE_WM_BASE(pipe, plane) + ((4) * (level))) + _MMIO(_PLANE_WM_BASE(pipe, plane) + ((4) * (level))) #define _PLANE_WM_TRANS_1(pipe) \ - _PIPE(pipe, PLANE_WM_TRANS_1_A_0, PLANE_WM_TRANS_1_B_0) + _PIPE(pipe, _PLANE_WM_TRANS_1_A_0, _PLANE_WM_TRANS_1_B_0) #define _PLANE_WM_TRANS_2(pipe) \ - _PIPE(pipe, PLANE_WM_TRANS_2_A_0, PLANE_WM_TRANS_2_B_0) + _PIPE(pipe, _PLANE_WM_TRANS_2_A_0, _PLANE_WM_TRANS_2_B_0) #define PLANE_WM_TRANS(pipe, plane) \ - _PLANE(plane, _PLANE_WM_TRANS_1(pipe), _PLANE_WM_TRANS_2(pipe)) + _MMIO(_PLANE(plane, _PLANE_WM_TRANS_1(pipe), _PLANE_WM_TRANS_2(pipe))) /* define the Watermark register on Ironlake */ -#define WM0_PIPEA_ILK 0x45100 +#define WM0_PIPEA_ILK _MMIO(0x45100) #define WM0_PIPE_PLANE_MASK (0xffff<<16) #define WM0_PIPE_PLANE_SHIFT 16 #define WM0_PIPE_SPRITE_MASK (0xff<<8) #define WM0_PIPE_SPRITE_SHIFT 8 #define WM0_PIPE_CURSOR_MASK (0xff) -#define WM0_PIPEB_ILK 0x45104 -#define WM0_PIPEC_IVB 0x45200 -#define WM1_LP_ILK 0x45108 +#define WM0_PIPEB_ILK _MMIO(0x45104) +#define WM0_PIPEC_IVB _MMIO(0x45200) +#define WM1_LP_ILK _MMIO(0x45108) #define WM1_LP_SR_EN (1<<31) #define WM1_LP_LATENCY_SHIFT 24 #define WM1_LP_LATENCY_MASK (0x7f<<24) @@ -4793,13 +4856,13 @@ enum skl_disp_power_wells { #define WM1_LP_SR_MASK (0x7ff<<8) #define WM1_LP_SR_SHIFT 8 #define WM1_LP_CURSOR_MASK (0xff) -#define WM2_LP_ILK 0x4510c +#define WM2_LP_ILK _MMIO(0x4510c) #define WM2_LP_EN (1<<31) -#define WM3_LP_ILK 0x45110 +#define WM3_LP_ILK _MMIO(0x45110) #define WM3_LP_EN (1<<31) -#define WM1S_LP_ILK 0x45120 -#define WM2S_LP_IVB 0x45124 -#define WM3S_LP_IVB 0x45128 +#define WM1S_LP_ILK _MMIO(0x45120) +#define WM2S_LP_IVB _MMIO(0x45124) +#define WM3S_LP_IVB _MMIO(0x45128) #define WM1S_LP_EN (1<<31) #define HSW_WM_LP_VAL(lat, fbc, pri, cur) \ @@ -4807,7 +4870,7 @@ enum skl_disp_power_wells { ((fbc) << WM1_LP_FBC_SHIFT) | ((pri) << WM1_LP_SR_SHIFT) | (cur)) /* Memory latency timer register */ -#define MLTR_ILK 0x11222 +#define MLTR_ILK _MMIO(0x11222) #define MLTR_WM1_SHIFT 0 #define MLTR_WM2_SHIFT 8 /* the unit of memory self-refresh latency time is 0.5us */ @@ -4815,7 +4878,7 @@ enum skl_disp_power_wells { /* the address where we get all kinds of latency value */ -#define SSKPD 0x5d10 +#define SSKPD _MMIO(0x5d10) #define SSKPD_WM_MASK 0x3f #define SSKPD_WM0_SHIFT 0 #define SSKPD_WM1_SHIFT 8 @@ -4848,8 +4911,8 @@ enum skl_disp_power_wells { /* GM45+ just has to be different */ #define _PIPEA_FRMCOUNT_G4X 0x70040 #define _PIPEA_FLIPCOUNT_G4X 0x70044 -#define PIPE_FRMCOUNT_G4X(pipe) _PIPE2(pipe, _PIPEA_FRMCOUNT_G4X) -#define PIPE_FLIPCOUNT_G4X(pipe) _PIPE2(pipe, _PIPEA_FLIPCOUNT_G4X) +#define PIPE_FRMCOUNT_G4X(pipe) _MMIO_PIPE2(pipe, _PIPEA_FRMCOUNT_G4X) +#define PIPE_FLIPCOUNT_G4X(pipe) _MMIO_PIPE2(pipe, _PIPEA_FLIPCOUNT_G4X) /* Cursor A & B regs */ #define _CURACNTR 0x70080 @@ -4887,7 +4950,7 @@ enum skl_disp_power_wells { #define CURSOR_POS_SIGN 0x8000 #define CURSOR_X_SHIFT 0 #define CURSOR_Y_SHIFT 16 -#define CURSIZE 0x700a0 +#define CURSIZE _MMIO(0x700a0) #define _CURBCNTR 0x700c0 #define _CURBBASE 0x700c4 #define _CURBPOS 0x700c8 @@ -4896,7 +4959,7 @@ enum skl_disp_power_wells { #define _CURBBASE_IVB 0x71084 #define _CURBPOS_IVB 0x71088 -#define _CURSOR2(pipe, reg) (dev_priv->info.cursor_offsets[(pipe)] - \ +#define _CURSOR2(pipe, reg) _MMIO(dev_priv->info.cursor_offsets[(pipe)] - \ dev_priv->info.cursor_offsets[PIPE_A] + (reg) + \ dev_priv->info.display_mmio_offset) @@ -4957,16 +5020,16 @@ enum skl_disp_power_wells { #define _DSPAOFFSET 0x701A4 /* HSW */ #define _DSPASURFLIVE 0x701AC -#define DSPCNTR(plane) _PIPE2(plane, _DSPACNTR) -#define DSPADDR(plane) _PIPE2(plane, _DSPAADDR) -#define DSPSTRIDE(plane) _PIPE2(plane, _DSPASTRIDE) -#define DSPPOS(plane) _PIPE2(plane, _DSPAPOS) -#define DSPSIZE(plane) _PIPE2(plane, _DSPASIZE) -#define DSPSURF(plane) _PIPE2(plane, _DSPASURF) -#define DSPTILEOFF(plane) _PIPE2(plane, _DSPATILEOFF) -#define DSPLINOFF(plane) DSPADDR(plane) -#define DSPOFFSET(plane) _PIPE2(plane, _DSPAOFFSET) -#define DSPSURFLIVE(plane) _PIPE2(plane, _DSPASURFLIVE) +#define DSPCNTR(plane) _MMIO_PIPE2(plane, _DSPACNTR) +#define DSPADDR(plane) _MMIO_PIPE2(plane, _DSPAADDR) +#define DSPSTRIDE(plane) _MMIO_PIPE2(plane, _DSPASTRIDE) +#define DSPPOS(plane) _MMIO_PIPE2(plane, _DSPAPOS) +#define DSPSIZE(plane) _MMIO_PIPE2(plane, _DSPASIZE) +#define DSPSURF(plane) _MMIO_PIPE2(plane, _DSPASURF) +#define DSPTILEOFF(plane) _MMIO_PIPE2(plane, _DSPATILEOFF) +#define DSPLINOFF(plane) DSPADDR(plane) +#define DSPOFFSET(plane) _MMIO_PIPE2(plane, _DSPAOFFSET) +#define DSPSURFLIVE(plane) _MMIO_PIPE2(plane, _DSPASURFLIVE) /* CHV pipe B blender and primary plane */ #define _CHV_BLEND_A 0x60a00 @@ -4980,11 +5043,11 @@ enum skl_disp_power_wells { #define _PRIMCNSTALPHA_A 0x60a10 #define PRIM_CONST_ALPHA_ENABLE (1<<31) -#define CHV_BLEND(pipe) _TRANSCODER2(pipe, _CHV_BLEND_A) -#define CHV_CANVAS(pipe) _TRANSCODER2(pipe, _CHV_CANVAS_A) -#define PRIMPOS(plane) _TRANSCODER2(plane, _PRIMPOS_A) -#define PRIMSIZE(plane) _TRANSCODER2(plane, _PRIMSIZE_A) -#define PRIMCNSTALPHA(plane) _TRANSCODER2(plane, _PRIMCNSTALPHA_A) +#define CHV_BLEND(pipe) _MMIO_TRANS2(pipe, _CHV_BLEND_A) +#define CHV_CANVAS(pipe) _MMIO_TRANS2(pipe, _CHV_CANVAS_A) +#define PRIMPOS(plane) _MMIO_TRANS2(plane, _PRIMPOS_A) +#define PRIMSIZE(plane) _MMIO_TRANS2(plane, _PRIMSIZE_A) +#define PRIMCNSTALPHA(plane) _MMIO_TRANS2(plane, _PRIMCNSTALPHA_A) /* Display/Sprite base address macros */ #define DISP_BASEADDR_MASK (0xfffff000) @@ -5002,9 +5065,10 @@ enum skl_disp_power_wells { * [10:1f] all * [30:32] all */ -#define SWF0(i) (dev_priv->info.display_mmio_offset + 0x70410 + (i) * 4) -#define SWF1(i) (dev_priv->info.display_mmio_offset + 0x71410 + (i) * 4) -#define SWF3(i) (dev_priv->info.display_mmio_offset + 0x72414 + (i) * 4) +#define SWF0(i) _MMIO(dev_priv->info.display_mmio_offset + 0x70410 + (i) * 4) +#define SWF1(i) _MMIO(dev_priv->info.display_mmio_offset + 0x71410 + (i) * 4) +#define SWF3(i) _MMIO(dev_priv->info.display_mmio_offset + 0x72414 + (i) * 4) +#define SWF_ILK(i) _MMIO(0x4F000 + (i) * 4) /* Pipe B */ #define _PIPEBDSL (dev_priv->info.display_mmio_offset + 0x71000) @@ -5086,18 +5150,18 @@ enum skl_disp_power_wells { #define _DVSBSCALE 0x73204 #define _DVSBGAMC 0x73300 -#define DVSCNTR(pipe) _PIPE(pipe, _DVSACNTR, _DVSBCNTR) -#define DVSLINOFF(pipe) _PIPE(pipe, _DVSALINOFF, _DVSBLINOFF) -#define DVSSTRIDE(pipe) _PIPE(pipe, _DVSASTRIDE, _DVSBSTRIDE) -#define DVSPOS(pipe) _PIPE(pipe, _DVSAPOS, _DVSBPOS) -#define DVSSURF(pipe) _PIPE(pipe, _DVSASURF, _DVSBSURF) -#define DVSKEYMAX(pipe) _PIPE(pipe, _DVSAKEYMAXVAL, _DVSBKEYMAXVAL) -#define DVSSIZE(pipe) _PIPE(pipe, _DVSASIZE, _DVSBSIZE) -#define DVSSCALE(pipe) _PIPE(pipe, _DVSASCALE, _DVSBSCALE) -#define DVSTILEOFF(pipe) _PIPE(pipe, _DVSATILEOFF, _DVSBTILEOFF) -#define DVSKEYVAL(pipe) _PIPE(pipe, _DVSAKEYVAL, _DVSBKEYVAL) -#define DVSKEYMSK(pipe) _PIPE(pipe, _DVSAKEYMSK, _DVSBKEYMSK) -#define DVSSURFLIVE(pipe) _PIPE(pipe, _DVSASURFLIVE, _DVSBSURFLIVE) +#define DVSCNTR(pipe) _MMIO_PIPE(pipe, _DVSACNTR, _DVSBCNTR) +#define DVSLINOFF(pipe) _MMIO_PIPE(pipe, _DVSALINOFF, _DVSBLINOFF) +#define DVSSTRIDE(pipe) _MMIO_PIPE(pipe, _DVSASTRIDE, _DVSBSTRIDE) +#define DVSPOS(pipe) _MMIO_PIPE(pipe, _DVSAPOS, _DVSBPOS) +#define DVSSURF(pipe) _MMIO_PIPE(pipe, _DVSASURF, _DVSBSURF) +#define DVSKEYMAX(pipe) _MMIO_PIPE(pipe, _DVSAKEYMAXVAL, _DVSBKEYMAXVAL) +#define DVSSIZE(pipe) _MMIO_PIPE(pipe, _DVSASIZE, _DVSBSIZE) +#define DVSSCALE(pipe) _MMIO_PIPE(pipe, _DVSASCALE, _DVSBSCALE) +#define DVSTILEOFF(pipe) _MMIO_PIPE(pipe, _DVSATILEOFF, _DVSBTILEOFF) +#define DVSKEYVAL(pipe) _MMIO_PIPE(pipe, _DVSAKEYVAL, _DVSBKEYVAL) +#define DVSKEYMSK(pipe) _MMIO_PIPE(pipe, _DVSAKEYMSK, _DVSBKEYMSK) +#define DVSSURFLIVE(pipe) _MMIO_PIPE(pipe, _DVSASURFLIVE, _DVSBSURFLIVE) #define _SPRA_CTL 0x70280 #define SPRITE_ENABLE (1<<31) @@ -5160,20 +5224,20 @@ enum skl_disp_power_wells { #define _SPRB_SCALE 0x71304 #define _SPRB_GAMC 0x71400 -#define SPRCTL(pipe) _PIPE(pipe, _SPRA_CTL, _SPRB_CTL) -#define SPRLINOFF(pipe) _PIPE(pipe, _SPRA_LINOFF, _SPRB_LINOFF) -#define SPRSTRIDE(pipe) _PIPE(pipe, _SPRA_STRIDE, _SPRB_STRIDE) -#define SPRPOS(pipe) _PIPE(pipe, _SPRA_POS, _SPRB_POS) -#define SPRSIZE(pipe) _PIPE(pipe, _SPRA_SIZE, _SPRB_SIZE) -#define SPRKEYVAL(pipe) _PIPE(pipe, _SPRA_KEYVAL, _SPRB_KEYVAL) -#define SPRKEYMSK(pipe) _PIPE(pipe, _SPRA_KEYMSK, _SPRB_KEYMSK) -#define SPRSURF(pipe) _PIPE(pipe, _SPRA_SURF, _SPRB_SURF) -#define SPRKEYMAX(pipe) _PIPE(pipe, _SPRA_KEYMAX, _SPRB_KEYMAX) -#define SPRTILEOFF(pipe) _PIPE(pipe, _SPRA_TILEOFF, _SPRB_TILEOFF) -#define SPROFFSET(pipe) _PIPE(pipe, _SPRA_OFFSET, _SPRB_OFFSET) -#define SPRSCALE(pipe) _PIPE(pipe, _SPRA_SCALE, _SPRB_SCALE) -#define SPRGAMC(pipe) _PIPE(pipe, _SPRA_GAMC, _SPRB_GAMC) -#define SPRSURFLIVE(pipe) _PIPE(pipe, _SPRA_SURFLIVE, _SPRB_SURFLIVE) +#define SPRCTL(pipe) _MMIO_PIPE(pipe, _SPRA_CTL, _SPRB_CTL) +#define SPRLINOFF(pipe) _MMIO_PIPE(pipe, _SPRA_LINOFF, _SPRB_LINOFF) +#define SPRSTRIDE(pipe) _MMIO_PIPE(pipe, _SPRA_STRIDE, _SPRB_STRIDE) +#define SPRPOS(pipe) _MMIO_PIPE(pipe, _SPRA_POS, _SPRB_POS) +#define SPRSIZE(pipe) _MMIO_PIPE(pipe, _SPRA_SIZE, _SPRB_SIZE) +#define SPRKEYVAL(pipe) _MMIO_PIPE(pipe, _SPRA_KEYVAL, _SPRB_KEYVAL) +#define SPRKEYMSK(pipe) _MMIO_PIPE(pipe, _SPRA_KEYMSK, _SPRB_KEYMSK) +#define SPRSURF(pipe) _MMIO_PIPE(pipe, _SPRA_SURF, _SPRB_SURF) +#define SPRKEYMAX(pipe) _MMIO_PIPE(pipe, _SPRA_KEYMAX, _SPRB_KEYMAX) +#define SPRTILEOFF(pipe) _MMIO_PIPE(pipe, _SPRA_TILEOFF, _SPRB_TILEOFF) +#define SPROFFSET(pipe) _MMIO_PIPE(pipe, _SPRA_OFFSET, _SPRB_OFFSET) +#define SPRSCALE(pipe) _MMIO_PIPE(pipe, _SPRA_SCALE, _SPRB_SCALE) +#define SPRGAMC(pipe) _MMIO_PIPE(pipe, _SPRA_GAMC, _SPRB_GAMC) +#define SPRSURFLIVE(pipe) _MMIO_PIPE(pipe, _SPRA_SURFLIVE, _SPRB_SURFLIVE) #define _SPACNTR (VLV_DISPLAY_BASE + 0x72180) #define SP_ENABLE (1<<31) @@ -5223,18 +5287,18 @@ enum skl_disp_power_wells { #define _SPBCONSTALPHA (VLV_DISPLAY_BASE + 0x722a8) #define _SPBGAMC (VLV_DISPLAY_BASE + 0x722f4) -#define SPCNTR(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPACNTR, _SPBCNTR) -#define SPLINOFF(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPALINOFF, _SPBLINOFF) -#define SPSTRIDE(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPASTRIDE, _SPBSTRIDE) -#define SPPOS(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAPOS, _SPBPOS) -#define SPSIZE(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPASIZE, _SPBSIZE) -#define SPKEYMINVAL(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAKEYMINVAL, _SPBKEYMINVAL) -#define SPKEYMSK(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAKEYMSK, _SPBKEYMSK) -#define SPSURF(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPASURF, _SPBSURF) -#define SPKEYMAXVAL(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAKEYMAXVAL, _SPBKEYMAXVAL) -#define SPTILEOFF(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPATILEOFF, _SPBTILEOFF) -#define SPCONSTALPHA(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPACONSTALPHA, _SPBCONSTALPHA) -#define SPGAMC(pipe, plane) _PIPE((pipe) * 2 + (plane), _SPAGAMC, _SPBGAMC) +#define SPCNTR(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPACNTR, _SPBCNTR) +#define SPLINOFF(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPALINOFF, _SPBLINOFF) +#define SPSTRIDE(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPASTRIDE, _SPBSTRIDE) +#define SPPOS(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPAPOS, _SPBPOS) +#define SPSIZE(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPASIZE, _SPBSIZE) +#define SPKEYMINVAL(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPAKEYMINVAL, _SPBKEYMINVAL) +#define SPKEYMSK(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPAKEYMSK, _SPBKEYMSK) +#define SPSURF(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPASURF, _SPBSURF) +#define SPKEYMAXVAL(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPAKEYMAXVAL, _SPBKEYMAXVAL) +#define SPTILEOFF(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPATILEOFF, _SPBTILEOFF) +#define SPCONSTALPHA(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPACONSTALPHA, _SPBCONSTALPHA) +#define SPGAMC(pipe, plane) _MMIO_PIPE((pipe) * 2 + (plane), _SPAGAMC, _SPBGAMC) /* * CHV pipe B sprite CSC @@ -5243,29 +5307,29 @@ enum skl_disp_power_wells { * |yg| = |c3 c4 c5| x |yg + yg_ioff| + |yg_ooff| * |cb| |c6 c7 c8| |cb + cr_ioff| |cb_ooff| */ -#define SPCSCYGOFF(sprite) (VLV_DISPLAY_BASE + 0x6d900 + (sprite) * 0x1000) -#define SPCSCCBOFF(sprite) (VLV_DISPLAY_BASE + 0x6d904 + (sprite) * 0x1000) -#define SPCSCCROFF(sprite) (VLV_DISPLAY_BASE + 0x6d908 + (sprite) * 0x1000) +#define SPCSCYGOFF(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d900 + (sprite) * 0x1000) +#define SPCSCCBOFF(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d904 + (sprite) * 0x1000) +#define SPCSCCROFF(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d908 + (sprite) * 0x1000) #define SPCSC_OOFF(x) (((x) & 0x7ff) << 16) /* s11 */ #define SPCSC_IOFF(x) (((x) & 0x7ff) << 0) /* s11 */ -#define SPCSCC01(sprite) (VLV_DISPLAY_BASE + 0x6d90c + (sprite) * 0x1000) -#define SPCSCC23(sprite) (VLV_DISPLAY_BASE + 0x6d910 + (sprite) * 0x1000) -#define SPCSCC45(sprite) (VLV_DISPLAY_BASE + 0x6d914 + (sprite) * 0x1000) -#define SPCSCC67(sprite) (VLV_DISPLAY_BASE + 0x6d918 + (sprite) * 0x1000) -#define SPCSCC8(sprite) (VLV_DISPLAY_BASE + 0x6d91c + (sprite) * 0x1000) +#define SPCSCC01(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d90c + (sprite) * 0x1000) +#define SPCSCC23(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d910 + (sprite) * 0x1000) +#define SPCSCC45(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d914 + (sprite) * 0x1000) +#define SPCSCC67(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d918 + (sprite) * 0x1000) +#define SPCSCC8(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d91c + (sprite) * 0x1000) #define SPCSC_C1(x) (((x) & 0x7fff) << 16) /* s3.12 */ #define SPCSC_C0(x) (((x) & 0x7fff) << 0) /* s3.12 */ -#define SPCSCYGICLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d920 + (sprite) * 0x1000) -#define SPCSCCBICLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d924 + (sprite) * 0x1000) -#define SPCSCCRICLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d928 + (sprite) * 0x1000) +#define SPCSCYGICLAMP(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d920 + (sprite) * 0x1000) +#define SPCSCCBICLAMP(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d924 + (sprite) * 0x1000) +#define SPCSCCRICLAMP(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d928 + (sprite) * 0x1000) #define SPCSC_IMAX(x) (((x) & 0x7ff) << 16) /* s11 */ #define SPCSC_IMIN(x) (((x) & 0x7ff) << 0) /* s11 */ -#define SPCSCYGOCLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d92c + (sprite) * 0x1000) -#define SPCSCCBOCLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d930 + (sprite) * 0x1000) -#define SPCSCCROCLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d934 + (sprite) * 0x1000) +#define SPCSCYGOCLAMP(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d92c + (sprite) * 0x1000) +#define SPCSCCBOCLAMP(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d930 + (sprite) * 0x1000) +#define SPCSCCROCLAMP(sprite) _MMIO(VLV_DISPLAY_BASE + 0x6d934 + (sprite) * 0x1000) #define SPCSC_OMAX(x) ((x) << 16) /* u10 */ #define SPCSC_OMIN(x) ((x) << 0) /* u10 */ @@ -5346,7 +5410,7 @@ enum skl_disp_power_wells { #define _PLANE_CTL_2(pipe) _PIPE(pipe, _PLANE_CTL_2_A, _PLANE_CTL_2_B) #define _PLANE_CTL_3(pipe) _PIPE(pipe, _PLANE_CTL_3_A, _PLANE_CTL_3_B) #define PLANE_CTL(pipe, plane) \ - _PLANE(plane, _PLANE_CTL_1(pipe), _PLANE_CTL_2(pipe)) + _MMIO_PLANE(plane, _PLANE_CTL_1(pipe), _PLANE_CTL_2(pipe)) #define _PLANE_STRIDE_1_B 0x71188 #define _PLANE_STRIDE_2_B 0x71288 @@ -5358,7 +5422,7 @@ enum skl_disp_power_wells { #define _PLANE_STRIDE_3(pipe) \ _PIPE(pipe, _PLANE_STRIDE_3_A, _PLANE_STRIDE_3_B) #define PLANE_STRIDE(pipe, plane) \ - _PLANE(plane, _PLANE_STRIDE_1(pipe), _PLANE_STRIDE_2(pipe)) + _MMIO_PLANE(plane, _PLANE_STRIDE_1(pipe), _PLANE_STRIDE_2(pipe)) #define _PLANE_POS_1_B 0x7118c #define _PLANE_POS_2_B 0x7128c @@ -5367,7 +5431,7 @@ enum skl_disp_power_wells { #define _PLANE_POS_2(pipe) _PIPE(pipe, _PLANE_POS_2_A, _PLANE_POS_2_B) #define _PLANE_POS_3(pipe) _PIPE(pipe, _PLANE_POS_3_A, _PLANE_POS_3_B) #define PLANE_POS(pipe, plane) \ - _PLANE(plane, _PLANE_POS_1(pipe), _PLANE_POS_2(pipe)) + _MMIO_PLANE(plane, _PLANE_POS_1(pipe), _PLANE_POS_2(pipe)) #define _PLANE_SIZE_1_B 0x71190 #define _PLANE_SIZE_2_B 0x71290 @@ -5376,7 +5440,7 @@ enum skl_disp_power_wells { #define _PLANE_SIZE_2(pipe) _PIPE(pipe, _PLANE_SIZE_2_A, _PLANE_SIZE_2_B) #define _PLANE_SIZE_3(pipe) _PIPE(pipe, _PLANE_SIZE_3_A, _PLANE_SIZE_3_B) #define PLANE_SIZE(pipe, plane) \ - _PLANE(plane, _PLANE_SIZE_1(pipe), _PLANE_SIZE_2(pipe)) + _MMIO_PLANE(plane, _PLANE_SIZE_1(pipe), _PLANE_SIZE_2(pipe)) #define _PLANE_SURF_1_B 0x7119c #define _PLANE_SURF_2_B 0x7129c @@ -5385,35 +5449,35 @@ enum skl_disp_power_wells { #define _PLANE_SURF_2(pipe) _PIPE(pipe, _PLANE_SURF_2_A, _PLANE_SURF_2_B) #define _PLANE_SURF_3(pipe) _PIPE(pipe, _PLANE_SURF_3_A, _PLANE_SURF_3_B) #define PLANE_SURF(pipe, plane) \ - _PLANE(plane, _PLANE_SURF_1(pipe), _PLANE_SURF_2(pipe)) + _MMIO_PLANE(plane, _PLANE_SURF_1(pipe), _PLANE_SURF_2(pipe)) #define _PLANE_OFFSET_1_B 0x711a4 #define _PLANE_OFFSET_2_B 0x712a4 #define _PLANE_OFFSET_1(pipe) _PIPE(pipe, _PLANE_OFFSET_1_A, _PLANE_OFFSET_1_B) #define _PLANE_OFFSET_2(pipe) _PIPE(pipe, _PLANE_OFFSET_2_A, _PLANE_OFFSET_2_B) #define PLANE_OFFSET(pipe, plane) \ - _PLANE(plane, _PLANE_OFFSET_1(pipe), _PLANE_OFFSET_2(pipe)) + _MMIO_PLANE(plane, _PLANE_OFFSET_1(pipe), _PLANE_OFFSET_2(pipe)) #define _PLANE_KEYVAL_1_B 0x71194 #define _PLANE_KEYVAL_2_B 0x71294 #define _PLANE_KEYVAL_1(pipe) _PIPE(pipe, _PLANE_KEYVAL_1_A, _PLANE_KEYVAL_1_B) #define _PLANE_KEYVAL_2(pipe) _PIPE(pipe, _PLANE_KEYVAL_2_A, _PLANE_KEYVAL_2_B) #define PLANE_KEYVAL(pipe, plane) \ - _PLANE(plane, _PLANE_KEYVAL_1(pipe), _PLANE_KEYVAL_2(pipe)) + _MMIO_PLANE(plane, _PLANE_KEYVAL_1(pipe), _PLANE_KEYVAL_2(pipe)) #define _PLANE_KEYMSK_1_B 0x71198 #define _PLANE_KEYMSK_2_B 0x71298 #define _PLANE_KEYMSK_1(pipe) _PIPE(pipe, _PLANE_KEYMSK_1_A, _PLANE_KEYMSK_1_B) #define _PLANE_KEYMSK_2(pipe) _PIPE(pipe, _PLANE_KEYMSK_2_A, _PLANE_KEYMSK_2_B) #define PLANE_KEYMSK(pipe, plane) \ - _PLANE(plane, _PLANE_KEYMSK_1(pipe), _PLANE_KEYMSK_2(pipe)) + _MMIO_PLANE(plane, _PLANE_KEYMSK_1(pipe), _PLANE_KEYMSK_2(pipe)) #define _PLANE_KEYMAX_1_B 0x711a0 #define _PLANE_KEYMAX_2_B 0x712a0 #define _PLANE_KEYMAX_1(pipe) _PIPE(pipe, _PLANE_KEYMAX_1_A, _PLANE_KEYMAX_1_B) #define _PLANE_KEYMAX_2(pipe) _PIPE(pipe, _PLANE_KEYMAX_2_A, _PLANE_KEYMAX_2_B) #define PLANE_KEYMAX(pipe, plane) \ - _PLANE(plane, _PLANE_KEYMAX_1(pipe), _PLANE_KEYMAX_2(pipe)) + _MMIO_PLANE(plane, _PLANE_KEYMAX_1(pipe), _PLANE_KEYMAX_2(pipe)) #define _PLANE_BUF_CFG_1_B 0x7127c #define _PLANE_BUF_CFG_2_B 0x7137c @@ -5422,7 +5486,7 @@ enum skl_disp_power_wells { #define _PLANE_BUF_CFG_2(pipe) \ _PIPE(pipe, _PLANE_BUF_CFG_2_A, _PLANE_BUF_CFG_2_B) #define PLANE_BUF_CFG(pipe, plane) \ - _PLANE(plane, _PLANE_BUF_CFG_1(pipe), _PLANE_BUF_CFG_2(pipe)) + _MMIO_PLANE(plane, _PLANE_BUF_CFG_1(pipe), _PLANE_BUF_CFG_2(pipe)) #define _PLANE_NV12_BUF_CFG_1_B 0x71278 #define _PLANE_NV12_BUF_CFG_2_B 0x71378 @@ -5431,26 +5495,26 @@ enum skl_disp_power_wells { #define _PLANE_NV12_BUF_CFG_2(pipe) \ _PIPE(pipe, _PLANE_NV12_BUF_CFG_2_A, _PLANE_NV12_BUF_CFG_2_B) #define PLANE_NV12_BUF_CFG(pipe, plane) \ - _PLANE(plane, _PLANE_NV12_BUF_CFG_1(pipe), _PLANE_NV12_BUF_CFG_2(pipe)) + _MMIO_PLANE(plane, _PLANE_NV12_BUF_CFG_1(pipe), _PLANE_NV12_BUF_CFG_2(pipe)) /* SKL new cursor registers */ #define _CUR_BUF_CFG_A 0x7017c #define _CUR_BUF_CFG_B 0x7117c -#define CUR_BUF_CFG(pipe) _PIPE(pipe, _CUR_BUF_CFG_A, _CUR_BUF_CFG_B) +#define CUR_BUF_CFG(pipe) _MMIO_PIPE(pipe, _CUR_BUF_CFG_A, _CUR_BUF_CFG_B) /* VBIOS regs */ -#define VGACNTRL 0x71400 +#define VGACNTRL _MMIO(0x71400) # define VGA_DISP_DISABLE (1 << 31) # define VGA_2X_MODE (1 << 30) # define VGA_PIPE_B_SELECT (1 << 29) -#define VLV_VGACNTRL (VLV_DISPLAY_BASE + 0x71400) +#define VLV_VGACNTRL _MMIO(VLV_DISPLAY_BASE + 0x71400) /* Ironlake */ -#define CPU_VGACNTRL 0x41000 +#define CPU_VGACNTRL _MMIO(0x41000) -#define DIGITAL_PORT_HOTPLUG_CNTRL 0x44030 +#define DIGITAL_PORT_HOTPLUG_CNTRL _MMIO(0x44030) #define DIGITAL_PORTA_HOTPLUG_ENABLE (1 << 4) #define DIGITAL_PORTA_PULSE_DURATION_2ms (0 << 2) /* pre-HSW */ #define DIGITAL_PORTA_PULSE_DURATION_4_5ms (1 << 2) /* pre-HSW */ @@ -5463,26 +5527,26 @@ enum skl_disp_power_wells { #define DIGITAL_PORTA_HOTPLUG_LONG_DETECT (2 << 0) /* refresh rate hardware control */ -#define RR_HW_CTL 0x45300 +#define RR_HW_CTL _MMIO(0x45300) #define RR_HW_LOW_POWER_FRAMES_MASK 0xff #define RR_HW_HIGH_POWER_FRAMES_MASK 0xff00 -#define FDI_PLL_BIOS_0 0x46000 +#define FDI_PLL_BIOS_0 _MMIO(0x46000) #define FDI_PLL_FB_CLOCK_MASK 0xff -#define FDI_PLL_BIOS_1 0x46004 -#define FDI_PLL_BIOS_2 0x46008 -#define DISPLAY_PORT_PLL_BIOS_0 0x4600c -#define DISPLAY_PORT_PLL_BIOS_1 0x46010 -#define DISPLAY_PORT_PLL_BIOS_2 0x46014 +#define FDI_PLL_BIOS_1 _MMIO(0x46004) +#define FDI_PLL_BIOS_2 _MMIO(0x46008) +#define DISPLAY_PORT_PLL_BIOS_0 _MMIO(0x4600c) +#define DISPLAY_PORT_PLL_BIOS_1 _MMIO(0x46010) +#define DISPLAY_PORT_PLL_BIOS_2 _MMIO(0x46014) -#define PCH_3DCGDIS0 0x46020 +#define PCH_3DCGDIS0 _MMIO(0x46020) # define MARIUNIT_CLOCK_GATE_DISABLE (1 << 18) # define SVSMUNIT_CLOCK_GATE_DISABLE (1 << 1) -#define PCH_3DCGDIS1 0x46024 +#define PCH_3DCGDIS1 _MMIO(0x46024) # define VFMUNIT_CLOCK_GATE_DISABLE (1 << 11) -#define FDI_PLL_FREQ_CTL 0x46030 +#define FDI_PLL_FREQ_CTL _MMIO(0x46030) #define FDI_PLL_FREQ_CHANGE_REQUEST (1<<24) #define FDI_PLL_FREQ_LOCK_LIMIT_MASK 0xfff00 #define FDI_PLL_FREQ_DISABLE_COUNT_LIMIT_MASK 0xff @@ -5519,14 +5583,14 @@ enum skl_disp_power_wells { #define _PIPEB_LINK_M2 0x61048 #define _PIPEB_LINK_N2 0x6104c -#define PIPE_DATA_M1(tran) _TRANSCODER2(tran, _PIPEA_DATA_M1) -#define PIPE_DATA_N1(tran) _TRANSCODER2(tran, _PIPEA_DATA_N1) -#define PIPE_DATA_M2(tran) _TRANSCODER2(tran, _PIPEA_DATA_M2) -#define PIPE_DATA_N2(tran) _TRANSCODER2(tran, _PIPEA_DATA_N2) -#define PIPE_LINK_M1(tran) _TRANSCODER2(tran, _PIPEA_LINK_M1) -#define PIPE_LINK_N1(tran) _TRANSCODER2(tran, _PIPEA_LINK_N1) -#define PIPE_LINK_M2(tran) _TRANSCODER2(tran, _PIPEA_LINK_M2) -#define PIPE_LINK_N2(tran) _TRANSCODER2(tran, _PIPEA_LINK_N2) +#define PIPE_DATA_M1(tran) _MMIO_TRANS2(tran, _PIPEA_DATA_M1) +#define PIPE_DATA_N1(tran) _MMIO_TRANS2(tran, _PIPEA_DATA_N1) +#define PIPE_DATA_M2(tran) _MMIO_TRANS2(tran, _PIPEA_DATA_M2) +#define PIPE_DATA_N2(tran) _MMIO_TRANS2(tran, _PIPEA_DATA_N2) +#define PIPE_LINK_M1(tran) _MMIO_TRANS2(tran, _PIPEA_LINK_M1) +#define PIPE_LINK_N1(tran) _MMIO_TRANS2(tran, _PIPEA_LINK_N1) +#define PIPE_LINK_M2(tran) _MMIO_TRANS2(tran, _PIPEA_LINK_M2) +#define PIPE_LINK_N2(tran) _MMIO_TRANS2(tran, _PIPEA_LINK_N2) /* CPU panel fitter */ /* IVB+ has 3 fitters, 0 is 7x5 capable, the other two only 3x3 */ @@ -5549,11 +5613,11 @@ enum skl_disp_power_wells { #define _PFA_HSCALE 0x68090 #define _PFB_HSCALE 0x68890 -#define PF_CTL(pipe) _PIPE(pipe, _PFA_CTL_1, _PFB_CTL_1) -#define PF_WIN_SZ(pipe) _PIPE(pipe, _PFA_WIN_SZ, _PFB_WIN_SZ) -#define PF_WIN_POS(pipe) _PIPE(pipe, _PFA_WIN_POS, _PFB_WIN_POS) -#define PF_VSCALE(pipe) _PIPE(pipe, _PFA_VSCALE, _PFB_VSCALE) -#define PF_HSCALE(pipe) _PIPE(pipe, _PFA_HSCALE, _PFB_HSCALE) +#define PF_CTL(pipe) _MMIO_PIPE(pipe, _PFA_CTL_1, _PFB_CTL_1) +#define PF_WIN_SZ(pipe) _MMIO_PIPE(pipe, _PFA_WIN_SZ, _PFB_WIN_SZ) +#define PF_WIN_POS(pipe) _MMIO_PIPE(pipe, _PFA_WIN_POS, _PFB_WIN_POS) +#define PF_VSCALE(pipe) _MMIO_PIPE(pipe, _PFA_VSCALE, _PFB_VSCALE) +#define PF_HSCALE(pipe) _MMIO_PIPE(pipe, _PFA_HSCALE, _PFB_HSCALE) #define _PSA_CTL 0x68180 #define _PSB_CTL 0x68980 @@ -5563,9 +5627,9 @@ enum skl_disp_power_wells { #define _PSA_WIN_POS 0x68170 #define _PSB_WIN_POS 0x68970 -#define PS_CTL(pipe) _PIPE(pipe, _PSA_CTL, _PSB_CTL) -#define PS_WIN_SZ(pipe) _PIPE(pipe, _PSA_WIN_SZ, _PSB_WIN_SZ) -#define PS_WIN_POS(pipe) _PIPE(pipe, _PSA_WIN_POS, _PSB_WIN_POS) +#define PS_CTL(pipe) _MMIO_PIPE(pipe, _PSA_CTL, _PSB_CTL) +#define PS_WIN_SZ(pipe) _MMIO_PIPE(pipe, _PSA_WIN_SZ, _PSB_WIN_SZ) +#define PS_WIN_POS(pipe) _MMIO_PIPE(pipe, _PSA_WIN_POS, _PSB_WIN_POS) /* * Skylake scalers @@ -5654,48 +5718,63 @@ enum skl_disp_power_wells { #define _PS_ECC_STAT_1C 0x691D0 #define _ID(id, a, b) ((a) + (id)*((b)-(a))) -#define SKL_PS_CTRL(pipe, id) _PIPE(pipe, \ +#define SKL_PS_CTRL(pipe, id) _MMIO_PIPE(pipe, \ _ID(id, _PS_1A_CTRL, _PS_2A_CTRL), \ _ID(id, _PS_1B_CTRL, _PS_2B_CTRL)) -#define SKL_PS_PWR_GATE(pipe, id) _PIPE(pipe, \ +#define SKL_PS_PWR_GATE(pipe, id) _MMIO_PIPE(pipe, \ _ID(id, _PS_PWR_GATE_1A, _PS_PWR_GATE_2A), \ _ID(id, _PS_PWR_GATE_1B, _PS_PWR_GATE_2B)) -#define SKL_PS_WIN_POS(pipe, id) _PIPE(pipe, \ +#define SKL_PS_WIN_POS(pipe, id) _MMIO_PIPE(pipe, \ _ID(id, _PS_WIN_POS_1A, _PS_WIN_POS_2A), \ _ID(id, _PS_WIN_POS_1B, _PS_WIN_POS_2B)) -#define SKL_PS_WIN_SZ(pipe, id) _PIPE(pipe, \ +#define SKL_PS_WIN_SZ(pipe, id) _MMIO_PIPE(pipe, \ _ID(id, _PS_WIN_SZ_1A, _PS_WIN_SZ_2A), \ _ID(id, _PS_WIN_SZ_1B, _PS_WIN_SZ_2B)) -#define SKL_PS_VSCALE(pipe, id) _PIPE(pipe, \ +#define SKL_PS_VSCALE(pipe, id) _MMIO_PIPE(pipe, \ _ID(id, _PS_VSCALE_1A, _PS_VSCALE_2A), \ _ID(id, _PS_VSCALE_1B, _PS_VSCALE_2B)) -#define SKL_PS_HSCALE(pipe, id) _PIPE(pipe, \ +#define SKL_PS_HSCALE(pipe, id) _MMIO_PIPE(pipe, \ _ID(id, _PS_HSCALE_1A, _PS_HSCALE_2A), \ _ID(id, _PS_HSCALE_1B, _PS_HSCALE_2B)) -#define SKL_PS_VPHASE(pipe, id) _PIPE(pipe, \ +#define SKL_PS_VPHASE(pipe, id) _MMIO_PIPE(pipe, \ _ID(id, _PS_VPHASE_1A, _PS_VPHASE_2A), \ _ID(id, _PS_VPHASE_1B, _PS_VPHASE_2B)) -#define SKL_PS_HPHASE(pipe, id) _PIPE(pipe, \ +#define SKL_PS_HPHASE(pipe, id) _MMIO_PIPE(pipe, \ _ID(id, _PS_HPHASE_1A, _PS_HPHASE_2A), \ _ID(id, _PS_HPHASE_1B, _PS_HPHASE_2B)) -#define SKL_PS_ECC_STAT(pipe, id) _PIPE(pipe, \ +#define SKL_PS_ECC_STAT(pipe, id) _MMIO_PIPE(pipe, \ _ID(id, _PS_ECC_STAT_1A, _PS_ECC_STAT_2A), \ - _ID(id, _PS_ECC_STAT_1B, _PS_ECC_STAT_2B) + _ID(id, _PS_ECC_STAT_1B, _PS_ECC_STAT_2B)) /* legacy palette */ #define _LGC_PALETTE_A 0x4a000 #define _LGC_PALETTE_B 0x4a800 -#define LGC_PALETTE(pipe, i) (_PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B) + (i) * 4) +#define LGC_PALETTE(pipe, i) _MMIO(_PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B) + (i) * 4) #define _GAMMA_MODE_A 0x4a480 #define _GAMMA_MODE_B 0x4ac80 -#define GAMMA_MODE(pipe) _PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B) +#define GAMMA_MODE(pipe) _MMIO_PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B) #define GAMMA_MODE_MODE_MASK (3 << 0) #define GAMMA_MODE_MODE_8BIT (0 << 0) #define GAMMA_MODE_MODE_10BIT (1 << 0) #define GAMMA_MODE_MODE_12BIT (2 << 0) #define GAMMA_MODE_MODE_SPLIT (3 << 0) +/* DMC/CSR */ +#define CSR_PROGRAM(i) _MMIO(0x80000 + (i) * 4) +#define CSR_SSP_BASE_ADDR_GEN9 0x00002FC0 +#define CSR_HTP_ADDR_SKL 0x00500034 +#define CSR_SSP_BASE _MMIO(0x8F074) +#define CSR_HTP_SKL _MMIO(0x8F004) +#define CSR_LAST_WRITE _MMIO(0x8F034) +#define CSR_LAST_WRITE_VALUE 0xc003b400 +/* MMIO address range for CSR program (0x80000 - 0x82FFF) */ +#define CSR_MMIO_START_RANGE 0x80000 +#define CSR_MMIO_END_RANGE 0x8FFFF +#define SKL_CSR_DC3_DC5_COUNT _MMIO(0x80030) +#define SKL_CSR_DC5_DC6_COUNT _MMIO(0x8002C) +#define BXT_CSR_DC3_DC5_COUNT _MMIO(0x80038) + /* interrupts */ #define DE_MASTER_IRQ_CONTROL (1 << 31) #define DE_SPRITEB_FLIP_DONE (1 << 29) @@ -5747,20 +5826,20 @@ enum skl_disp_power_wells { #define DE_PIPEA_VBLANK_IVB (1<<0) #define DE_PIPE_VBLANK_IVB(pipe) (1 << ((pipe) * 5)) -#define VLV_MASTER_IER 0x4400c /* Gunit master IER */ +#define VLV_MASTER_IER _MMIO(0x4400c) /* Gunit master IER */ #define MASTER_INTERRUPT_ENABLE (1<<31) -#define DEISR 0x44000 -#define DEIMR 0x44004 -#define DEIIR 0x44008 -#define DEIER 0x4400c +#define DEISR _MMIO(0x44000) +#define DEIMR _MMIO(0x44004) +#define DEIIR _MMIO(0x44008) +#define DEIER _MMIO(0x4400c) -#define GTISR 0x44010 -#define GTIMR 0x44014 -#define GTIIR 0x44018 -#define GTIER 0x4401c +#define GTISR _MMIO(0x44010) +#define GTIMR _MMIO(0x44014) +#define GTIIR _MMIO(0x44018) +#define GTIER _MMIO(0x4401c) -#define GEN8_MASTER_IRQ 0x44200 +#define GEN8_MASTER_IRQ _MMIO(0x44200) #define GEN8_MASTER_IRQ_CONTROL (1<<31) #define GEN8_PCU_IRQ (1<<30) #define GEN8_DE_PCH_IRQ (1<<23) @@ -5777,10 +5856,10 @@ enum skl_disp_power_wells { #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_GT_ISR(which) _MMIO(0x44300 + (0x10 * (which))) +#define GEN8_GT_IMR(which) _MMIO(0x44304 + (0x10 * (which))) +#define GEN8_GT_IIR(which) _MMIO(0x44308 + (0x10 * (which))) +#define GEN8_GT_IER(which) _MMIO(0x4430c + (0x10 * (which))) #define GEN8_RCS_IRQ_SHIFT 0 #define GEN8_BCS_IRQ_SHIFT 16 @@ -5789,10 +5868,10 @@ enum skl_disp_power_wells { #define GEN8_VECS_IRQ_SHIFT 0 #define GEN8_WD_IRQ_SHIFT 16 -#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_DE_PIPE_ISR(pipe) _MMIO(0x44400 + (0x10 * (pipe))) +#define GEN8_DE_PIPE_IMR(pipe) _MMIO(0x44404 + (0x10 * (pipe))) +#define GEN8_DE_PIPE_IIR(pipe) _MMIO(0x44408 + (0x10 * (pipe))) +#define GEN8_DE_PIPE_IER(pipe) _MMIO(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) @@ -5825,10 +5904,10 @@ enum skl_disp_power_wells { GEN9_PIPE_PLANE2_FAULT | \ GEN9_PIPE_PLANE1_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_DE_PORT_ISR _MMIO(0x44440) +#define GEN8_DE_PORT_IMR _MMIO(0x44444) +#define GEN8_DE_PORT_IIR _MMIO(0x44448) +#define GEN8_DE_PORT_IER _MMIO(0x4444c) #define GEN9_AUX_CHANNEL_D (1 << 27) #define GEN9_AUX_CHANNEL_C (1 << 26) #define GEN9_AUX_CHANNEL_B (1 << 25) @@ -5842,23 +5921,23 @@ enum skl_disp_power_wells { #define BXT_DE_PORT_GMBUS (1 << 1) #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_ISR _MMIO(0x44460) +#define GEN8_DE_MISC_IMR _MMIO(0x44464) +#define GEN8_DE_MISC_IIR _MMIO(0x44468) +#define GEN8_DE_MISC_IER _MMIO(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 GEN8_PCU_ISR _MMIO(0x444e0) +#define GEN8_PCU_IMR _MMIO(0x444e4) +#define GEN8_PCU_IIR _MMIO(0x444e8) +#define GEN8_PCU_IER _MMIO(0x444ec) -#define ILK_DISPLAY_CHICKEN2 0x42004 +#define ILK_DISPLAY_CHICKEN2 _MMIO(0x42004) /* Required on all Ironlake and Sandybridge according to the B-Spec. */ #define ILK_ELPIN_409_SELECT (1 << 25) #define ILK_DPARB_GATE (1<<22) #define ILK_VSDPFD_FULL (1<<21) -#define FUSE_STRAP 0x42014 +#define FUSE_STRAP _MMIO(0x42014) #define ILK_INTERNAL_GRAPHICS_DISABLE (1 << 31) #define ILK_INTERNAL_DISPLAY_DISABLE (1 << 30) #define ILK_DISPLAY_DEBUG_DISABLE (1 << 29) @@ -5867,18 +5946,18 @@ enum skl_disp_power_wells { #define HSW_CDCLK_LIMIT (1 << 24) #define ILK_DESKTOP (1 << 23) -#define ILK_DSPCLK_GATE_D 0x42020 +#define ILK_DSPCLK_GATE_D _MMIO(0x42020) #define ILK_VRHUNIT_CLOCK_GATE_DISABLE (1 << 28) #define ILK_DPFCUNIT_CLOCK_GATE_DISABLE (1 << 9) #define ILK_DPFCRUNIT_CLOCK_GATE_DISABLE (1 << 8) #define ILK_DPFDUNIT_CLOCK_GATE_ENABLE (1 << 7) #define ILK_DPARBUNIT_CLOCK_GATE_ENABLE (1 << 5) -#define IVB_CHICKEN3 0x4200c +#define IVB_CHICKEN3 _MMIO(0x4200c) # define CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE (1 << 5) # define CHICKEN3_DGMG_DONE_FIX_DISABLE (1 << 2) -#define CHICKEN_PAR1_1 0x42080 +#define CHICKEN_PAR1_1 _MMIO(0x42080) #define DPA_MASK_VBLANK_SRD (1 << 15) #define FORCE_ARB_IDLE_PLANES (1 << 14) @@ -5886,70 +5965,70 @@ enum skl_disp_power_wells { #define _CHICKEN_PIPESL_1_B 0x420b4 #define HSW_FBCQ_DIS (1 << 22) #define BDW_DPRS_MASK_VBLANK_SRD (1 << 0) -#define CHICKEN_PIPESL_1(pipe) _PIPE(pipe, _CHICKEN_PIPESL_1_A, _CHICKEN_PIPESL_1_B) +#define CHICKEN_PIPESL_1(pipe) _MMIO_PIPE(pipe, _CHICKEN_PIPESL_1_A, _CHICKEN_PIPESL_1_B) -#define DISP_ARB_CTL 0x45000 +#define DISP_ARB_CTL _MMIO(0x45000) #define DISP_TILE_SURFACE_SWIZZLING (1<<13) #define DISP_FBC_WM_DIS (1<<15) -#define DISP_ARB_CTL2 0x45004 +#define DISP_ARB_CTL2 _MMIO(0x45004) #define DISP_DATA_PARTITION_5_6 (1<<6) -#define DBUF_CTL 0x45008 +#define DBUF_CTL _MMIO(0x45008) #define DBUF_POWER_REQUEST (1<<31) #define DBUF_POWER_STATE (1<<30) -#define GEN7_MSG_CTL 0x45010 +#define GEN7_MSG_CTL _MMIO(0x45010) #define WAIT_FOR_PCH_RESET_ACK (1<<1) #define WAIT_FOR_PCH_FLR_ACK (1<<0) -#define HSW_NDE_RSTWRN_OPT 0x46408 +#define HSW_NDE_RSTWRN_OPT _MMIO(0x46408) #define RESET_PCH_HANDSHAKE_ENABLE (1<<4) -#define SKL_DFSM 0x51000 +#define SKL_DFSM _MMIO(0x51000) #define SKL_DFSM_CDCLK_LIMIT_MASK (3 << 23) #define SKL_DFSM_CDCLK_LIMIT_675 (0 << 23) #define SKL_DFSM_CDCLK_LIMIT_540 (1 << 23) #define SKL_DFSM_CDCLK_LIMIT_450 (2 << 23) #define SKL_DFSM_CDCLK_LIMIT_337_5 (3 << 23) -#define FF_SLICE_CS_CHICKEN2 0x20e4 +#define FF_SLICE_CS_CHICKEN2 _MMIO(0x20e4) #define GEN9_TSG_BARRIER_ACK_DISABLE (1<<8) /* GEN7 chicken */ -#define GEN7_COMMON_SLICE_CHICKEN1 0x7010 +#define GEN7_COMMON_SLICE_CHICKEN1 _MMIO(0x7010) # define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC ((1<<10) | (1<<26)) # define GEN9_RHWO_OPTIMIZATION_DISABLE (1<<14) -#define COMMON_SLICE_CHICKEN2 0x7014 +#define COMMON_SLICE_CHICKEN2 _MMIO(0x7014) # define GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE (1<<0) -#define HIZ_CHICKEN 0x7018 +#define HIZ_CHICKEN _MMIO(0x7018) # define CHV_HZ_8X8_MODE_IN_1X (1<<15) # define BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE (1<<3) -#define GEN9_SLICE_COMMON_ECO_CHICKEN0 0x7308 +#define GEN9_SLICE_COMMON_ECO_CHICKEN0 _MMIO(0x7308) #define DISABLE_PIXEL_MASK_CAMMING (1<<14) -#define GEN7_L3SQCREG1 0xB010 +#define GEN7_L3SQCREG1 _MMIO(0xB010) #define VLV_B0_WA_L3SQCREG1_VALUE 0x00D30000 -#define GEN8_L3SQCREG1 0xB100 +#define GEN8_L3SQCREG1 _MMIO(0xB100) #define BDW_WA_L3SQCREG1_DEFAULT 0x784000 -#define GEN7_L3CNTLREG1 0xB01C +#define GEN7_L3CNTLREG1 _MMIO(0xB01C) #define GEN7_WA_FOR_GEN7_L3_CONTROL 0x3C47FF8C #define GEN7_L3AGDIS (1<<19) -#define GEN7_L3CNTLREG2 0xB020 -#define GEN7_L3CNTLREG3 0xB024 +#define GEN7_L3CNTLREG2 _MMIO(0xB020) +#define GEN7_L3CNTLREG3 _MMIO(0xB024) -#define GEN7_L3_CHICKEN_MODE_REGISTER 0xB030 +#define GEN7_L3_CHICKEN_MODE_REGISTER _MMIO(0xB030) #define GEN7_WA_L3_CHICKEN_MODE 0x20000000 -#define GEN7_L3SQCREG4 0xb034 +#define GEN7_L3SQCREG4 _MMIO(0xb034) #define L3SQ_URB_READ_CAM_MATCH_DISABLE (1<<27) -#define GEN8_L3SQCREG4 0xb118 +#define GEN8_L3SQCREG4 _MMIO(0xb118) #define GEN8_LQSC_RO_PERF_DIS (1<<27) #define GEN8_LQSC_FLUSH_COHERENT_LINES (1<<21) /* GEN8 chicken */ -#define HDC_CHICKEN0 0x7300 +#define HDC_CHICKEN0 _MMIO(0x7300) #define HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE (1<<15) #define HDC_FENCE_DEST_SLM_DISABLE (1<<14) #define HDC_DONOT_FETCH_MEM_WHEN_MASKED (1<<11) @@ -5958,17 +6037,17 @@ enum skl_disp_power_wells { #define HDC_BARRIER_PERFORMANCE_DISABLE (1<<10) /* GEN9 chicken */ -#define SLICE_ECO_CHICKEN0 0x7308 +#define SLICE_ECO_CHICKEN0 _MMIO(0x7308) #define PIXEL_MASK_CAMMING_DISABLE (1 << 14) /* WaCatErrorRejectionIssue */ -#define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG 0x9030 +#define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG _MMIO(0x9030) #define GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB (1<<11) -#define HSW_SCRATCH1 0xb038 +#define HSW_SCRATCH1 _MMIO(0xb038) #define HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE (1<<27) -#define BDW_SCRATCH1 0xb11c +#define BDW_SCRATCH1 _MMIO(0xb11c) #define GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE (1<<2) /* PCH */ @@ -6062,12 +6141,12 @@ enum skl_disp_power_wells { SDE_FDI_RXB_CPT | \ SDE_FDI_RXA_CPT) -#define SDEISR 0xc4000 -#define SDEIMR 0xc4004 -#define SDEIIR 0xc4008 -#define SDEIER 0xc400c +#define SDEISR _MMIO(0xc4000) +#define SDEIMR _MMIO(0xc4004) +#define SDEIIR _MMIO(0xc4008) +#define SDEIER _MMIO(0xc400c) -#define SERR_INT 0xc4040 +#define SERR_INT _MMIO(0xc4040) #define SERR_INT_POISON (1<<31) #define SERR_INT_TRANS_C_FIFO_UNDERRUN (1<<6) #define SERR_INT_TRANS_B_FIFO_UNDERRUN (1<<3) @@ -6075,7 +6154,7 @@ enum skl_disp_power_wells { #define SERR_INT_TRANS_FIFO_UNDERRUN(pipe) (1<<((pipe)*3)) /* digital port hotplug */ -#define PCH_PORT_HOTPLUG 0xc4030 /* SHOTPLUG_CTL */ +#define PCH_PORT_HOTPLUG _MMIO(0xc4030) /* SHOTPLUG_CTL */ #define PORTA_HOTPLUG_ENABLE (1 << 28) /* LPT:LP+ & BXT */ #define PORTA_HOTPLUG_STATUS_MASK (3 << 24) /* SPT+ & BXT */ #define PORTA_HOTPLUG_NO_DETECT (0 << 24) /* SPT+ & BXT */ @@ -6112,42 +6191,42 @@ enum skl_disp_power_wells { #define PORTB_HOTPLUG_SHORT_DETECT (1 << 0) #define PORTB_HOTPLUG_LONG_DETECT (2 << 0) -#define PCH_PORT_HOTPLUG2 0xc403C /* SHOTPLUG_CTL2 SPT+ */ +#define PCH_PORT_HOTPLUG2 _MMIO(0xc403C) /* SHOTPLUG_CTL2 SPT+ */ #define PORTE_HOTPLUG_ENABLE (1 << 4) #define PORTE_HOTPLUG_STATUS_MASK (3 << 0) #define PORTE_HOTPLUG_NO_DETECT (0 << 0) #define PORTE_HOTPLUG_SHORT_DETECT (1 << 0) #define PORTE_HOTPLUG_LONG_DETECT (2 << 0) -#define PCH_GPIOA 0xc5010 -#define PCH_GPIOB 0xc5014 -#define PCH_GPIOC 0xc5018 -#define PCH_GPIOD 0xc501c -#define PCH_GPIOE 0xc5020 -#define PCH_GPIOF 0xc5024 +#define PCH_GPIOA _MMIO(0xc5010) +#define PCH_GPIOB _MMIO(0xc5014) +#define PCH_GPIOC _MMIO(0xc5018) +#define PCH_GPIOD _MMIO(0xc501c) +#define PCH_GPIOE _MMIO(0xc5020) +#define PCH_GPIOF _MMIO(0xc5024) -#define PCH_GMBUS0 0xc5100 -#define PCH_GMBUS1 0xc5104 -#define PCH_GMBUS2 0xc5108 -#define PCH_GMBUS3 0xc510c -#define PCH_GMBUS4 0xc5110 -#define PCH_GMBUS5 0xc5120 +#define PCH_GMBUS0 _MMIO(0xc5100) +#define PCH_GMBUS1 _MMIO(0xc5104) +#define PCH_GMBUS2 _MMIO(0xc5108) +#define PCH_GMBUS3 _MMIO(0xc510c) +#define PCH_GMBUS4 _MMIO(0xc5110) +#define PCH_GMBUS5 _MMIO(0xc5120) #define _PCH_DPLL_A 0xc6014 #define _PCH_DPLL_B 0xc6018 -#define PCH_DPLL(pll) (pll == 0 ? _PCH_DPLL_A : _PCH_DPLL_B) +#define PCH_DPLL(pll) _MMIO(pll == 0 ? _PCH_DPLL_A : _PCH_DPLL_B) #define _PCH_FPA0 0xc6040 #define FP_CB_TUNE (0x3<<22) #define _PCH_FPA1 0xc6044 #define _PCH_FPB0 0xc6048 #define _PCH_FPB1 0xc604c -#define PCH_FP0(pll) (pll == 0 ? _PCH_FPA0 : _PCH_FPB0) -#define PCH_FP1(pll) (pll == 0 ? _PCH_FPA1 : _PCH_FPB1) +#define PCH_FP0(pll) _MMIO(pll == 0 ? _PCH_FPA0 : _PCH_FPB0) +#define PCH_FP1(pll) _MMIO(pll == 0 ? _PCH_FPA1 : _PCH_FPB1) -#define PCH_DPLL_TEST 0xc606c +#define PCH_DPLL_TEST _MMIO(0xc606c) -#define PCH_DREF_CONTROL 0xC6200 +#define PCH_DREF_CONTROL _MMIO(0xC6200) #define DREF_CONTROL_MASK 0x7fc3 #define DREF_CPU_SOURCE_OUTPUT_DISABLE (0<<13) #define DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD (2<<13) @@ -6170,19 +6249,19 @@ enum skl_disp_power_wells { #define DREF_SSC4_DISABLE (0) #define DREF_SSC4_ENABLE (1) -#define PCH_RAWCLK_FREQ 0xc6204 +#define PCH_RAWCLK_FREQ _MMIO(0xc6204) #define FDL_TP1_TIMER_SHIFT 12 #define FDL_TP1_TIMER_MASK (3<<12) #define FDL_TP2_TIMER_SHIFT 10 #define FDL_TP2_TIMER_MASK (3<<10) #define RAWCLK_FREQ_MASK 0x3ff -#define PCH_DPLL_TMR_CFG 0xc6208 +#define PCH_DPLL_TMR_CFG _MMIO(0xc6208) -#define PCH_SSC4_PARMS 0xc6210 -#define PCH_SSC4_AUX_PARMS 0xc6214 +#define PCH_SSC4_PARMS _MMIO(0xc6210) +#define PCH_SSC4_AUX_PARMS _MMIO(0xc6214) -#define PCH_DPLL_SEL 0xc7000 +#define PCH_DPLL_SEL _MMIO(0xc7000) #define TRANS_DPLLB_SEL(pipe) (1 << ((pipe) * 4)) #define TRANS_DPLLA_SEL(pipe) 0 #define TRANS_DPLL_ENABLE(pipe) (1 << ((pipe) * 4 + 3)) @@ -6230,79 +6309,73 @@ enum skl_disp_power_wells { #define _VIDEO_DIP_DATA_B 0xe1208 #define _VIDEO_DIP_GCP_B 0xe1210 -#define TVIDEO_DIP_CTL(pipe) _PIPE(pipe, _VIDEO_DIP_CTL_A, _VIDEO_DIP_CTL_B) -#define TVIDEO_DIP_DATA(pipe) _PIPE(pipe, _VIDEO_DIP_DATA_A, _VIDEO_DIP_DATA_B) -#define TVIDEO_DIP_GCP(pipe) _PIPE(pipe, _VIDEO_DIP_GCP_A, _VIDEO_DIP_GCP_B) +#define TVIDEO_DIP_CTL(pipe) _MMIO_PIPE(pipe, _VIDEO_DIP_CTL_A, _VIDEO_DIP_CTL_B) +#define TVIDEO_DIP_DATA(pipe) _MMIO_PIPE(pipe, _VIDEO_DIP_DATA_A, _VIDEO_DIP_DATA_B) +#define TVIDEO_DIP_GCP(pipe) _MMIO_PIPE(pipe, _VIDEO_DIP_GCP_A, _VIDEO_DIP_GCP_B) /* Per-transcoder DIP controls (VLV) */ -#define VLV_VIDEO_DIP_CTL_A (VLV_DISPLAY_BASE + 0x60200) -#define VLV_VIDEO_DIP_DATA_A (VLV_DISPLAY_BASE + 0x60208) -#define VLV_VIDEO_DIP_GDCP_PAYLOAD_A (VLV_DISPLAY_BASE + 0x60210) +#define _VLV_VIDEO_DIP_CTL_A (VLV_DISPLAY_BASE + 0x60200) +#define _VLV_VIDEO_DIP_DATA_A (VLV_DISPLAY_BASE + 0x60208) +#define _VLV_VIDEO_DIP_GDCP_PAYLOAD_A (VLV_DISPLAY_BASE + 0x60210) -#define VLV_VIDEO_DIP_CTL_B (VLV_DISPLAY_BASE + 0x61170) -#define VLV_VIDEO_DIP_DATA_B (VLV_DISPLAY_BASE + 0x61174) -#define VLV_VIDEO_DIP_GDCP_PAYLOAD_B (VLV_DISPLAY_BASE + 0x61178) +#define _VLV_VIDEO_DIP_CTL_B (VLV_DISPLAY_BASE + 0x61170) +#define _VLV_VIDEO_DIP_DATA_B (VLV_DISPLAY_BASE + 0x61174) +#define _VLV_VIDEO_DIP_GDCP_PAYLOAD_B (VLV_DISPLAY_BASE + 0x61178) -#define CHV_VIDEO_DIP_CTL_C (VLV_DISPLAY_BASE + 0x611f0) -#define CHV_VIDEO_DIP_DATA_C (VLV_DISPLAY_BASE + 0x611f4) -#define CHV_VIDEO_DIP_GDCP_PAYLOAD_C (VLV_DISPLAY_BASE + 0x611f8) +#define _CHV_VIDEO_DIP_CTL_C (VLV_DISPLAY_BASE + 0x611f0) +#define _CHV_VIDEO_DIP_DATA_C (VLV_DISPLAY_BASE + 0x611f4) +#define _CHV_VIDEO_DIP_GDCP_PAYLOAD_C (VLV_DISPLAY_BASE + 0x611f8) #define VLV_TVIDEO_DIP_CTL(pipe) \ - _PIPE3((pipe), VLV_VIDEO_DIP_CTL_A, \ - VLV_VIDEO_DIP_CTL_B, CHV_VIDEO_DIP_CTL_C) + _MMIO_PIPE3((pipe), _VLV_VIDEO_DIP_CTL_A, \ + _VLV_VIDEO_DIP_CTL_B, _CHV_VIDEO_DIP_CTL_C) #define VLV_TVIDEO_DIP_DATA(pipe) \ - _PIPE3((pipe), VLV_VIDEO_DIP_DATA_A, \ - VLV_VIDEO_DIP_DATA_B, CHV_VIDEO_DIP_DATA_C) + _MMIO_PIPE3((pipe), _VLV_VIDEO_DIP_DATA_A, \ + _VLV_VIDEO_DIP_DATA_B, _CHV_VIDEO_DIP_DATA_C) #define VLV_TVIDEO_DIP_GCP(pipe) \ - _PIPE3((pipe), VLV_VIDEO_DIP_GDCP_PAYLOAD_A, \ - VLV_VIDEO_DIP_GDCP_PAYLOAD_B, CHV_VIDEO_DIP_GDCP_PAYLOAD_C) + _MMIO_PIPE3((pipe), _VLV_VIDEO_DIP_GDCP_PAYLOAD_A, \ + _VLV_VIDEO_DIP_GDCP_PAYLOAD_B, _CHV_VIDEO_DIP_GDCP_PAYLOAD_C) /* Haswell DIP controls */ -#define HSW_VIDEO_DIP_CTL_A 0x60200 -#define HSW_VIDEO_DIP_AVI_DATA_A 0x60220 -#define HSW_VIDEO_DIP_VS_DATA_A 0x60260 -#define HSW_VIDEO_DIP_SPD_DATA_A 0x602A0 -#define HSW_VIDEO_DIP_GMP_DATA_A 0x602E0 -#define HSW_VIDEO_DIP_VSC_DATA_A 0x60320 -#define HSW_VIDEO_DIP_AVI_ECC_A 0x60240 -#define HSW_VIDEO_DIP_VS_ECC_A 0x60280 -#define HSW_VIDEO_DIP_SPD_ECC_A 0x602C0 -#define HSW_VIDEO_DIP_GMP_ECC_A 0x60300 -#define HSW_VIDEO_DIP_VSC_ECC_A 0x60344 -#define HSW_VIDEO_DIP_GCP_A 0x60210 - -#define HSW_VIDEO_DIP_CTL_B 0x61200 -#define HSW_VIDEO_DIP_AVI_DATA_B 0x61220 -#define HSW_VIDEO_DIP_VS_DATA_B 0x61260 -#define HSW_VIDEO_DIP_SPD_DATA_B 0x612A0 -#define HSW_VIDEO_DIP_GMP_DATA_B 0x612E0 -#define HSW_VIDEO_DIP_VSC_DATA_B 0x61320 -#define HSW_VIDEO_DIP_BVI_ECC_B 0x61240 -#define HSW_VIDEO_DIP_VS_ECC_B 0x61280 -#define HSW_VIDEO_DIP_SPD_ECC_B 0x612C0 -#define HSW_VIDEO_DIP_GMP_ECC_B 0x61300 -#define HSW_VIDEO_DIP_VSC_ECC_B 0x61344 -#define HSW_VIDEO_DIP_GCP_B 0x61210 - -#define HSW_TVIDEO_DIP_CTL(trans) \ - _TRANSCODER2(trans, HSW_VIDEO_DIP_CTL_A) -#define HSW_TVIDEO_DIP_AVI_DATA(trans, i) \ - (_TRANSCODER2(trans, HSW_VIDEO_DIP_AVI_DATA_A) + (i) * 4) -#define HSW_TVIDEO_DIP_VS_DATA(trans, i) \ - (_TRANSCODER2(trans, HSW_VIDEO_DIP_VS_DATA_A) + (i) * 4) -#define HSW_TVIDEO_DIP_SPD_DATA(trans, i) \ - (_TRANSCODER2(trans, HSW_VIDEO_DIP_SPD_DATA_A) + (i) * 4) -#define HSW_TVIDEO_DIP_GCP(trans) \ - _TRANSCODER2(trans, HSW_VIDEO_DIP_GCP_A) -#define HSW_TVIDEO_DIP_VSC_DATA(trans, i) \ - (_TRANSCODER2(trans, HSW_VIDEO_DIP_VSC_DATA_A) + (i) * 4) - -#define HSW_STEREO_3D_CTL_A 0x70020 -#define S3D_ENABLE (1<<31) -#define HSW_STEREO_3D_CTL_B 0x71020 - -#define HSW_STEREO_3D_CTL(trans) \ - _PIPE2(trans, HSW_STEREO_3D_CTL_A) + +#define _HSW_VIDEO_DIP_CTL_A 0x60200 +#define _HSW_VIDEO_DIP_AVI_DATA_A 0x60220 +#define _HSW_VIDEO_DIP_VS_DATA_A 0x60260 +#define _HSW_VIDEO_DIP_SPD_DATA_A 0x602A0 +#define _HSW_VIDEO_DIP_GMP_DATA_A 0x602E0 +#define _HSW_VIDEO_DIP_VSC_DATA_A 0x60320 +#define _HSW_VIDEO_DIP_AVI_ECC_A 0x60240 +#define _HSW_VIDEO_DIP_VS_ECC_A 0x60280 +#define _HSW_VIDEO_DIP_SPD_ECC_A 0x602C0 +#define _HSW_VIDEO_DIP_GMP_ECC_A 0x60300 +#define _HSW_VIDEO_DIP_VSC_ECC_A 0x60344 +#define _HSW_VIDEO_DIP_GCP_A 0x60210 + +#define _HSW_VIDEO_DIP_CTL_B 0x61200 +#define _HSW_VIDEO_DIP_AVI_DATA_B 0x61220 +#define _HSW_VIDEO_DIP_VS_DATA_B 0x61260 +#define _HSW_VIDEO_DIP_SPD_DATA_B 0x612A0 +#define _HSW_VIDEO_DIP_GMP_DATA_B 0x612E0 +#define _HSW_VIDEO_DIP_VSC_DATA_B 0x61320 +#define _HSW_VIDEO_DIP_BVI_ECC_B 0x61240 +#define _HSW_VIDEO_DIP_VS_ECC_B 0x61280 +#define _HSW_VIDEO_DIP_SPD_ECC_B 0x612C0 +#define _HSW_VIDEO_DIP_GMP_ECC_B 0x61300 +#define _HSW_VIDEO_DIP_VSC_ECC_B 0x61344 +#define _HSW_VIDEO_DIP_GCP_B 0x61210 + +#define HSW_TVIDEO_DIP_CTL(trans) _MMIO_TRANS2(trans, _HSW_VIDEO_DIP_CTL_A) +#define HSW_TVIDEO_DIP_AVI_DATA(trans, i) _MMIO_TRANS2(trans, _HSW_VIDEO_DIP_AVI_DATA_A + (i) * 4) +#define HSW_TVIDEO_DIP_VS_DATA(trans, i) _MMIO_TRANS2(trans, _HSW_VIDEO_DIP_VS_DATA_A + (i) * 4) +#define HSW_TVIDEO_DIP_SPD_DATA(trans, i) _MMIO_TRANS2(trans, _HSW_VIDEO_DIP_SPD_DATA_A + (i) * 4) +#define HSW_TVIDEO_DIP_GCP(trans) _MMIO_TRANS2(trans, _HSW_VIDEO_DIP_GCP_A) +#define HSW_TVIDEO_DIP_VSC_DATA(trans, i) _MMIO_TRANS2(trans, _HSW_VIDEO_DIP_VSC_DATA_A + (i) * 4) + +#define _HSW_STEREO_3D_CTL_A 0x70020 +#define S3D_ENABLE (1<<31) +#define _HSW_STEREO_3D_CTL_B 0x71020 + +#define HSW_STEREO_3D_CTL(trans) _MMIO_PIPE2(trans, _HSW_STEREO_3D_CTL_A) #define _PCH_TRANS_HTOTAL_B 0xe1000 #define _PCH_TRANS_HBLANK_B 0xe1004 @@ -6310,16 +6383,15 @@ enum skl_disp_power_wells { #define _PCH_TRANS_VTOTAL_B 0xe100c #define _PCH_TRANS_VBLANK_B 0xe1010 #define _PCH_TRANS_VSYNC_B 0xe1014 -#define _PCH_TRANS_VSYNCSHIFT_B 0xe1028 +#define _PCH_TRANS_VSYNCSHIFT_B 0xe1028 -#define PCH_TRANS_HTOTAL(pipe) _PIPE(pipe, _PCH_TRANS_HTOTAL_A, _PCH_TRANS_HTOTAL_B) -#define PCH_TRANS_HBLANK(pipe) _PIPE(pipe, _PCH_TRANS_HBLANK_A, _PCH_TRANS_HBLANK_B) -#define PCH_TRANS_HSYNC(pipe) _PIPE(pipe, _PCH_TRANS_HSYNC_A, _PCH_TRANS_HSYNC_B) -#define PCH_TRANS_VTOTAL(pipe) _PIPE(pipe, _PCH_TRANS_VTOTAL_A, _PCH_TRANS_VTOTAL_B) -#define PCH_TRANS_VBLANK(pipe) _PIPE(pipe, _PCH_TRANS_VBLANK_A, _PCH_TRANS_VBLANK_B) -#define PCH_TRANS_VSYNC(pipe) _PIPE(pipe, _PCH_TRANS_VSYNC_A, _PCH_TRANS_VSYNC_B) -#define PCH_TRANS_VSYNCSHIFT(pipe) _PIPE(pipe, _PCH_TRANS_VSYNCSHIFT_A, \ - _PCH_TRANS_VSYNCSHIFT_B) +#define PCH_TRANS_HTOTAL(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_HTOTAL_A, _PCH_TRANS_HTOTAL_B) +#define PCH_TRANS_HBLANK(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_HBLANK_A, _PCH_TRANS_HBLANK_B) +#define PCH_TRANS_HSYNC(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_HSYNC_A, _PCH_TRANS_HSYNC_B) +#define PCH_TRANS_VTOTAL(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_VTOTAL_A, _PCH_TRANS_VTOTAL_B) +#define PCH_TRANS_VBLANK(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_VBLANK_A, _PCH_TRANS_VBLANK_B) +#define PCH_TRANS_VSYNC(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_VSYNC_A, _PCH_TRANS_VSYNC_B) +#define PCH_TRANS_VSYNCSHIFT(pipe) _MMIO_PIPE(pipe, _PCH_TRANS_VSYNCSHIFT_A, _PCH_TRANS_VSYNCSHIFT_B) #define _PCH_TRANSB_DATA_M1 0xe1030 #define _PCH_TRANSB_DATA_N1 0xe1034 @@ -6330,19 +6402,19 @@ enum skl_disp_power_wells { #define _PCH_TRANSB_LINK_M2 0xe1048 #define _PCH_TRANSB_LINK_N2 0xe104c -#define PCH_TRANS_DATA_M1(pipe) _PIPE(pipe, _PCH_TRANSA_DATA_M1, _PCH_TRANSB_DATA_M1) -#define PCH_TRANS_DATA_N1(pipe) _PIPE(pipe, _PCH_TRANSA_DATA_N1, _PCH_TRANSB_DATA_N1) -#define PCH_TRANS_DATA_M2(pipe) _PIPE(pipe, _PCH_TRANSA_DATA_M2, _PCH_TRANSB_DATA_M2) -#define PCH_TRANS_DATA_N2(pipe) _PIPE(pipe, _PCH_TRANSA_DATA_N2, _PCH_TRANSB_DATA_N2) -#define PCH_TRANS_LINK_M1(pipe) _PIPE(pipe, _PCH_TRANSA_LINK_M1, _PCH_TRANSB_LINK_M1) -#define PCH_TRANS_LINK_N1(pipe) _PIPE(pipe, _PCH_TRANSA_LINK_N1, _PCH_TRANSB_LINK_N1) -#define PCH_TRANS_LINK_M2(pipe) _PIPE(pipe, _PCH_TRANSA_LINK_M2, _PCH_TRANSB_LINK_M2) -#define PCH_TRANS_LINK_N2(pipe) _PIPE(pipe, _PCH_TRANSA_LINK_N2, _PCH_TRANSB_LINK_N2) +#define PCH_TRANS_DATA_M1(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_DATA_M1, _PCH_TRANSB_DATA_M1) +#define PCH_TRANS_DATA_N1(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_DATA_N1, _PCH_TRANSB_DATA_N1) +#define PCH_TRANS_DATA_M2(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_DATA_M2, _PCH_TRANSB_DATA_M2) +#define PCH_TRANS_DATA_N2(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_DATA_N2, _PCH_TRANSB_DATA_N2) +#define PCH_TRANS_LINK_M1(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_LINK_M1, _PCH_TRANSB_LINK_M1) +#define PCH_TRANS_LINK_N1(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_LINK_N1, _PCH_TRANSB_LINK_N1) +#define PCH_TRANS_LINK_M2(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_LINK_M2, _PCH_TRANSB_LINK_M2) +#define PCH_TRANS_LINK_N2(pipe) _MMIO_PIPE(pipe, _PCH_TRANSA_LINK_N2, _PCH_TRANSB_LINK_N2) #define _PCH_TRANSACONF 0xf0008 #define _PCH_TRANSBCONF 0xf1008 -#define PCH_TRANSCONF(pipe) _PIPE(pipe, _PCH_TRANSACONF, _PCH_TRANSBCONF) -#define LPT_TRANSCONF _PCH_TRANSACONF /* lpt has only one transcoder */ +#define PCH_TRANSCONF(pipe) _MMIO_PIPE(pipe, _PCH_TRANSACONF, _PCH_TRANSBCONF) +#define LPT_TRANSCONF PCH_TRANSCONF(PIPE_A) /* lpt has only one transcoder */ #define TRANS_DISABLE (0<<31) #define TRANS_ENABLE (1<<31) #define TRANS_STATE_MASK (1<<30) @@ -6363,47 +6435,47 @@ enum skl_disp_power_wells { #define _TRANSA_CHICKEN1 0xf0060 #define _TRANSB_CHICKEN1 0xf1060 -#define TRANS_CHICKEN1(pipe) _PIPE(pipe, _TRANSA_CHICKEN1, _TRANSB_CHICKEN1) +#define TRANS_CHICKEN1(pipe) _MMIO_PIPE(pipe, _TRANSA_CHICKEN1, _TRANSB_CHICKEN1) #define TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE (1<<10) #define TRANS_CHICKEN1_DP0UNIT_GC_DISABLE (1<<4) #define _TRANSA_CHICKEN2 0xf0064 #define _TRANSB_CHICKEN2 0xf1064 -#define TRANS_CHICKEN2(pipe) _PIPE(pipe, _TRANSA_CHICKEN2, _TRANSB_CHICKEN2) +#define TRANS_CHICKEN2(pipe) _MMIO_PIPE(pipe, _TRANSA_CHICKEN2, _TRANSB_CHICKEN2) #define TRANS_CHICKEN2_TIMING_OVERRIDE (1<<31) #define TRANS_CHICKEN2_FDI_POLARITY_REVERSED (1<<29) #define TRANS_CHICKEN2_FRAME_START_DELAY_MASK (3<<27) #define TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER (1<<26) #define TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH (1<<25) -#define SOUTH_CHICKEN1 0xc2000 +#define SOUTH_CHICKEN1 _MMIO(0xc2000) #define FDIA_PHASE_SYNC_SHIFT_OVR 19 #define FDIA_PHASE_SYNC_SHIFT_EN 18 #define FDI_PHASE_SYNC_OVR(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_OVR - ((pipe) * 2))) #define FDI_PHASE_SYNC_EN(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2))) #define FDI_BC_BIFURCATION_SELECT (1 << 12) #define SPT_PWM_GRANULARITY (1<<0) -#define SOUTH_CHICKEN2 0xc2004 +#define SOUTH_CHICKEN2 _MMIO(0xc2004) #define FDI_MPHY_IOSFSB_RESET_STATUS (1<<13) #define FDI_MPHY_IOSFSB_RESET_CTL (1<<12) #define LPT_PWM_GRANULARITY (1<<5) #define DPLS_EDP_PPS_FIX_DIS (1<<0) -#define _FDI_RXA_CHICKEN 0xc200c -#define _FDI_RXB_CHICKEN 0xc2010 +#define _FDI_RXA_CHICKEN 0xc200c +#define _FDI_RXB_CHICKEN 0xc2010 #define FDI_RX_PHASE_SYNC_POINTER_OVR (1<<1) #define FDI_RX_PHASE_SYNC_POINTER_EN (1<<0) -#define FDI_RX_CHICKEN(pipe) _PIPE(pipe, _FDI_RXA_CHICKEN, _FDI_RXB_CHICKEN) +#define FDI_RX_CHICKEN(pipe) _MMIO_PIPE(pipe, _FDI_RXA_CHICKEN, _FDI_RXB_CHICKEN) -#define SOUTH_DSPCLK_GATE_D 0xc2020 +#define SOUTH_DSPCLK_GATE_D _MMIO(0xc2020) #define PCH_DPLUNIT_CLOCK_GATE_DISABLE (1<<30) #define PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1<<29) #define PCH_CPUNIT_CLOCK_GATE_DISABLE (1<<14) #define PCH_LP_PARTITION_LEVEL_DISABLE (1<<12) /* CPU: FDI_TX */ -#define _FDI_TXA_CTL 0x60100 -#define _FDI_TXB_CTL 0x61100 -#define FDI_TX_CTL(pipe) _PIPE(pipe, _FDI_TXA_CTL, _FDI_TXB_CTL) +#define _FDI_TXA_CTL 0x60100 +#define _FDI_TXB_CTL 0x61100 +#define FDI_TX_CTL(pipe) _MMIO_PIPE(pipe, _FDI_TXA_CTL, _FDI_TXB_CTL) #define FDI_TX_DISABLE (0<<31) #define FDI_TX_ENABLE (1<<31) #define FDI_LINK_TRAIN_PATTERN_1 (0<<28) @@ -6453,7 +6525,7 @@ enum skl_disp_power_wells { /* FDI_RX, FDI_X is hard-wired to Transcoder_X */ #define _FDI_RXA_CTL 0xf000c #define _FDI_RXB_CTL 0xf100c -#define FDI_RX_CTL(pipe) _PIPE(pipe, _FDI_RXA_CTL, _FDI_RXB_CTL) +#define FDI_RX_CTL(pipe) _MMIO_PIPE(pipe, _FDI_RXA_CTL, _FDI_RXB_CTL) #define FDI_RX_ENABLE (1<<31) /* train, dp width same as FDI_TX */ #define FDI_FS_ERRC_ENABLE (1<<27) @@ -6489,14 +6561,14 @@ enum skl_disp_power_wells { #define FDI_RX_TP1_TO_TP2_48 (2<<20) #define FDI_RX_TP1_TO_TP2_64 (3<<20) #define FDI_RX_FDI_DELAY_90 (0x90<<0) -#define FDI_RX_MISC(pipe) _PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC) +#define FDI_RX_MISC(pipe) _MMIO_PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC) -#define _FDI_RXA_TUSIZE1 0xf0030 -#define _FDI_RXA_TUSIZE2 0xf0038 -#define _FDI_RXB_TUSIZE1 0xf1030 -#define _FDI_RXB_TUSIZE2 0xf1038 -#define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1) -#define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2) +#define _FDI_RXA_TUSIZE1 0xf0030 +#define _FDI_RXA_TUSIZE2 0xf0038 +#define _FDI_RXB_TUSIZE1 0xf1030 +#define _FDI_RXB_TUSIZE2 0xf1038 +#define FDI_RX_TUSIZE1(pipe) _MMIO_PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1) +#define FDI_RX_TUSIZE2(pipe) _MMIO_PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2) /* FDI_RX interrupt register format */ #define FDI_RX_INTER_LANE_ALIGN (1<<10) @@ -6511,44 +6583,41 @@ enum skl_disp_power_wells { #define FDI_RX_CROSS_CLOCK_OVERFLOW (1<<1) #define FDI_RX_SYMBOL_QUEUE_OVERFLOW (1<<0) -#define _FDI_RXA_IIR 0xf0014 -#define _FDI_RXA_IMR 0xf0018 -#define _FDI_RXB_IIR 0xf1014 -#define _FDI_RXB_IMR 0xf1018 -#define FDI_RX_IIR(pipe) _PIPE(pipe, _FDI_RXA_IIR, _FDI_RXB_IIR) -#define FDI_RX_IMR(pipe) _PIPE(pipe, _FDI_RXA_IMR, _FDI_RXB_IMR) +#define _FDI_RXA_IIR 0xf0014 +#define _FDI_RXA_IMR 0xf0018 +#define _FDI_RXB_IIR 0xf1014 +#define _FDI_RXB_IMR 0xf1018 +#define FDI_RX_IIR(pipe) _MMIO_PIPE(pipe, _FDI_RXA_IIR, _FDI_RXB_IIR) +#define FDI_RX_IMR(pipe) _MMIO_PIPE(pipe, _FDI_RXA_IMR, _FDI_RXB_IMR) -#define FDI_PLL_CTL_1 0xfe000 -#define FDI_PLL_CTL_2 0xfe004 +#define FDI_PLL_CTL_1 _MMIO(0xfe000) +#define FDI_PLL_CTL_2 _MMIO(0xfe004) -#define PCH_LVDS 0xe1180 +#define PCH_LVDS _MMIO(0xe1180) #define LVDS_DETECTED (1 << 1) /* vlv has 2 sets of panel control regs. */ -#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 _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_VLV(port) ((port) << 30) -#define PIPEA_PP_OFF_DELAYS (VLV_DISPLAY_BASE + 0x6120c) -#define PIPEA_PP_DIVISOR (VLV_DISPLAY_BASE + 0x61210) - -#define PIPEB_PP_STATUS (VLV_DISPLAY_BASE + 0x61300) -#define PIPEB_PP_CONTROL (VLV_DISPLAY_BASE + 0x61304) -#define PIPEB_PP_ON_DELAYS (VLV_DISPLAY_BASE + 0x61308) -#define PIPEB_PP_OFF_DELAYS (VLV_DISPLAY_BASE + 0x6130c) -#define PIPEB_PP_DIVISOR (VLV_DISPLAY_BASE + 0x61310) - -#define VLV_PIPE_PP_STATUS(pipe) _PIPE(pipe, PIPEA_PP_STATUS, PIPEB_PP_STATUS) -#define VLV_PIPE_PP_CONTROL(pipe) _PIPE(pipe, PIPEA_PP_CONTROL, PIPEB_PP_CONTROL) -#define VLV_PIPE_PP_ON_DELAYS(pipe) \ - _PIPE(pipe, PIPEA_PP_ON_DELAYS, PIPEB_PP_ON_DELAYS) -#define VLV_PIPE_PP_OFF_DELAYS(pipe) \ - _PIPE(pipe, PIPEA_PP_OFF_DELAYS, PIPEB_PP_OFF_DELAYS) -#define VLV_PIPE_PP_DIVISOR(pipe) \ - _PIPE(pipe, PIPEA_PP_DIVISOR, PIPEB_PP_DIVISOR) - -#define PCH_PP_STATUS 0xc7200 -#define PCH_PP_CONTROL 0xc7204 +#define _PIPEA_PP_OFF_DELAYS (VLV_DISPLAY_BASE + 0x6120c) +#define _PIPEA_PP_DIVISOR (VLV_DISPLAY_BASE + 0x61210) + +#define _PIPEB_PP_STATUS (VLV_DISPLAY_BASE + 0x61300) +#define _PIPEB_PP_CONTROL (VLV_DISPLAY_BASE + 0x61304) +#define _PIPEB_PP_ON_DELAYS (VLV_DISPLAY_BASE + 0x61308) +#define _PIPEB_PP_OFF_DELAYS (VLV_DISPLAY_BASE + 0x6130c) +#define _PIPEB_PP_DIVISOR (VLV_DISPLAY_BASE + 0x61310) + +#define VLV_PIPE_PP_STATUS(pipe) _MMIO_PIPE(pipe, _PIPEA_PP_STATUS, _PIPEB_PP_STATUS) +#define VLV_PIPE_PP_CONTROL(pipe) _MMIO_PIPE(pipe, _PIPEA_PP_CONTROL, _PIPEB_PP_CONTROL) +#define VLV_PIPE_PP_ON_DELAYS(pipe) _MMIO_PIPE(pipe, _PIPEA_PP_ON_DELAYS, _PIPEB_PP_ON_DELAYS) +#define VLV_PIPE_PP_OFF_DELAYS(pipe) _MMIO_PIPE(pipe, _PIPEA_PP_OFF_DELAYS, _PIPEB_PP_OFF_DELAYS) +#define VLV_PIPE_PP_DIVISOR(pipe) _MMIO_PIPE(pipe, _PIPEA_PP_DIVISOR, _PIPEB_PP_DIVISOR) + +#define _PCH_PP_STATUS 0xc7200 +#define _PCH_PP_CONTROL 0xc7204 #define PANEL_UNLOCK_REGS (0xabcd << 16) #define PANEL_UNLOCK_MASK (0xffff << 16) #define BXT_POWER_CYCLE_DELAY_MASK (0x1f0) @@ -6558,7 +6627,7 @@ enum skl_disp_power_wells { #define PANEL_POWER_RESET (1 << 1) #define PANEL_POWER_OFF (0 << 0) #define PANEL_POWER_ON (1 << 0) -#define PCH_PP_ON_DELAYS 0xc7208 +#define _PCH_PP_ON_DELAYS 0xc7208 #define PANEL_PORT_SELECT_MASK (3 << 30) #define PANEL_PORT_SELECT_LVDS (0 << 30) #define PANEL_PORT_SELECT_DPA (1 << 30) @@ -6569,52 +6638,64 @@ enum skl_disp_power_wells { #define PANEL_LIGHT_ON_DELAY_MASK (0x1fff) #define PANEL_LIGHT_ON_DELAY_SHIFT 0 -#define PCH_PP_OFF_DELAYS 0xc720c +#define _PCH_PP_OFF_DELAYS 0xc720c #define PANEL_POWER_DOWN_DELAY_MASK (0x1fff0000) #define PANEL_POWER_DOWN_DELAY_SHIFT 16 #define PANEL_LIGHT_OFF_DELAY_MASK (0x1fff) #define PANEL_LIGHT_OFF_DELAY_SHIFT 0 -#define PCH_PP_DIVISOR 0xc7210 +#define _PCH_PP_DIVISOR 0xc7210 #define PP_REFERENCE_DIVIDER_MASK (0xffffff00) #define PP_REFERENCE_DIVIDER_SHIFT 8 #define PANEL_POWER_CYCLE_DELAY_MASK (0x1f) #define PANEL_POWER_CYCLE_DELAY_SHIFT 0 +#define PCH_PP_STATUS _MMIO(_PCH_PP_STATUS) +#define PCH_PP_CONTROL _MMIO(_PCH_PP_CONTROL) +#define PCH_PP_ON_DELAYS _MMIO(_PCH_PP_ON_DELAYS) +#define PCH_PP_OFF_DELAYS _MMIO(_PCH_PP_OFF_DELAYS) +#define PCH_PP_DIVISOR _MMIO(_PCH_PP_DIVISOR) + /* BXT PPS changes - 2nd set of PPS registers */ #define _BXT_PP_STATUS2 0xc7300 #define _BXT_PP_CONTROL2 0xc7304 #define _BXT_PP_ON_DELAYS2 0xc7308 #define _BXT_PP_OFF_DELAYS2 0xc730c -#define BXT_PP_STATUS(n) _PIPE(n, PCH_PP_STATUS, _BXT_PP_STATUS2) -#define BXT_PP_CONTROL(n) _PIPE(n, PCH_PP_CONTROL, _BXT_PP_CONTROL2) -#define BXT_PP_ON_DELAYS(n) _PIPE(n, PCH_PP_ON_DELAYS, _BXT_PP_ON_DELAYS2) -#define BXT_PP_OFF_DELAYS(n) _PIPE(n, PCH_PP_OFF_DELAYS, _BXT_PP_OFF_DELAYS2) - -#define PCH_DP_B 0xe4100 -#define PCH_DPB_AUX_CH_CTL 0xe4110 -#define PCH_DPB_AUX_CH_DATA1 0xe4114 -#define PCH_DPB_AUX_CH_DATA2 0xe4118 -#define PCH_DPB_AUX_CH_DATA3 0xe411c -#define PCH_DPB_AUX_CH_DATA4 0xe4120 -#define PCH_DPB_AUX_CH_DATA5 0xe4124 - -#define PCH_DP_C 0xe4200 -#define PCH_DPC_AUX_CH_CTL 0xe4210 -#define PCH_DPC_AUX_CH_DATA1 0xe4214 -#define PCH_DPC_AUX_CH_DATA2 0xe4218 -#define PCH_DPC_AUX_CH_DATA3 0xe421c -#define PCH_DPC_AUX_CH_DATA4 0xe4220 -#define PCH_DPC_AUX_CH_DATA5 0xe4224 - -#define PCH_DP_D 0xe4300 -#define PCH_DPD_AUX_CH_CTL 0xe4310 -#define PCH_DPD_AUX_CH_DATA1 0xe4314 -#define PCH_DPD_AUX_CH_DATA2 0xe4318 -#define PCH_DPD_AUX_CH_DATA3 0xe431c -#define PCH_DPD_AUX_CH_DATA4 0xe4320 -#define PCH_DPD_AUX_CH_DATA5 0xe4324 +#define BXT_PP_STATUS(n) _MMIO_PIPE(n, _PCH_PP_STATUS, _BXT_PP_STATUS2) +#define BXT_PP_CONTROL(n) _MMIO_PIPE(n, _PCH_PP_CONTROL, _BXT_PP_CONTROL2) +#define BXT_PP_ON_DELAYS(n) _MMIO_PIPE(n, _PCH_PP_ON_DELAYS, _BXT_PP_ON_DELAYS2) +#define BXT_PP_OFF_DELAYS(n) _MMIO_PIPE(n, _PCH_PP_OFF_DELAYS, _BXT_PP_OFF_DELAYS2) + +#define _PCH_DP_B 0xe4100 +#define PCH_DP_B _MMIO(_PCH_DP_B) +#define _PCH_DPB_AUX_CH_CTL 0xe4110 +#define _PCH_DPB_AUX_CH_DATA1 0xe4114 +#define _PCH_DPB_AUX_CH_DATA2 0xe4118 +#define _PCH_DPB_AUX_CH_DATA3 0xe411c +#define _PCH_DPB_AUX_CH_DATA4 0xe4120 +#define _PCH_DPB_AUX_CH_DATA5 0xe4124 + +#define _PCH_DP_C 0xe4200 +#define PCH_DP_C _MMIO(_PCH_DP_C) +#define _PCH_DPC_AUX_CH_CTL 0xe4210 +#define _PCH_DPC_AUX_CH_DATA1 0xe4214 +#define _PCH_DPC_AUX_CH_DATA2 0xe4218 +#define _PCH_DPC_AUX_CH_DATA3 0xe421c +#define _PCH_DPC_AUX_CH_DATA4 0xe4220 +#define _PCH_DPC_AUX_CH_DATA5 0xe4224 + +#define _PCH_DP_D 0xe4300 +#define PCH_DP_D _MMIO(_PCH_DP_D) +#define _PCH_DPD_AUX_CH_CTL 0xe4310 +#define _PCH_DPD_AUX_CH_DATA1 0xe4314 +#define _PCH_DPD_AUX_CH_DATA2 0xe4318 +#define _PCH_DPD_AUX_CH_DATA3 0xe431c +#define _PCH_DPD_AUX_CH_DATA4 0xe4320 +#define _PCH_DPD_AUX_CH_DATA5 0xe4324 + +#define PCH_DP_AUX_CH_CTL(port) _MMIO_PORT((port) - PORT_B, _PCH_DPB_AUX_CH_CTL, _PCH_DPC_AUX_CH_CTL) +#define PCH_DP_AUX_CH_DATA(port, i) _MMIO(_PORT((port) - PORT_B, _PCH_DPB_AUX_CH_DATA1, _PCH_DPC_AUX_CH_DATA1) + (i) * 4) /* 5 registers */ /* CPT */ #define PORT_TRANS_A_SEL_CPT 0 @@ -6627,10 +6708,10 @@ enum skl_disp_power_wells { #define SDVO_PORT_TO_PIPE_CHV(val) (((val) & (3<<24)) >> 24) #define DP_PORT_TO_PIPE_CHV(val) (((val) & (3<<16)) >> 16) -#define TRANS_DP_CTL_A 0xe0300 -#define TRANS_DP_CTL_B 0xe1300 -#define TRANS_DP_CTL_C 0xe2300 -#define TRANS_DP_CTL(pipe) _PIPE(pipe, TRANS_DP_CTL_A, TRANS_DP_CTL_B) +#define _TRANS_DP_CTL_A 0xe0300 +#define _TRANS_DP_CTL_B 0xe1300 +#define _TRANS_DP_CTL_C 0xe2300 +#define TRANS_DP_CTL(pipe) _MMIO_PIPE(pipe, _TRANS_DP_CTL_A, _TRANS_DP_CTL_B) #define TRANS_DP_OUTPUT_ENABLE (1<<31) #define TRANS_DP_PORT_SEL_B (0<<29) #define TRANS_DP_PORT_SEL_C (1<<29) @@ -6683,40 +6764,40 @@ enum skl_disp_power_wells { #define EDP_LINK_TRAIN_VOL_EMP_MASK_IVB (0x3f<<22) -#define VLV_PMWGICZ 0x1300a4 +#define VLV_PMWGICZ _MMIO(0x1300a4) -#define FORCEWAKE 0xA18C -#define FORCEWAKE_VLV 0x1300b0 -#define FORCEWAKE_ACK_VLV 0x1300b4 -#define FORCEWAKE_MEDIA_VLV 0x1300b8 -#define FORCEWAKE_ACK_MEDIA_VLV 0x1300bc -#define FORCEWAKE_ACK_HSW 0x130044 -#define FORCEWAKE_ACK 0x130090 -#define VLV_GTLC_WAKE_CTRL 0x130090 +#define FORCEWAKE _MMIO(0xA18C) +#define FORCEWAKE_VLV _MMIO(0x1300b0) +#define FORCEWAKE_ACK_VLV _MMIO(0x1300b4) +#define FORCEWAKE_MEDIA_VLV _MMIO(0x1300b8) +#define FORCEWAKE_ACK_MEDIA_VLV _MMIO(0x1300bc) +#define FORCEWAKE_ACK_HSW _MMIO(0x130044) +#define FORCEWAKE_ACK _MMIO(0x130090) +#define VLV_GTLC_WAKE_CTRL _MMIO(0x130090) #define VLV_GTLC_RENDER_CTX_EXISTS (1 << 25) #define VLV_GTLC_MEDIA_CTX_EXISTS (1 << 24) #define VLV_GTLC_ALLOWWAKEREQ (1 << 0) -#define VLV_GTLC_PW_STATUS 0x130094 +#define VLV_GTLC_PW_STATUS _MMIO(0x130094) #define VLV_GTLC_ALLOWWAKEACK (1 << 0) #define VLV_GTLC_ALLOWWAKEERR (1 << 1) #define VLV_GTLC_PW_MEDIA_STATUS_MASK (1 << 5) #define VLV_GTLC_PW_RENDER_STATUS_MASK (1 << 7) -#define FORCEWAKE_MT 0xa188 /* multi-threaded */ -#define FORCEWAKE_MEDIA_GEN9 0xa270 -#define FORCEWAKE_RENDER_GEN9 0xa278 -#define FORCEWAKE_BLITTER_GEN9 0xa188 -#define FORCEWAKE_ACK_MEDIA_GEN9 0x0D88 -#define FORCEWAKE_ACK_RENDER_GEN9 0x0D84 -#define FORCEWAKE_ACK_BLITTER_GEN9 0x130044 +#define FORCEWAKE_MT _MMIO(0xa188) /* multi-threaded */ +#define FORCEWAKE_MEDIA_GEN9 _MMIO(0xa270) +#define FORCEWAKE_RENDER_GEN9 _MMIO(0xa278) +#define FORCEWAKE_BLITTER_GEN9 _MMIO(0xa188) +#define FORCEWAKE_ACK_MEDIA_GEN9 _MMIO(0x0D88) +#define FORCEWAKE_ACK_RENDER_GEN9 _MMIO(0x0D84) +#define FORCEWAKE_ACK_BLITTER_GEN9 _MMIO(0x130044) #define FORCEWAKE_KERNEL 0x1 #define FORCEWAKE_USER 0x2 -#define FORCEWAKE_MT_ACK 0x130040 -#define ECOBUS 0xa180 +#define FORCEWAKE_MT_ACK _MMIO(0x130040) +#define ECOBUS _MMIO(0xa180) #define FORCEWAKE_MT_ENABLE (1<<5) -#define VLV_SPAREG2H 0xA194 +#define VLV_SPAREG2H _MMIO(0xA194) -#define GTFIFODBG 0x120000 +#define GTFIFODBG _MMIO(0x120000) #define GT_FIFO_SBDROPERR (1<<6) #define GT_FIFO_BLOBDROPERR (1<<5) #define GT_FIFO_SB_READ_ABORTERR (1<<4) @@ -6725,23 +6806,23 @@ enum skl_disp_power_wells { #define GT_FIFO_IAWRERR (1<<1) #define GT_FIFO_IARDERR (1<<0) -#define GTFIFOCTL 0x120008 +#define GTFIFOCTL _MMIO(0x120008) #define GT_FIFO_FREE_ENTRIES_MASK 0x7f #define GT_FIFO_NUM_RESERVED_ENTRIES 20 #define GT_FIFO_CTL_BLOCK_ALL_POLICY_STALL (1 << 12) #define GT_FIFO_CTL_RC6_POLICY_STALL (1 << 11) -#define HSW_IDICR 0x9008 +#define HSW_IDICR _MMIO(0x9008) #define IDIHASHMSK(x) (((x) & 0x3f) << 16) -#define HSW_EDRAM_PRESENT 0x120010 +#define HSW_EDRAM_PRESENT _MMIO(0x120010) #define EDRAM_ENABLED 0x1 -#define GEN6_UCGCTL1 0x9400 +#define GEN6_UCGCTL1 _MMIO(0x9400) # define GEN6_EU_TCUNIT_CLOCK_GATE_DISABLE (1 << 16) # define GEN6_BLBUNIT_CLOCK_GATE_DISABLE (1 << 5) # define GEN6_CSUNIT_CLOCK_GATE_DISABLE (1 << 7) -#define GEN6_UCGCTL2 0x9404 +#define GEN6_UCGCTL2 _MMIO(0x9404) # define GEN6_VFUNIT_CLOCK_GATE_DISABLE (1 << 31) # define GEN7_VDSUNIT_CLOCK_GATE_DISABLE (1 << 30) # define GEN7_TDLUNIT_CLOCK_GATE_DISABLE (1 << 22) @@ -6749,30 +6830,30 @@ enum skl_disp_power_wells { # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11) -#define GEN6_UCGCTL3 0x9408 +#define GEN6_UCGCTL3 _MMIO(0x9408) -#define GEN7_UCGCTL4 0x940c +#define GEN7_UCGCTL4 _MMIO(0x940c) #define GEN7_L3BANK2X_CLOCK_GATE_DISABLE (1<<25) -#define GEN6_RCGCTL1 0x9410 -#define GEN6_RCGCTL2 0x9414 -#define GEN6_RSTCTL 0x9420 +#define GEN6_RCGCTL1 _MMIO(0x9410) +#define GEN6_RCGCTL2 _MMIO(0x9414) +#define GEN6_RSTCTL _MMIO(0x9420) -#define GEN8_UCGCTL6 0x9430 +#define GEN8_UCGCTL6 _MMIO(0x9430) #define GEN8_GAPSUNIT_CLOCK_GATE_DISABLE (1<<24) #define GEN8_SDEUNIT_CLOCK_GATE_DISABLE (1<<14) #define GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ (1<<28) -#define GEN6_GFXPAUSE 0xA000 -#define GEN6_RPNSWREQ 0xA008 +#define GEN6_GFXPAUSE _MMIO(0xA000) +#define GEN6_RPNSWREQ _MMIO(0xA008) #define GEN6_TURBO_DISABLE (1<<31) #define GEN6_FREQUENCY(x) ((x)<<25) #define HSW_FREQUENCY(x) ((x)<<24) #define GEN9_FREQUENCY(x) ((x)<<23) #define GEN6_OFFSET(x) ((x)<<19) #define GEN6_AGGRESSIVE_TURBO (0<<15) -#define GEN6_RC_VIDEO_FREQ 0xA00C -#define GEN6_RC_CONTROL 0xA090 +#define GEN6_RC_VIDEO_FREQ _MMIO(0xA00C) +#define GEN6_RC_CONTROL _MMIO(0xA090) #define GEN6_RC_CTL_RC6pp_ENABLE (1<<16) #define GEN6_RC_CTL_RC6p_ENABLE (1<<17) #define GEN6_RC_CTL_RC6_ENABLE (1<<18) @@ -6782,16 +6863,16 @@ enum skl_disp_power_wells { #define GEN7_RC_CTL_TO_MODE (1<<28) #define GEN6_RC_CTL_EI_MODE(x) ((x)<<27) #define GEN6_RC_CTL_HW_ENABLE (1<<31) -#define GEN6_RP_DOWN_TIMEOUT 0xA010 -#define GEN6_RP_INTERRUPT_LIMITS 0xA014 -#define GEN6_RPSTAT1 0xA01C +#define GEN6_RP_DOWN_TIMEOUT _MMIO(0xA010) +#define GEN6_RP_INTERRUPT_LIMITS _MMIO(0xA014) +#define GEN6_RPSTAT1 _MMIO(0xA01C) #define GEN6_CAGF_SHIFT 8 #define HSW_CAGF_SHIFT 7 #define GEN9_CAGF_SHIFT 23 #define GEN6_CAGF_MASK (0x7f << GEN6_CAGF_SHIFT) #define HSW_CAGF_MASK (0x7f << HSW_CAGF_SHIFT) #define GEN9_CAGF_MASK (0x1ff << GEN9_CAGF_SHIFT) -#define GEN6_RP_CONTROL 0xA024 +#define GEN6_RP_CONTROL _MMIO(0xA024) #define GEN6_RP_MEDIA_TURBO (1<<11) #define GEN6_RP_MEDIA_MODE_MASK (3<<9) #define GEN6_RP_MEDIA_HW_TURBO_MODE (3<<9) @@ -6805,53 +6886,53 @@ enum skl_disp_power_wells { #define GEN6_RP_UP_BUSY_CONT (0x4<<3) #define GEN6_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 -#define GEN6_RP_CUR_UP_EI 0xA050 +#define GEN6_RP_UP_THRESHOLD _MMIO(0xA02C) +#define GEN6_RP_DOWN_THRESHOLD _MMIO(0xA030) +#define GEN6_RP_CUR_UP_EI _MMIO(0xA050) #define GEN6_CURICONT_MASK 0xffffff -#define GEN6_RP_CUR_UP 0xA054 +#define GEN6_RP_CUR_UP _MMIO(0xA054) #define GEN6_CURBSYTAVG_MASK 0xffffff -#define GEN6_RP_PREV_UP 0xA058 -#define GEN6_RP_CUR_DOWN_EI 0xA05C +#define GEN6_RP_PREV_UP _MMIO(0xA058) +#define GEN6_RP_CUR_DOWN_EI _MMIO(0xA05C) #define GEN6_CURIAVG_MASK 0xffffff -#define GEN6_RP_CUR_DOWN 0xA060 -#define GEN6_RP_PREV_DOWN 0xA064 -#define GEN6_RP_UP_EI 0xA068 -#define GEN6_RP_DOWN_EI 0xA06C -#define GEN6_RP_IDLE_HYSTERSIS 0xA070 -#define GEN6_RPDEUHWTC 0xA080 -#define GEN6_RPDEUC 0xA084 -#define GEN6_RPDEUCSW 0xA088 -#define GEN6_RC_STATE 0xA094 -#define GEN6_RC1_WAKE_RATE_LIMIT 0xA098 -#define GEN6_RC6_WAKE_RATE_LIMIT 0xA09C -#define GEN6_RC6pp_WAKE_RATE_LIMIT 0xA0A0 -#define GEN6_RC_EVALUATION_INTERVAL 0xA0A8 -#define GEN6_RC_IDLE_HYSTERSIS 0xA0AC -#define GEN6_RC_SLEEP 0xA0B0 -#define GEN6_RCUBMABDTMR 0xA0B0 -#define GEN6_RC1e_THRESHOLD 0xA0B4 -#define GEN6_RC6_THRESHOLD 0xA0B8 -#define GEN6_RC6p_THRESHOLD 0xA0BC -#define VLV_RCEDATA 0xA0BC -#define GEN6_RC6pp_THRESHOLD 0xA0C0 -#define GEN6_PMINTRMSK 0xA168 +#define GEN6_RP_CUR_DOWN _MMIO(0xA060) +#define GEN6_RP_PREV_DOWN _MMIO(0xA064) +#define GEN6_RP_UP_EI _MMIO(0xA068) +#define GEN6_RP_DOWN_EI _MMIO(0xA06C) +#define GEN6_RP_IDLE_HYSTERSIS _MMIO(0xA070) +#define GEN6_RPDEUHWTC _MMIO(0xA080) +#define GEN6_RPDEUC _MMIO(0xA084) +#define GEN6_RPDEUCSW _MMIO(0xA088) +#define GEN6_RC_STATE _MMIO(0xA094) +#define GEN6_RC1_WAKE_RATE_LIMIT _MMIO(0xA098) +#define GEN6_RC6_WAKE_RATE_LIMIT _MMIO(0xA09C) +#define GEN6_RC6pp_WAKE_RATE_LIMIT _MMIO(0xA0A0) +#define GEN6_RC_EVALUATION_INTERVAL _MMIO(0xA0A8) +#define GEN6_RC_IDLE_HYSTERSIS _MMIO(0xA0AC) +#define GEN6_RC_SLEEP _MMIO(0xA0B0) +#define GEN6_RCUBMABDTMR _MMIO(0xA0B0) +#define GEN6_RC1e_THRESHOLD _MMIO(0xA0B4) +#define GEN6_RC6_THRESHOLD _MMIO(0xA0B8) +#define GEN6_RC6p_THRESHOLD _MMIO(0xA0BC) +#define VLV_RCEDATA _MMIO(0xA0BC) +#define GEN6_RC6pp_THRESHOLD _MMIO(0xA0C0) +#define GEN6_PMINTRMSK _MMIO(0xA168) #define GEN8_PMINTR_REDIRECT_TO_NON_DISP (1<<31) -#define VLV_PWRDWNUPCTL 0xA294 -#define GEN9_MEDIA_PG_IDLE_HYSTERESIS 0xA0C4 -#define GEN9_RENDER_PG_IDLE_HYSTERESIS 0xA0C8 -#define GEN9_PG_ENABLE 0xA210 +#define VLV_PWRDWNUPCTL _MMIO(0xA294) +#define GEN9_MEDIA_PG_IDLE_HYSTERESIS _MMIO(0xA0C4) +#define GEN9_RENDER_PG_IDLE_HYSTERESIS _MMIO(0xA0C8) +#define GEN9_PG_ENABLE _MMIO(0xA210) #define GEN9_RENDER_PG_ENABLE (1<<0) #define GEN9_MEDIA_PG_ENABLE (1<<1) -#define VLV_CHICKEN_3 (VLV_DISPLAY_BASE + 0x7040C) +#define VLV_CHICKEN_3 _MMIO(VLV_DISPLAY_BASE + 0x7040C) #define PIXEL_OVERLAP_CNT_MASK (3 << 30) #define PIXEL_OVERLAP_CNT_SHIFT 30 -#define GEN6_PMISR 0x44020 -#define GEN6_PMIMR 0x44024 /* rps_lock */ -#define GEN6_PMIIR 0x44028 -#define GEN6_PMIER 0x4402C +#define GEN6_PMISR _MMIO(0x44020) +#define GEN6_PMIMR _MMIO(0x44024) /* rps_lock */ +#define GEN6_PMIIR _MMIO(0x44028) +#define GEN6_PMIER _MMIO(0x4402C) #define GEN6_PM_MBOX_EVENT (1<<25) #define GEN6_PM_THERMAL_EVENT (1<<24) #define GEN6_PM_RP_DOWN_TIMEOUT (1<<6) @@ -6863,30 +6944,30 @@ enum skl_disp_power_wells { GEN6_PM_RP_DOWN_THRESHOLD | \ GEN6_PM_RP_DOWN_TIMEOUT) -#define GEN7_GT_SCRATCH(i) (0x4F100 + (i) * 4) +#define GEN7_GT_SCRATCH(i) _MMIO(0x4F100 + (i) * 4) #define GEN7_GT_SCRATCH_REG_NUM 8 -#define VLV_GTLC_SURVIVABILITY_REG 0x130098 +#define VLV_GTLC_SURVIVABILITY_REG _MMIO(0x130098) #define VLV_GFX_CLK_STATUS_BIT (1<<3) #define VLV_GFX_CLK_FORCE_ON_BIT (1<<2) -#define GEN6_GT_GFX_RC6_LOCKED 0x138104 -#define VLV_COUNTER_CONTROL 0x138104 +#define GEN6_GT_GFX_RC6_LOCKED _MMIO(0x138104) +#define VLV_COUNTER_CONTROL _MMIO(0x138104) #define VLV_COUNT_RANGE_HIGH (1<<15) #define VLV_MEDIA_RC0_COUNT_EN (1<<5) #define VLV_RENDER_RC0_COUNT_EN (1<<4) #define VLV_MEDIA_RC6_COUNT_EN (1<<1) #define VLV_RENDER_RC6_COUNT_EN (1<<0) -#define GEN6_GT_GFX_RC6 0x138108 -#define VLV_GT_RENDER_RC6 0x138108 -#define VLV_GT_MEDIA_RC6 0x13810C +#define GEN6_GT_GFX_RC6 _MMIO(0x138108) +#define VLV_GT_RENDER_RC6 _MMIO(0x138108) +#define VLV_GT_MEDIA_RC6 _MMIO(0x13810C) -#define GEN6_GT_GFX_RC6p 0x13810C -#define GEN6_GT_GFX_RC6pp 0x138110 -#define VLV_RENDER_C0_COUNT 0x138118 -#define VLV_MEDIA_C0_COUNT 0x13811C +#define GEN6_GT_GFX_RC6p _MMIO(0x13810C) +#define GEN6_GT_GFX_RC6pp _MMIO(0x138110) +#define VLV_RENDER_C0_COUNT _MMIO(0x138118) +#define VLV_MEDIA_C0_COUNT _MMIO(0x13811C) -#define GEN6_PCODE_MAILBOX 0x138124 +#define GEN6_PCODE_MAILBOX _MMIO(0x138124) #define GEN6_PCODE_READY (1<<31) #define GEN6_PCODE_WRITE_RC6VIDS 0x4 #define GEN6_PCODE_READ_RC6VIDS 0x5 @@ -6909,12 +6990,12 @@ enum skl_disp_power_wells { #define HSW_PCODE_DE_WRITE_FREQ_REQ 0x17 #define DISPLAY_IPS_CONTROL 0x19 #define HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL 0x1A -#define GEN6_PCODE_DATA 0x138128 +#define GEN6_PCODE_DATA _MMIO(0x138128) #define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8 #define GEN6_PCODE_FREQ_RING_RATIO_SHIFT 16 -#define GEN6_PCODE_DATA1 0x13812C +#define GEN6_PCODE_DATA1 _MMIO(0x13812C) -#define GEN6_GT_CORE_STATUS 0x138060 +#define GEN6_GT_CORE_STATUS _MMIO(0x138060) #define GEN6_CORE_CPD_STATE_MASK (7<<4) #define GEN6_RCn_MASK 7 #define GEN6_RC0 0 @@ -6922,26 +7003,26 @@ enum skl_disp_power_wells { #define GEN6_RC6 3 #define GEN6_RC7 4 -#define GEN8_GT_SLICE_INFO 0x138064 +#define GEN8_GT_SLICE_INFO _MMIO(0x138064) #define GEN8_LSLICESTAT_MASK 0x7 -#define CHV_POWER_SS0_SIG1 0xa720 -#define CHV_POWER_SS1_SIG1 0xa728 +#define CHV_POWER_SS0_SIG1 _MMIO(0xa720) +#define CHV_POWER_SS1_SIG1 _MMIO(0xa728) #define CHV_SS_PG_ENABLE (1<<1) #define CHV_EU08_PG_ENABLE (1<<9) #define CHV_EU19_PG_ENABLE (1<<17) #define CHV_EU210_PG_ENABLE (1<<25) -#define CHV_POWER_SS0_SIG2 0xa724 -#define CHV_POWER_SS1_SIG2 0xa72c +#define CHV_POWER_SS0_SIG2 _MMIO(0xa724) +#define CHV_POWER_SS1_SIG2 _MMIO(0xa72c) #define CHV_EU311_PG_ENABLE (1<<1) -#define GEN9_SLICE_PGCTL_ACK(slice) (0x804c + (slice)*0x4) +#define GEN9_SLICE_PGCTL_ACK(slice) _MMIO(0x804c + (slice)*0x4) #define GEN9_PGCTL_SLICE_ACK (1 << 0) #define GEN9_PGCTL_SS_ACK(subslice) (1 << (2 + (subslice)*2)) -#define GEN9_SS01_EU_PGCTL_ACK(slice) (0x805c + (slice)*0x8) -#define GEN9_SS23_EU_PGCTL_ACK(slice) (0x8060 + (slice)*0x8) +#define GEN9_SS01_EU_PGCTL_ACK(slice) _MMIO(0x805c + (slice)*0x8) +#define GEN9_SS23_EU_PGCTL_ACK(slice) _MMIO(0x8060 + (slice)*0x8) #define GEN9_PGCTL_SSA_EU08_ACK (1 << 0) #define GEN9_PGCTL_SSA_EU19_ACK (1 << 2) #define GEN9_PGCTL_SSA_EU210_ACK (1 << 4) @@ -6951,18 +7032,17 @@ enum skl_disp_power_wells { #define GEN9_PGCTL_SSB_EU210_ACK (1 << 12) #define GEN9_PGCTL_SSB_EU311_ACK (1 << 14) -#define GEN7_MISCCPCTL (0x9424) +#define GEN7_MISCCPCTL _MMIO(0x9424) #define GEN7_DOP_CLOCK_GATE_ENABLE (1<<0) #define GEN8_DOP_CLOCK_GATE_CFCLK_ENABLE (1<<2) #define GEN8_DOP_CLOCK_GATE_GUC_ENABLE (1<<4) #define GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE (1<<6) -#define GEN8_GARBCNTL 0xB004 +#define GEN8_GARBCNTL _MMIO(0xB004) #define GEN9_GAPS_TSV_CREDIT_DISABLE (1<<7) /* IVYBRIDGE DPF */ -#define GEN7_L3CDERRST1 0xB008 /* L3CD Error Status 1 */ -#define HSW_L3CDERRST11 0xB208 /* L3CD Error Status register 1 slice 1 */ +#define GEN7_L3CDERRST1(slice) _MMIO(0xB008 + (slice) * 0x200) /* L3CD Error Status 1 */ #define GEN7_L3CDERRST1_ROW_MASK (0x7ff<<14) #define GEN7_PARITY_ERROR_VALID (1<<13) #define GEN7_L3CDERRST1_BANK_MASK (3<<11) @@ -6975,119 +7055,102 @@ enum skl_disp_power_wells { ((reg & GEN7_L3CDERRST1_SUBBANK_MASK) >> 8) #define GEN7_L3CDERRST1_ENABLE (1<<7) -#define GEN7_L3LOG_BASE 0xB070 -#define HSW_L3LOG_BASE_SLICE1 0xB270 +#define GEN7_L3LOG(slice, i) _MMIO(0xB070 + (slice) * 0x200 + (i) * 4) #define GEN7_L3LOG_SIZE 0x80 -#define GEN7_HALF_SLICE_CHICKEN1 0xe100 /* IVB GT1 + VLV */ -#define GEN7_HALF_SLICE_CHICKEN1_GT2 0xf100 +#define GEN7_HALF_SLICE_CHICKEN1 _MMIO(0xe100) /* IVB GT1 + VLV */ +#define GEN7_HALF_SLICE_CHICKEN1_GT2 _MMIO(0xf100) #define GEN7_MAX_PS_THREAD_DEP (8<<12) #define GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE (1<<10) #define GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE (1<<4) #define GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE (1<<3) -#define GEN9_HALF_SLICE_CHICKEN5 0xe188 +#define GEN9_HALF_SLICE_CHICKEN5 _MMIO(0xe188) #define GEN9_DG_MIRROR_FIX_ENABLE (1<<5) #define GEN9_CCS_TLB_PREFETCH_ENABLE (1<<3) -#define GEN8_ROW_CHICKEN 0xe4f0 +#define GEN8_ROW_CHICKEN _MMIO(0xe4f0) #define PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE (1<<8) #define STALL_DOP_GATING_DISABLE (1<<5) -#define GEN7_ROW_CHICKEN2 0xe4f4 -#define GEN7_ROW_CHICKEN2_GT2 0xf4f4 +#define GEN7_ROW_CHICKEN2 _MMIO(0xe4f4) +#define GEN7_ROW_CHICKEN2_GT2 _MMIO(0xf4f4) #define DOP_CLOCK_GATING_DISABLE (1<<0) -#define HSW_ROW_CHICKEN3 0xe49c +#define HSW_ROW_CHICKEN3 _MMIO(0xe49c) #define HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE (1 << 6) -#define HALF_SLICE_CHICKEN2 0xe180 +#define HALF_SLICE_CHICKEN2 _MMIO(0xe180) #define GEN8_ST_PO_DISABLE (1<<13) -#define HALF_SLICE_CHICKEN3 0xe184 +#define HALF_SLICE_CHICKEN3 _MMIO(0xe184) #define HSW_SAMPLE_C_PERFORMANCE (1<<9) #define GEN8_CENTROID_PIXEL_OPT_DIS (1<<8) #define GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC (1<<5) #define GEN8_SAMPLER_POWER_BYPASS_DIS (1<<1) -#define GEN9_HALF_SLICE_CHICKEN7 0xe194 +#define GEN9_HALF_SLICE_CHICKEN7 _MMIO(0xe194) #define GEN9_ENABLE_YV12_BUGFIX (1<<4) /* Audio */ -#define G4X_AUD_VID_DID (dev_priv->info.display_mmio_offset + 0x62020) +#define G4X_AUD_VID_DID _MMIO(dev_priv->info.display_mmio_offset + 0x62020) #define INTEL_AUDIO_DEVCL 0x808629FB #define INTEL_AUDIO_DEVBLC 0x80862801 #define INTEL_AUDIO_DEVCTG 0x80862802 -#define G4X_AUD_CNTL_ST 0x620B4 +#define G4X_AUD_CNTL_ST _MMIO(0x620B4) #define G4X_ELDV_DEVCL_DEVBLC (1 << 13) #define G4X_ELDV_DEVCTG (1 << 14) #define G4X_ELD_ADDR_MASK (0xf << 5) #define G4X_ELD_ACK (1 << 4) -#define G4X_HDMIW_HDMIEDID 0x6210C +#define G4X_HDMIW_HDMIEDID _MMIO(0x6210C) #define _IBX_HDMIW_HDMIEDID_A 0xE2050 #define _IBX_HDMIW_HDMIEDID_B 0xE2150 -#define IBX_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \ - _IBX_HDMIW_HDMIEDID_A, \ - _IBX_HDMIW_HDMIEDID_B) +#define IBX_HDMIW_HDMIEDID(pipe) _MMIO_PIPE(pipe, _IBX_HDMIW_HDMIEDID_A, \ + _IBX_HDMIW_HDMIEDID_B) #define _IBX_AUD_CNTL_ST_A 0xE20B4 #define _IBX_AUD_CNTL_ST_B 0xE21B4 -#define IBX_AUD_CNTL_ST(pipe) _PIPE(pipe, \ - _IBX_AUD_CNTL_ST_A, \ - _IBX_AUD_CNTL_ST_B) +#define IBX_AUD_CNTL_ST(pipe) _MMIO_PIPE(pipe, _IBX_AUD_CNTL_ST_A, \ + _IBX_AUD_CNTL_ST_B) #define IBX_ELD_BUFFER_SIZE_MASK (0x1f << 10) #define IBX_ELD_ADDRESS_MASK (0x1f << 5) #define IBX_ELD_ACK (1 << 4) -#define IBX_AUD_CNTL_ST2 0xE20C0 +#define IBX_AUD_CNTL_ST2 _MMIO(0xE20C0) #define IBX_CP_READY(port) ((1 << 1) << (((port) - 1) * 4)) #define IBX_ELD_VALID(port) ((1 << 0) << (((port) - 1) * 4)) #define _CPT_HDMIW_HDMIEDID_A 0xE5050 #define _CPT_HDMIW_HDMIEDID_B 0xE5150 -#define CPT_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \ - _CPT_HDMIW_HDMIEDID_A, \ - _CPT_HDMIW_HDMIEDID_B) +#define CPT_HDMIW_HDMIEDID(pipe) _MMIO_PIPE(pipe, _CPT_HDMIW_HDMIEDID_A, _CPT_HDMIW_HDMIEDID_B) #define _CPT_AUD_CNTL_ST_A 0xE50B4 #define _CPT_AUD_CNTL_ST_B 0xE51B4 -#define CPT_AUD_CNTL_ST(pipe) _PIPE(pipe, \ - _CPT_AUD_CNTL_ST_A, \ - _CPT_AUD_CNTL_ST_B) -#define CPT_AUD_CNTRL_ST2 0xE50C0 +#define CPT_AUD_CNTL_ST(pipe) _MMIO_PIPE(pipe, _CPT_AUD_CNTL_ST_A, _CPT_AUD_CNTL_ST_B) +#define CPT_AUD_CNTRL_ST2 _MMIO(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_HDMIW_HDMIEDID(pipe) _MMIO_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) +#define VLV_AUD_CNTL_ST(pipe) _MMIO_PIPE(pipe, _VLV_AUD_CNTL_ST_A, _VLV_AUD_CNTL_ST_B) +#define VLV_AUD_CNTL_ST2 _MMIO(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. */ -#define GEN7_SO_WRITE_OFFSET(n) (0x5280 + (n) * 4) +#define GEN7_SO_WRITE_OFFSET(n) _MMIO(0x5280 + (n) * 4) #define _IBX_AUD_CONFIG_A 0xe2000 #define _IBX_AUD_CONFIG_B 0xe2100 -#define IBX_AUD_CFG(pipe) _PIPE(pipe, \ - _IBX_AUD_CONFIG_A, \ - _IBX_AUD_CONFIG_B) +#define IBX_AUD_CFG(pipe) _MMIO_PIPE(pipe, _IBX_AUD_CONFIG_A, _IBX_AUD_CONFIG_B) #define _CPT_AUD_CONFIG_A 0xe5000 #define _CPT_AUD_CONFIG_B 0xe5100 -#define CPT_AUD_CFG(pipe) _PIPE(pipe, \ - _CPT_AUD_CONFIG_A, \ - _CPT_AUD_CONFIG_B) +#define CPT_AUD_CFG(pipe) _MMIO_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 VLV_AUD_CFG(pipe) _MMIO_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) @@ -7112,72 +7175,62 @@ enum skl_disp_power_wells { /* HSW Audio */ #define _HSW_AUD_CONFIG_A 0x65000 #define _HSW_AUD_CONFIG_B 0x65100 -#define HSW_AUD_CFG(pipe) _PIPE(pipe, \ - _HSW_AUD_CONFIG_A, \ - _HSW_AUD_CONFIG_B) +#define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe, _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B) #define _HSW_AUD_MISC_CTRL_A 0x65010 #define _HSW_AUD_MISC_CTRL_B 0x65110 -#define HSW_AUD_MISC_CTRL(pipe) _PIPE(pipe, \ - _HSW_AUD_MISC_CTRL_A, \ - _HSW_AUD_MISC_CTRL_B) +#define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe, _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B) #define _HSW_AUD_DIP_ELD_CTRL_ST_A 0x650b4 #define _HSW_AUD_DIP_ELD_CTRL_ST_B 0x651b4 -#define HSW_AUD_DIP_ELD_CTRL(pipe) _PIPE(pipe, \ - _HSW_AUD_DIP_ELD_CTRL_ST_A, \ - _HSW_AUD_DIP_ELD_CTRL_ST_B) +#define HSW_AUD_DIP_ELD_CTRL(pipe) _MMIO_PIPE(pipe, _HSW_AUD_DIP_ELD_CTRL_ST_A, _HSW_AUD_DIP_ELD_CTRL_ST_B) /* Audio Digital Converter */ #define _HSW_AUD_DIG_CNVT_1 0x65080 #define _HSW_AUD_DIG_CNVT_2 0x65180 -#define AUD_DIG_CNVT(pipe) _PIPE(pipe, \ - _HSW_AUD_DIG_CNVT_1, \ - _HSW_AUD_DIG_CNVT_2) +#define AUD_DIG_CNVT(pipe) _MMIO_PIPE(pipe, _HSW_AUD_DIG_CNVT_1, _HSW_AUD_DIG_CNVT_2) #define DIP_PORT_SEL_MASK 0x3 #define _HSW_AUD_EDID_DATA_A 0x65050 #define _HSW_AUD_EDID_DATA_B 0x65150 -#define HSW_AUD_EDID_DATA(pipe) _PIPE(pipe, \ - _HSW_AUD_EDID_DATA_A, \ - _HSW_AUD_EDID_DATA_B) +#define HSW_AUD_EDID_DATA(pipe) _MMIO_PIPE(pipe, _HSW_AUD_EDID_DATA_A, _HSW_AUD_EDID_DATA_B) -#define HSW_AUD_PIPE_CONV_CFG 0x6507c -#define HSW_AUD_PIN_ELD_CP_VLD 0x650c0 +#define HSW_AUD_PIPE_CONV_CFG _MMIO(0x6507c) +#define HSW_AUD_PIN_ELD_CP_VLD _MMIO(0x650c0) #define AUDIO_INACTIVE(trans) ((1 << 3) << ((trans) * 4)) #define AUDIO_OUTPUT_ENABLE(trans) ((1 << 2) << ((trans) * 4)) #define AUDIO_CP_READY(trans) ((1 << 1) << ((trans) * 4)) #define AUDIO_ELD_VALID(trans) ((1 << 0) << ((trans) * 4)) -#define HSW_AUD_CHICKENBIT 0x65f10 +#define HSW_AUD_CHICKENBIT _MMIO(0x65f10) #define SKL_AUD_CODEC_WAKE_SIGNAL (1 << 15) /* HSW Power Wells */ -#define HSW_PWR_WELL_BIOS 0x45400 /* CTL1 */ -#define HSW_PWR_WELL_DRIVER 0x45404 /* CTL2 */ -#define HSW_PWR_WELL_KVMR 0x45408 /* CTL3 */ -#define HSW_PWR_WELL_DEBUG 0x4540C /* CTL4 */ +#define HSW_PWR_WELL_BIOS _MMIO(0x45400) /* CTL1 */ +#define HSW_PWR_WELL_DRIVER _MMIO(0x45404) /* CTL2 */ +#define HSW_PWR_WELL_KVMR _MMIO(0x45408) /* CTL3 */ +#define HSW_PWR_WELL_DEBUG _MMIO(0x4540C) /* CTL4 */ #define HSW_PWR_WELL_ENABLE_REQUEST (1<<31) #define HSW_PWR_WELL_STATE_ENABLED (1<<30) -#define HSW_PWR_WELL_CTL5 0x45410 +#define HSW_PWR_WELL_CTL5 _MMIO(0x45410) #define HSW_PWR_WELL_ENABLE_SINGLE_STEP (1<<31) #define HSW_PWR_WELL_PWR_GATE_OVERRIDE (1<<20) #define HSW_PWR_WELL_FORCE_ON (1<<19) -#define HSW_PWR_WELL_CTL6 0x45414 +#define HSW_PWR_WELL_CTL6 _MMIO(0x45414) /* SKL Fuse Status */ -#define SKL_FUSE_STATUS 0x42000 +#define SKL_FUSE_STATUS _MMIO(0x42000) #define SKL_FUSE_DOWNLOAD_STATUS (1<<31) #define SKL_FUSE_PG0_DIST_STATUS (1<<27) #define SKL_FUSE_PG1_DIST_STATUS (1<<26) #define SKL_FUSE_PG2_DIST_STATUS (1<<25) /* Per-pipe DDI Function Control */ -#define TRANS_DDI_FUNC_CTL_A 0x60400 -#define TRANS_DDI_FUNC_CTL_B 0x61400 -#define TRANS_DDI_FUNC_CTL_C 0x62400 -#define TRANS_DDI_FUNC_CTL_EDP 0x6F400 -#define TRANS_DDI_FUNC_CTL(tran) _TRANSCODER2(tran, TRANS_DDI_FUNC_CTL_A) +#define _TRANS_DDI_FUNC_CTL_A 0x60400 +#define _TRANS_DDI_FUNC_CTL_B 0x61400 +#define _TRANS_DDI_FUNC_CTL_C 0x62400 +#define _TRANS_DDI_FUNC_CTL_EDP 0x6F400 +#define TRANS_DDI_FUNC_CTL(tran) _MMIO_TRANS2(tran, _TRANS_DDI_FUNC_CTL_A) #define TRANS_DDI_FUNC_ENABLE (1<<31) /* Those bits are ignored by pipe EDP since it can only connect to DDI A */ @@ -7207,9 +7260,9 @@ enum skl_disp_power_wells { #define TRANS_DDI_BFI_ENABLE (1<<4) /* DisplayPort Transport Control */ -#define DP_TP_CTL_A 0x64040 -#define DP_TP_CTL_B 0x64140 -#define DP_TP_CTL(port) _PORT(port, DP_TP_CTL_A, DP_TP_CTL_B) +#define _DP_TP_CTL_A 0x64040 +#define _DP_TP_CTL_B 0x64140 +#define DP_TP_CTL(port) _MMIO_PORT(port, _DP_TP_CTL_A, _DP_TP_CTL_B) #define DP_TP_CTL_ENABLE (1<<31) #define DP_TP_CTL_MODE_SST (0<<27) #define DP_TP_CTL_MODE_MST (1<<27) @@ -7225,9 +7278,9 @@ enum skl_disp_power_wells { #define DP_TP_CTL_SCRAMBLE_DISABLE (1<<7) /* DisplayPort Transport Status */ -#define DP_TP_STATUS_A 0x64044 -#define DP_TP_STATUS_B 0x64144 -#define DP_TP_STATUS(port) _PORT(port, DP_TP_STATUS_A, DP_TP_STATUS_B) +#define _DP_TP_STATUS_A 0x64044 +#define _DP_TP_STATUS_B 0x64144 +#define DP_TP_STATUS(port) _MMIO_PORT(port, _DP_TP_STATUS_A, _DP_TP_STATUS_B) #define DP_TP_STATUS_IDLE_DONE (1<<25) #define DP_TP_STATUS_ACT_SENT (1<<24) #define DP_TP_STATUS_MODE_STATUS_MST (1<<23) @@ -7237,9 +7290,9 @@ enum skl_disp_power_wells { #define DP_TP_STATUS_PAYLOAD_MAPPING_VC0 (3 << 0) /* DDI Buffer Control */ -#define DDI_BUF_CTL_A 0x64000 -#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_A 0x64000 +#define _DDI_BUF_CTL_B 0x64100 +#define DDI_BUF_CTL(port) _MMIO_PORT(port, _DDI_BUF_CTL_A, _DDI_BUF_CTL_B) #define DDI_BUF_CTL_ENABLE (1<<31) #define DDI_BUF_TRANS_SELECT(n) ((n) << 24) #define DDI_BUF_EMP_MASK (0xf<<24) @@ -7252,17 +7305,17 @@ enum skl_disp_power_wells { #define DDI_INIT_DISPLAY_DETECTED (1<<0) /* DDI Buffer Translations */ -#define DDI_BUF_TRANS_A 0x64E00 -#define DDI_BUF_TRANS_B 0x64E60 -#define DDI_BUF_TRANS_LO(port, i) (_PORT(port, DDI_BUF_TRANS_A, DDI_BUF_TRANS_B) + (i) * 8) -#define DDI_BUF_TRANS_HI(port, i) (_PORT(port, DDI_BUF_TRANS_A, DDI_BUF_TRANS_B) + (i) * 8 + 4) +#define _DDI_BUF_TRANS_A 0x64E00 +#define _DDI_BUF_TRANS_B 0x64E60 +#define DDI_BUF_TRANS_LO(port, i) _MMIO(_PORT(port, _DDI_BUF_TRANS_A, _DDI_BUF_TRANS_B) + (i) * 8) +#define DDI_BUF_TRANS_HI(port, i) _MMIO(_PORT(port, _DDI_BUF_TRANS_A, _DDI_BUF_TRANS_B) + (i) * 8 + 4) /* Sideband Interface (SBI) is programmed indirectly, via * SBI_ADDR, which contains the register offset; and SBI_DATA, * which contains the payload */ -#define SBI_ADDR 0xC6000 -#define SBI_DATA 0xC6004 -#define SBI_CTL_STAT 0xC6008 +#define SBI_ADDR _MMIO(0xC6000) +#define SBI_DATA _MMIO(0xC6004) +#define SBI_CTL_STAT _MMIO(0xC6008) #define SBI_CTL_DEST_ICLK (0x0<<16) #define SBI_CTL_DEST_MPHY (0x1<<16) #define SBI_CTL_OP_IORD (0x2<<8) @@ -7275,6 +7328,7 @@ enum skl_disp_power_wells { #define SBI_READY (0x0<<0) /* SBI offsets */ +#define SBI_SSCDIVINTPHASE 0x0200 #define SBI_SSCDIVINTPHASE6 0x0600 #define SBI_SSCDIVINTPHASE_DIVSEL_MASK ((0x7f)<<1) #define SBI_SSCDIVINTPHASE_DIVSEL(x) ((x)<<1) @@ -7282,6 +7336,7 @@ enum skl_disp_power_wells { #define SBI_SSCDIVINTPHASE_INCVAL(x) ((x)<<8) #define SBI_SSCDIVINTPHASE_DIR(x) ((x)<<15) #define SBI_SSCDIVINTPHASE_PROPAGATE (1<<0) +#define SBI_SSCDITHPHASE 0x0204 #define SBI_SSCCTL 0x020c #define SBI_SSCCTL6 0x060C #define SBI_SSCCTL_PATHALT (1<<3) @@ -7293,12 +7348,12 @@ enum skl_disp_power_wells { #define SBI_GEN0_CFG_BUFFENABLE_DISABLE (1<<0) /* LPT PIXCLK_GATE */ -#define PIXCLK_GATE 0xC6020 +#define PIXCLK_GATE _MMIO(0xC6020) #define PIXCLK_GATE_UNGATE (1<<0) #define PIXCLK_GATE_GATE (0<<0) /* SPLL */ -#define SPLL_CTL 0x46020 +#define SPLL_CTL _MMIO(0x46020) #define SPLL_PLL_ENABLE (1<<31) #define SPLL_PLL_SSC (1<<28) #define SPLL_PLL_NON_SSC (2<<28) @@ -7310,9 +7365,9 @@ enum skl_disp_power_wells { #define SPLL_PLL_FREQ_MASK (3<<26) /* WRPLL */ -#define WRPLL_CTL1 0x46040 -#define WRPLL_CTL2 0x46060 -#define WRPLL_CTL(pll) (pll == 0 ? WRPLL_CTL1 : WRPLL_CTL2) +#define _WRPLL_CTL1 0x46040 +#define _WRPLL_CTL2 0x46060 +#define WRPLL_CTL(pll) _MMIO_PIPE(pll, _WRPLL_CTL1, _WRPLL_CTL2) #define WRPLL_PLL_ENABLE (1<<31) #define WRPLL_PLL_SSC (1<<28) #define WRPLL_PLL_NON_SSC (2<<28) @@ -7329,9 +7384,9 @@ enum skl_disp_power_wells { #define WRPLL_DIVIDER_FB_MASK (0xff<<16) /* Port clock selection */ -#define PORT_CLK_SEL_A 0x46100 -#define PORT_CLK_SEL_B 0x46104 -#define PORT_CLK_SEL(port) _PORT(port, PORT_CLK_SEL_A, PORT_CLK_SEL_B) +#define _PORT_CLK_SEL_A 0x46100 +#define _PORT_CLK_SEL_B 0x46104 +#define PORT_CLK_SEL(port) _MMIO_PORT(port, _PORT_CLK_SEL_A, _PORT_CLK_SEL_B) #define PORT_CLK_SEL_LCPLL_2700 (0<<29) #define PORT_CLK_SEL_LCPLL_1350 (1<<29) #define PORT_CLK_SEL_LCPLL_810 (2<<29) @@ -7343,18 +7398,18 @@ enum skl_disp_power_wells { #define PORT_CLK_SEL_MASK (7<<29) /* Transcoder clock selection */ -#define TRANS_CLK_SEL_A 0x46140 -#define TRANS_CLK_SEL_B 0x46144 -#define TRANS_CLK_SEL(tran) _TRANSCODER(tran, TRANS_CLK_SEL_A, TRANS_CLK_SEL_B) +#define _TRANS_CLK_SEL_A 0x46140 +#define _TRANS_CLK_SEL_B 0x46144 +#define TRANS_CLK_SEL(tran) _MMIO_TRANS(tran, _TRANS_CLK_SEL_A, _TRANS_CLK_SEL_B) /* For each transcoder, we need to select the corresponding port clock */ #define TRANS_CLK_SEL_DISABLED (0x0<<29) #define TRANS_CLK_SEL_PORT(x) (((x)+1)<<29) -#define TRANSA_MSA_MISC 0x60410 -#define TRANSB_MSA_MISC 0x61410 -#define TRANSC_MSA_MISC 0x62410 -#define TRANS_EDP_MSA_MISC 0x6f410 -#define TRANS_MSA_MISC(tran) _TRANSCODER2(tran, TRANSA_MSA_MISC) +#define _TRANSA_MSA_MISC 0x60410 +#define _TRANSB_MSA_MISC 0x61410 +#define _TRANSC_MSA_MISC 0x62410 +#define _TRANS_EDP_MSA_MISC 0x6f410 +#define TRANS_MSA_MISC(tran) _MMIO_TRANS2(tran, _TRANSA_MSA_MISC) #define TRANS_MSA_SYNC_CLK (1<<0) #define TRANS_MSA_6_BPC (0<<5) @@ -7364,7 +7419,7 @@ enum skl_disp_power_wells { #define TRANS_MSA_16_BPC (4<<5) /* LCPLL Control */ -#define LCPLL_CTL 0x130040 +#define LCPLL_CTL _MMIO(0x130040) #define LCPLL_PLL_DISABLE (1<<31) #define LCPLL_PLL_LOCK (1<<30) #define LCPLL_CLK_FREQ_MASK (3<<26) @@ -7384,7 +7439,7 @@ enum skl_disp_power_wells { */ /* CDCLK_CTL */ -#define CDCLK_CTL 0x46000 +#define CDCLK_CTL _MMIO(0x46000) #define CDCLK_FREQ_SEL_MASK (3<<26) #define CDCLK_FREQ_450_432 (0<<26) #define CDCLK_FREQ_540 (1<<26) @@ -7400,12 +7455,12 @@ enum skl_disp_power_wells { #define BXT_CDCLK_SSA_PRECHARGE_ENABLE (1<<16) /* LCPLL_CTL */ -#define LCPLL1_CTL 0x46010 -#define LCPLL2_CTL 0x46014 +#define LCPLL1_CTL _MMIO(0x46010) +#define LCPLL2_CTL _MMIO(0x46014) #define LCPLL_PLL_ENABLE (1<<31) /* DPLL control1 */ -#define DPLL_CTRL1 0x6C058 +#define DPLL_CTRL1 _MMIO(0x6C058) #define DPLL_CTRL1_HDMI_MODE(id) (1<<((id)*6+5)) #define DPLL_CTRL1_SSC(id) (1<<((id)*6+4)) #define DPLL_CTRL1_LINK_RATE_MASK(id) (7<<((id)*6+1)) @@ -7420,7 +7475,7 @@ enum skl_disp_power_wells { #define DPLL_CTRL1_LINK_RATE_2160 5 /* DPLL control2 */ -#define DPLL_CTRL2 0x6C05C +#define DPLL_CTRL2 _MMIO(0x6C05C) #define DPLL_CTRL2_DDI_CLK_OFF(port) (1<<((port)+15)) #define DPLL_CTRL2_DDI_CLK_SEL_MASK(port) (3<<((port)*3+1)) #define DPLL_CTRL2_DDI_CLK_SEL_SHIFT(port) ((port)*3+1) @@ -7428,21 +7483,21 @@ enum skl_disp_power_wells { #define DPLL_CTRL2_DDI_SEL_OVERRIDE(port) (1<<((port)*3)) /* DPLL Status */ -#define DPLL_STATUS 0x6C060 +#define DPLL_STATUS _MMIO(0x6C060) #define DPLL_LOCK(id) (1<<((id)*8)) /* DPLL cfg */ -#define DPLL1_CFGCR1 0x6C040 -#define DPLL2_CFGCR1 0x6C048 -#define DPLL3_CFGCR1 0x6C050 +#define _DPLL1_CFGCR1 0x6C040 +#define _DPLL2_CFGCR1 0x6C048 +#define _DPLL3_CFGCR1 0x6C050 #define DPLL_CFGCR1_FREQ_ENABLE (1<<31) #define DPLL_CFGCR1_DCO_FRACTION_MASK (0x7fff<<9) #define DPLL_CFGCR1_DCO_FRACTION(x) ((x)<<9) #define DPLL_CFGCR1_DCO_INTEGER_MASK (0x1ff) -#define DPLL1_CFGCR2 0x6C044 -#define DPLL2_CFGCR2 0x6C04C -#define DPLL3_CFGCR2 0x6C054 +#define _DPLL1_CFGCR2 0x6C044 +#define _DPLL2_CFGCR2 0x6C04C +#define _DPLL3_CFGCR2 0x6C054 #define DPLL_CFGCR2_QDIV_RATIO_MASK (0xff<<8) #define DPLL_CFGCR2_QDIV_RATIO(x) ((x)<<8) #define DPLL_CFGCR2_QDIV_MODE(x) ((x)<<7) @@ -7460,58 +7515,59 @@ enum skl_disp_power_wells { #define DPLL_CFGCR2_PDIV_7 (4<<2) #define DPLL_CFGCR2_CENTRAL_FREQ_MASK (3) -#define DPLL_CFGCR1(id) (DPLL1_CFGCR1 + ((id) - SKL_DPLL1) * 8) -#define DPLL_CFGCR2(id) (DPLL1_CFGCR2 + ((id) - SKL_DPLL1) * 8) +#define DPLL_CFGCR1(id) _MMIO_PIPE((id) - SKL_DPLL1, _DPLL1_CFGCR1, _DPLL2_CFGCR1) +#define DPLL_CFGCR2(id) _MMIO_PIPE((id) - SKL_DPLL1, _DPLL1_CFGCR2, _DPLL2_CFGCR2) /* BXT display engine PLL */ -#define BXT_DE_PLL_CTL 0x6d000 +#define BXT_DE_PLL_CTL _MMIO(0x6d000) #define BXT_DE_PLL_RATIO(x) (x) /* {60,65,100} * 19.2MHz */ #define BXT_DE_PLL_RATIO_MASK 0xff -#define BXT_DE_PLL_ENABLE 0x46070 +#define BXT_DE_PLL_ENABLE _MMIO(0x46070) #define BXT_DE_PLL_PLL_ENABLE (1 << 31) #define BXT_DE_PLL_LOCK (1 << 30) /* GEN9 DC */ -#define DC_STATE_EN 0x45504 +#define DC_STATE_EN _MMIO(0x45504) +#define DC_STATE_DISABLE 0 #define DC_STATE_EN_UPTO_DC5 (1<<0) #define DC_STATE_EN_DC9 (1<<3) #define DC_STATE_EN_UPTO_DC6 (2<<0) #define DC_STATE_EN_UPTO_DC5_DC6_MASK 0x3 -#define DC_STATE_DEBUG 0x45520 +#define DC_STATE_DEBUG _MMIO(0x45520) #define DC_STATE_DEBUG_MASK_MEMORY_UP (1<<1) /* Please see hsw_read_dcomp() and hsw_write_dcomp() before using this register, * since on HSW we can't write to it using I915_WRITE. */ -#define D_COMP_HSW (MCHBAR_MIRROR_BASE_SNB + 0x5F0C) -#define D_COMP_BDW 0x138144 +#define D_COMP_HSW _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5F0C) +#define D_COMP_BDW _MMIO(0x138144) #define D_COMP_RCOMP_IN_PROGRESS (1<<9) #define D_COMP_COMP_FORCE (1<<8) #define D_COMP_COMP_DISABLE (1<<0) /* Pipe WM_LINETIME - watermark line time */ -#define PIPE_WM_LINETIME_A 0x45270 -#define PIPE_WM_LINETIME_B 0x45274 -#define PIPE_WM_LINETIME(pipe) _PIPE(pipe, PIPE_WM_LINETIME_A, \ - PIPE_WM_LINETIME_B) +#define _PIPE_WM_LINETIME_A 0x45270 +#define _PIPE_WM_LINETIME_B 0x45274 +#define PIPE_WM_LINETIME(pipe) _MMIO_PIPE(pipe, _PIPE_WM_LINETIME_A, _PIPE_WM_LINETIME_B) #define PIPE_WM_LINETIME_MASK (0x1ff) #define PIPE_WM_LINETIME_TIME(x) ((x)) #define PIPE_WM_LINETIME_IPS_LINETIME_MASK (0x1ff<<16) #define PIPE_WM_LINETIME_IPS_LINETIME(x) ((x)<<16) /* SFUSE_STRAP */ -#define SFUSE_STRAP 0xc2014 +#define SFUSE_STRAP _MMIO(0xc2014) #define SFUSE_STRAP_FUSE_LOCK (1<<13) #define SFUSE_STRAP_DISPLAY_DISABLED (1<<7) +#define SFUSE_STRAP_CRT_DISABLED (1<<6) #define SFUSE_STRAP_DDIB_DETECTED (1<<2) #define SFUSE_STRAP_DDIC_DETECTED (1<<1) #define SFUSE_STRAP_DDID_DETECTED (1<<0) -#define WM_MISC 0x45260 +#define WM_MISC _MMIO(0x45260) #define WM_MISC_DATA_PARTITION_5_6 (1 << 0) -#define WM_DBG 0x45280 +#define WM_DBG _MMIO(0x45280) #define WM_DBG_DISALLOW_MULTIPLE_LP (1<<0) #define WM_DBG_DISALLOW_MAXFIFO (1<<1) #define WM_DBG_DISALLOW_SPRITE (1<<2) @@ -7548,28 +7604,29 @@ enum skl_disp_power_wells { #define _PIPE_B_CSC_POSTOFF_ME 0x49144 #define _PIPE_B_CSC_POSTOFF_LO 0x49148 -#define PIPE_CSC_COEFF_RY_GY(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RY_GY, _PIPE_B_CSC_COEFF_RY_GY) -#define PIPE_CSC_COEFF_BY(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BY, _PIPE_B_CSC_COEFF_BY) -#define PIPE_CSC_COEFF_RU_GU(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RU_GU, _PIPE_B_CSC_COEFF_RU_GU) -#define PIPE_CSC_COEFF_BU(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BU, _PIPE_B_CSC_COEFF_BU) -#define PIPE_CSC_COEFF_RV_GV(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RV_GV, _PIPE_B_CSC_COEFF_RV_GV) -#define PIPE_CSC_COEFF_BV(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BV, _PIPE_B_CSC_COEFF_BV) -#define PIPE_CSC_MODE(pipe) _PIPE(pipe, _PIPE_A_CSC_MODE, _PIPE_B_CSC_MODE) -#define PIPE_CSC_PREOFF_HI(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_HI, _PIPE_B_CSC_PREOFF_HI) -#define PIPE_CSC_PREOFF_ME(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_ME, _PIPE_B_CSC_PREOFF_ME) -#define PIPE_CSC_PREOFF_LO(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_LO, _PIPE_B_CSC_PREOFF_LO) -#define PIPE_CSC_POSTOFF_HI(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_HI, _PIPE_B_CSC_POSTOFF_HI) -#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) +#define PIPE_CSC_COEFF_RY_GY(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_RY_GY, _PIPE_B_CSC_COEFF_RY_GY) +#define PIPE_CSC_COEFF_BY(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_BY, _PIPE_B_CSC_COEFF_BY) +#define PIPE_CSC_COEFF_RU_GU(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_RU_GU, _PIPE_B_CSC_COEFF_RU_GU) +#define PIPE_CSC_COEFF_BU(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_BU, _PIPE_B_CSC_COEFF_BU) +#define PIPE_CSC_COEFF_RV_GV(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_RV_GV, _PIPE_B_CSC_COEFF_RV_GV) +#define PIPE_CSC_COEFF_BV(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_BV, _PIPE_B_CSC_COEFF_BV) +#define PIPE_CSC_MODE(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_MODE, _PIPE_B_CSC_MODE) +#define PIPE_CSC_PREOFF_HI(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_PREOFF_HI, _PIPE_B_CSC_PREOFF_HI) +#define PIPE_CSC_PREOFF_ME(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_PREOFF_ME, _PIPE_B_CSC_PREOFF_ME) +#define PIPE_CSC_PREOFF_LO(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_PREOFF_LO, _PIPE_B_CSC_PREOFF_LO) +#define PIPE_CSC_POSTOFF_HI(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_HI, _PIPE_B_CSC_POSTOFF_HI) +#define PIPE_CSC_POSTOFF_ME(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, _PIPE_B_CSC_POSTOFF_ME) +#define PIPE_CSC_POSTOFF_LO(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, _PIPE_B_CSC_POSTOFF_LO) /* MIPI DSI registers */ #define _MIPI_PORT(port, a, c) _PORT3(port, a, 0, c) /* ports A and C only */ +#define _MMIO_MIPI(port, a, c) _MMIO(_MIPI_PORT(port, a, c)) /* BXT MIPI clock controls */ #define BXT_MAX_VAR_OUTPUT_KHZ 39500 -#define BXT_MIPI_CLOCK_CTL 0x46090 +#define BXT_MIPI_CLOCK_CTL _MMIO(0x46090) #define BXT_MIPI1_DIV_SHIFT 26 #define BXT_MIPI2_DIV_SHIFT 10 #define BXT_MIPI_DIV_SHIFT(port) \ @@ -7631,20 +7688,20 @@ enum skl_disp_power_wells { /* BXT MIPI mode configure */ #define _BXT_MIPIA_TRANS_HACTIVE 0x6B0F8 #define _BXT_MIPIC_TRANS_HACTIVE 0x6B8F8 -#define BXT_MIPI_TRANS_HACTIVE(tc) _MIPI_PORT(tc, \ +#define BXT_MIPI_TRANS_HACTIVE(tc) _MMIO_MIPI(tc, \ _BXT_MIPIA_TRANS_HACTIVE, _BXT_MIPIC_TRANS_HACTIVE) #define _BXT_MIPIA_TRANS_VACTIVE 0x6B0FC #define _BXT_MIPIC_TRANS_VACTIVE 0x6B8FC -#define BXT_MIPI_TRANS_VACTIVE(tc) _MIPI_PORT(tc, \ +#define BXT_MIPI_TRANS_VACTIVE(tc) _MMIO_MIPI(tc, \ _BXT_MIPIA_TRANS_VACTIVE, _BXT_MIPIC_TRANS_VACTIVE) #define _BXT_MIPIA_TRANS_VTOTAL 0x6B100 #define _BXT_MIPIC_TRANS_VTOTAL 0x6B900 -#define BXT_MIPI_TRANS_VTOTAL(tc) _MIPI_PORT(tc, \ +#define BXT_MIPI_TRANS_VTOTAL(tc) _MMIO_MIPI(tc, \ _BXT_MIPIA_TRANS_VTOTAL, _BXT_MIPIC_TRANS_VTOTAL) -#define BXT_DSI_PLL_CTL 0x161000 +#define BXT_DSI_PLL_CTL _MMIO(0x161000) #define BXT_DSI_PLL_PVD_RATIO_SHIFT 16 #define BXT_DSI_PLL_PVD_RATIO_MASK (3 << BXT_DSI_PLL_PVD_RATIO_SHIFT) #define BXT_DSI_PLL_PVD_RATIO_1 (1 << BXT_DSI_PLL_PVD_RATIO_SHIFT) @@ -7660,21 +7717,20 @@ enum skl_disp_power_wells { #define BXT_DSI_PLL_RATIO_MAX 0x7D #define BXT_DSI_PLL_RATIO_MIN 0x22 #define BXT_DSI_PLL_RATIO_MASK 0xFF -#define BXT_REF_CLOCK_KHZ 19500 +#define BXT_REF_CLOCK_KHZ 19200 -#define BXT_DSI_PLL_ENABLE 0x46080 +#define BXT_DSI_PLL_ENABLE _MMIO(0x46080) #define BXT_DSI_PLL_DO_ENABLE (1 << 31) #define BXT_DSI_PLL_LOCKED (1 << 30) #define _MIPIA_PORT_CTRL (VLV_DISPLAY_BASE + 0x61190) #define _MIPIC_PORT_CTRL (VLV_DISPLAY_BASE + 0x61700) -#define MIPI_PORT_CTRL(port) _MIPI_PORT(port, _MIPIA_PORT_CTRL, _MIPIC_PORT_CTRL) +#define MIPI_PORT_CTRL(port) _MMIO_MIPI(port, _MIPIA_PORT_CTRL, _MIPIC_PORT_CTRL) /* BXT port control */ #define _BXT_MIPIA_PORT_CTRL 0x6B0C0 #define _BXT_MIPIC_PORT_CTRL 0x6B8C0 -#define BXT_MIPI_PORT_CTRL(tc) _MIPI_PORT(tc, _BXT_MIPIA_PORT_CTRL, \ - _BXT_MIPIC_PORT_CTRL) +#define BXT_MIPI_PORT_CTRL(tc) _MMIO_MIPI(tc, _BXT_MIPIA_PORT_CTRL, _BXT_MIPIC_PORT_CTRL) #define DPI_ENABLE (1 << 31) /* A + C */ #define MIPIA_MIPI4DPHY_DELAY_COUNT_SHIFT 27 @@ -7718,8 +7774,7 @@ enum skl_disp_power_wells { #define _MIPIA_TEARING_CTRL (VLV_DISPLAY_BASE + 0x61194) #define _MIPIC_TEARING_CTRL (VLV_DISPLAY_BASE + 0x61704) -#define MIPI_TEARING_CTRL(port) _MIPI_PORT(port, \ - _MIPIA_TEARING_CTRL, _MIPIC_TEARING_CTRL) +#define MIPI_TEARING_CTRL(port) _MMIO_MIPI(port, _MIPIA_TEARING_CTRL, _MIPIC_TEARING_CTRL) #define TEARING_EFFECT_DELAY_SHIFT 0 #define TEARING_EFFECT_DELAY_MASK (0xffff << 0) @@ -7730,8 +7785,7 @@ enum skl_disp_power_wells { #define _MIPIA_DEVICE_READY (dev_priv->mipi_mmio_base + 0xb000) #define _MIPIC_DEVICE_READY (dev_priv->mipi_mmio_base + 0xb800) -#define MIPI_DEVICE_READY(port) _MIPI_PORT(port, _MIPIA_DEVICE_READY, \ - _MIPIC_DEVICE_READY) +#define MIPI_DEVICE_READY(port) _MMIO_MIPI(port, _MIPIA_DEVICE_READY, _MIPIC_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) @@ -7741,12 +7795,10 @@ enum skl_disp_power_wells { #define _MIPIA_INTR_STAT (dev_priv->mipi_mmio_base + 0xb004) #define _MIPIC_INTR_STAT (dev_priv->mipi_mmio_base + 0xb804) -#define MIPI_INTR_STAT(port) _MIPI_PORT(port, _MIPIA_INTR_STAT, \ - _MIPIC_INTR_STAT) +#define MIPI_INTR_STAT(port) _MMIO_MIPI(port, _MIPIA_INTR_STAT, _MIPIC_INTR_STAT) #define _MIPIA_INTR_EN (dev_priv->mipi_mmio_base + 0xb008) #define _MIPIC_INTR_EN (dev_priv->mipi_mmio_base + 0xb808) -#define MIPI_INTR_EN(port) _MIPI_PORT(port, _MIPIA_INTR_EN, \ - _MIPIC_INTR_EN) +#define MIPI_INTR_EN(port) _MMIO_MIPI(port, _MIPIA_INTR_EN, _MIPIC_INTR_EN) #define TEARING_EFFECT (1 << 31) #define SPL_PKT_SENT_INTERRUPT (1 << 30) #define GEN_READ_DATA_AVAIL (1 << 29) @@ -7782,8 +7834,7 @@ enum skl_disp_power_wells { #define _MIPIA_DSI_FUNC_PRG (dev_priv->mipi_mmio_base + 0xb00c) #define _MIPIC_DSI_FUNC_PRG (dev_priv->mipi_mmio_base + 0xb80c) -#define MIPI_DSI_FUNC_PRG(port) _MIPI_PORT(port, _MIPIA_DSI_FUNC_PRG, \ - _MIPIC_DSI_FUNC_PRG) +#define MIPI_DSI_FUNC_PRG(port) _MMIO_MIPI(port, _MIPIA_DSI_FUNC_PRG, _MIPIC_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) @@ -7806,32 +7857,27 @@ enum skl_disp_power_wells { #define _MIPIA_HS_TX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb010) #define _MIPIC_HS_TX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb810) -#define MIPI_HS_TX_TIMEOUT(port) _MIPI_PORT(port, _MIPIA_HS_TX_TIMEOUT, \ - _MIPIC_HS_TX_TIMEOUT) +#define MIPI_HS_TX_TIMEOUT(port) _MMIO_MIPI(port, _MIPIA_HS_TX_TIMEOUT, _MIPIC_HS_TX_TIMEOUT) #define HIGH_SPEED_TX_TIMEOUT_COUNTER_MASK 0xffffff #define _MIPIA_LP_RX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb014) #define _MIPIC_LP_RX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb814) -#define MIPI_LP_RX_TIMEOUT(port) _MIPI_PORT(port, _MIPIA_LP_RX_TIMEOUT, \ - _MIPIC_LP_RX_TIMEOUT) +#define MIPI_LP_RX_TIMEOUT(port) _MMIO_MIPI(port, _MIPIA_LP_RX_TIMEOUT, _MIPIC_LP_RX_TIMEOUT) #define LOW_POWER_RX_TIMEOUT_COUNTER_MASK 0xffffff #define _MIPIA_TURN_AROUND_TIMEOUT (dev_priv->mipi_mmio_base + 0xb018) #define _MIPIC_TURN_AROUND_TIMEOUT (dev_priv->mipi_mmio_base + 0xb818) -#define MIPI_TURN_AROUND_TIMEOUT(port) _MIPI_PORT(port, \ - _MIPIA_TURN_AROUND_TIMEOUT, _MIPIC_TURN_AROUND_TIMEOUT) +#define MIPI_TURN_AROUND_TIMEOUT(port) _MMIO_MIPI(port, _MIPIA_TURN_AROUND_TIMEOUT, _MIPIC_TURN_AROUND_TIMEOUT) #define TURN_AROUND_TIMEOUT_MASK 0x3f #define _MIPIA_DEVICE_RESET_TIMER (dev_priv->mipi_mmio_base + 0xb01c) #define _MIPIC_DEVICE_RESET_TIMER (dev_priv->mipi_mmio_base + 0xb81c) -#define MIPI_DEVICE_RESET_TIMER(port) _MIPI_PORT(port, \ - _MIPIA_DEVICE_RESET_TIMER, _MIPIC_DEVICE_RESET_TIMER) +#define MIPI_DEVICE_RESET_TIMER(port) _MMIO_MIPI(port, _MIPIA_DEVICE_RESET_TIMER, _MIPIC_DEVICE_RESET_TIMER) #define DEVICE_RESET_TIMER_MASK 0xffff #define _MIPIA_DPI_RESOLUTION (dev_priv->mipi_mmio_base + 0xb020) #define _MIPIC_DPI_RESOLUTION (dev_priv->mipi_mmio_base + 0xb820) -#define MIPI_DPI_RESOLUTION(port) _MIPI_PORT(port, _MIPIA_DPI_RESOLUTION, \ - _MIPIC_DPI_RESOLUTION) +#define MIPI_DPI_RESOLUTION(port) _MMIO_MIPI(port, _MIPIA_DPI_RESOLUTION, _MIPIC_DPI_RESOLUTION) #define VERTICAL_ADDRESS_SHIFT 16 #define VERTICAL_ADDRESS_MASK (0xffff << 16) #define HORIZONTAL_ADDRESS_SHIFT 0 @@ -7839,8 +7885,7 @@ enum skl_disp_power_wells { #define _MIPIA_DBI_FIFO_THROTTLE (dev_priv->mipi_mmio_base + 0xb024) #define _MIPIC_DBI_FIFO_THROTTLE (dev_priv->mipi_mmio_base + 0xb824) -#define MIPI_DBI_FIFO_THROTTLE(port) _MIPI_PORT(port, \ - _MIPIA_DBI_FIFO_THROTTLE, _MIPIC_DBI_FIFO_THROTTLE) +#define MIPI_DBI_FIFO_THROTTLE(port) _MMIO_MIPI(port, _MIPIA_DBI_FIFO_THROTTLE, _MIPIC_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) @@ -7848,50 +7893,41 @@ enum skl_disp_power_wells { /* regs below are bits 15:0 */ #define _MIPIA_HSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb028) #define _MIPIC_HSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb828) -#define MIPI_HSYNC_PADDING_COUNT(port) _MIPI_PORT(port, \ - _MIPIA_HSYNC_PADDING_COUNT, _MIPIC_HSYNC_PADDING_COUNT) +#define MIPI_HSYNC_PADDING_COUNT(port) _MMIO_MIPI(port, _MIPIA_HSYNC_PADDING_COUNT, _MIPIC_HSYNC_PADDING_COUNT) #define _MIPIA_HBP_COUNT (dev_priv->mipi_mmio_base + 0xb02c) #define _MIPIC_HBP_COUNT (dev_priv->mipi_mmio_base + 0xb82c) -#define MIPI_HBP_COUNT(port) _MIPI_PORT(port, _MIPIA_HBP_COUNT, \ - _MIPIC_HBP_COUNT) +#define MIPI_HBP_COUNT(port) _MMIO_MIPI(port, _MIPIA_HBP_COUNT, _MIPIC_HBP_COUNT) #define _MIPIA_HFP_COUNT (dev_priv->mipi_mmio_base + 0xb030) #define _MIPIC_HFP_COUNT (dev_priv->mipi_mmio_base + 0xb830) -#define MIPI_HFP_COUNT(port) _MIPI_PORT(port, _MIPIA_HFP_COUNT, \ - _MIPIC_HFP_COUNT) +#define MIPI_HFP_COUNT(port) _MMIO_MIPI(port, _MIPIA_HFP_COUNT, _MIPIC_HFP_COUNT) #define _MIPIA_HACTIVE_AREA_COUNT (dev_priv->mipi_mmio_base + 0xb034) #define _MIPIC_HACTIVE_AREA_COUNT (dev_priv->mipi_mmio_base + 0xb834) -#define MIPI_HACTIVE_AREA_COUNT(port) _MIPI_PORT(port, \ - _MIPIA_HACTIVE_AREA_COUNT, _MIPIC_HACTIVE_AREA_COUNT) +#define MIPI_HACTIVE_AREA_COUNT(port) _MMIO_MIPI(port, _MIPIA_HACTIVE_AREA_COUNT, _MIPIC_HACTIVE_AREA_COUNT) #define _MIPIA_VSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb038) #define _MIPIC_VSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb838) -#define MIPI_VSYNC_PADDING_COUNT(port) _MIPI_PORT(port, \ - _MIPIA_VSYNC_PADDING_COUNT, _MIPIC_VSYNC_PADDING_COUNT) +#define MIPI_VSYNC_PADDING_COUNT(port) _MMIO_MIPI(port, _MIPIA_VSYNC_PADDING_COUNT, _MIPIC_VSYNC_PADDING_COUNT) #define _MIPIA_VBP_COUNT (dev_priv->mipi_mmio_base + 0xb03c) #define _MIPIC_VBP_COUNT (dev_priv->mipi_mmio_base + 0xb83c) -#define MIPI_VBP_COUNT(port) _MIPI_PORT(port, _MIPIA_VBP_COUNT, \ - _MIPIC_VBP_COUNT) +#define MIPI_VBP_COUNT(port) _MMIO_MIPI(port, _MIPIA_VBP_COUNT, _MIPIC_VBP_COUNT) #define _MIPIA_VFP_COUNT (dev_priv->mipi_mmio_base + 0xb040) #define _MIPIC_VFP_COUNT (dev_priv->mipi_mmio_base + 0xb840) -#define MIPI_VFP_COUNT(port) _MIPI_PORT(port, _MIPIA_VFP_COUNT, \ - _MIPIC_VFP_COUNT) +#define MIPI_VFP_COUNT(port) _MMIO_MIPI(port, _MIPIA_VFP_COUNT, _MIPIC_VFP_COUNT) #define _MIPIA_HIGH_LOW_SWITCH_COUNT (dev_priv->mipi_mmio_base + 0xb044) #define _MIPIC_HIGH_LOW_SWITCH_COUNT (dev_priv->mipi_mmio_base + 0xb844) -#define MIPI_HIGH_LOW_SWITCH_COUNT(port) _MIPI_PORT(port, \ - _MIPIA_HIGH_LOW_SWITCH_COUNT, _MIPIC_HIGH_LOW_SWITCH_COUNT) +#define MIPI_HIGH_LOW_SWITCH_COUNT(port) _MMIO_MIPI(port, _MIPIA_HIGH_LOW_SWITCH_COUNT, _MIPIC_HIGH_LOW_SWITCH_COUNT) /* regs above are bits 15:0 */ #define _MIPIA_DPI_CONTROL (dev_priv->mipi_mmio_base + 0xb048) #define _MIPIC_DPI_CONTROL (dev_priv->mipi_mmio_base + 0xb848) -#define MIPI_DPI_CONTROL(port) _MIPI_PORT(port, _MIPIA_DPI_CONTROL, \ - _MIPIC_DPI_CONTROL) +#define MIPI_DPI_CONTROL(port) _MMIO_MIPI(port, _MIPIA_DPI_CONTROL, _MIPIC_DPI_CONTROL) #define DPI_LP_MODE (1 << 6) #define BACKLIGHT_OFF (1 << 5) #define BACKLIGHT_ON (1 << 4) @@ -7902,29 +7938,26 @@ enum skl_disp_power_wells { #define _MIPIA_DPI_DATA (dev_priv->mipi_mmio_base + 0xb04c) #define _MIPIC_DPI_DATA (dev_priv->mipi_mmio_base + 0xb84c) -#define MIPI_DPI_DATA(port) _MIPI_PORT(port, _MIPIA_DPI_DATA, \ - _MIPIC_DPI_DATA) +#define MIPI_DPI_DATA(port) _MMIO_MIPI(port, _MIPIA_DPI_DATA, _MIPIC_DPI_DATA) #define COMMAND_BYTE_SHIFT 0 #define COMMAND_BYTE_MASK (0x3f << 0) #define _MIPIA_INIT_COUNT (dev_priv->mipi_mmio_base + 0xb050) #define _MIPIC_INIT_COUNT (dev_priv->mipi_mmio_base + 0xb850) -#define MIPI_INIT_COUNT(port) _MIPI_PORT(port, _MIPIA_INIT_COUNT, \ - _MIPIC_INIT_COUNT) +#define MIPI_INIT_COUNT(port) _MMIO_MIPI(port, _MIPIA_INIT_COUNT, _MIPIC_INIT_COUNT) #define MASTER_INIT_TIMER_SHIFT 0 #define MASTER_INIT_TIMER_MASK (0xffff << 0) #define _MIPIA_MAX_RETURN_PKT_SIZE (dev_priv->mipi_mmio_base + 0xb054) #define _MIPIC_MAX_RETURN_PKT_SIZE (dev_priv->mipi_mmio_base + 0xb854) -#define MIPI_MAX_RETURN_PKT_SIZE(port) _MIPI_PORT(port, \ +#define MIPI_MAX_RETURN_PKT_SIZE(port) _MMIO_MIPI(port, \ _MIPIA_MAX_RETURN_PKT_SIZE, _MIPIC_MAX_RETURN_PKT_SIZE) #define MAX_RETURN_PKT_SIZE_SHIFT 0 #define MAX_RETURN_PKT_SIZE_MASK (0x3ff << 0) #define _MIPIA_VIDEO_MODE_FORMAT (dev_priv->mipi_mmio_base + 0xb058) #define _MIPIC_VIDEO_MODE_FORMAT (dev_priv->mipi_mmio_base + 0xb858) -#define MIPI_VIDEO_MODE_FORMAT(port) _MIPI_PORT(port, \ - _MIPIA_VIDEO_MODE_FORMAT, _MIPIC_VIDEO_MODE_FORMAT) +#define MIPI_VIDEO_MODE_FORMAT(port) _MMIO_MIPI(port, _MIPIA_VIDEO_MODE_FORMAT, _MIPIC_VIDEO_MODE_FORMAT) #define RANDOM_DPI_DISPLAY_RESOLUTION (1 << 4) #define DISABLE_VIDEO_BTA (1 << 3) #define IP_TG_CONFIG (1 << 2) @@ -7934,8 +7967,7 @@ enum skl_disp_power_wells { #define _MIPIA_EOT_DISABLE (dev_priv->mipi_mmio_base + 0xb05c) #define _MIPIC_EOT_DISABLE (dev_priv->mipi_mmio_base + 0xb85c) -#define MIPI_EOT_DISABLE(port) _MIPI_PORT(port, _MIPIA_EOT_DISABLE, \ - _MIPIC_EOT_DISABLE) +#define MIPI_EOT_DISABLE(port) _MMIO_MIPI(port, _MIPIA_EOT_DISABLE, _MIPIC_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) @@ -7947,31 +7979,26 @@ enum skl_disp_power_wells { #define _MIPIA_LP_BYTECLK (dev_priv->mipi_mmio_base + 0xb060) #define _MIPIC_LP_BYTECLK (dev_priv->mipi_mmio_base + 0xb860) -#define MIPI_LP_BYTECLK(port) _MIPI_PORT(port, _MIPIA_LP_BYTECLK, \ - _MIPIC_LP_BYTECLK) +#define MIPI_LP_BYTECLK(port) _MMIO_MIPI(port, _MIPIA_LP_BYTECLK, _MIPIC_LP_BYTECLK) #define LP_BYTECLK_SHIFT 0 #define LP_BYTECLK_MASK (0xffff << 0) /* bits 31:0 */ #define _MIPIA_LP_GEN_DATA (dev_priv->mipi_mmio_base + 0xb064) #define _MIPIC_LP_GEN_DATA (dev_priv->mipi_mmio_base + 0xb864) -#define MIPI_LP_GEN_DATA(port) _MIPI_PORT(port, _MIPIA_LP_GEN_DATA, \ - _MIPIC_LP_GEN_DATA) +#define MIPI_LP_GEN_DATA(port) _MMIO_MIPI(port, _MIPIA_LP_GEN_DATA, _MIPIC_LP_GEN_DATA) /* bits 31:0 */ #define _MIPIA_HS_GEN_DATA (dev_priv->mipi_mmio_base + 0xb068) #define _MIPIC_HS_GEN_DATA (dev_priv->mipi_mmio_base + 0xb868) -#define MIPI_HS_GEN_DATA(port) _MIPI_PORT(port, _MIPIA_HS_GEN_DATA, \ - _MIPIC_HS_GEN_DATA) +#define MIPI_HS_GEN_DATA(port) _MMIO_MIPI(port, _MIPIA_HS_GEN_DATA, _MIPIC_HS_GEN_DATA) #define _MIPIA_LP_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb06c) #define _MIPIC_LP_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb86c) -#define MIPI_LP_GEN_CTRL(port) _MIPI_PORT(port, _MIPIA_LP_GEN_CTRL, \ - _MIPIC_LP_GEN_CTRL) +#define MIPI_LP_GEN_CTRL(port) _MMIO_MIPI(port, _MIPIA_LP_GEN_CTRL, _MIPIC_LP_GEN_CTRL) #define _MIPIA_HS_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb070) #define _MIPIC_HS_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb870) -#define MIPI_HS_GEN_CTRL(port) _MIPI_PORT(port, _MIPIA_HS_GEN_CTRL, \ - _MIPIC_HS_GEN_CTRL) +#define MIPI_HS_GEN_CTRL(port) _MMIO_MIPI(port, _MIPIA_HS_GEN_CTRL, _MIPIC_HS_GEN_CTRL) #define LONG_PACKET_WORD_COUNT_SHIFT 8 #define LONG_PACKET_WORD_COUNT_MASK (0xffff << 8) #define SHORT_PACKET_PARAM_SHIFT 8 @@ -7984,8 +8011,7 @@ enum skl_disp_power_wells { #define _MIPIA_GEN_FIFO_STAT (dev_priv->mipi_mmio_base + 0xb074) #define _MIPIC_GEN_FIFO_STAT (dev_priv->mipi_mmio_base + 0xb874) -#define MIPI_GEN_FIFO_STAT(port) _MIPI_PORT(port, _MIPIA_GEN_FIFO_STAT, \ - _MIPIC_GEN_FIFO_STAT) +#define MIPI_GEN_FIFO_STAT(port) _MMIO_MIPI(port, _MIPIA_GEN_FIFO_STAT, _MIPIC_GEN_FIFO_STAT) #define DPI_FIFO_EMPTY (1 << 28) #define DBI_FIFO_EMPTY (1 << 27) #define LP_CTRL_FIFO_EMPTY (1 << 26) @@ -8003,16 +8029,14 @@ enum skl_disp_power_wells { #define _MIPIA_HS_LS_DBI_ENABLE (dev_priv->mipi_mmio_base + 0xb078) #define _MIPIC_HS_LS_DBI_ENABLE (dev_priv->mipi_mmio_base + 0xb878) -#define MIPI_HS_LP_DBI_ENABLE(port) _MIPI_PORT(port, \ - _MIPIA_HS_LS_DBI_ENABLE, _MIPIC_HS_LS_DBI_ENABLE) +#define MIPI_HS_LP_DBI_ENABLE(port) _MMIO_MIPI(port, _MIPIA_HS_LS_DBI_ENABLE, _MIPIC_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 (dev_priv->mipi_mmio_base + 0xb080) #define _MIPIC_DPHY_PARAM (dev_priv->mipi_mmio_base + 0xb880) -#define MIPI_DPHY_PARAM(port) _MIPI_PORT(port, _MIPIA_DPHY_PARAM, \ - _MIPIC_DPHY_PARAM) +#define MIPI_DPHY_PARAM(port) _MMIO_MIPI(port, _MIPIA_DPHY_PARAM, _MIPIC_DPHY_PARAM) #define EXIT_ZERO_COUNT_SHIFT 24 #define EXIT_ZERO_COUNT_MASK (0x3f << 24) #define TRAIL_COUNT_SHIFT 16 @@ -8025,15 +8049,11 @@ enum skl_disp_power_wells { /* bits 31:0 */ #define _MIPIA_DBI_BW_CTRL (dev_priv->mipi_mmio_base + 0xb084) #define _MIPIC_DBI_BW_CTRL (dev_priv->mipi_mmio_base + 0xb884) -#define MIPI_DBI_BW_CTRL(port) _MIPI_PORT(port, _MIPIA_DBI_BW_CTRL, \ - _MIPIC_DBI_BW_CTRL) - -#define _MIPIA_CLK_LANE_SWITCH_TIME_CNT (dev_priv->mipi_mmio_base \ - + 0xb088) -#define _MIPIC_CLK_LANE_SWITCH_TIME_CNT (dev_priv->mipi_mmio_base \ - + 0xb888) -#define MIPI_CLK_LANE_SWITCH_TIME_CNT(port) _MIPI_PORT(port, \ - _MIPIA_CLK_LANE_SWITCH_TIME_CNT, _MIPIC_CLK_LANE_SWITCH_TIME_CNT) +#define MIPI_DBI_BW_CTRL(port) _MMIO_MIPI(port, _MIPIA_DBI_BW_CTRL, _MIPIC_DBI_BW_CTRL) + +#define _MIPIA_CLK_LANE_SWITCH_TIME_CNT (dev_priv->mipi_mmio_base + 0xb088) +#define _MIPIC_CLK_LANE_SWITCH_TIME_CNT (dev_priv->mipi_mmio_base + 0xb888) +#define MIPI_CLK_LANE_SWITCH_TIME_CNT(port) _MMIO_MIPI(port, _MIPIA_CLK_LANE_SWITCH_TIME_CNT, _MIPIC_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 @@ -8041,19 +8061,16 @@ enum skl_disp_power_wells { #define _MIPIA_STOP_STATE_STALL (dev_priv->mipi_mmio_base + 0xb08c) #define _MIPIC_STOP_STATE_STALL (dev_priv->mipi_mmio_base + 0xb88c) -#define MIPI_STOP_STATE_STALL(port) _MIPI_PORT(port, \ - _MIPIA_STOP_STATE_STALL, _MIPIC_STOP_STATE_STALL) +#define MIPI_STOP_STATE_STALL(port) _MMIO_MIPI(port, _MIPIA_STOP_STATE_STALL, _MIPIC_STOP_STATE_STALL) #define STOP_STATE_STALL_COUNTER_SHIFT 0 #define STOP_STATE_STALL_COUNTER_MASK (0xff << 0) #define _MIPIA_INTR_STAT_REG_1 (dev_priv->mipi_mmio_base + 0xb090) #define _MIPIC_INTR_STAT_REG_1 (dev_priv->mipi_mmio_base + 0xb890) -#define MIPI_INTR_STAT_REG_1(port) _MIPI_PORT(port, \ - _MIPIA_INTR_STAT_REG_1, _MIPIC_INTR_STAT_REG_1) +#define MIPI_INTR_STAT_REG_1(port) _MMIO_MIPI(port, _MIPIA_INTR_STAT_REG_1, _MIPIC_INTR_STAT_REG_1) #define _MIPIA_INTR_EN_REG_1 (dev_priv->mipi_mmio_base + 0xb094) #define _MIPIC_INTR_EN_REG_1 (dev_priv->mipi_mmio_base + 0xb894) -#define MIPI_INTR_EN_REG_1(port) _MIPI_PORT(port, _MIPIA_INTR_EN_REG_1, \ - _MIPIC_INTR_EN_REG_1) +#define MIPI_INTR_EN_REG_1(port) _MMIO_MIPI(port, _MIPIA_INTR_EN_REG_1, _MIPIC_INTR_EN_REG_1) #define RX_CONTENTION_DETECTED (1 << 0) /* XXX: only pipe A ?!? */ @@ -8073,8 +8090,7 @@ enum skl_disp_power_wells { #define _MIPIA_CTRL (dev_priv->mipi_mmio_base + 0xb104) #define _MIPIC_CTRL (dev_priv->mipi_mmio_base + 0xb904) -#define MIPI_CTRL(port) _MIPI_PORT(port, _MIPIA_CTRL, \ - _MIPIC_CTRL) +#define MIPI_CTRL(port) _MMIO_MIPI(port, _MIPIA_CTRL, _MIPIC_CTRL) #define ESCAPE_CLOCK_DIVIDER_SHIFT 5 /* A only */ #define ESCAPE_CLOCK_DIVIDER_MASK (3 << 5) #define ESCAPE_CLOCK_DIVIDER_1 (0 << 5) @@ -8087,29 +8103,24 @@ enum skl_disp_power_wells { #define RGB_FLIP_TO_BGR (1 << 2) #define BXT_PIPE_SELECT_MASK (7 << 7) -#define BXT_PIPE_SELECT_C (2 << 7) -#define BXT_PIPE_SELECT_B (1 << 7) -#define BXT_PIPE_SELECT_A (0 << 7) +#define BXT_PIPE_SELECT(pipe) ((pipe) << 7) #define _MIPIA_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb108) #define _MIPIC_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb908) -#define MIPI_DATA_ADDRESS(port) _MIPI_PORT(port, _MIPIA_DATA_ADDRESS, \ - _MIPIC_DATA_ADDRESS) +#define MIPI_DATA_ADDRESS(port) _MMIO_MIPI(port, _MIPIA_DATA_ADDRESS, _MIPIC_DATA_ADDRESS) #define DATA_MEM_ADDRESS_SHIFT 5 #define DATA_MEM_ADDRESS_MASK (0x7ffffff << 5) #define DATA_VALID (1 << 0) #define _MIPIA_DATA_LENGTH (dev_priv->mipi_mmio_base + 0xb10c) #define _MIPIC_DATA_LENGTH (dev_priv->mipi_mmio_base + 0xb90c) -#define MIPI_DATA_LENGTH(port) _MIPI_PORT(port, _MIPIA_DATA_LENGTH, \ - _MIPIC_DATA_LENGTH) +#define MIPI_DATA_LENGTH(port) _MMIO_MIPI(port, _MIPIA_DATA_LENGTH, _MIPIC_DATA_LENGTH) #define DATA_LENGTH_SHIFT 0 #define DATA_LENGTH_MASK (0xfffff << 0) #define _MIPIA_COMMAND_ADDRESS (dev_priv->mipi_mmio_base + 0xb110) #define _MIPIC_COMMAND_ADDRESS (dev_priv->mipi_mmio_base + 0xb910) -#define MIPI_COMMAND_ADDRESS(port) _MIPI_PORT(port, \ - _MIPIA_COMMAND_ADDRESS, _MIPIC_COMMAND_ADDRESS) +#define MIPI_COMMAND_ADDRESS(port) _MMIO_MIPI(port, _MIPIA_COMMAND_ADDRESS, _MIPIC_COMMAND_ADDRESS) #define COMMAND_MEM_ADDRESS_SHIFT 5 #define COMMAND_MEM_ADDRESS_MASK (0x7ffffff << 5) #define AUTO_PWG_ENABLE (1 << 2) @@ -8118,21 +8129,17 @@ enum skl_disp_power_wells { #define _MIPIA_COMMAND_LENGTH (dev_priv->mipi_mmio_base + 0xb114) #define _MIPIC_COMMAND_LENGTH (dev_priv->mipi_mmio_base + 0xb914) -#define MIPI_COMMAND_LENGTH(port) _MIPI_PORT(port, _MIPIA_COMMAND_LENGTH, \ - _MIPIC_COMMAND_LENGTH) +#define MIPI_COMMAND_LENGTH(port) _MMIO_MIPI(port, _MIPIA_COMMAND_LENGTH, _MIPIC_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 (dev_priv->mipi_mmio_base + 0xb118) #define _MIPIC_READ_DATA_RETURN0 (dev_priv->mipi_mmio_base + 0xb918) -#define MIPI_READ_DATA_RETURN(port, n) \ - (_MIPI_PORT(port, _MIPIA_READ_DATA_RETURN0, _MIPIC_READ_DATA_RETURN0) \ - + 4 * (n)) /* n: 0...7 */ +#define MIPI_READ_DATA_RETURN(port, n) _MMIO(_MIPI(port, _MIPIA_READ_DATA_RETURN0, _MIPIC_READ_DATA_RETURN0) + 4 * (n)) /* n: 0...7 */ #define _MIPIA_READ_DATA_VALID (dev_priv->mipi_mmio_base + 0xb138) #define _MIPIC_READ_DATA_VALID (dev_priv->mipi_mmio_base + 0xb938) -#define MIPI_READ_DATA_VALID(port) _MIPI_PORT(port, \ - _MIPIA_READ_DATA_VALID, _MIPIC_READ_DATA_VALID) +#define MIPI_READ_DATA_VALID(port) _MMIO_MIPI(port, _MIPIA_READ_DATA_VALID, _MIPIC_READ_DATA_VALID) #define READ_DATA_VALID(n) (1 << (n)) /* For UMS only (deprecated): */ @@ -8140,12 +8147,12 @@ enum skl_disp_power_wells { #define _PALETTE_B (dev_priv->info.display_mmio_offset + 0xa800) /* MOCS (Memory Object Control State) registers */ -#define GEN9_LNCFCMOCS0 0xb020 /* L3 Cache Control base */ +#define GEN9_LNCFCMOCS(i) _MMIO(0xb020 + (i) * 4) /* L3 Cache Control */ -#define GEN9_GFX_MOCS_0 0xc800 /* Graphics MOCS base register*/ -#define GEN9_MFX0_MOCS_0 0xc900 /* Media 0 MOCS base register*/ -#define GEN9_MFX1_MOCS_0 0xca00 /* Media 1 MOCS base register*/ -#define GEN9_VEBOX_MOCS_0 0xcb00 /* Video MOCS base register*/ -#define GEN9_BLT_MOCS_0 0xcc00 /* Blitter MOCS base register*/ +#define GEN9_GFX_MOCS(i) _MMIO(0xc800 + (i) * 4) /* Graphics MOCS registers */ +#define GEN9_MFX0_MOCS(i) _MMIO(0xc900 + (i) * 4) /* Media 0 MOCS registers */ +#define GEN9_MFX1_MOCS(i) _MMIO(0xca00 + (i) * 4) /* Media 1 MOCS registers */ +#define GEN9_VEBOX_MOCS(i) _MMIO(0xcb00 + (i) * 4) /* Video MOCS registers */ +#define GEN9_BLT_MOCS(i) _MMIO(0xcc00 + (i) * 4) /* Blitter MOCS registers */ #endif /* _I915_REG_H_ */ diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 2d9182189..a8af594fb 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -49,7 +49,7 @@ static void i915_save_display(struct drm_device *dev) dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS); dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS); dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR); - } else if (!IS_VALLEYVIEW(dev)) { + } else if (INTEL_INFO(dev)->gen <= 4) { dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL); dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS); dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS); @@ -84,7 +84,7 @@ static void i915_restore_display(struct drm_device *dev) I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS); I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR); I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL); - } else if (!IS_VALLEYVIEW(dev)) { + } else if (INTEL_INFO(dev)->gen <= 4) { I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS); I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS); I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR); diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 50ce9ce2b..37e3f0ddf 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -35,7 +35,8 @@ #define dev_to_drm_minor(d) dev_get_drvdata((d)) #ifdef CONFIG_PM -static u32 calc_residency(struct drm_device *dev, const u32 reg) +static u32 calc_residency(struct drm_device *dev, + i915_reg_t reg) { struct drm_i915_private *dev_priv = dev->dev_private; u64 raw_time; /* 32b value may overflow during fixed point math */ @@ -48,7 +49,7 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg) intel_runtime_pm_get(dev_priv); /* On VLV and CHV, residency time is in CZ units rather than 1.28us */ - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { units = 1; div = dev_priv->czclk_freq; @@ -283,7 +284,7 @@ static ssize_t gt_act_freq_mhz_show(struct device *kdev, intel_runtime_pm_get(dev_priv); mutex_lock(&dev_priv->rps.hw_lock); - if (IS_VALLEYVIEW(dev_priv->dev)) { + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { u32 freq; freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); ret = intel_gpu_freq(dev_priv, (freq >> 8) & 0xff); @@ -597,7 +598,7 @@ void i915_setup_sysfs(struct drm_device *dev) if (ret) DRM_ERROR("RC6p residency sysfs setup failed\n"); } - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { ret = sysfs_merge_group(&dev->primary->kdev->kobj, &media_rc6_attr_group); if (ret) @@ -618,7 +619,7 @@ void i915_setup_sysfs(struct drm_device *dev) } ret = 0; - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) 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); @@ -634,7 +635,7 @@ 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); - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) sysfs_remove_files(&dev->primary->kdev->kobj, vlv_attrs); else sysfs_remove_files(&dev->primary->kdev->kobj, gen6_attrs); diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 04fe8491c..52b2d4099 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -664,7 +664,7 @@ TRACE_EVENT(i915_flip_complete, ); TRACE_EVENT_CONDITION(i915_reg_rw, - TP_PROTO(bool write, u32 reg, u64 val, int len, bool trace), + TP_PROTO(bool write, i915_reg_t reg, u64 val, int len, bool trace), TP_ARGS(write, reg, val, len, trace), @@ -679,7 +679,7 @@ TRACE_EVENT_CONDITION(i915_reg_rw, TP_fast_assign( __entry->val = (u64)val; - __entry->reg = reg; + __entry->reg = i915_mmio_reg_offset(reg); __entry->write = write; __entry->len = len; ), diff --git a/drivers/gpu/drm/i915/i915_vgpu.c b/drivers/gpu/drm/i915/i915_vgpu.c index 5eee75bff..dea7429be 100644 --- a/drivers/gpu/drm/i915/i915_vgpu.c +++ b/drivers/gpu/drm/i915/i915_vgpu.c @@ -69,13 +69,13 @@ void i915_check_vgpu(struct drm_device *dev) if (!IS_HASWELL(dev)) return; - magic = readq(dev_priv->regs + vgtif_reg(magic)); + magic = __raw_i915_read64(dev_priv, vgtif_reg(magic)); if (magic != VGT_MAGIC) return; version = INTEL_VGT_IF_VERSION_ENCODE( - readw(dev_priv->regs + vgtif_reg(version_major)), - readw(dev_priv->regs + vgtif_reg(version_minor))); + __raw_i915_read16(dev_priv, vgtif_reg(version_major)), + __raw_i915_read16(dev_priv, vgtif_reg(version_minor))); if (version != INTEL_VGT_IF_VERSION) { DRM_INFO("VGT interface version mismatch!\n"); return; diff --git a/drivers/gpu/drm/i915/i915_vgpu.h b/drivers/gpu/drm/i915/i915_vgpu.h index 21c97f44d..3c83b47b5 100644 --- a/drivers/gpu/drm/i915/i915_vgpu.h +++ b/drivers/gpu/drm/i915/i915_vgpu.h @@ -92,14 +92,10 @@ struct vgt_if { uint32_t g2v_notify; uint32_t rsv6[7]; - uint32_t pdp0_lo; - uint32_t pdp0_hi; - uint32_t pdp1_lo; - uint32_t pdp1_hi; - uint32_t pdp2_lo; - uint32_t pdp2_hi; - uint32_t pdp3_lo; - uint32_t pdp3_hi; + struct { + uint32_t lo; + uint32_t hi; + } pdp[4]; uint32_t execlist_context_descriptor_lo; uint32_t execlist_context_descriptor_hi; @@ -108,7 +104,7 @@ struct vgt_if { } __packed; #define vgtif_reg(x) \ - (VGT_PVINFO_PAGE + (long)&((struct vgt_if *)NULL)->x) + _MMIO((VGT_PVINFO_PAGE + (long)&((struct vgt_if *)NULL)->x)) /* vGPU display status to be used by the host side */ #define VGT_DRV_DISPLAY_NOT_READY 0 diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index f1975f267..d0b1c9afa 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -94,6 +94,9 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) __drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->base); crtc_state->update_pipe = false; + crtc_state->disable_lp_wm = false; + crtc_state->disable_cxsr = false; + crtc_state->wm_changed = false; return &crtc_state->base; } @@ -205,8 +208,6 @@ int intel_atomic_setup_scalers(struct drm_device *dev, * but since this plane is unchanged just do the * minimum required validation. */ - if (plane->type == DRM_PLANE_TYPE_PRIMARY) - intel_crtc->atomic.wait_for_flips = true; crtc_state->base.planes_changed = true; } diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index a11980696..c6bb0fc1e 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -84,6 +84,7 @@ intel_plane_duplicate_state(struct drm_plane *plane) state = &intel_state->base; __drm_atomic_helper_plane_duplicate_state(plane, state); + intel_state->wait_req = NULL; return state; } @@ -100,6 +101,7 @@ void intel_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state) { + WARN_ON(state && to_intel_plane_state(state)->wait_req); drm_atomic_helper_plane_destroy_state(plane, state); } diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 4dccd9b00..30f921421 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -161,9 +161,9 @@ static bool audio_rate_need_prog(struct intel_crtc *crtc, } static bool intel_eld_uptodate(struct drm_connector *connector, - int reg_eldv, uint32_t bits_eldv, - int reg_elda, uint32_t bits_elda, - int reg_edid) + i915_reg_t reg_eldv, uint32_t bits_eldv, + i915_reg_t reg_elda, uint32_t bits_elda, + i915_reg_t reg_edid) { struct drm_i915_private *dev_priv = connector->dev->dev_private; uint8_t *eld = connector->eld; @@ -262,7 +262,8 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder) tmp |= AUD_CONFIG_N_PROG_ENABLE; tmp &= ~AUD_CONFIG_UPPER_N_MASK; tmp &= ~AUD_CONFIG_LOWER_N_MASK; - if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT)) + if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT) || + intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DP_MST)) tmp |= AUD_CONFIG_N_VALUE_INDEX; I915_WRITE(HSW_AUD_CFG(pipe), tmp); @@ -364,8 +365,7 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder) enum port port = intel_dig_port->port; enum pipe pipe = intel_crtc->pipe; uint32_t tmp, eldv; - int aud_config; - int aud_cntrl_st2; + i915_reg_t aud_config, aud_cntrl_st2; DRM_DEBUG_KMS("Disable audio codec on port %c, pipe %c\n", port_name(port), pipe_name(pipe)); @@ -376,7 +376,7 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder) if (HAS_PCH_IBX(dev_priv->dev)) { aud_config = IBX_AUD_CFG(pipe); aud_cntrl_st2 = IBX_AUD_CNTL_ST2; - } else if (IS_VALLEYVIEW(dev_priv)) { + } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { aud_config = VLV_AUD_CFG(pipe); aud_cntrl_st2 = VLV_AUD_CNTL_ST2; } else { @@ -416,10 +416,7 @@ static void ilk_audio_codec_enable(struct drm_connector *connector, uint32_t eldv; uint32_t tmp; int len, i; - int hdmiw_hdmiedid; - int aud_config; - int aud_cntl_st; - int aud_cntrl_st2; + i915_reg_t hdmiw_hdmiedid, aud_config, aud_cntl_st, aud_cntrl_st2; DRM_DEBUG_KMS("Enable audio codec on port %c, pipe %c, %u bytes ELD\n", port_name(port), pipe_name(pipe), drm_eld_size(eld)); @@ -439,7 +436,8 @@ static void ilk_audio_codec_enable(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)) { + } else if (IS_VALLEYVIEW(connector->dev) || + IS_CHERRYVIEW(connector->dev)) { hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); aud_config = VLV_AUD_CFG(pipe); aud_cntl_st = VLV_AUD_CNTL_ST(pipe); @@ -478,7 +476,8 @@ static void ilk_audio_codec_enable(struct drm_connector *connector, tmp &= ~AUD_CONFIG_N_VALUE_INDEX; tmp &= ~AUD_CONFIG_N_PROG_ENABLE; tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; - if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT)) + if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT) || + intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DP_MST)) tmp |= AUD_CONFIG_N_VALUE_INDEX; else tmp |= audio_config_hdmi_pixel_clock(adjusted_mode); @@ -516,7 +515,8 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder) /* ELD Conn_Type */ connector->eld[5] &= ~(3 << 2); - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || + intel_pipe_has_type(crtc, INTEL_OUTPUT_DP_MST)) connector->eld[5] |= (1 << 2); connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; @@ -525,6 +525,12 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder) dev_priv->display.audio_codec_enable(connector, intel_encoder, adjusted_mode); + mutex_lock(&dev_priv->av_mutex); + intel_dig_port->audio_connector = connector; + /* referred in audio callbacks */ + dev_priv->dig_port_map[port] = intel_encoder; + mutex_unlock(&dev_priv->av_mutex); + if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port); } @@ -548,6 +554,11 @@ void intel_audio_codec_disable(struct intel_encoder *intel_encoder) if (dev_priv->display.audio_codec_disable) dev_priv->display.audio_codec_disable(intel_encoder); + mutex_lock(&dev_priv->av_mutex); + intel_dig_port->audio_connector = NULL; + dev_priv->dig_port_map[port] = NULL; + mutex_unlock(&dev_priv->av_mutex); + if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port); } @@ -563,7 +574,7 @@ void intel_init_audio(struct drm_device *dev) if (IS_G4X(dev)) { dev_priv->display.audio_codec_enable = g4x_audio_codec_enable; dev_priv->display.audio_codec_disable = g4x_audio_codec_disable; - } else if (IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { dev_priv->display.audio_codec_enable = ilk_audio_codec_enable; dev_priv->display.audio_codec_disable = ilk_audio_codec_disable; } else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) { @@ -591,7 +602,7 @@ static void i915_audio_component_codec_wake_override(struct device *dev, struct drm_i915_private *dev_priv = dev_to_i915(dev); u32 tmp; - if (!IS_SKYLAKE(dev_priv)) + if (!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)) return; /* @@ -632,44 +643,40 @@ static int i915_audio_component_sync_audio_rate(struct device *dev, int port, int rate) { struct drm_i915_private *dev_priv = dev_to_i915(dev); - struct drm_device *drm_dev = dev_priv->dev; struct intel_encoder *intel_encoder; - struct intel_digital_port *intel_dig_port; struct intel_crtc *crtc; struct drm_display_mode *mode; struct i915_audio_component *acomp = dev_priv->audio_component; - enum pipe pipe = -1; + enum pipe pipe = INVALID_PIPE; u32 tmp; int n; + int err = 0; - /* HSW, BDW SKL need this fix */ + /* HSW, BDW, SKL, KBL need this fix */ if (!IS_SKYLAKE(dev_priv) && - !IS_BROADWELL(dev_priv) && - !IS_HASWELL(dev_priv)) + !IS_KABYLAKE(dev_priv) && + !IS_BROADWELL(dev_priv) && + !IS_HASWELL(dev_priv)) return 0; mutex_lock(&dev_priv->av_mutex); /* 1. get the pipe */ - for_each_intel_encoder(drm_dev, intel_encoder) { - if (intel_encoder->type != INTEL_OUTPUT_HDMI) - continue; - intel_dig_port = enc_to_dig_port(&intel_encoder->base); - if (port == intel_dig_port->port) { - crtc = to_intel_crtc(intel_encoder->base.crtc); - if (!crtc) { - DRM_DEBUG_KMS("%s: crtc is NULL\n", __func__); - continue; - } - pipe = crtc->pipe; - break; - } + intel_encoder = dev_priv->dig_port_map[port]; + /* intel_encoder might be NULL for DP MST */ + if (!intel_encoder || !intel_encoder->base.crtc || + intel_encoder->type != INTEL_OUTPUT_HDMI) { + DRM_DEBUG_KMS("no valid port %c\n", port_name(port)); + err = -ENODEV; + goto unlock; } - + crtc = to_intel_crtc(intel_encoder->base.crtc); + pipe = crtc->pipe; if (pipe == INVALID_PIPE) { DRM_DEBUG_KMS("no pipe for the port %c\n", port_name(port)); - mutex_unlock(&dev_priv->av_mutex); - return -ENODEV; + err = -ENODEV; + goto unlock; } + DRM_DEBUG_KMS("pipe %c connects port %c\n", pipe_name(pipe), port_name(port)); mode = &crtc->config->base.adjusted_mode; @@ -682,8 +689,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev, tmp = I915_READ(HSW_AUD_CFG(pipe)); tmp &= ~AUD_CONFIG_N_PROG_ENABLE; I915_WRITE(HSW_AUD_CFG(pipe), tmp); - mutex_unlock(&dev_priv->av_mutex); - return 0; + goto unlock; } n = audio_config_get_n(mode, rate); @@ -693,8 +699,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev, tmp = I915_READ(HSW_AUD_CFG(pipe)); tmp &= ~AUD_CONFIG_N_PROG_ENABLE; I915_WRITE(HSW_AUD_CFG(pipe), tmp); - mutex_unlock(&dev_priv->av_mutex); - return 0; + goto unlock; } /* 3. set the N/CTS/M */ @@ -702,8 +707,37 @@ static int i915_audio_component_sync_audio_rate(struct device *dev, tmp = audio_config_setup_n_reg(n, tmp); I915_WRITE(HSW_AUD_CFG(pipe), tmp); + unlock: mutex_unlock(&dev_priv->av_mutex); - return 0; + return err; +} + +static int i915_audio_component_get_eld(struct device *dev, int port, + bool *enabled, + unsigned char *buf, int max_bytes) +{ + struct drm_i915_private *dev_priv = dev_to_i915(dev); + struct intel_encoder *intel_encoder; + struct intel_digital_port *intel_dig_port; + const u8 *eld; + int ret = -EINVAL; + + mutex_lock(&dev_priv->av_mutex); + intel_encoder = dev_priv->dig_port_map[port]; + /* intel_encoder might be NULL for DP MST */ + if (intel_encoder) { + ret = 0; + intel_dig_port = enc_to_dig_port(&intel_encoder->base); + *enabled = intel_dig_port->audio_connector != NULL; + if (*enabled) { + eld = intel_dig_port->audio_connector->eld; + ret = drm_eld_size(eld); + memcpy(buf, eld, min(max_bytes, ret)); + } + } + + mutex_unlock(&dev_priv->av_mutex); + return ret; } static const struct i915_audio_component_ops i915_audio_component_ops = { @@ -713,6 +747,7 @@ static const struct i915_audio_component_ops i915_audio_component_ops = { .codec_wake_override = i915_audio_component_codec_wake_override, .get_cdclk_freq = i915_audio_component_get_cdclk_freq, .sync_audio_rate = i915_audio_component_sync_audio_rate, + .get_eld = i915_audio_component_get_eld, }; static int i915_audio_component_bind(struct device *i915_dev, diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index ce82f9c7d..eba3e0f87 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -24,7 +24,7 @@ * Eric Anholt <eric@anholt.net> * */ -#include <linux/dmi.h> + #include <drm/drm_dp_helper.h> #include <drm/drmP.h> #include <drm/i915_drm.h> @@ -332,10 +332,10 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv, drm_mode_debug_printmodeline(panel_fixed_mode); } -static int intel_bios_ssc_frequency(struct drm_device *dev, +static int intel_bios_ssc_frequency(struct drm_i915_private *dev_priv, bool alternate) { - switch (INTEL_INFO(dev)->gen) { + switch (INTEL_INFO(dev_priv)->gen) { case 2: return alternate ? 66667 : 48000; case 3: @@ -350,26 +350,29 @@ static void parse_general_features(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) { - struct drm_device *dev = dev_priv->dev; const struct bdb_general_features *general; general = find_section(bdb, BDB_GENERAL_FEATURES); - if (general) { - dev_priv->vbt.int_tv_support = general->int_tv_support; + if (!general) + return; + + dev_priv->vbt.int_tv_support = general->int_tv_support; + /* int_crt_support can't be trusted on earlier platforms */ + if (bdb->version >= 155 && + (HAS_DDI(dev_priv) || IS_VALLEYVIEW(dev_priv))) dev_priv->vbt.int_crt_support = general->int_crt_support; - dev_priv->vbt.lvds_use_ssc = general->enable_ssc; - dev_priv->vbt.lvds_ssc_freq = - intel_bios_ssc_frequency(dev, general->ssc_freq); - dev_priv->vbt.display_clock_mode = general->display_clock_mode; - dev_priv->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted; - DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n", - dev_priv->vbt.int_tv_support, - dev_priv->vbt.int_crt_support, - dev_priv->vbt.lvds_use_ssc, - dev_priv->vbt.lvds_ssc_freq, - dev_priv->vbt.display_clock_mode, - dev_priv->vbt.fdi_rx_polarity_inverted); - } + dev_priv->vbt.lvds_use_ssc = general->enable_ssc; + dev_priv->vbt.lvds_ssc_freq = + intel_bios_ssc_frequency(dev_priv, general->ssc_freq); + dev_priv->vbt.display_clock_mode = general->display_clock_mode; + dev_priv->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted; + DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n", + dev_priv->vbt.int_tv_support, + dev_priv->vbt.int_crt_support, + dev_priv->vbt.lvds_use_ssc, + dev_priv->vbt.lvds_ssc_freq, + dev_priv->vbt.display_clock_mode, + dev_priv->vbt.fdi_rx_polarity_inverted); } static void @@ -1054,10 +1057,9 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, static void parse_ddi_ports(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) { - struct drm_device *dev = dev_priv->dev; enum port port; - if (!HAS_DDI(dev)) + if (!HAS_DDI(dev_priv)) return; if (!dev_priv->vbt.child_dev_num) @@ -1170,7 +1172,6 @@ parse_device_mapping(struct drm_i915_private *dev_priv, 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_PIN_VGADDC; @@ -1195,8 +1196,8 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) * 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_priv, + !HAS_PCH_SPLIT(dev_priv)); DRM_DEBUG_KMS("Set default to SSC at %d kHz\n", dev_priv->vbt.lvds_ssc_freq); for (port = PORT_A; port < I915_MAX_PORTS; port++) { @@ -1211,88 +1212,79 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) } } -static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id) +static const struct bdb_header *get_bdb_header(const struct vbt_header *vbt) { - DRM_DEBUG_KMS("Falling back to manually reading VBT from " - "VBIOS ROM for %s\n", - id->ident); - return 1; + const void *_vbt = vbt; + + return _vbt + vbt->bdb_offset; } -static const struct dmi_system_id intel_no_opregion_vbt[] = { - { - .callback = intel_no_opregion_vbt_callback, - .ident = "ThinkCentre A57", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"), - }, - }, - { } -}; - -static const struct bdb_header *validate_vbt(const void *base, - size_t size, - const void *_vbt, - const char *source) +/** + * intel_bios_is_valid_vbt - does the given buffer contain a valid VBT + * @buf: pointer to a buffer to validate + * @size: size of the buffer + * + * Returns true on valid VBT. + */ +bool intel_bios_is_valid_vbt(const void *buf, size_t size) { - size_t offset = _vbt - base; - const struct vbt_header *vbt = _vbt; + const struct vbt_header *vbt = buf; const struct bdb_header *bdb; - if (offset + sizeof(struct vbt_header) > size) { + if (!vbt) + return false; + + if (sizeof(struct vbt_header) > size) { DRM_DEBUG_DRIVER("VBT header incomplete\n"); - return NULL; + return false; } if (memcmp(vbt->signature, "$VBT", 4)) { DRM_DEBUG_DRIVER("VBT invalid signature\n"); - return NULL; + return false; } - offset += vbt->bdb_offset; - if (offset + sizeof(struct bdb_header) > size) { + if (vbt->bdb_offset + sizeof(struct bdb_header) > size) { DRM_DEBUG_DRIVER("BDB header incomplete\n"); - return NULL; + return false; } - bdb = base + offset; - if (offset + bdb->bdb_size > size) { + bdb = get_bdb_header(vbt); + if (vbt->bdb_offset + bdb->bdb_size > size) { DRM_DEBUG_DRIVER("BDB incomplete\n"); - return NULL; + return false; } - DRM_DEBUG_KMS("Using VBT from %s: %20s\n", - source, vbt->signature); - return bdb; + return vbt; } -static const struct bdb_header *find_vbt(void __iomem *bios, size_t size) +static const struct vbt_header *find_vbt(void __iomem *bios, size_t size) { - const struct bdb_header *bdb = NULL; size_t i; /* Scour memory looking for the VBT signature. */ for (i = 0; i + 4 < size; i++) { - if (ioread32(bios + i) == *((const u32 *) "$VBT")) { - /* - * This is the one place where we explicitly discard the - * address space (__iomem) of the BIOS/VBT. From now on - * everything is based on 'base', and treated as regular - * memory. - */ - void *_bios = (void __force *) bios; + void *vbt; - bdb = validate_vbt(_bios, size, _bios + i, "PCI ROM"); - break; - } + if (ioread32(bios + i) != *((const u32 *) "$VBT")) + continue; + + /* + * This is the one place where we explicitly discard the address + * space (__iomem) of the BIOS/VBT. + */ + vbt = (void __force *) bios + i; + if (intel_bios_is_valid_vbt(vbt, size - i)) + return vbt; + + break; } - return bdb; + return NULL; } /** - * intel_parse_bios - find VBT and initialize settings from the BIOS + * intel_bios_init - find VBT and initialize settings from the BIOS * @dev: DRM device * * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers @@ -1301,37 +1293,39 @@ static const struct bdb_header *find_vbt(void __iomem *bios, size_t size) * Returns 0 on success, nonzero on failure. */ int -intel_parse_bios(struct drm_device *dev) +intel_bios_init(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = dev->dev_private; - struct pci_dev *pdev = dev->pdev; - const struct bdb_header *bdb = NULL; + struct pci_dev *pdev = dev_priv->dev->pdev; + const struct vbt_header *vbt = dev_priv->opregion.vbt; + const struct bdb_header *bdb; u8 __iomem *bios = NULL; - if (HAS_PCH_NOP(dev)) + if (HAS_PCH_NOP(dev_priv)) return -ENODEV; init_vbt_defaults(dev_priv); - /* XXX Should this validation be moved to intel_opregion.c? */ - if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt) - bdb = validate_vbt(dev_priv->opregion.header, OPREGION_SIZE, - dev_priv->opregion.vbt, "OpRegion"); - - if (bdb == NULL) { + if (!vbt) { size_t size; bios = pci_map_rom(pdev, &size); if (!bios) return -1; - bdb = find_vbt(bios, size); - if (!bdb) { + vbt = find_vbt(bios, size); + if (!vbt) { pci_unmap_rom(pdev, bios); return -1; } + + DRM_DEBUG_KMS("Found valid VBT in PCI ROM\n"); } + bdb = get_bdb_header(vbt); + + DRM_DEBUG_KMS("VBT signature \"%.*s\", BDB version %d\n", + (int)sizeof(vbt->signature), vbt->signature, bdb->version); + /* Grab useful general definitions */ parse_general_features(dev_priv, bdb); parse_general_definitions(dev_priv, bdb); diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 7ec8c9aef..54eac1003 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -28,8 +28,6 @@ #ifndef _I830_BIOS_H_ #define _I830_BIOS_H_ -#include <drm/drmP.h> - struct vbt_header { u8 signature[20]; /**< Always starts with 'VBT$' */ u16 version; /**< decimal */ @@ -588,8 +586,6 @@ struct bdb_psr { struct psr_table psr_table[16]; } __packed; -int intel_parse_bios(struct drm_device *dev); - /* * Driver<->VBIOS interaction occurs through scratch bits in * GR18 & SWF*. diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 6a2c76e36..a7b4a524f 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -50,7 +50,7 @@ struct intel_crt { * encoder's enable/disable callbacks */ struct intel_connector *connector; bool force_hotplug_required; - u32 adpa_reg; + i915_reg_t adpa_reg; }; static struct intel_crt *intel_encoder_to_crt(struct intel_encoder *encoder) @@ -71,22 +71,29 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder, struct intel_crt *crt = intel_encoder_to_crt(encoder); enum intel_display_power_domain power_domain; u32 tmp; + bool ret; power_domain = intel_display_port_power_domain(encoder); - if (!intel_display_power_is_enabled(dev_priv, power_domain)) + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; + ret = false; + tmp = I915_READ(crt->adpa_reg); if (!(tmp & ADPA_DAC_ENABLE)) - return false; + goto out; if (HAS_PCH_CPT(dev)) *pipe = PORT_TO_PIPE_CPT(tmp); else *pipe = PORT_TO_PIPE(tmp); - return true; + ret = true; +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } static unsigned int intel_crt_get_flags(struct intel_encoder *encoder) @@ -480,12 +487,8 @@ intel_crt_load_detect(struct intel_crt *crt) uint32_t vsample; uint32_t vblank, vblank_start, vblank_end; uint32_t dsl; - uint32_t bclrpat_reg; - uint32_t vtotal_reg; - uint32_t vblank_reg; - uint32_t vsync_reg; - uint32_t pipeconf_reg; - uint32_t pipe_dsl_reg; + i915_reg_t bclrpat_reg, vtotal_reg, + vblank_reg, vsync_reg, pipeconf_reg, pipe_dsl_reg; uint8_t st00; enum drm_connector_status status; @@ -518,7 +521,7 @@ intel_crt_load_detect(struct intel_crt *crt) /* Wait for next Vblank to substitue * border color for Color info */ intel_wait_for_vblank(dev, pipe); - st00 = I915_READ8(VGA_MSR_WRITE); + st00 = I915_READ8(_VGA_MSR_WRITE); status = ((st00 & (1 << 4)) != 0) ? connector_status_connected : connector_status_disconnected; @@ -563,7 +566,7 @@ intel_crt_load_detect(struct intel_crt *crt) do { count++; /* Read the ST00 VGA status register */ - st00 = I915_READ8(VGA_MSR_WRITE); + st00 = I915_READ8(_VGA_MSR_WRITE); if (st00 & (1 << 4)) detect++; } while ((I915_READ(pipe_dsl_reg) == dsl)); @@ -781,11 +784,37 @@ void intel_crt_init(struct drm_device *dev) struct intel_crt *crt; struct intel_connector *intel_connector; struct drm_i915_private *dev_priv = dev->dev_private; + i915_reg_t adpa_reg; + u32 adpa; /* Skip machines without VGA that falsely report hotplug events */ if (dmi_check_system(intel_no_crt)) return; + if (HAS_PCH_SPLIT(dev)) + adpa_reg = PCH_ADPA; + else if (IS_VALLEYVIEW(dev)) + adpa_reg = VLV_ADPA; + else + adpa_reg = ADPA; + + adpa = I915_READ(adpa_reg); + if ((adpa & ADPA_DAC_ENABLE) == 0) { + /* + * On some machines (some IVB at least) CRT can be + * fused off, but there's no known fuse bit to + * indicate that. On these machine the ADPA register + * works normally, except the DAC enable bit won't + * take. So the only way to tell is attempt to enable + * it and see what happens. + */ + I915_WRITE(adpa_reg, adpa | ADPA_DAC_ENABLE | + ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); + if ((I915_READ(adpa_reg) & ADPA_DAC_ENABLE) == 0) + return; + I915_WRITE(adpa_reg, adpa); + } + crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL); if (!crt) return; @@ -802,7 +831,7 @@ void intel_crt_init(struct drm_device *dev) &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); drm_encoder_init(dev, &crt->base.base, &intel_crt_enc_funcs, - DRM_MODE_ENCODER_DAC); + DRM_MODE_ENCODER_DAC, NULL); intel_connector_attach_encoder(intel_connector, &crt->base); @@ -819,15 +848,10 @@ void intel_crt_init(struct drm_device *dev) connector->interlace_allowed = 1; connector->doublescan_allowed = 0; - if (HAS_PCH_SPLIT(dev)) - crt->adpa_reg = PCH_ADPA; - else if (IS_VALLEYVIEW(dev)) - crt->adpa_reg = VLV_ADPA; - else - crt->adpa_reg = ADPA; + crt->adpa_reg = adpa_reg; crt->base.compute_config = intel_crt_compute_config; - if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev)) { + if (HAS_PCH_SPLIT(dev)) { crt->base.disable = pch_disable_crt; crt->base.post_disable = pch_post_disable_crt; } else { diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index ffe83a6c2..3fdf691d3 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -46,21 +46,10 @@ /*(DEBLOBBED)*/ -/* -* SKL CSR registers for DC5 and DC6 -*/ -#define CSR_PROGRAM(i) (0x80000 + (i) * 4) -#define CSR_SSP_BASE_ADDR_GEN9 0x00002FC0 -#define CSR_HTP_ADDR_SKL 0x00500034 -#define CSR_SSP_BASE 0x8F074 -#define CSR_HTP_SKL 0x8F004 -#define CSR_LAST_WRITE 0x8F034 -#define CSR_LAST_WRITE_VALUE 0xc003b400 -/* MMIO address range for CSR program (0x80000 - 0x82FFF) */ +#define SKL_CSR_VERSION_REQUIRED CSR_VERSION(1, 23) + #define CSR_MAX_FW_SIZE 0x2FFF #define CSR_DEFAULT_FW_OFFSET 0xFFFFFFFF -#define CSR_MMIO_START_RANGE 0x80000 -#define CSR_MMIO_END_RANGE 0x8FFFF struct intel_css_header { /* 0x09 for DMC */ @@ -176,167 +165,148 @@ struct stepping_info { char substepping; }; +/* + * Kabylake derivated from Skylake H0, so SKL H0 + * is the right firmware for KBL A0 (revid 0). + */ +static const struct stepping_info kbl_stepping_info[] = { + {'H', '0'}, {'I', '0'} +}; + static const struct stepping_info skl_stepping_info[] = { - {'A', '0'}, {'B', '0'}, {'C', '0'}, - {'D', '0'}, {'E', '0'}, {'F', '0'}, - {'G', '0'}, {'H', '0'}, {'I', '0'} + {'A', '0'}, {'B', '0'}, {'C', '0'}, + {'D', '0'}, {'E', '0'}, {'F', '0'}, + {'G', '0'}, {'H', '0'}, {'I', '0'} }; -static struct stepping_info bxt_stepping_info[] = { +static const struct stepping_info bxt_stepping_info[] = { {'A', '0'}, {'A', '1'}, {'A', '2'}, {'B', '0'}, {'B', '1'}, {'B', '2'} }; -static char intel_get_stepping(struct drm_device *dev) -{ - if (IS_SKYLAKE(dev) && (dev->pdev->revision < - ARRAY_SIZE(skl_stepping_info))) - return skl_stepping_info[dev->pdev->revision].stepping; - else if (IS_BROXTON(dev) && (dev->pdev->revision < - ARRAY_SIZE(bxt_stepping_info))) - return bxt_stepping_info[dev->pdev->revision].stepping; - else - return -ENODATA; -} - -static char intel_get_substepping(struct drm_device *dev) -{ - if (IS_SKYLAKE(dev) && (dev->pdev->revision < - ARRAY_SIZE(skl_stepping_info))) - return skl_stepping_info[dev->pdev->revision].substepping; - else if (IS_BROXTON(dev) && (dev->pdev->revision < - ARRAY_SIZE(bxt_stepping_info))) - return bxt_stepping_info[dev->pdev->revision].substepping; - else - return -ENODATA; -} - -/** - * intel_csr_load_status_get() - to get firmware loading status. - * @dev_priv: i915 device. - * - * This function helps to get the firmware loading status. - * - * Return: Firmware loading status. - */ -enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv) +static const struct stepping_info *intel_get_stepping_info(struct drm_device *dev) { - enum csr_state state; - - mutex_lock(&dev_priv->csr_lock); - state = dev_priv->csr.state; - mutex_unlock(&dev_priv->csr_lock); + const struct stepping_info *si; + unsigned int size; + + if (IS_KABYLAKE(dev)) { + size = ARRAY_SIZE(kbl_stepping_info); + si = kbl_stepping_info; + } else if (IS_SKYLAKE(dev)) { + size = ARRAY_SIZE(skl_stepping_info); + si = skl_stepping_info; + } else if (IS_BROXTON(dev)) { + size = ARRAY_SIZE(bxt_stepping_info); + si = bxt_stepping_info; + } else { + return NULL; + } - return state; -} + if (INTEL_REVID(dev) < size) + return si + INTEL_REVID(dev); -/** - * intel_csr_load_status_set() - help to set firmware loading status. - * @dev_priv: i915 device. - * @state: enumeration of firmware loading status. - * - * Set the firmware loading status. - */ -void intel_csr_load_status_set(struct drm_i915_private *dev_priv, - enum csr_state state) -{ - mutex_lock(&dev_priv->csr_lock); - dev_priv->csr.state = state; - mutex_unlock(&dev_priv->csr_lock); + return NULL; } /** * intel_csr_load_program() - write the firmware from memory to register. - * @dev: drm device. + * @dev_priv: i915 drm device. * * CSR firmware is read from a .bin file and kept in internal memory one time. * Everytime display comes back from low power state this function is called to * copy the firmware from internal memory to registers. */ -void intel_csr_load_program(struct drm_device *dev) +void intel_csr_load_program(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = dev->dev_private; u32 *payload = dev_priv->csr.dmc_payload; uint32_t i, fw_size; - if (!IS_GEN9(dev)) { + if (!IS_GEN9(dev_priv)) { DRM_ERROR("No CSR support available for this platform\n"); return; } - /* - * FIXME: Firmware gets lost on S3/S4, but not when entering system - * standby or suspend-to-idle (which is just like forced runtime pm). - * Unfortunately the ACPI subsystem doesn't yet give us a way to - * differentiate this, hence figure it out with this hack. - */ - if (I915_READ(CSR_PROGRAM(0))) + if (!dev_priv->csr.dmc_payload) { + DRM_ERROR("Tried to program CSR with empty payload\n"); return; + } - mutex_lock(&dev_priv->csr_lock); fw_size = dev_priv->csr.dmc_fw_size; for (i = 0; i < fw_size; i++) I915_WRITE(CSR_PROGRAM(i), payload[i]); for (i = 0; i < dev_priv->csr.mmio_count; i++) { I915_WRITE(dev_priv->csr.mmioaddr[i], - dev_priv->csr.mmiodata[i]); + dev_priv->csr.mmiodata[i]); } - dev_priv->csr.state = FW_LOADED; - mutex_unlock(&dev_priv->csr_lock); + dev_priv->csr.dc_state = 0; } -static void finish_csr_load(const struct firmware *fw, void *context) +static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, + const struct firmware *fw) { - struct drm_i915_private *dev_priv = context; struct drm_device *dev = dev_priv->dev; struct intel_css_header *css_header; struct intel_package_header *package_header; struct intel_dmc_header *dmc_header; struct intel_csr *csr = &dev_priv->csr; - char stepping = intel_get_stepping(dev); - char substepping = intel_get_substepping(dev); + const struct stepping_info *stepping_info = intel_get_stepping_info(dev); + char stepping, substepping; uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes; uint32_t i; uint32_t *dmc_payload; - bool fw_loaded = false; - if (!fw) { - i915_firmware_load_error_print(csr->fw_path, 0); - goto out; - } + if (!fw) + return NULL; - if ((stepping == -ENODATA) || (substepping == -ENODATA)) { + if (!stepping_info) { DRM_ERROR("Unknown stepping info, firmware loading failed\n"); - goto out; + return NULL; } + stepping = stepping_info->stepping; + substepping = stepping_info->substepping; + /* Extract CSS Header information*/ css_header = (struct intel_css_header *)fw->data; if (sizeof(struct intel_css_header) != - (css_header->header_len * 4)) { + (css_header->header_len * 4)) { DRM_ERROR("Firmware has wrong CSS header length %u bytes\n", - (css_header->header_len * 4)); - goto out; + (css_header->header_len * 4)); + return NULL; + } + + csr->version = css_header->version; + + if (IS_SKYLAKE(dev) && csr->version < SKL_CSR_VERSION_REQUIRED) { + DRM_INFO("Refusing to load old Skylake DMC firmware v%u.%u," + " please upgrade to v%u.%u or later" + " [https://01.org/linuxgraphics/intel-linux-graphics-firmwares].\n", + CSR_VERSION_MAJOR(csr->version), + CSR_VERSION_MINOR(csr->version), + CSR_VERSION_MAJOR(SKL_CSR_VERSION_REQUIRED), + CSR_VERSION_MINOR(SKL_CSR_VERSION_REQUIRED)); + return NULL; } + readcount += sizeof(struct intel_css_header); /* Extract Package Header information*/ package_header = (struct intel_package_header *) - &fw->data[readcount]; + &fw->data[readcount]; if (sizeof(struct intel_package_header) != - (package_header->header_len * 4)) { + (package_header->header_len * 4)) { DRM_ERROR("Firmware has wrong package header length %u bytes\n", - (package_header->header_len * 4)); - goto out; + (package_header->header_len * 4)); + return NULL; } readcount += sizeof(struct intel_package_header); /* Search for dmc_offset to find firware binary. */ for (i = 0; i < package_header->num_entries; i++) { if (package_header->fw_info[i].substepping == '*' && - stepping == package_header->fw_info[i].stepping) { + stepping == package_header->fw_info[i].stepping) { dmc_offset = package_header->fw_info[i].offset; break; } else if (stepping == package_header->fw_info[i].stepping && @@ -344,12 +314,12 @@ static void finish_csr_load(const struct firmware *fw, void *context) dmc_offset = package_header->fw_info[i].offset; break; } else if (package_header->fw_info[i].stepping == '*' && - package_header->fw_info[i].substepping == '*') + package_header->fw_info[i].substepping == '*') dmc_offset = package_header->fw_info[i].offset; } if (dmc_offset == CSR_DEFAULT_FW_OFFSET) { DRM_ERROR("Firmware not supported for %c stepping\n", stepping); - goto out; + return NULL; } readcount += dmc_offset; @@ -357,26 +327,26 @@ static void finish_csr_load(const struct firmware *fw, void *context) dmc_header = (struct intel_dmc_header *)&fw->data[readcount]; if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) { DRM_ERROR("Firmware has wrong dmc header length %u bytes\n", - (dmc_header->header_len)); - goto out; + (dmc_header->header_len)); + return NULL; } readcount += sizeof(struct intel_dmc_header); /* Cache the dmc header info. */ if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) { DRM_ERROR("Firmware has wrong mmio count %u\n", - dmc_header->mmio_count); - goto out; + dmc_header->mmio_count); + return NULL; } csr->mmio_count = dmc_header->mmio_count; for (i = 0; i < dmc_header->mmio_count; i++) { if (dmc_header->mmioaddr[i] < CSR_MMIO_START_RANGE || - dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) { + dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) { DRM_ERROR(" Firmware has wrong mmio address 0x%x\n", - dmc_header->mmioaddr[i]); - goto out; + dmc_header->mmioaddr[i]); + return NULL; } - csr->mmioaddr[i] = dmc_header->mmioaddr[i]; + csr->mmioaddr[i] = _MMIO(dmc_header->mmioaddr[i]); csr->mmiodata[i] = dmc_header->mmiodata[i]; } @@ -384,56 +354,80 @@ static void finish_csr_load(const struct firmware *fw, void *context) nbytes = dmc_header->fw_size * 4; if (nbytes > CSR_MAX_FW_SIZE) { DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes); - goto out; + return NULL; } csr->dmc_fw_size = dmc_header->fw_size; - csr->dmc_payload = kmalloc(nbytes, GFP_KERNEL); - if (!csr->dmc_payload) { + dmc_payload = kmalloc(nbytes, GFP_KERNEL); + if (!dmc_payload) { DRM_ERROR("Memory allocation failed for dmc payload\n"); - goto out; + return NULL; } - dmc_payload = csr->dmc_payload; memcpy(dmc_payload, &fw->data[readcount], nbytes); + return dmc_payload; +} + +static void csr_load_work_fn(struct work_struct *work) +{ + struct drm_i915_private *dev_priv; + struct intel_csr *csr; + const struct firmware *fw; + int ret; + + dev_priv = container_of(work, typeof(*dev_priv), csr.work); + csr = &dev_priv->csr; + + ret = reject_firmware(&fw, dev_priv->csr.fw_path, + &dev_priv->dev->pdev->dev); + if (!fw) + goto out; + + dev_priv->csr.dmc_payload = parse_csr_fw(dev_priv, fw); + if (!dev_priv->csr.dmc_payload) + goto out; + /* load csr program during system boot, as needed for DC states */ - intel_csr_load_program(dev); - fw_loaded = true; + intel_csr_load_program(dev_priv); - DRM_DEBUG_KMS("Finished loading %s\n", dev_priv->csr.fw_path); out: - if (fw_loaded) - intel_runtime_pm_put(dev_priv); - else - intel_csr_load_status_set(dev_priv, FW_FAILED); + if (dev_priv->csr.dmc_payload) { + intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); + + DRM_INFO("Finished loading %s (v%u.%u)\n", + dev_priv->csr.fw_path, + CSR_VERSION_MAJOR(csr->version), + CSR_VERSION_MINOR(csr->version)); + } else { + DRM_ERROR("Failed to load DMC firmware, disabling rpm\n"); + } release_firmware(fw); } /** * intel_csr_ucode_init() - initialize the firmware loading. - * @dev: drm device. + * @dev_priv: i915 drm device. * * This function is called at the time of loading the display driver to read * firmware from a .bin file and copied into a internal memory. */ -void intel_csr_ucode_init(struct drm_device *dev) +void intel_csr_ucode_init(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = dev->dev_private; struct intel_csr *csr = &dev_priv->csr; - int ret; - if (!HAS_CSR(dev)) + INIT_WORK(&dev_priv->csr.work, csr_load_work_fn); + + if (!HAS_CSR(dev_priv)) return; - if (IS_SKYLAKE(dev)) + if (IS_SKYLAKE(dev_priv)) csr->fw_path = I915_CSR_SKL; else if (IS_BROXTON(dev_priv)) csr->fw_path = I915_CSR_BXT; else { DRM_ERROR("Unexpected: no known CSR firmware for platform\n"); - intel_csr_load_status_set(dev_priv, FW_FAILED); return; } @@ -443,43 +437,24 @@ void intel_csr_ucode_init(struct drm_device *dev) * Obtain a runtime pm reference, until CSR is loaded, * to avoid entering runtime-suspend. */ - intel_runtime_pm_get(dev_priv); - - /* CSR supported for platform, load firmware */ - ret = reject_firmware_nowait(THIS_MODULE, true, csr->fw_path, - &dev_priv->dev->pdev->dev, - GFP_KERNEL, dev_priv, - finish_csr_load); - if (ret) { - i915_firmware_load_error_print(csr->fw_path, ret); - intel_csr_load_status_set(dev_priv, FW_FAILED); - } + intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); + + schedule_work(&dev_priv->csr.work); } /** * intel_csr_ucode_fini() - unload the CSR firmware. - * @dev: drm device. + * @dev_priv: i915 drm device. * * Firmmware unloading includes freeing the internal momory and reset the * firmware loading status. */ -void intel_csr_ucode_fini(struct drm_device *dev) +void intel_csr_ucode_fini(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = dev->dev_private; - - if (!HAS_CSR(dev)) + if (!HAS_CSR(dev_priv)) return; - intel_csr_load_status_set(dev_priv, FW_FAILED); - kfree(dev_priv->csr.dmc_payload); -} + flush_work(&dev_priv->csr.work); -void assert_csr_loaded(struct drm_i915_private *dev_priv) -{ - WARN_ONCE(intel_csr_load_status_get(dev_priv) != FW_LOADED, - "CSR is not loaded.\n"); - WARN_ONCE(!I915_READ(CSR_PROGRAM(0)), - "CSR program storage start is NULL\n"); - WARN_ONCE(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n"); - WARN_ONCE(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n"); + kfree(dev_priv->csr.dmc_payload); } diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 7e6158b88..084d55865 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -133,12 +133,12 @@ static const struct ddi_buf_trans skl_ddi_translations_dp[] = { { 0x00002016, 0x000000A0, 0x0 }, { 0x00005012, 0x0000009B, 0x0 }, { 0x00007011, 0x00000088, 0x0 }, - { 0x00009010, 0x000000C7, 0x0 }, + { 0x80009010, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */ { 0x00002016, 0x0000009B, 0x0 }, { 0x00005012, 0x00000088, 0x0 }, - { 0x00007011, 0x000000C7, 0x0 }, + { 0x80007011, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */ { 0x00002016, 0x000000DF, 0x0 }, - { 0x00005012, 0x000000C7, 0x0 }, + { 0x80005012, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */ }; /* Skylake U */ @@ -146,12 +146,12 @@ static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = { { 0x0000201B, 0x000000A2, 0x0 }, { 0x00005012, 0x00000088, 0x0 }, { 0x00007011, 0x00000087, 0x0 }, - { 0x80009010, 0x000000C7, 0x1 }, /* Uses I_boost level 0x1 */ + { 0x80009010, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */ { 0x0000201B, 0x0000009D, 0x0 }, - { 0x00005012, 0x000000C7, 0x0 }, - { 0x00007011, 0x000000C7, 0x0 }, + { 0x80005012, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */ + { 0x80007011, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */ { 0x00002016, 0x00000088, 0x0 }, - { 0x00005012, 0x000000C7, 0x0 }, + { 0x80005012, 0x000000C0, 0x1 }, /* Uses I_boost level 0x1 */ }; /* Skylake Y */ @@ -159,12 +159,12 @@ static const struct ddi_buf_trans skl_y_ddi_translations_dp[] = { { 0x00000018, 0x000000A2, 0x0 }, { 0x00005012, 0x00000088, 0x0 }, { 0x00007011, 0x00000087, 0x0 }, - { 0x80009010, 0x000000C7, 0x3 }, /* Uses I_boost level 0x3 */ + { 0x80009010, 0x000000C0, 0x3 }, /* Uses I_boost level 0x3 */ { 0x00000018, 0x0000009D, 0x0 }, - { 0x00005012, 0x000000C7, 0x0 }, - { 0x00007011, 0x000000C7, 0x0 }, + { 0x80005012, 0x000000C0, 0x3 }, /* Uses I_boost level 0x3 */ + { 0x80007011, 0x000000C0, 0x3 }, /* Uses I_boost level 0x3 */ { 0x00000018, 0x00000088, 0x0 }, - { 0x00005012, 0x000000C7, 0x0 }, + { 0x80005012, 0x000000C0, 0x3 }, /* Uses I_boost level 0x3 */ }; /* @@ -345,7 +345,7 @@ enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) static bool intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port) { - return intel_dig_port->hdmi.hdmi_reg; + return i915_mmio_reg_valid(intel_dig_port->hdmi.hdmi_reg); } static const struct ddi_buf_trans *skl_get_buf_trans_dp(struct drm_device *dev, @@ -353,10 +353,10 @@ static const struct ddi_buf_trans *skl_get_buf_trans_dp(struct drm_device *dev, { const struct ddi_buf_trans *ddi_translations; - if (IS_SKL_ULX(dev)) { + if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) { ddi_translations = skl_y_ddi_translations_dp; *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp); - } else if (IS_SKL_ULT(dev)) { + } else if (IS_SKL_ULT(dev) || IS_KBL_ULT(dev)) { ddi_translations = skl_u_ddi_translations_dp; *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); } else { @@ -373,7 +373,7 @@ static const struct ddi_buf_trans *skl_get_buf_trans_edp(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; const struct ddi_buf_trans *ddi_translations; - if (IS_SKL_ULX(dev)) { + if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) { if (dev_priv->edp_low_vswing) { ddi_translations = skl_y_ddi_translations_edp; *n_entries = ARRAY_SIZE(skl_y_ddi_translations_edp); @@ -381,7 +381,7 @@ static const struct ddi_buf_trans *skl_get_buf_trans_edp(struct drm_device *dev, ddi_translations = skl_y_ddi_translations_dp; *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp); } - } else if (IS_SKL_ULT(dev)) { + } else if (IS_SKL_ULT(dev) || IS_KBL_ULT(dev)) { if (dev_priv->edp_low_vswing) { ddi_translations = skl_u_ddi_translations_edp; *n_entries = ARRAY_SIZE(skl_u_ddi_translations_edp); @@ -408,7 +408,7 @@ skl_get_buf_trans_hdmi(struct drm_device *dev, { const struct ddi_buf_trans *ddi_translations; - if (IS_SKL_ULX(dev)) { + if (IS_SKL_ULX(dev) || IS_KBL_ULX(dev)) { ddi_translations = skl_y_ddi_translations_hdmi; *n_entries = ARRAY_SIZE(skl_y_ddi_translations_hdmi); } else { @@ -448,7 +448,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, bxt_ddi_vswing_sequence(dev, hdmi_level, port, INTEL_OUTPUT_HDMI); return; - } else if (IS_SKYLAKE(dev)) { + } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { ddi_translations_fdi = NULL; ddi_translations_dp = skl_get_buf_trans_dp(dev, &n_dp_entries); @@ -576,7 +576,7 @@ void intel_prepare_ddi(struct drm_device *dev) static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, enum port port) { - uint32_t reg = DDI_BUF_CTL(port); + i915_reg_t reg = DDI_BUF_CTL(port); int i; for (i = 0; i < 16; i++) { @@ -675,15 +675,16 @@ void hsw_fdi_link_train(struct drm_crtc *crtc) temp = I915_READ(DP_TP_STATUS(PORT_E)); if (temp & DP_TP_STATUS_AUTOTRAIN_DONE) { DRM_DEBUG_KMS("FDI link training done on step %d\n", i); + break; + } - /* Enable normal pixel sending for FDI */ - I915_WRITE(DP_TP_CTL(PORT_E), - DP_TP_CTL_FDI_AUTOTRAIN | - DP_TP_CTL_LINK_TRAIN_NORMAL | - DP_TP_CTL_ENHANCED_FRAME_ENABLE | - DP_TP_CTL_ENABLE); - - return; + /* + * Leave things enabled even if we failed to train FDI. + * Results in less fireworks from the state checker. + */ + if (i == ARRAY_SIZE(hsw_ddi_translations_fdi) * 2 - 1) { + DRM_ERROR("FDI link training failed!\n"); + break; } temp = I915_READ(DDI_BUF_CTL(PORT_E)); @@ -712,7 +713,12 @@ void hsw_fdi_link_train(struct drm_crtc *crtc) POSTING_READ(FDI_RX_MISC(PIPE_A)); } - DRM_ERROR("FDI link training failed!\n"); + /* Enable normal pixel sending for FDI */ + I915_WRITE(DP_TP_CTL(PORT_E), + DP_TP_CTL_FDI_AUTOTRAIN | + DP_TP_CTL_LINK_TRAIN_NORMAL | + DP_TP_CTL_ENHANCED_FRAME_ENABLE | + DP_TP_CTL_ENABLE); } void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder) @@ -931,7 +937,8 @@ static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget, /* Otherwise a < c && b >= d, do nothing */ } -static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv, int reg) +static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv, + i915_reg_t reg) { int refclk = LC_FREQ; int n, p, r; @@ -967,7 +974,7 @@ static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv, int reg) static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv, uint32_t dpll) { - uint32_t cfgcr1_reg, cfgcr2_reg; + i915_reg_t cfgcr1_reg, cfgcr2_reg; uint32_t cfgcr1_val, cfgcr2_val; uint32_t p0, p1, p2, dco_freq; @@ -1112,10 +1119,10 @@ static void hsw_ddi_clock_get(struct intel_encoder *encoder, link_clock = 270000; break; case PORT_CLK_SEL_WRPLL1: - link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL1); + link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL(0)); break; case PORT_CLK_SEL_WRPLL2: - link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL2); + link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL(1)); break; case PORT_CLK_SEL_SPLL: pll = I915_READ(SPLL_CTL) & SPLL_PLL_FREQ_MASK; @@ -1184,7 +1191,7 @@ void intel_ddi_clock_get(struct intel_encoder *encoder, if (INTEL_INFO(dev)->gen <= 8) hsw_ddi_clock_get(encoder, pipe_config); - else if (IS_SKYLAKE(dev)) + else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) skl_ddi_clock_get(encoder, pipe_config); else if (IS_BROXTON(dev)) bxt_ddi_clock_get(encoder, pipe_config); @@ -1781,7 +1788,7 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc, struct intel_encoder *intel_encoder = intel_ddi_get_crtc_new_encoder(crtc_state); - if (IS_SKYLAKE(dev)) + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) return skl_ddi_pll_select(intel_crtc, crtc_state, intel_encoder); else if (IS_BROXTON(dev)) @@ -1943,7 +1950,7 @@ 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) { - uint32_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder); + i915_reg_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder); uint32_t val = I915_READ(reg); val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK | TRANS_DDI_DP_VC_PAYLOAD_ALLOC); @@ -1962,13 +1969,16 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector) enum transcoder cpu_transcoder; enum intel_display_power_domain power_domain; uint32_t tmp; + bool ret; power_domain = intel_display_port_power_domain(intel_encoder); - if (!intel_display_power_is_enabled(dev_priv, power_domain)) + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; - if (!intel_encoder->get_hw_state(intel_encoder, &pipe)) - return false; + if (!intel_encoder->get_hw_state(intel_encoder, &pipe)) { + ret = false; + goto out; + } if (port == PORT_A) cpu_transcoder = TRANSCODER_EDP; @@ -1980,23 +1990,33 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector) switch (tmp & TRANS_DDI_MODE_SELECT_MASK) { case TRANS_DDI_MODE_SELECT_HDMI: case TRANS_DDI_MODE_SELECT_DVI: - return (type == DRM_MODE_CONNECTOR_HDMIA); + ret = type == DRM_MODE_CONNECTOR_HDMIA; + break; case TRANS_DDI_MODE_SELECT_DP_SST: - if (type == DRM_MODE_CONNECTOR_eDP) - return true; - return (type == DRM_MODE_CONNECTOR_DisplayPort); + ret = type == DRM_MODE_CONNECTOR_eDP || + type == DRM_MODE_CONNECTOR_DisplayPort; + break; + case TRANS_DDI_MODE_SELECT_DP_MST: /* if the transcoder is in MST state then * connector isn't connected */ - return false; + ret = false; + break; case TRANS_DDI_MODE_SELECT_FDI: - return (type == DRM_MODE_CONNECTOR_VGA); + ret = type == DRM_MODE_CONNECTOR_VGA; + break; default: - return false; + ret = false; + break; } + +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } bool intel_ddi_get_hw_state(struct intel_encoder *encoder, @@ -2008,15 +2028,18 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum intel_display_power_domain power_domain; u32 tmp; int i; + bool ret; power_domain = intel_display_port_power_domain(encoder); - if (!intel_display_power_is_enabled(dev_priv, power_domain)) + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; + ret = false; + tmp = I915_READ(DDI_BUF_CTL(port)); if (!(tmp & DDI_BUF_CTL_ENABLE)) - return false; + goto out; if (port == PORT_A) { tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)); @@ -2034,25 +2057,32 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder, break; } - return true; - } else { - for (i = TRANSCODER_A; i <= TRANSCODER_C; i++) { - tmp = I915_READ(TRANS_DDI_FUNC_CTL(i)); + ret = true; - if ((tmp & TRANS_DDI_PORT_MASK) - == TRANS_DDI_SELECT_PORT(port)) { - if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_DP_MST) - return false; + goto out; + } - *pipe = i; - return true; - } + for (i = TRANSCODER_A; i <= TRANSCODER_C; i++) { + tmp = I915_READ(TRANS_DDI_FUNC_CTL(i)); + + if ((tmp & TRANS_DDI_PORT_MASK) == TRANS_DDI_SELECT_PORT(port)) { + if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == + TRANS_DDI_MODE_SELECT_DP_MST) + goto out; + + *pipe = i; + ret = true; + + goto out; } } DRM_DEBUG_KMS("No pipe for ddi port %c found\n", port_name(port)); - return false; +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc) @@ -2098,21 +2128,21 @@ static void skl_ddi_set_iboost(struct drm_device *dev, u32 level, iboost = dp_iboost; } else { ddi_translations = skl_get_buf_trans_dp(dev, &n_entries); - iboost = ddi_translations[port].i_boost; + iboost = ddi_translations[level].i_boost; } } else if (type == INTEL_OUTPUT_EDP) { if (dp_iboost) { iboost = dp_iboost; } else { ddi_translations = skl_get_buf_trans_edp(dev, &n_entries); - iboost = ddi_translations[port].i_boost; + iboost = ddi_translations[level].i_boost; } } else if (type == INTEL_OUTPUT_HDMI) { if (hdmi_iboost) { iboost = hdmi_iboost; } else { ddi_translations = skl_get_buf_trans_hdmi(dev, &n_entries); - iboost = ddi_translations[port].i_boost; + iboost = ddi_translations[level].i_boost; } } else { return; @@ -2264,7 +2294,7 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp) level = translate_signal_level(signal_levels); - if (IS_SKYLAKE(dev)) + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) skl_ddi_set_iboost(dev, level, port, encoder->type); else if (IS_BROXTON(dev)) bxt_ddi_vswing_sequence(dev, level, port, encoder->type); @@ -2272,30 +2302,21 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp) return DDI_BUF_TRANS_SELECT(level); } -static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) +void intel_ddi_clk_select(struct intel_encoder *encoder, + const struct intel_crtc_state *pipe_config) { - 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 *crtc = to_intel_crtc(encoder->crtc); - enum port port = intel_ddi_get_encoder_port(intel_encoder); - int type = intel_encoder->type; - int hdmi_level; - - if (type == INTEL_OUTPUT_EDP) { - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - intel_edp_panel_on(intel_dp); - } + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum port port = intel_ddi_get_encoder_port(encoder); - if (IS_SKYLAKE(dev)) { - uint32_t dpll = crtc->config->ddi_pll_sel; + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { + uint32_t dpll = pipe_config->ddi_pll_sel; uint32_t val; /* * DPLL0 is used for eDP and is the only "private" DPLL (as * opposed to shared) on SKL */ - if (type == INTEL_OUTPUT_EDP) { + if (encoder->type == INTEL_OUTPUT_EDP) { WARN_ON(dpll != SKL_DPLL0); val = I915_READ(DPLL_CTRL1); @@ -2303,7 +2324,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | DPLL_CTRL1_SSC(dpll) | DPLL_CTRL1_LINK_RATE_MASK(dpll)); - val |= crtc->config->dpll_hw_state.ctrl1 << (dpll * 6); + val |= pipe_config->dpll_hw_state.ctrl1 << (dpll * 6); I915_WRITE(DPLL_CTRL1, val); POSTING_READ(DPLL_CTRL1); @@ -2319,10 +2340,28 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) I915_WRITE(DPLL_CTRL2, val); - } else if (INTEL_INFO(dev)->gen < 9) { - WARN_ON(crtc->config->ddi_pll_sel == PORT_CLK_SEL_NONE); - I915_WRITE(PORT_CLK_SEL(port), crtc->config->ddi_pll_sel); + } else if (INTEL_INFO(dev_priv)->gen < 9) { + WARN_ON(pipe_config->ddi_pll_sel == PORT_CLK_SEL_NONE); + I915_WRITE(PORT_CLK_SEL(port), pipe_config->ddi_pll_sel); } +} + +static void intel_ddi_pre_enable(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 *crtc = to_intel_crtc(encoder->crtc); + enum port port = intel_ddi_get_encoder_port(intel_encoder); + int type = intel_encoder->type; + int hdmi_level; + + if (type == INTEL_OUTPUT_EDP) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + intel_edp_panel_on(intel_dp); + } + + intel_ddi_clk_select(intel_encoder, crtc->config); if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); @@ -2382,7 +2421,7 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder) intel_edp_panel_off(intel_dp); } - if (IS_SKYLAKE(dev)) + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) I915_WRITE(DPLL_CTRL2, (I915_READ(DPLL_CTRL2) | DPLL_CTRL2_DDI_CLK_OFF(port))); else if (INTEL_INFO(dev)->gen < 9) @@ -2492,12 +2531,14 @@ static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv, { uint32_t val; - if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS)) + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) return false; val = I915_READ(WRPLL_CTL(pll->id)); hw_state->wrpll = val; + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + return val & WRPLL_PLL_ENABLE; } @@ -2507,12 +2548,14 @@ static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv, { uint32_t val; - if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS)) + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) return false; val = I915_READ(SPLL_CTL); hw_state->spll = val; + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + return val & SPLL_PLL_ENABLE; } @@ -2554,7 +2597,7 @@ static const char * const skl_ddi_pll_names[] = { }; struct skl_dpll_regs { - u32 ctl, cfgcr1, cfgcr2; + i915_reg_t ctl, cfgcr1, cfgcr2; }; /* this array is indexed by the *shared* pll id */ @@ -2567,13 +2610,13 @@ static const struct skl_dpll_regs skl_dpll_regs[3] = { }, { /* DPLL 2 */ - .ctl = WRPLL_CTL1, + .ctl = WRPLL_CTL(0), .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2), .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2), }, { /* DPLL 3 */ - .ctl = WRPLL_CTL2, + .ctl = WRPLL_CTL(1), .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3), .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3), }, @@ -2629,16 +2672,19 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, uint32_t val; unsigned int dpll; const struct skl_dpll_regs *regs = skl_dpll_regs; + bool ret; - if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS)) + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) return false; + ret = false; + /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */ dpll = pll->id + 1; val = I915_READ(regs[pll->id].ctl); if (!(val & LCPLL_PLL_ENABLE)) - return false; + goto out; val = I915_READ(DPLL_CTRL1); hw_state->ctrl1 = (val >> (dpll * 6)) & 0x3f; @@ -2648,8 +2694,12 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1); hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2); } + ret = true; - return true; +out: + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + + return ret; } static void skl_shared_dplls_init(struct drm_i915_private *dev_priv) @@ -2916,13 +2966,16 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, { enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ uint32_t val; + bool ret; - if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS)) + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) return false; + ret = false; + val = I915_READ(BXT_PORT_PLL_ENABLE(port)); if (!(val & PORT_PLL_ENABLE)) - return false; + goto out; hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port)); hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK; @@ -2969,7 +3022,12 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, I915_READ(BXT_PORT_PCS_DW12_LN23(port))); hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD; - return true; + ret = true; + +out: + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + + return ret; } static void bxt_shared_dplls_init(struct drm_i915_private *dev_priv) @@ -2993,22 +3051,22 @@ void intel_ddi_pll_init(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; uint32_t val = I915_READ(LCPLL_CTL); - if (IS_SKYLAKE(dev)) + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) skl_shared_dplls_init(dev_priv); else if (IS_BROXTON(dev)) bxt_shared_dplls_init(dev_priv); else hsw_shared_dplls_init(dev_priv); - if (IS_SKYLAKE(dev)) { + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { int cdclk_freq; cdclk_freq = dev_priv->display.get_display_clock_speed(dev); dev_priv->skl_boot_cdclk = cdclk_freq; + if (skl_sanitize_cdclk(dev_priv)) + DRM_DEBUG_KMS("Sanitized cdclk programmed by pre-os\n"); if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) DRM_ERROR("LCPLL1 is disabled\n"); - else - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); } else if (IS_BROXTON(dev)) { broxton_init_cdclk(dev); broxton_ddi_phy_init(dev); @@ -3027,11 +3085,11 @@ void intel_ddi_pll_init(struct drm_device *dev) } } -void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder) +void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) { - struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); - struct intel_dp *intel_dp = &intel_dig_port->dp; - struct drm_i915_private *dev_priv = encoder->dev->dev_private; + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct drm_i915_private *dev_priv = + to_i915(intel_dig_port->base.base.dev); enum port port = intel_dig_port->port; uint32_t val; bool wait = false; @@ -3099,6 +3157,23 @@ void intel_ddi_fdi_disable(struct drm_crtc *crtc) I915_WRITE(FDI_RX_CTL(PIPE_A), val); } +bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv, + struct intel_crtc *intel_crtc) +{ + u32 temp; + + if (intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_AUDIO)) { + temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); + + intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO); + + if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe)) + return true; + } + + return false; +} + void intel_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { @@ -3142,7 +3217,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder, pipe_config->has_hdmi_sink = true; intel_hdmi = enc_to_intel_hdmi(&encoder->base); - if (intel_hdmi->infoframe_enabled(&encoder->base)) + if (intel_hdmi->infoframe_enabled(&encoder->base, pipe_config)) pipe_config->has_infoframe = true; break; case TRANS_DDI_MODE_SELECT_DVI: @@ -3159,11 +3234,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder, break; } - if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) { - temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); - if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe)) - pipe_config->has_audio = true; - } + pipe_config->has_audio = + intel_ddi_is_audio_enabled(dev_priv, intel_crtc); if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp_bpp && pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) { @@ -3275,7 +3347,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) encoder = &intel_encoder->base; drm_encoder_init(dev, encoder, &intel_ddi_funcs, - DRM_MODE_ENCODER_TMDS); + DRM_MODE_ENCODER_TMDS, NULL); intel_encoder->compute_config = intel_ddi_compute_config; intel_encoder->enable = intel_enable_ddi; @@ -3290,6 +3362,20 @@ void intel_ddi_init(struct drm_device *dev, enum port port) (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES); + /* + * Bspec says that DDI_A_4_LANES is the only supported configuration + * for Broxton. Yet some BIOS fail to set this bit on port A if eDP + * wasn't lit up at boot. Force this bit on in our internal + * configuration so that we use the proper lane count for our + * calculations. + */ + if (IS_BROXTON(dev) && port == PORT_A) { + if (!(intel_dig_port->saved_port_bits & DDI_A_4_LANES)) { + DRM_DEBUG_KMS("BXT BIOS forgot to set DDI_A_4_LANES for port A; fixing\n"); + intel_dig_port->saved_port_bits |= DDI_A_4_LANES; + } + } + intel_encoder->type = INTEL_OUTPUT_UNKNOWN; intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->cloneable = 0; @@ -3303,8 +3389,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) * On BXT A0/A1, sw needs to activate DDIA HPD logic and * interrupts to check the external panel connection. */ - if (IS_BROXTON(dev_priv) && (INTEL_REVID(dev) < BXT_REVID_B0) - && port == PORT_B) + if (IS_BXT_REVID(dev, 0, BXT_REVID_A1) && port == PORT_B) dev_priv->hotplug.irq_port[PORT_A] = intel_dig_port; else dev_priv->hotplug.irq_port[port] = intel_dig_port; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f859a5b87..46947fffd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -44,6 +44,8 @@ #include <drm/drm_plane_helper.h> #include <drm/drm_rect.h> #include <linux/dma_remapping.h> +#include <linux/reservation.h> +#include <linux/dma-buf.h> /* Primary plane formats for gen <= 3 */ static const uint32_t i8xx_primary_formats[] = { @@ -186,7 +188,7 @@ int intel_hrawclk(struct drm_device *dev) uint32_t clkcfg; /* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */ - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) return 200; clkcfg = I915_READ(CLKCFG); @@ -214,7 +216,7 @@ int intel_hrawclk(struct drm_device *dev) static void intel_update_czclk(struct drm_i915_private *dev_priv) { - if (!IS_VALLEYVIEW(dev_priv)) + if (!(IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))) return; dev_priv->czclk_freq = vlv_get_cck_clock_hpll(dev_priv, "czclk", @@ -715,11 +717,12 @@ static bool intel_PLL_is_valid(struct drm_device *dev, if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) INTELPllInvalid("m1 out of range\n"); - if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev) && !IS_BROXTON(dev)) + if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev) && + !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev)) if (clock->m1 <= clock->m2) INTELPllInvalid("m1 <= m2\n"); - if (!IS_VALLEYVIEW(dev) && !IS_BROXTON(dev)) { + if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && !IS_BROXTON(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) @@ -1096,7 +1099,7 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, 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); + i915_reg_t reg = PIPEDSL(pipe); u32 line1, line2; u32 line_mask; @@ -1136,7 +1139,7 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc) enum pipe pipe = crtc->pipe; if (INTEL_INFO(dev)->gen >= 4) { - int reg = PIPECONF(cpu_transcoder); + i915_reg_t reg = PIPECONF(cpu_transcoder); /* Wait for the Pipe State to go off */ if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0, @@ -1286,7 +1289,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe) { struct drm_device *dev = dev_priv->dev; - int pp_reg; + i915_reg_t pp_reg; u32 val; enum pipe panel_pipe = PIPE_A; bool locked = true; @@ -1304,7 +1307,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT) panel_pipe = PIPE_B; /* XXX: else fix for eDP */ - } else if (IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { /* presumably write lock depends on pipe, not port select */ pp_reg = VLV_PIPE_PP_CONTROL(pipe); panel_pipe = pipe; @@ -1348,18 +1351,21 @@ void assert_pipe(struct drm_i915_private *dev_priv, bool cur_state; enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, pipe); + enum intel_display_power_domain power_domain; /* if we need the pipe quirk it must be always on */ if ((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) || (pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE)) state = true; - if (!intel_display_power_is_enabled(dev_priv, - POWER_DOMAIN_TRANSCODER(cpu_transcoder))) { - cur_state = false; - } else { + power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder); + if (intel_display_power_get_if_enabled(dev_priv, power_domain)) { u32 val = I915_READ(PIPECONF(cpu_transcoder)); cur_state = !!(val & PIPECONF_ENABLE); + + intel_display_power_put(dev_priv, power_domain); + } else { + cur_state = false; } I915_STATE_WARN(cur_state != state, @@ -1422,7 +1428,7 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv, "plane %d assertion failure, should be off on pipe %c but is still active\n", sprite, pipe_name(pipe)); } - } else if (IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { for_each_sprite(dev_priv, pipe, sprite) { u32 val = I915_READ(SPCNTR(pipe, sprite)); I915_STATE_WARN(val & SP_ENABLE, @@ -1481,8 +1487,7 @@ static bool dp_pipe_enabled(struct drm_i915_private *dev_priv, return false; if (HAS_PCH_CPT(dev_priv->dev)) { - u32 trans_dp_ctl_reg = TRANS_DP_CTL(pipe); - u32 trans_dp_ctl = I915_READ(trans_dp_ctl_reg); + u32 trans_dp_ctl = I915_READ(TRANS_DP_CTL(pipe)); if ((trans_dp_ctl & TRANS_DP_PORT_SEL_MASK) != port_sel) return false; } else if (IS_CHERRYVIEW(dev_priv->dev)) { @@ -1546,12 +1551,13 @@ static bool adpa_pipe_enabled(struct drm_i915_private *dev_priv, } static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, - enum pipe pipe, int reg, u32 port_sel) + enum pipe pipe, i915_reg_t reg, + u32 port_sel) { u32 val = I915_READ(reg); I915_STATE_WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val), "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", - reg, pipe_name(pipe)); + i915_mmio_reg_offset(reg), pipe_name(pipe)); I915_STATE_WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0 && (val & DP_PIPEB_SELECT), @@ -1559,12 +1565,12 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, } static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, - enum pipe pipe, int reg) + enum pipe pipe, i915_reg_t reg) { u32 val = I915_READ(reg); I915_STATE_WARN(hdmi_pipe_enabled(dev_priv, pipe, val), "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", - reg, pipe_name(pipe)); + i915_mmio_reg_offset(reg), pipe_name(pipe)); I915_STATE_WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_ENABLE) == 0 && (val & SDVO_PIPE_B_SELECT), @@ -1600,14 +1606,11 @@ static void vlv_enable_pll(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - int reg = DPLL(crtc->pipe); + i915_reg_t reg = DPLL(crtc->pipe); u32 dpll = pipe_config->dpll_hw_state.dpll; assert_pipe_disabled(dev_priv, crtc->pipe); - /* No really, not for ILK+ */ - BUG_ON(!IS_VALLEYVIEW(dev_priv->dev)); - /* PLL is protected by panel, make sure we can write it */ if (IS_MOBILE(dev_priv->dev)) assert_panel_unlocked(dev_priv, crtc->pipe); @@ -1645,8 +1648,6 @@ static void chv_enable_pll(struct intel_crtc *crtc, assert_pipe_disabled(dev_priv, crtc->pipe); - BUG_ON(!IS_CHERRYVIEW(dev_priv->dev)); - mutex_lock(&dev_priv->sb_lock); /* Enable back the 10bit clock to display controller */ @@ -1689,7 +1690,7 @@ static void i9xx_enable_pll(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - int reg = DPLL(crtc->pipe); + i915_reg_t reg = DPLL(crtc->pipe); u32 dpll = crtc->config->dpll_hw_state.dpll; assert_pipe_disabled(dev_priv, crtc->pipe); @@ -1838,7 +1839,7 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, unsigned int expected_mask) { u32 port_mask; - int dpll_reg; + i915_reg_t dpll_reg; switch (dport->port) { case PORT_B: @@ -1963,7 +1964,8 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, struct drm_device *dev = dev_priv->dev; struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - uint32_t reg, val, pipeconf_val; + i915_reg_t reg; + uint32_t val, pipeconf_val; /* PCH only available on ILK+ */ BUG_ON(!HAS_PCH_SPLIT(dev)); @@ -2052,7 +2054,8 @@ static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv, enum pipe pipe) { struct drm_device *dev = dev_priv->dev; - uint32_t reg, val; + i915_reg_t reg; + uint32_t val; /* FDI relies on the transcoder */ assert_fdi_tx_disabled(dev_priv, pipe); @@ -2069,7 +2072,7 @@ static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv, if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50)) DRM_ERROR("failed to disable transcoder %c\n", pipe_name(pipe)); - if (!HAS_PCH_IBX(dev)) { + if (HAS_PCH_CPT(dev)) { /* Workaround: Clear the timing override chicken bit again. */ reg = TRANS_CHICKEN2(pipe); val = I915_READ(reg); @@ -2107,10 +2110,9 @@ static void intel_enable_pipe(struct intel_crtc *crtc) struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; enum pipe pipe = crtc->pipe; - enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, - pipe); + enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; enum pipe pch_transcoder; - int reg; + i915_reg_t reg; u32 val; DRM_DEBUG_KMS("enabling pipe %c\n", pipe_name(pipe)); @@ -2130,7 +2132,7 @@ static void intel_enable_pipe(struct intel_crtc *crtc) * need the check. */ if (HAS_GMCH_DISPLAY(dev_priv->dev)) - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI)) + if (crtc->config->has_dsi_encoder) assert_dsi_pll_enabled(dev_priv); else assert_pll_enabled(dev_priv, pipe); @@ -2171,7 +2173,7 @@ static void intel_disable_pipe(struct intel_crtc *crtc) struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; enum pipe pipe = crtc->pipe; - int reg; + i915_reg_t reg; u32 val; DRM_DEBUG_KMS("disabling pipe %c\n", pipe_name(pipe)); @@ -2270,20 +2272,20 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height, fb_format_modifier, 0)); } -static int +static void intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, const struct drm_plane_state *plane_state) { - struct intel_rotation_info *info = &view->rotation_info; + struct intel_rotation_info *info = &view->params.rotation_info; unsigned int tile_height, tile_pitch; *view = i915_ggtt_view_normal; if (!plane_state) - return 0; + return; if (!intel_rotation_90_or_270(plane_state->rotation)) - return 0; + return; *view = i915_ggtt_view_rotated; @@ -2310,8 +2312,6 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, info->size_uv = info->width_pages_uv * info->height_pages_uv * PAGE_SIZE; } - - return 0; } static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv) @@ -2319,7 +2319,7 @@ static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv) if (INTEL_INFO(dev_priv)->gen >= 9) return 256 * 1024; else if (IS_BROADWATER(dev_priv) || IS_CRESTLINE(dev_priv) || - IS_VALLEYVIEW(dev_priv)) + IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) return 128 * 1024; else if (INTEL_INFO(dev_priv)->gen >= 4) return 4 * 1024; @@ -2330,9 +2330,7 @@ static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv) int intel_pin_and_fence_fb_obj(struct drm_plane *plane, struct drm_framebuffer *fb, - const struct drm_plane_state *plane_state, - struct intel_engine_cs *pipelined, - struct drm_i915_gem_request **pipelined_request) + const struct drm_plane_state *plane_state) { struct drm_device *dev = fb->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -2367,9 +2365,7 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane, return -EINVAL; } - ret = intel_fill_fb_ggtt_view(&view, fb, plane_state); - if (ret) - return ret; + intel_fill_fb_ggtt_view(&view, fb, plane_state); /* Note that the w/a also requires 64 PTE of padding following the * bo. We currently fill all unused PTE with the shadow page and so @@ -2388,11 +2384,10 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane, */ intel_runtime_pm_get(dev_priv); - dev_priv->mm.interruptible = false; - ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined, - pipelined_request, &view); + ret = i915_gem_object_pin_to_display_plane(obj, alignment, + &view); if (ret) - goto err_interruptible; + goto err_pm; /* Install a fence for tiled scan-out. Pre-i965 always needs a * fence, whereas 965+ only requires a fence if using @@ -2418,14 +2413,12 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane, i915_gem_object_pin_fence(obj); } - dev_priv->mm.interruptible = true; intel_runtime_pm_put(dev_priv); return 0; err_unpin: i915_gem_object_unpin_from_display_plane(obj, &view); -err_interruptible: - dev_priv->mm.interruptible = true; +err_pm: intel_runtime_pm_put(dev_priv); return ret; } @@ -2435,12 +2428,10 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb, { struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct i915_ggtt_view view; - int ret; WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex)); - ret = intel_fill_fb_ggtt_view(&view, fb, plane_state); - WARN_ONCE(ret, "Couldn't get view from plane state!"); + intel_fill_fb_ggtt_view(&view, fb, plane_state); if (view.type == I915_GGTT_VIEW_NORMAL) i915_gem_object_unpin_fence(obj); @@ -2695,7 +2686,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc, int plane = intel_crtc->plane; unsigned long linear_offset; u32 dspcntr; - u32 reg = DSPCNTR(plane); + i915_reg_t reg = DSPCNTR(plane); int pixel_size; if (!visible || !fb) { @@ -2825,7 +2816,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc, int plane = intel_crtc->plane; unsigned long linear_offset; u32 dspcntr; - u32 reg = DSPCNTR(plane); + i915_reg_t reg = DSPCNTR(plane); int pixel_size; if (!visible || !fb) { @@ -2950,30 +2941,32 @@ u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier, } } -unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane, - struct drm_i915_gem_object *obj, - unsigned int plane) +u32 intel_plane_obj_offset(struct intel_plane *intel_plane, + struct drm_i915_gem_object *obj, + unsigned int plane) { - const struct i915_ggtt_view *view = &i915_ggtt_view_normal; + struct i915_ggtt_view view; struct i915_vma *vma; - unsigned char *offset; + u64 offset; - if (intel_rotation_90_or_270(intel_plane->base.state->rotation)) - view = &i915_ggtt_view_rotated; + intel_fill_fb_ggtt_view(&view, intel_plane->base.state->fb, + intel_plane->base.state); - vma = i915_gem_obj_to_ggtt_view(obj, view); + vma = i915_gem_obj_to_ggtt_view(obj, &view); if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n", - view->type)) + view.type)) return -1; - offset = (unsigned char *)vma->node.start; + offset = vma->node.start; if (plane == 1) { - offset += vma->ggtt_view.rotation_info.uv_start_page * + offset += vma->ggtt_view.params.rotation_info.uv_start_page * PAGE_SIZE; } - return (unsigned long)offset; + WARN_ON(upper_32_bits(offset)); + + return lower_32_bits(offset); } static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id) @@ -3099,7 +3092,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc, u32 tile_height, plane_offset, plane_size; unsigned int rotation; int x_offset, y_offset; - unsigned long surf_addr; + u32 surf_addr; struct intel_crtc_state *crtc_state = intel_crtc->config; struct intel_plane_state *plane_state; int src_x = 0, src_y = 0, src_w = 0, src_h = 0; @@ -3197,8 +3190,8 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - if (dev_priv->fbc.disable_fbc) - dev_priv->fbc.disable_fbc(dev_priv); + if (dev_priv->fbc.deactivate) + dev_priv->fbc.deactivate(dev_priv); dev_priv->display.update_primary_plane(crtc, fb, x, y); @@ -3227,10 +3220,9 @@ static void intel_update_primary_planes(struct drm_device *dev) struct intel_plane_state *plane_state; drm_modeset_lock_crtc(crtc, &plane->base); - plane_state = to_intel_plane_state(plane->base.state); - if (plane_state->base.fb) + if (crtc->state->active && plane_state->base.fb) plane->commit_plane(&plane->base, plane_state); drm_modeset_unlock_crtc(crtc); @@ -3306,32 +3298,6 @@ void intel_finish_reset(struct drm_device *dev) drm_modeset_unlock_all(dev); } -static void -intel_finish_fb(struct drm_framebuffer *old_fb) -{ - struct drm_i915_gem_object *obj = intel_fb_obj(old_fb); - struct drm_i915_private *dev_priv = to_i915(obj->base.dev); - bool was_interruptible = dev_priv->mm.interruptible; - int ret; - - /* Big Hammer, we also need to ensure that any pending - * MI_WAIT_FOR_EVENT inside a user batch buffer on the - * current scanout is retired before unpinning the old - * framebuffer. Note that we rely on userspace rendering - * into the buffer attached to the pipe they are waiting - * on. If not, userspace generates a GPU hang with IPEHR - * point to the MI_WAIT_FOR_EVENT. - * - * This should only fail upon a hung GPU, in which case we - * can safely continue. - */ - dev_priv->mm.interruptible = false; - ret = i915_gem_object_wait_rendering(obj, true); - dev_priv->mm.interruptible = was_interruptible; - - WARN_ON(ret); -} - static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -3401,7 +3367,8 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; - u32 reg, temp; + i915_reg_t reg; + u32 temp; /* enable normal train */ reg = FDI_TX_CTL(pipe); @@ -3443,7 +3410,8 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; - u32 reg, temp, tries; + i915_reg_t reg; + u32 temp, tries; /* FDI needs bits from pipe first */ assert_pipe_enabled(dev_priv, pipe); @@ -3543,7 +3511,8 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; - u32 reg, temp, i, retry; + i915_reg_t reg; + u32 temp, i, retry; /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit for train result */ @@ -3675,7 +3644,8 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; - u32 reg, temp, i, j; + i915_reg_t reg; + u32 temp, i, j; /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit for train result */ @@ -3792,8 +3762,8 @@ static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc) struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = intel_crtc->pipe; - u32 reg, temp; - + i915_reg_t reg; + u32 temp; /* enable PCH FDI RX PLL, wait warmup plus DMI latency */ reg = FDI_RX_CTL(pipe); @@ -3829,7 +3799,8 @@ static void ironlake_fdi_pll_disable(struct intel_crtc *intel_crtc) struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = intel_crtc->pipe; - u32 reg, temp; + i915_reg_t reg; + u32 temp; /* Switch from PCDclk to Rawclk */ reg = FDI_RX_CTL(pipe); @@ -3859,7 +3830,8 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; - u32 reg, temp; + i915_reg_t reg; + u32 temp; /* disable CPU FDI tx and PCH FDI rx */ reg = FDI_TX_CTL(pipe); @@ -3952,15 +3924,23 @@ static void page_flip_completed(struct intel_crtc *intel_crtc) work->pending_flip_obj); } -void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) +static int intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; + long ret; WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue)); - if (WARN_ON(wait_event_timeout(dev_priv->pending_flip_queue, - !intel_crtc_has_pending_flip(crtc), - 60*HZ) == 0)) { + + ret = wait_event_interruptible_timeout( + dev_priv->pending_flip_queue, + !intel_crtc_has_pending_flip(crtc), + 60*HZ); + + if (ret < 0) + return ret; + + if (ret == 0) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); spin_lock_irq(&dev->event_lock); @@ -3971,11 +3951,22 @@ void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) spin_unlock_irq(&dev->event_lock); } - if (crtc->primary->fb) { - mutex_lock(&dev->struct_mutex); - intel_finish_fb(crtc->primary->fb); - mutex_unlock(&dev->struct_mutex); - } + return 0; +} + +static void lpt_disable_iclkip(struct drm_i915_private *dev_priv) +{ + u32 temp; + + I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_GATE); + + mutex_lock(&dev_priv->sb_lock); + + temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK); + temp |= SBI_SSCCTL_DISABLE; + intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK); + + mutex_unlock(&dev_priv->sb_lock); } /* Program iCLKIP clock to the desired frequency */ @@ -3987,18 +3978,7 @@ static void lpt_program_iclkip(struct drm_crtc *crtc) u32 divsel, phaseinc, auxdiv, phasedir = 0; u32 temp; - mutex_lock(&dev_priv->sb_lock); - - /* It is necessary to ungate the pixclk gate prior to programming - * the divisors, and gate it back when it is done. - */ - I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_GATE); - - /* Disable SSCCTL */ - intel_sbi_write(dev_priv, SBI_SSCCTL6, - intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK) | - SBI_SSCCTL_DISABLE, - SBI_ICLK); + lpt_disable_iclkip(dev_priv); /* 20MHz is a corner case which is out of range for the 7-bit divisor */ if (clock == 20000) { @@ -4016,7 +3996,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 = DIV_ROUND_CLOSEST(iclk_virtual_root_freq, clock); msb_divisor_value = desired_divisor / iclk_pi_range; pi_value = desired_divisor % iclk_pi_range; @@ -4038,6 +4018,8 @@ static void lpt_program_iclkip(struct drm_crtc *crtc) phasedir, phaseinc); + mutex_lock(&dev_priv->sb_lock); + /* Program SSCDIVINTPHASE6 */ temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK); temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK; @@ -4059,12 +4041,12 @@ static void lpt_program_iclkip(struct drm_crtc *crtc) temp &= ~SBI_SSCCTL_DISABLE; intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK); + mutex_unlock(&dev_priv->sb_lock); + /* Wait for initialization time */ udelay(24); I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE); - - mutex_unlock(&dev_priv->sb_lock); } static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc, @@ -4135,6 +4117,22 @@ static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc) } } +/* Return which DP Port should be selected for Transcoder DP control */ +static enum port +intel_trans_dp_port_sel(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct intel_encoder *encoder; + + for_each_encoder_on_crtc(dev, crtc, encoder) { + if (encoder->type == INTEL_OUTPUT_DISPLAYPORT || + encoder->type == INTEL_OUTPUT_EDP) + return enc_to_dig_port(&encoder->base)->port; + } + + return -1; +} + /* * Enable PCH resources required for PCH ports: * - PCH PLLs @@ -4149,7 +4147,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; - u32 reg, temp; + u32 temp; assert_pch_transcoder_disabled(dev_priv, pipe); @@ -4161,6 +4159,12 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) I915_WRITE(FDI_RX_TUSIZE1(pipe), I915_READ(PIPE_DATA_M1(pipe)) & TU_SIZE_MASK); + /* + * Sometimes spurious CPU pipe underruns happen during FDI + * training, at least with VGA+HDMI cloning. Suppress them. + */ + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); + /* For PCH output, training FDI link */ dev_priv->display.fdi_link_train(crtc); @@ -4194,10 +4198,14 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) intel_fdi_normal_train(crtc); + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); + /* For PCH DP, enable TRANS_DP_CTL */ if (HAS_PCH_CPT(dev) && intel_crtc->config->has_dp_encoder) { + const struct drm_display_mode *adjusted_mode = + &intel_crtc->config->base.adjusted_mode; u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5; - reg = TRANS_DP_CTL(pipe); + i915_reg_t reg = TRANS_DP_CTL(pipe); temp = I915_READ(reg); temp &= ~(TRANS_DP_PORT_SEL_MASK | TRANS_DP_SYNC_MASK | @@ -4205,19 +4213,19 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) temp |= TRANS_DP_OUTPUT_ENABLE; temp |= bpc << 9; /* same format but at 11:9 */ - if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC) + if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) temp |= TRANS_DP_HSYNC_ACTIVE_HIGH; - if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC) + if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) temp |= TRANS_DP_VSYNC_ACTIVE_HIGH; switch (intel_trans_dp_port_sel(crtc)) { - case PCH_DP_B: + case PORT_B: temp |= TRANS_DP_PORT_SEL_B; break; - case PCH_DP_C: + case PORT_C: temp |= TRANS_DP_PORT_SEL_C; break; - case PCH_DP_D: + case PORT_D: temp |= TRANS_DP_PORT_SEL_D; break; default: @@ -4357,7 +4365,7 @@ static void intel_shared_dpll_commit(struct drm_atomic_state *state) static void cpt_verify_modeset(struct drm_device *dev, int pipe) { struct drm_i915_private *dev_priv = dev->dev_private; - int dslreg = PIPEDSL(pipe); + i915_reg_t dslreg = PIPEDSL(pipe); u32 temp; temp = I915_READ(dslreg); @@ -4650,7 +4658,7 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc) return; if (HAS_GMCH_DISPLAY(dev_priv->dev)) { - if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI)) + if (intel_crtc->config->has_dsi_encoder) assert_dsi_pll_enabled(dev_priv); else assert_pll_enabled(dev_priv, pipe); @@ -4667,7 +4675,7 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc) } for (i = 0; i < 256; i++) { - u32 palreg; + i915_reg_t palreg; if (HAS_GMCH_DISPLAY(dev)) palreg = PALETTE(pipe, i); @@ -4721,14 +4729,6 @@ intel_post_enable_primary(struct drm_crtc *crtc) int pipe = intel_crtc->pipe; /* - * BDW signals flip done immediately if the plane - * is disabled, even if the plane enable is already - * armed to occur at the next vblank :( - */ - if (IS_BROADWELL(dev)) - intel_wait_for_vblank(dev, pipe); - - /* * 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 @@ -4746,9 +4746,9 @@ intel_post_enable_primary(struct drm_crtc *crtc) if (IS_GEN2(dev)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - /* Underruns don't raise interrupts, so check manually. */ - if (HAS_GMCH_DISPLAY(dev)) - i9xx_check_fifo_underruns(dev_priv); + /* Underruns don't always raise interrupts, so check manually. */ + intel_check_cpu_fifo_underruns(dev_priv); + intel_check_pch_fifo_underruns(dev_priv); } /** @@ -4805,31 +4805,26 @@ intel_pre_disable_primary(struct drm_crtc *crtc) static void intel_post_plane_update(struct intel_crtc *crtc) { struct intel_crtc_atomic_commit *atomic = &crtc->atomic; + struct intel_crtc_state *pipe_config = + to_intel_crtc_state(crtc->base.state); struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_plane *plane; if (atomic->wait_vblank) intel_wait_for_vblank(dev, crtc->pipe); intel_frontbuffer_flip(dev, atomic->fb_bits); - if (atomic->disable_cxsr) - crtc->wm.cxsr_allowed = true; + crtc->wm.cxsr_allowed = true; - if (crtc->atomic.update_wm_post) + if (pipe_config->wm_changed && pipe_config->base.active) intel_update_watermarks(&crtc->base); if (atomic->update_fbc) - intel_fbc_update(dev_priv); + intel_fbc_update(crtc); if (atomic->post_enable_primary) intel_post_enable_primary(&crtc->base); - drm_for_each_plane_mask(plane, dev, atomic->update_sprite_watermarks) - intel_update_sprite_watermarks(plane, &crtc->base, - 0, 0, 0, false, false); - memset(atomic, 0, sizeof(*atomic)); } @@ -4838,23 +4833,11 @@ static void intel_pre_plane_update(struct intel_crtc *crtc) struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc_atomic_commit *atomic = &crtc->atomic; - struct drm_plane *p; - - /* Track fb's for any planes being disabled */ - drm_for_each_plane_mask(p, dev, atomic->disabled_planes) { - struct intel_plane *plane = to_intel_plane(p); - - mutex_lock(&dev->struct_mutex); - i915_gem_track_fb(intel_fb_obj(plane->base.fb), NULL, - plane->frontbuffer_bit); - mutex_unlock(&dev->struct_mutex); - } - - if (atomic->wait_for_flips) - intel_crtc_wait_for_pending_flips(&crtc->base); + struct intel_crtc_state *pipe_config = + to_intel_crtc_state(crtc->base.state); if (atomic->disable_fbc) - intel_fbc_disable_crtc(crtc); + intel_fbc_deactivate(crtc); if (crtc->atomic.disable_ips) hsw_disable_ips(crtc); @@ -4862,10 +4845,13 @@ static void intel_pre_plane_update(struct intel_crtc *crtc) if (atomic->pre_disable_primary) intel_pre_disable_primary(&crtc->base); - if (atomic->disable_cxsr) { + if (pipe_config->disable_cxsr) { crtc->wm.cxsr_allowed = false; intel_set_memory_cxsr(dev_priv, false); } + + if (!needs_modeset(&pipe_config->base) && pipe_config->wm_changed) + intel_update_watermarks(&crtc->base); } static void intel_crtc_disable_planes(struct drm_crtc *crtc, unsigned plane_mask) @@ -4900,6 +4886,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) return; if (intel_crtc->config->has_pch_encoder) + intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); + + if (intel_crtc->config->has_pch_encoder) intel_prepare_shared_dpll(intel_crtc); if (intel_crtc->config->has_dp_encoder) @@ -4917,7 +4906,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) intel_crtc->active = true; intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true); for_each_encoder_on_crtc(dev, crtc, encoder) if (encoder->pre_enable) @@ -4955,6 +4943,13 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) if (HAS_PCH_CPT(dev)) cpt_verify_modeset(dev, intel_crtc->pipe); + + /* Must wait for vblank to avoid spurious PCH FIFO underruns */ + if (intel_crtc->config->has_pch_encoder) + intel_wait_for_vblank(dev, pipe); + intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true); + + intel_fbc_enable(intel_crtc); } /* IPS only exists on ULT machines and is tied to pipe A. */ @@ -4972,11 +4967,14 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) int pipe = intel_crtc->pipe, hsw_workaround_pipe; struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc->state); - bool is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI); if (WARN_ON(intel_crtc->active)) return; + if (intel_crtc->config->has_pch_encoder) + intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, + false); + if (intel_crtc_to_shared_dpll(intel_crtc)) intel_enable_shared_dpll(intel_crtc); @@ -5001,21 +4999,20 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) intel_crtc->active = true; - intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); + if (intel_crtc->config->has_pch_encoder) + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); + else + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); + for_each_encoder_on_crtc(dev, crtc, encoder) { - if (encoder->pre_pll_enable) - encoder->pre_pll_enable(encoder); if (encoder->pre_enable) encoder->pre_enable(encoder); } - if (intel_crtc->config->has_pch_encoder) { - intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, - true); + if (intel_crtc->config->has_pch_encoder) dev_priv->display.fdi_link_train(crtc); - } - if (!is_dsi) + if (!intel_crtc->config->has_dsi_encoder) intel_ddi_enable_pipe_clock(intel_crtc); if (INTEL_INFO(dev)->gen >= 9) @@ -5030,7 +5027,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) intel_crtc_load_lut(crtc); intel_ddi_set_pipe_settings(crtc); - if (!is_dsi) + if (!intel_crtc->config->has_dsi_encoder) intel_ddi_enable_transcoder_func(crtc); intel_update_watermarks(crtc); @@ -5039,7 +5036,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) if (intel_crtc->config->has_pch_encoder) lpt_pch_enable(crtc); - if (intel_crtc->config->dp_encoder_is_mst && !is_dsi) + if (intel_crtc->config->dp_encoder_is_mst) intel_ddi_set_vc_payload_alloc(crtc, true); assert_vblank_disabled(crtc); @@ -5050,6 +5047,14 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) intel_opregion_notify_encoder(encoder, true); } + if (intel_crtc->config->has_pch_encoder) { + intel_wait_for_vblank(dev, pipe); + intel_wait_for_vblank(dev, pipe); + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); + intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, + true); + } + /* If we change the relative order between pipe/planes enabling, we need * to change the workaround. */ hsw_workaround_pipe = pipe_config->hsw_workaround_pipe; @@ -5057,6 +5062,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) intel_wait_for_vblank(dev, hsw_workaround_pipe); intel_wait_for_vblank(dev, hsw_workaround_pipe); } + + intel_fbc_enable(intel_crtc); } static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force) @@ -5081,7 +5088,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; - u32 reg, temp; + + if (intel_crtc->config->has_pch_encoder) + intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); for_each_encoder_on_crtc(dev, crtc, encoder) encoder->disable(encoder); @@ -5089,15 +5098,22 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) drm_crtc_vblank_off(crtc); assert_vblank_disabled(crtc); + /* + * Sometimes spurious CPU pipe underruns happen when the + * pipe is already disabled, but FDI RX/TX is still enabled. + * Happens at least with VGA+HDMI cloning. Suppress them. + */ if (intel_crtc->config->has_pch_encoder) - intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); intel_disable_pipe(intel_crtc); ironlake_pfit_disable(intel_crtc, false); - if (intel_crtc->config->has_pch_encoder) + if (intel_crtc->config->has_pch_encoder) { ironlake_fdi_disable(crtc); + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); + } for_each_encoder_on_crtc(dev, crtc, encoder) if (encoder->post_disable) @@ -5107,6 +5123,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) ironlake_disable_pch_transcoder(dev_priv, pipe); if (HAS_PCH_CPT(dev)) { + i915_reg_t reg; + u32 temp; + /* disable TRANS_DP_CTL */ reg = TRANS_DP_CTL(pipe); temp = I915_READ(reg); @@ -5123,6 +5142,10 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) ironlake_fdi_pll_disable(intel_crtc); } + + intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true); + + intel_fbc_disable_crtc(intel_crtc); } static void haswell_crtc_disable(struct drm_crtc *crtc) @@ -5132,7 +5155,10 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; - bool is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI); + + if (intel_crtc->config->has_pch_encoder) + intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, + false); for_each_encoder_on_crtc(dev, crtc, encoder) { intel_opregion_notify_encoder(encoder, false); @@ -5142,15 +5168,12 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) drm_crtc_vblank_off(crtc); assert_vblank_disabled(crtc); - if (intel_crtc->config->has_pch_encoder) - intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, - false); intel_disable_pipe(intel_crtc); if (intel_crtc->config->dp_encoder_is_mst) intel_ddi_set_vc_payload_alloc(crtc, false); - if (!is_dsi) + if (!intel_crtc->config->has_dsi_encoder) intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder); if (INTEL_INFO(dev)->gen >= 9) @@ -5158,17 +5181,23 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) else ironlake_pfit_disable(intel_crtc, false); - if (!is_dsi) + if (!intel_crtc->config->has_dsi_encoder) intel_ddi_disable_pipe_clock(intel_crtc); + for_each_encoder_on_crtc(dev, crtc, encoder) + if (encoder->post_disable) + encoder->post_disable(encoder); + if (intel_crtc->config->has_pch_encoder) { lpt_disable_pch_transcoder(dev_priv); + lpt_disable_iclkip(dev_priv); intel_ddi_fdi_disable(crtc); + + intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, + true); } - for_each_encoder_on_crtc(dev, crtc, encoder) - if (encoder->post_disable) - encoder->post_disable(encoder); + intel_fbc_disable_crtc(intel_crtc); } static void i9xx_pfit_enable(struct intel_crtc *crtc) @@ -5199,15 +5228,15 @@ static enum intel_display_power_domain port_to_power_domain(enum port port) { switch (port) { case PORT_A: - return POWER_DOMAIN_PORT_DDI_A_4_LANES; + return POWER_DOMAIN_PORT_DDI_A_LANES; case PORT_B: - return POWER_DOMAIN_PORT_DDI_B_4_LANES; + return POWER_DOMAIN_PORT_DDI_B_LANES; case PORT_C: - return POWER_DOMAIN_PORT_DDI_C_4_LANES; + return POWER_DOMAIN_PORT_DDI_C_LANES; case PORT_D: - return POWER_DOMAIN_PORT_DDI_D_4_LANES; + return POWER_DOMAIN_PORT_DDI_D_LANES; case PORT_E: - return POWER_DOMAIN_PORT_DDI_E_2_LANES; + return POWER_DOMAIN_PORT_DDI_E_LANES; default: MISSING_CASE(port); return POWER_DOMAIN_PORT_OTHER; @@ -5234,10 +5263,6 @@ static enum intel_display_power_domain port_to_aux_power_domain(enum port port) } } -#define for_each_power_domain(domain, mask) \ - for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \ - if ((1 << (domain)) & (mask)) - enum intel_display_power_domain intel_display_port_power_domain(struct intel_encoder *intel_encoder) { @@ -5302,13 +5327,11 @@ static unsigned long get_crtc_power_domains(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe; unsigned long mask; - enum transcoder transcoder; + enum transcoder transcoder = intel_crtc->config->cpu_transcoder; if (!crtc->state->active) return 0; - transcoder = intel_pipe_to_cpu_transcoder(dev->dev_private, pipe); - mask = BIT(POWER_DOMAIN_PIPE(pipe)); mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder)); if (intel_crtc->config->pch_pfit.enabled || @@ -5395,7 +5418,7 @@ static void intel_update_max_cdclk(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - if (IS_SKYLAKE(dev)) { + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK; if (limit == SKL_DFSM_CDCLK_LIMIT_675) @@ -5452,7 +5475,7 @@ static void intel_update_cdclk(struct drm_device *dev) * BSpec erroneously claims we should aim for 4MHz, but * in fact 1MHz is the correct frequency. */ - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { /* * Program the gmbus_freq based on the cdclk frequency. * BSpec erroneously claims we should aim for 4MHz, but @@ -5812,32 +5835,16 @@ void skl_uninit_cdclk(struct drm_i915_private *dev_priv) if (I915_READ(DBUF_CTL) & DBUF_POWER_STATE) DRM_ERROR("DBuf power disable timeout\n"); - /* - * DMC assumes ownership of LCPLL and will get confused if we touch it. - */ - if (dev_priv->csr.dmc_payload) { - /* disable DPLL0 */ - I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) & - ~LCPLL_PLL_ENABLE); - if (wait_for(!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK), 1)) - DRM_ERROR("Couldn't disable DPLL0\n"); - } - - intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + /* disable DPLL0 */ + I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) & ~LCPLL_PLL_ENABLE); + if (wait_for(!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK), 1)) + DRM_ERROR("Couldn't disable DPLL0\n"); } void skl_init_cdclk(struct drm_i915_private *dev_priv) { - u32 val; unsigned int required_vco; - /* enable PCH reset handshake */ - val = I915_READ(HSW_NDE_RSTWRN_OPT); - I915_WRITE(HSW_NDE_RSTWRN_OPT, val | RESET_PCH_HANDSHAKE_ENABLE); - - /* enable PG1 and Misc I/O */ - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); - /* DPLL0 not enabled (happens on early BIOS versions) */ if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) { /* enable DPLL0 */ @@ -5858,6 +5865,45 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv) DRM_ERROR("DBuf power enable timeout\n"); } +int skl_sanitize_cdclk(struct drm_i915_private *dev_priv) +{ + uint32_t lcpll1 = I915_READ(LCPLL1_CTL); + uint32_t cdctl = I915_READ(CDCLK_CTL); + int freq = dev_priv->skl_boot_cdclk; + + /* + * check if the pre-os intialized the display + * There is SWF18 scratchpad register defined which is set by the + * pre-os which can be used by the OS drivers to check the status + */ + if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0) + goto sanitize; + + /* Is PLL enabled and locked ? */ + if (!((lcpll1 & LCPLL_PLL_ENABLE) && (lcpll1 & LCPLL_PLL_LOCK))) + goto sanitize; + + /* DPLL okay; verify the cdclock + * + * Noticed in some instances that the freq selection is correct but + * decimal part is programmed wrong from BIOS where pre-os does not + * enable display. Verify the same as well. + */ + if (cdctl == ((cdctl & CDCLK_FREQ_SEL_MASK) | skl_cdclk_decimal(freq))) + /* All well; nothing to sanitize */ + return false; +sanitize: + /* + * As of now initialize with max cdclk till + * we get dynamic cdclk support + * */ + dev_priv->skl_boot_cdclk = dev_priv->max_cdclk_freq; + skl_init_cdclk(dev_priv); + + /* we did have to sanitize */ + return true; +} + /* Adjust CDclk dividers to allow high res or save power if possible */ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) { @@ -6139,13 +6185,10 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; - bool is_dsi; if (WARN_ON(intel_crtc->active)) return; - is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI); - if (intel_crtc->config->has_dp_encoder) intel_dp_set_m_n(intel_crtc, M1_N1); @@ -6168,7 +6211,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) if (encoder->pre_pll_enable) encoder->pre_pll_enable(encoder); - if (!is_dsi) { + if (!intel_crtc->config->has_dsi_encoder) { if (IS_CHERRYVIEW(dev)) { chv_prepare_pll(intel_crtc, intel_crtc->config); chv_enable_pll(intel_crtc, intel_crtc->config); @@ -6247,6 +6290,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) for_each_encoder_on_crtc(dev, crtc, encoder) encoder->enable(encoder); + + intel_fbc_enable(intel_crtc); } static void i9xx_pfit_disable(struct intel_crtc *crtc) @@ -6294,7 +6339,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) if (encoder->post_disable) encoder->post_disable(encoder); - if (!intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI)) { + if (!intel_crtc->config->has_dsi_encoder) { if (IS_CHERRYVIEW(dev)) chv_disable_pll(dev_priv, pipe); else if (IS_VALLEYVIEW(dev)) @@ -6309,6 +6354,8 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) if (!IS_GEN2(dev)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); + + intel_fbc_disable_crtc(intel_crtc); } static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) @@ -6322,7 +6369,8 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) return; if (to_intel_plane_state(crtc->primary->state)->visible) { - intel_crtc_wait_for_pending_flips(crtc); + WARN_ON(intel_crtc->unpin_work); + intel_pre_disable_primary(crtc); intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary)); @@ -6447,13 +6495,11 @@ static void intel_connector_check_state(struct intel_connector *connector) int intel_connector_init(struct intel_connector *connector) { - struct drm_connector_state *connector_state; + drm_atomic_helper_connector_reset(&connector->base); - connector_state = kzalloc(sizeof *connector_state, GFP_KERNEL); - if (!connector_state) + if (!connector->base.state) return -ENOMEM; - connector->base.state = connector_state; return 0; } @@ -6642,6 +6688,15 @@ static void hsw_compute_ips_config(struct intel_crtc *crtc, pipe_config_supports_ips(dev_priv, pipe_config); } +static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc) +{ + const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + + /* GDG double wide on either pipe, otherwise pipe A only */ + return INTEL_INFO(dev_priv)->gen < 4 && + (crtc->pipe == PIPE_A || IS_I915G(dev_priv)); +} + static int intel_crtc_compute_config(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { @@ -6651,23 +6706,24 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, /* FIXME should check pixel clock limits on all platforms */ if (INTEL_INFO(dev)->gen < 4) { - int clock_limit = dev_priv->max_cdclk_freq; + int clock_limit = dev_priv->max_cdclk_freq * 9 / 10; /* - * Enable pixel doubling when the dot clock + * Enable double wide mode 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) { + if (intel_crtc_supports_double_wide(crtc) && + adjusted_mode->crtc_clock > clock_limit) { clock_limit *= 2; pipe_config->double_wide = true; } - if (adjusted_mode->crtc_clock > clock_limit * 9 / 10) + if (adjusted_mode->crtc_clock > clock_limit) { + DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n", + adjusted_mode->crtc_clock, clock_limit, + yesno(pipe_config->double_wide)); return -EINVAL; + } } /* @@ -7144,7 +7200,7 @@ static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state, WARN_ON(!crtc_state->base.state); - if (IS_VALLEYVIEW(dev) || IS_BROXTON(dev)) { + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) { refclk = 100000; } else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { @@ -7432,7 +7488,7 @@ static void chv_prepare_pll(struct intel_crtc *crtc, struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = crtc->pipe; - int dpll_reg = DPLL(crtc->pipe); + i915_reg_t dpll_reg = DPLL(crtc->pipe); enum dpio_channel port = vlv_pipe_to_channel(pipe); u32 loopfilter, tribuf_calcntr; u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac; @@ -7843,7 +7899,7 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) pipeconf |= PIPECONF_DOUBLE_WIDE; /* only g4x and later have fancy bpc/dither controls */ - if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) { + if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { /* Bspec claims that we can't use dithering for 30bpp pipes. */ if (intel_crtc->config->dither && intel_crtc->config->pipe_bpp != 30) pipeconf |= PIPECONF_DITHER_EN | @@ -7883,7 +7939,8 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) } else pipeconf |= PIPECONF_PROGRESSIVE; - if (IS_VALLEYVIEW(dev) && intel_crtc->config->limited_color_range) + if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && + intel_crtc->config->limited_color_range) pipeconf |= PIPECONF_COLOR_RANGE_SELECT; I915_WRITE(PIPECONF(intel_crtc->pipe), pipeconf); @@ -7898,8 +7955,6 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc, int refclk, num_connectors = 0; intel_clock_t clock; bool ok; - bool is_dsi = false; - struct intel_encoder *encoder; const intel_limit_t *limit; struct drm_atomic_state *state = crtc_state->base.state; struct drm_connector *connector; @@ -7909,26 +7964,14 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc, memset(&crtc_state->dpll_hw_state, 0, sizeof(crtc_state->dpll_hw_state)); - for_each_connector_in_state(state, connector, connector_state, i) { - if (connector_state->crtc != &crtc->base) - continue; - - encoder = to_intel_encoder(connector_state->best_encoder); - - switch (encoder->type) { - case INTEL_OUTPUT_DSI: - is_dsi = true; - break; - default: - break; - } + if (crtc_state->has_dsi_encoder) + return 0; - num_connectors++; + for_each_connector_in_state(state, connector, connector_state, i) { + if (connector_state->crtc == &crtc->base) + num_connectors++; } - if (is_dsi) - return 0; - if (!crtc_state->clock_set) { refclk = i9xx_get_refclk(crtc_state, num_connectors); @@ -8131,20 +8174,24 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + enum intel_display_power_domain power_domain; uint32_t tmp; + bool ret; - if (!intel_display_power_is_enabled(dev_priv, - POWER_DOMAIN_PIPE(crtc->pipe))) + power_domain = POWER_DOMAIN_PIPE(crtc->pipe); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; pipe_config->shared_dpll = DPLL_ID_PRIVATE; + ret = false; + tmp = I915_READ(PIPECONF(crtc->pipe)); if (!(tmp & PIPECONF_ENABLE)) - return false; + goto out; - if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) { + if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { switch (tmp & PIPECONF_BPC_MASK) { case PIPECONF_6BPC: pipe_config->pipe_bpp = 18; @@ -8160,7 +8207,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, } } - if (IS_VALLEYVIEW(dev) && (tmp & PIPECONF_COLOR_RANGE_SELECT)) + if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && + (tmp & PIPECONF_COLOR_RANGE_SELECT)) pipe_config->limited_color_range = true; if (INTEL_INFO(dev)->gen < 4) @@ -8188,7 +8236,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, pipe_config->pixel_multiplier = 1; } pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe)); - if (!IS_VALLEYVIEW(dev)) { + if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) { /* * DPLL_DVO_2X_MODE must be enabled for both DPLLs * on 830. Filter it out here so that we don't @@ -8221,7 +8269,12 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock / pipe_config->pixel_multiplier; - return true; + ret = true; + +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } static void ironlake_init_pch_refclk(struct drm_device *dev) @@ -8540,6 +8593,67 @@ static void lpt_disable_clkout_dp(struct drm_device *dev) mutex_unlock(&dev_priv->sb_lock); } +#define BEND_IDX(steps) ((50 + (steps)) / 5) + +static const uint16_t sscdivintphase[] = { + [BEND_IDX( 50)] = 0x3B23, + [BEND_IDX( 45)] = 0x3B23, + [BEND_IDX( 40)] = 0x3C23, + [BEND_IDX( 35)] = 0x3C23, + [BEND_IDX( 30)] = 0x3D23, + [BEND_IDX( 25)] = 0x3D23, + [BEND_IDX( 20)] = 0x3E23, + [BEND_IDX( 15)] = 0x3E23, + [BEND_IDX( 10)] = 0x3F23, + [BEND_IDX( 5)] = 0x3F23, + [BEND_IDX( 0)] = 0x0025, + [BEND_IDX( -5)] = 0x0025, + [BEND_IDX(-10)] = 0x0125, + [BEND_IDX(-15)] = 0x0125, + [BEND_IDX(-20)] = 0x0225, + [BEND_IDX(-25)] = 0x0225, + [BEND_IDX(-30)] = 0x0325, + [BEND_IDX(-35)] = 0x0325, + [BEND_IDX(-40)] = 0x0425, + [BEND_IDX(-45)] = 0x0425, + [BEND_IDX(-50)] = 0x0525, +}; + +/* + * Bend CLKOUT_DP + * steps -50 to 50 inclusive, in steps of 5 + * < 0 slow down the clock, > 0 speed up the clock, 0 == no bend (135MHz) + * change in clock period = -(steps / 10) * 5.787 ps + */ +static void lpt_bend_clkout_dp(struct drm_i915_private *dev_priv, int steps) +{ + uint32_t tmp; + int idx = BEND_IDX(steps); + + if (WARN_ON(steps % 5 != 0)) + return; + + if (WARN_ON(idx >= ARRAY_SIZE(sscdivintphase))) + return; + + mutex_lock(&dev_priv->sb_lock); + + if (steps % 10 != 0) + tmp = 0xAAAAAAAB; + else + tmp = 0x00000000; + intel_sbi_write(dev_priv, SBI_SSCDITHPHASE, tmp, SBI_ICLK); + + tmp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE, SBI_ICLK); + tmp &= 0xffff0000; + tmp |= sscdivintphase[idx]; + intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE, tmp, SBI_ICLK); + + mutex_unlock(&dev_priv->sb_lock); +} + +#undef BEND_IDX + static void lpt_init_pch_refclk(struct drm_device *dev) { struct intel_encoder *encoder; @@ -8555,10 +8669,12 @@ static void lpt_init_pch_refclk(struct drm_device *dev) } } - if (has_vga) + if (has_vga) { + lpt_bend_clkout_dp(to_i915(dev), 0); lpt_enable_clkout_dp(dev, true, true); - else + } else { lpt_disable_clkout_dp(dev); + } } /* @@ -8921,7 +9037,7 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, memset(&crtc_state->dpll_hw_state, 0, sizeof(crtc_state->dpll_hw_state)); - is_lvds = intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS); + is_lvds = intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS); WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)), "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev)); @@ -9262,18 +9378,21 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + enum intel_display_power_domain power_domain; uint32_t tmp; + bool ret; - if (!intel_display_power_is_enabled(dev_priv, - POWER_DOMAIN_PIPE(crtc->pipe))) + power_domain = POWER_DOMAIN_PIPE(crtc->pipe); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; pipe_config->shared_dpll = DPLL_ID_PRIVATE; + ret = false; tmp = I915_READ(PIPECONF(crtc->pipe)); if (!(tmp & PIPECONF_ENABLE)) - return false; + goto out; switch (tmp & PIPECONF_BPC_MASK) { case PIPECONF_6BPC: @@ -9336,7 +9455,12 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, ironlake_get_pfit_config(crtc, pipe_config); - return true; + ret = true; + +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) @@ -9350,8 +9474,8 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) I915_STATE_WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n"); I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n"); - I915_STATE_WARN(I915_READ(WRPLL_CTL1) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n"); - I915_STATE_WARN(I915_READ(WRPLL_CTL2) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n"); + I915_STATE_WARN(I915_READ(WRPLL_CTL(0)) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n"); + I915_STATE_WARN(I915_READ(WRPLL_CTL(1)) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n"); I915_STATE_WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n"); I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE, "CPU PWM1 enabled\n"); @@ -9695,14 +9819,10 @@ static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state) else cdclk = 337500; - /* - * FIXME move the cdclk caclulation to - * compute_config() so we can fail gracegully. - */ if (cdclk > dev_priv->max_cdclk_freq) { - DRM_ERROR("requested cdclk (%d kHz) exceeds max (%d kHz)\n", - cdclk, dev_priv->max_cdclk_freq); - cdclk = dev_priv->max_cdclk_freq; + DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n", + cdclk, dev_priv->max_cdclk_freq); + return -EINVAL; } to_intel_atomic_state(state)->cdclk = cdclk; @@ -9797,6 +9917,7 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv, break; case PORT_CLK_SEL_SPLL: pipe_config->shared_dpll = DPLL_ID_SPLL; + break; } } @@ -9813,7 +9934,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc, port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT; - if (IS_SKYLAKE(dev)) + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) skylake_get_ddi_pll(dev_priv, port, pipe_config); else if (IS_BROXTON(dev)) bxt_get_ddi_pll(dev_priv, port, pipe_config); @@ -9849,12 +9970,17 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - enum intel_display_power_domain pfit_domain; + enum intel_display_power_domain power_domain; + unsigned long power_domain_mask; uint32_t tmp; + bool ret; - if (!intel_display_power_is_enabled(dev_priv, - POWER_DOMAIN_PIPE(crtc->pipe))) + power_domain = POWER_DOMAIN_PIPE(crtc->pipe); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; + power_domain_mask = BIT(power_domain); + + ret = false; pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; pipe_config->shared_dpll = DPLL_ID_PRIVATE; @@ -9881,13 +10007,14 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, pipe_config->cpu_transcoder = TRANSCODER_EDP; } - if (!intel_display_power_is_enabled(dev_priv, - POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder))) - return false; + power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) + goto out; + power_domain_mask |= BIT(power_domain); tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder)); if (!(tmp & PIPECONF_ENABLE)) - return false; + goto out; haswell_get_ddi_port_state(crtc, pipe_config); @@ -9897,14 +10024,14 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, skl_init_scalers(dev, crtc, pipe_config); } - pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe); - if (INTEL_INFO(dev)->gen >= 9) { pipe_config->scaler_state.scaler_id = -1; pipe_config->scaler_state.scaler_users &= ~(1 << SKL_CRTC_INDEX); } - if (intel_display_power_is_enabled(dev_priv, pfit_domain)) { + power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe); + if (intel_display_power_get_if_enabled(dev_priv, power_domain)) { + power_domain_mask |= BIT(power_domain); if (INTEL_INFO(dev)->gen >= 9) skylake_get_pfit_config(crtc, pipe_config); else @@ -9922,7 +10049,13 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, pipe_config->pixel_multiplier = 1; } - return true; + ret = true; + +out: + for_each_power_domain(power_domain, power_domain_mask) + intel_display_power_put(dev_priv, power_domain); + + return ret; } static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on) @@ -10154,20 +10287,17 @@ __intel_framebuffer_create(struct drm_device *dev, int ret; intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); - if (!intel_fb) { - drm_gem_object_unreference(&obj->base); + if (!intel_fb) return ERR_PTR(-ENOMEM); - } ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj); if (ret) goto err; return &intel_fb->base; + err: - drm_gem_object_unreference(&obj->base); kfree(intel_fb); - return ERR_PTR(ret); } @@ -10207,6 +10337,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev, struct drm_display_mode *mode, int depth, int bpp) { + struct drm_framebuffer *fb; struct drm_i915_gem_object *obj; struct drm_mode_fb_cmd2 mode_cmd = { 0 }; @@ -10221,7 +10352,11 @@ intel_framebuffer_create_for_mode(struct drm_device *dev, bpp); mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth); - return intel_framebuffer_create(dev, &mode_cmd, obj); + fb = intel_framebuffer_create(dev, &mode_cmd, obj); + if (IS_ERR(fb)) + drm_gem_object_unreference_unlocked(&obj->base); + + return fb; } static struct drm_framebuffer * @@ -11124,7 +11259,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, */ if (ring->id == RCS) { intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit(ring, DERRMR); + intel_ring_emit_reg(ring, DERRMR); intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE | DERRMR_PIPEB_PRI_FLIP_DONE | DERRMR_PIPEC_PRI_FLIP_DONE)); @@ -11134,7 +11269,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, else intel_ring_emit(ring, MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT); - intel_ring_emit(ring, DERRMR); + intel_ring_emit_reg(ring, DERRMR); intel_ring_emit(ring, ring->scratch.gtt_offset + 256); if (IS_GEN8(dev)) { intel_ring_emit(ring, 0); @@ -11174,18 +11309,23 @@ static bool use_mmio_flip(struct intel_engine_cs *ring, return true; else if (i915.enable_execlists) return true; + else if (obj->base.dma_buf && + !reservation_object_test_signaled_rcu(obj->base.dma_buf->resv, + false)) + return true; else return ring != i915_gem_request_get_ring(obj->last_write_req); } static void skl_do_mmio_flip(struct intel_crtc *intel_crtc, + unsigned int rotation, struct intel_unpin_work *work) { struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_framebuffer *fb = intel_crtc->base.primary->fb; const enum pipe pipe = intel_crtc->pipe; - u32 ctl, stride; + u32 ctl, stride, tile_height; ctl = I915_READ(PLANE_CTL(pipe, 0)); ctl &= ~PLANE_CTL_TILED_MASK; @@ -11209,9 +11349,16 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc, * The stride is either expressed as a multiple of 64 bytes chunks for * linear buffers or in number of tiles for tiled buffers. */ - stride = fb->pitches[0] / - intel_fb_stride_alignment(dev, fb->modifier[0], - fb->pixel_format); + if (intel_rotation_90_or_270(rotation)) { + /* stride = Surface height in tiles */ + tile_height = intel_tile_height(dev, fb->pixel_format, + fb->modifier[0], 0); + stride = DIV_ROUND_UP(fb->height, tile_height); + } else { + stride = fb->pitches[0] / + intel_fb_stride_alignment(dev, fb->modifier[0], + fb->pixel_format); + } /* * Both PLANE_CTL and PLANE_STRIDE are not updated on vblank but on @@ -11232,10 +11379,9 @@ static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc, struct intel_framebuffer *intel_fb = to_intel_framebuffer(intel_crtc->base.primary->fb); struct drm_i915_gem_object *obj = intel_fb->obj; + i915_reg_t reg = DSPCNTR(intel_crtc->plane); u32 dspcntr; - u32 reg; - reg = DSPCNTR(intel_crtc->plane); dspcntr = I915_READ(reg); if (obj->tiling_mode != I915_TILING_NONE) @@ -11269,7 +11415,7 @@ static void intel_do_mmio_flip(struct intel_mmio_flip *mmio_flip) intel_pipe_update_start(crtc); if (INTEL_INFO(mmio_flip->i915)->gen >= 9) - skl_do_mmio_flip(crtc, work); + skl_do_mmio_flip(crtc, mmio_flip->rotation, work); else /* use_mmio_flip() retricts MMIO flips to ilk+ */ ilk_do_mmio_flip(crtc, work); @@ -11281,6 +11427,9 @@ static void intel_mmio_flip_work_func(struct work_struct *work) { struct intel_mmio_flip *mmio_flip = container_of(work, struct intel_mmio_flip, work); + struct intel_framebuffer *intel_fb = + to_intel_framebuffer(mmio_flip->crtc->base.primary->fb); + struct drm_i915_gem_object *obj = intel_fb->obj; if (mmio_flip->req) { WARN_ON(__i915_wait_request(mmio_flip->req, @@ -11290,16 +11439,19 @@ static void intel_mmio_flip_work_func(struct work_struct *work) i915_gem_request_unreference__unlocked(mmio_flip->req); } + /* For framebuffer backed by dmabuf, wait for fence */ + if (obj->base.dma_buf) + WARN_ON(reservation_object_wait_timeout_rcu(obj->base.dma_buf->resv, + false, false, + MAX_SCHEDULE_TIMEOUT) < 0); + intel_do_mmio_flip(mmio_flip); kfree(mmio_flip); } static int intel_queue_mmio_flip(struct drm_device *dev, struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_i915_gem_object *obj, - struct intel_engine_cs *ring, - uint32_t flags) + struct drm_i915_gem_object *obj) { struct intel_mmio_flip *mmio_flip; @@ -11310,6 +11462,7 @@ static int intel_queue_mmio_flip(struct drm_device *dev, mmio_flip->i915 = to_i915(dev); mmio_flip->req = i915_gem_request_reference(obj->last_write_req); mmio_flip->crtc = to_intel_crtc(crtc); + mmio_flip->rotation = crtc->primary->state->rotation; INIT_WORK(&mmio_flip->work, intel_mmio_flip_work_func); schedule_work(&mmio_flip->work); @@ -11493,7 +11646,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1; - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { ring = &dev_priv->ring[BCS]; if (obj->tiling_mode != intel_fb_obj(work->old_fb)->tiling_mode) /* vlv: DISPLAY_FLIP fails to change tiling */ @@ -11515,9 +11668,14 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, * synchronisation, so all we want here is to pin the framebuffer * into the display plane and skip any waits. */ + if (!mmio_flip) { + ret = i915_gem_object_sync(obj, ring, &request); + if (ret) + goto cleanup_pending; + } + ret = intel_pin_and_fence_fb_obj(crtc->primary, fb, - crtc->primary->state, - mmio_flip ? i915_gem_request_get_ring(obj->last_write_req) : ring, &request); + crtc->primary->state); if (ret) goto cleanup_pending; @@ -11526,8 +11684,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, work->gtt_offset += intel_crtc->dspaddr_offset; if (mmio_flip) { - ret = intel_queue_mmio_flip(dev, crtc, fb, obj, ring, - page_flip_flags); + ret = intel_queue_mmio_flip(dev, crtc, obj); if (ret) goto cleanup_unpin; @@ -11558,7 +11715,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, to_intel_plane(primary)->frontbuffer_bit); mutex_unlock(&dev->struct_mutex); - intel_fbc_disable_crtc(intel_crtc); + intel_fbc_deactivate(intel_crtc); intel_frontbuffer_flip_prepare(dev, to_intel_plane(primary)->frontbuffer_bit); @@ -11641,21 +11798,41 @@ retry: static bool intel_wm_need_update(struct drm_plane *plane, struct drm_plane_state *state) { - /* Update watermarks on tiling changes. */ - if (!plane->state->fb || !state->fb || - plane->state->fb->modifier[0] != state->fb->modifier[0] || - plane->state->rotation != state->rotation) + struct intel_plane_state *new = to_intel_plane_state(state); + struct intel_plane_state *cur = to_intel_plane_state(plane->state); + + /* Update watermarks on tiling or size changes. */ + if (new->visible != cur->visible) return true; - if (plane->state->crtc_w != state->crtc_w) + if (!cur->base.fb || !new->base.fb) + return false; + + if (cur->base.fb->modifier[0] != new->base.fb->modifier[0] || + cur->base.rotation != new->base.rotation || + drm_rect_width(&new->src) != drm_rect_width(&cur->src) || + drm_rect_height(&new->src) != drm_rect_height(&cur->src) || + drm_rect_width(&new->dst) != drm_rect_width(&cur->dst) || + drm_rect_height(&new->dst) != drm_rect_height(&cur->dst)) return true; return false; } +static bool needs_scaling(struct intel_plane_state *state) +{ + int src_w = drm_rect_width(&state->src) >> 16; + int src_h = drm_rect_height(&state->src) >> 16; + int dst_w = drm_rect_width(&state->dst); + int dst_h = drm_rect_height(&state->dst); + + return (src_w != dst_w || src_h != dst_h); +} + int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, struct drm_plane_state *plane_state) { + struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state); struct drm_crtc *crtc = crtc_state->crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_plane *plane = plane_state->plane; @@ -11668,7 +11845,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, bool mode_changed = needs_modeset(crtc_state); bool was_crtc_enabled = crtc->state->active; bool is_crtc_enabled = crtc_state->active; - bool turn_off, turn_on, visible, was_visible; struct drm_framebuffer *fb = plane_state->fb; @@ -11681,14 +11857,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, return ret; } - /* - * Disabling a plane is always okay; we just need to update - * fb tracking in a special way since cleanup_fb() won't - * get called by the plane helpers. - */ - if (old_plane_state->base.fb && !fb) - intel_crtc->atomic.disabled_planes |= 1 << i; - was_visible = old_plane_state->visible; visible = to_intel_plane_state(plane_state)->visible; @@ -11711,25 +11879,17 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, plane->base.id, was_visible, visible, turn_off, turn_on, mode_changed); - if (turn_on) { - intel_crtc->atomic.update_wm_pre = true; - /* must disable cxsr around plane enable/disable */ - if (plane->type != DRM_PLANE_TYPE_CURSOR) { - intel_crtc->atomic.disable_cxsr = true; - /* to potentially re-enable cxsr */ - intel_crtc->atomic.wait_vblank = true; - intel_crtc->atomic.update_wm_post = true; - } - } else if (turn_off) { - intel_crtc->atomic.update_wm_post = true; + if (turn_on || turn_off) { + pipe_config->wm_changed = true; + /* must disable cxsr around plane enable/disable */ if (plane->type != DRM_PLANE_TYPE_CURSOR) { if (is_crtc_enabled) intel_crtc->atomic.wait_vblank = true; - intel_crtc->atomic.disable_cxsr = true; + pipe_config->disable_cxsr = true; } } else if (intel_wm_need_update(plane, plane_state)) { - intel_crtc->atomic.update_wm_pre = true; + pipe_config->wm_changed = true; } if (visible || was_visible) @@ -11738,7 +11898,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, switch (plane->type) { case DRM_PLANE_TYPE_PRIMARY: - intel_crtc->atomic.wait_for_flips = true; intel_crtc->atomic.pre_disable_primary = turn_off; intel_crtc->atomic.post_enable_primary = turn_on; @@ -11786,11 +11945,23 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, case DRM_PLANE_TYPE_CURSOR: break; case DRM_PLANE_TYPE_OVERLAY: - if (turn_off && !mode_changed) { + /* + * WaCxSRDisabledForSpriteScaling:ivb + * + * cstate->update_wm was already set above, so this flag will + * take effect when we commit and program watermarks. + */ + if (IS_IVYBRIDGE(dev) && + needs_scaling(to_intel_plane_state(plane_state)) && + !needs_scaling(old_plane_state)) { + to_intel_crtc_state(crtc_state)->disable_lp_wm = true; + } else if (turn_off && !mode_changed) { intel_crtc->atomic.wait_vblank = true; intel_crtc->atomic.update_sprite_watermarks |= 1 << i; } + + break; } return 0; } @@ -11863,7 +12034,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, } if (mode_changed && !crtc_state->active) - intel_crtc->atomic.update_wm_post = true; + pipe_config->wm_changed = true; if (mode_changed && crtc_state->enable && dev_priv->display.crtc_compute_clock && @@ -11875,6 +12046,12 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, } ret = 0; + if (dev_priv->display.compute_pipe_wm) { + ret = dev_priv->display.compute_pipe_wm(intel_crtc, state); + if (ret) + return ret; + } + if (INTEL_INFO(dev)->gen >= 9) { if (mode_changed) ret = skl_update_scaler_crtc(pipe_config); @@ -11958,7 +12135,7 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc, struct drm_connector_state *connector_state; int bpp, i; - if ((IS_G4X(dev) || IS_VALLEYVIEW(dev))) + if ((IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))) bpp = 10*3; else if (INTEL_INFO(dev)->gen >= 5) bpp = 12*3; @@ -12074,7 +12251,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, pipe_config->dpll_hw_state.pll9, pipe_config->dpll_hw_state.pll10, pipe_config->dpll_hw_state.pcsdw12); - } else if (IS_SKYLAKE(dev)) { + } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: " "ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n", pipe_config->ddi_pll_sel, @@ -12332,6 +12509,18 @@ intel_modeset_update_crtc_state(struct drm_atomic_state *state) crtc->hwmode = crtc->state->adjusted_mode; else crtc->hwmode.crtc_clock = 0; + + /* + * Update legacy state to satisfy fbc code. This can + * be removed when fbc uses the atomic state. + */ + if (drm_atomic_get_existing_plane_state(state, crtc->primary)) { + struct drm_plane_state *plane_state = crtc->primary->state; + + crtc->primary->fb = plane_state->fb; + crtc->x = plane_state->src_x >> 16; + crtc->y = plane_state->src_y >> 16; + } } } @@ -12357,7 +12546,7 @@ static bool intel_fuzzy_clock_check(int clock1, int clock2) list_for_each_entry((intel_crtc), \ &(dev)->mode_config.crtc_list, \ base.head) \ - if (mask & (1 <<(intel_crtc)->pipe)) + for_each_if (mask & (1 <<(intel_crtc)->pipe)) static bool intel_compare_m_n(unsigned int m, unsigned int n, @@ -12541,6 +12730,8 @@ intel_pipe_config_compare(struct drm_device *dev, } else PIPE_CONF_CHECK_M_N_ALT(dp_m_n, dp_m2_n2); + PIPE_CONF_CHECK_I(has_dsi_encoder); + PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hdisplay); PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_htotal); PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hblank_start); @@ -12558,7 +12749,7 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_I(pixel_multiplier); PIPE_CONF_CHECK_I(has_hdmi_sink); if ((INTEL_INFO(dev)->gen < 8 && !IS_HASWELL(dev)) || - IS_VALLEYVIEW(dev)) + IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) PIPE_CONF_CHECK_I(limited_color_range); PIPE_CONF_CHECK_I(has_infoframe); @@ -13095,6 +13286,45 @@ static int intel_modeset_checks(struct drm_atomic_state *state) return 0; } +/* + * Handle calculation of various watermark data at the end of the atomic check + * phase. The code here should be run after the per-crtc and per-plane 'check' + * handlers to ensure that all derived state has been updated. + */ +static void calc_watermark_data(struct drm_atomic_state *state) +{ + struct drm_device *dev = state->dev; + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); + struct drm_crtc *crtc; + struct drm_crtc_state *cstate; + struct drm_plane *plane; + struct drm_plane_state *pstate; + + /* + * Calculate watermark configuration details now that derived + * plane/crtc state is all properly updated. + */ + drm_for_each_crtc(crtc, dev) { + cstate = drm_atomic_get_existing_crtc_state(state, crtc) ?: + crtc->state; + + if (cstate->active) + intel_state->wm_config.num_pipes_active++; + } + drm_for_each_legacy_plane(plane, dev) { + pstate = drm_atomic_get_existing_plane_state(state, plane) ?: + plane->state; + + if (!to_intel_plane_state(pstate)->visible) + continue; + + intel_state->wm_config.sprites_enabled = true; + if (pstate->crtc_w != pstate->src_w >> 16 || + pstate->crtc_h != pstate->src_h >> 16) + intel_state->wm_config.sprites_scaled = true; + } +} + /** * intel_atomic_check - validate state object * @dev: drm device @@ -13103,6 +13333,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state) static int intel_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; int ret, i; @@ -13170,10 +13401,81 @@ static int intel_atomic_check(struct drm_device *dev, if (ret) return ret; } else - to_intel_atomic_state(state)->cdclk = - to_i915(state->dev)->cdclk_freq; + intel_state->cdclk = to_i915(state->dev)->cdclk_freq; + + ret = drm_atomic_helper_check_planes(state->dev, state); + if (ret) + return ret; + + calc_watermark_data(state); - return drm_atomic_helper_check_planes(state->dev, state); + return 0; +} + +static int intel_atomic_prepare_commit(struct drm_device *dev, + struct drm_atomic_state *state, + bool async) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_plane_state *plane_state; + struct drm_crtc_state *crtc_state; + struct drm_plane *plane; + struct drm_crtc *crtc; + int i, ret; + + if (async) { + DRM_DEBUG_KMS("i915 does not yet support async commit\n"); + return -EINVAL; + } + + for_each_crtc_in_state(state, crtc, crtc_state, i) { + ret = intel_crtc_wait_for_pending_flips(crtc); + if (ret) + return ret; + + if (atomic_read(&to_intel_crtc(crtc)->unpin_work_count) >= 2) + flush_workqueue(dev_priv->wq); + } + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; + + ret = drm_atomic_helper_prepare_planes(dev, state); + if (!ret && !async && !i915_reset_in_progress(&dev_priv->gpu_error)) { + u32 reset_counter; + + reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); + mutex_unlock(&dev->struct_mutex); + + for_each_plane_in_state(state, plane, plane_state, i) { + struct intel_plane_state *intel_plane_state = + to_intel_plane_state(plane_state); + + if (!intel_plane_state->wait_req) + continue; + + ret = __i915_wait_request(intel_plane_state->wait_req, + reset_counter, true, + NULL, NULL); + + /* Swallow -EIO errors to allow updates during hw lockup. */ + if (ret == -EIO) + ret = 0; + + if (ret) + break; + } + + if (!ret) + return 0; + + mutex_lock(&dev->struct_mutex); + drm_atomic_helper_cleanup_planes(dev, state); + } + + mutex_unlock(&dev->struct_mutex); + return ret; } /** @@ -13197,22 +13499,20 @@ static int intel_atomic_commit(struct drm_device *dev, bool async) { struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; + struct drm_crtc *crtc; int ret = 0; int i; bool any_ms = false; - if (async) { - DRM_DEBUG_KMS("i915 does not yet support async commit\n"); - return -EINVAL; - } - - ret = drm_atomic_helper_prepare_planes(dev, state); - if (ret) + ret = intel_atomic_prepare_commit(dev, state, async); + if (ret) { + DRM_DEBUG_ATOMIC("Preparing state failed with %i\n", ret); return ret; + } drm_atomic_helper_swap_state(dev, state); + dev_priv->wm.config = to_intel_atomic_state(state)->wm_config; for_each_crtc_in_state(state, crtc, crtc_state, i) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -13228,6 +13528,16 @@ static int intel_atomic_commit(struct drm_device *dev, dev_priv->display.crtc_disable(crtc); intel_crtc->active = false; intel_disable_shared_dpll(intel_crtc); + + /* + * Underruns don't always raise + * interrupts, so check manually. + */ + intel_check_cpu_fifo_underruns(dev_priv); + intel_check_pch_fifo_underruns(dev_priv); + + if (!crtc->state->active) + intel_update_watermarks(crtc); } } @@ -13250,6 +13560,9 @@ static int intel_atomic_commit(struct drm_device *dev, to_intel_crtc_state(crtc->state)->update_pipe; unsigned long put_domains = 0; + if (modeset) + intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET); + if (modeset && crtc->state->active) { update_scanline_offset(to_intel_crtc(crtc)); dev_priv->display.crtc_enable(crtc); @@ -13265,18 +13578,26 @@ static int intel_atomic_commit(struct drm_device *dev, if (!modeset) intel_pre_plane_update(intel_crtc); - drm_atomic_helper_commit_planes_on_crtc(crtc_state); + if (crtc->state->active && + (crtc->state->planes_changed || update_pipe)) + drm_atomic_helper_commit_planes_on_crtc(crtc_state); if (put_domains) modeset_put_power_domains(dev_priv, put_domains); intel_post_plane_update(intel_crtc); + + if (modeset) + intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET); } /* FIXME: add subpixel order */ drm_atomic_helper_wait_for_vblanks(dev, state); + + mutex_lock(&dev->struct_mutex); drm_atomic_helper_cleanup_planes(dev, state); + mutex_unlock(&dev->struct_mutex); if (any_ms) intel_modeset_check_state(dev, state); @@ -13341,7 +13662,7 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv, { uint32_t val; - if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS)) + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) return false; val = I915_READ(PCH_DPLL(pll->id)); @@ -13349,6 +13670,8 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv, hw_state->fp0 = I915_READ(PCH_FP0(pll->id)); hw_state->fp1 = I915_READ(PCH_FP1(pll->id)); + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + return val & DPLL_VCO_ENABLE; } @@ -13445,6 +13768,8 @@ static void intel_shared_dpll_init(struct drm_device *dev) * bits. Some older platforms need special physical address handling for * cursor planes. * + * Must be called with struct_mutex held. + * * Returns 0 on success, negative error code on failure. */ int @@ -13455,28 +13780,71 @@ intel_prepare_plane_fb(struct drm_plane *plane, struct drm_framebuffer *fb = new_state->fb; struct intel_plane *intel_plane = to_intel_plane(plane); struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); + struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb); int ret = 0; - if (!obj) + if (!obj && !old_obj) return 0; - mutex_lock(&dev->struct_mutex); + if (old_obj) { + struct drm_crtc_state *crtc_state = + drm_atomic_get_existing_crtc_state(new_state->state, plane->state->crtc); + + /* Big Hammer, we also need to ensure that any pending + * MI_WAIT_FOR_EVENT inside a user batch buffer on the + * current scanout is retired before unpinning the old + * framebuffer. Note that we rely on userspace rendering + * into the buffer attached to the pipe they are waiting + * on. If not, userspace generates a GPU hang with IPEHR + * point to the MI_WAIT_FOR_EVENT. + * + * This should only fail upon a hung GPU, in which case we + * can safely continue. + */ + if (needs_modeset(crtc_state)) + ret = i915_gem_object_wait_rendering(old_obj, true); + + /* Swallow -EIO errors to allow updates during hw lockup. */ + if (ret && ret != -EIO) + return ret; + } - if (plane->type == DRM_PLANE_TYPE_CURSOR && + /* For framebuffer backed by dmabuf, wait for fence */ + if (obj && obj->base.dma_buf) { + long lret; + + lret = reservation_object_wait_timeout_rcu(obj->base.dma_buf->resv, + false, true, + MAX_SCHEDULE_TIMEOUT); + if (lret == -ERESTARTSYS) + return lret; + + WARN(lret < 0, "waiting returns %li\n", lret); + } + + if (!obj) { + ret = 0; + } else if (plane->type == DRM_PLANE_TYPE_CURSOR && INTEL_INFO(dev)->cursor_needs_physical) { int align = IS_I830(dev) ? 16 * 1024 : 256; ret = i915_gem_object_attach_phys(obj, align); if (ret) DRM_DEBUG_KMS("failed to attach phys object\n"); } else { - ret = intel_pin_and_fence_fb_obj(plane, fb, new_state, NULL, NULL); + ret = intel_pin_and_fence_fb_obj(plane, fb, new_state); } - if (ret == 0) - i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit); + if (ret == 0) { + if (obj) { + struct intel_plane_state *plane_state = + to_intel_plane_state(new_state); - mutex_unlock(&dev->struct_mutex); + i915_gem_request_assign(&plane_state->wait_req, + obj->last_write_req); + } + + i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit); + } return ret; } @@ -13487,23 +13855,35 @@ intel_prepare_plane_fb(struct drm_plane *plane, * @fb: old framebuffer that was on plane * * Cleans up a framebuffer that has just been removed from a plane. + * + * Must be called with struct_mutex held. */ void intel_cleanup_plane_fb(struct drm_plane *plane, const struct drm_plane_state *old_state) { struct drm_device *dev = plane->dev; - struct drm_i915_gem_object *obj = intel_fb_obj(old_state->fb); + struct intel_plane *intel_plane = to_intel_plane(plane); + struct intel_plane_state *old_intel_state; + struct drm_i915_gem_object *old_obj = intel_fb_obj(old_state->fb); + struct drm_i915_gem_object *obj = intel_fb_obj(plane->state->fb); - if (!obj) + old_intel_state = to_intel_plane_state(old_state); + + if (!obj && !old_obj) return; - if (plane->type != DRM_PLANE_TYPE_CURSOR || - !INTEL_INFO(dev)->cursor_needs_physical) { - mutex_lock(&dev->struct_mutex); + if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR || + !INTEL_INFO(dev)->cursor_needs_physical)) intel_unpin_fb_obj(old_state->fb, old_state); - mutex_unlock(&dev->struct_mutex); - } + + /* prepare_fb aborted? */ + if ((old_obj && (old_obj->frontbuffer_bits & intel_plane->frontbuffer_bit)) || + (obj && !(obj->frontbuffer_bits & intel_plane->frontbuffer_bit))) + i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit); + + i915_gem_request_assign(&old_intel_state->wait_req, NULL); + } int @@ -13522,7 +13902,7 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state crtc_clock = crtc_state->base.adjusted_mode.crtc_clock; cdclk = to_intel_atomic_state(crtc_state->base.state)->cdclk; - if (!crtc_clock || !cdclk) + if (WARN_ON_ONCE(!crtc_clock || cdclk < crtc_clock)) return DRM_PLANE_HELPER_NO_SCALING; /* @@ -13571,18 +13951,8 @@ intel_commit_primary_plane(struct drm_plane *plane, struct drm_framebuffer *fb = state->base.fb; struct drm_device *dev = plane->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc; - struct drm_rect *src = &state->src; crtc = crtc ? crtc : plane->crtc; - intel_crtc = to_intel_crtc(crtc); - - plane->fb = fb; - crtc->x = src->x1 >> 16; - crtc->y = src->y1 >> 16; - - if (!crtc->state->active) - return; dev_priv->display.update_primary_plane(crtc, fb, state->src.x1 >> 16, @@ -13608,12 +13978,8 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc, to_intel_crtc_state(old_crtc_state); bool modeset = needs_modeset(crtc->state); - if (intel_crtc->atomic.update_wm_pre) - intel_update_watermarks(crtc); - /* Perform vblank evasion around commit operation */ - if (crtc->state->active) - intel_pipe_update_start(intel_crtc); + intel_pipe_update_start(intel_crtc); if (modeset) return; @@ -13629,8 +13995,7 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc, { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - if (crtc->state->active) - intel_pipe_update_end(intel_crtc); + intel_pipe_update_end(intel_crtc); } /** @@ -13707,7 +14072,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, drm_universal_plane_init(dev, &primary->base, 0, &intel_plane_funcs, intel_primary_formats, num_formats, - DRM_PLANE_TYPE_PRIMARY); + DRM_PLANE_TYPE_PRIMARY, NULL); if (INTEL_INFO(dev)->gen >= 4) intel_create_rotation_property(dev, primary); @@ -13859,7 +14224,7 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, &intel_plane_funcs, intel_cursor_formats, ARRAY_SIZE(intel_cursor_formats), - DRM_PLANE_TYPE_CURSOR); + DRM_PLANE_TYPE_CURSOR, NULL); if (INTEL_INFO(dev)->gen >= 4) { if (!dev->mode_config.rotation_property) @@ -13936,7 +14301,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) goto fail; ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, primary, - cursor, &intel_crtc_funcs); + cursor, &intel_crtc_funcs, NULL); if (ret) goto fail; @@ -14062,7 +14427,14 @@ static bool intel_crt_present(struct drm_device *dev) if (IS_CHERRYVIEW(dev)) return false; - if (IS_VALLEYVIEW(dev) && !dev_priv->vbt.int_crt_support) + if (HAS_PCH_LPT_H(dev) && I915_READ(SFUSE_STRAP) & SFUSE_STRAP_CRT_DISABLED) + return false; + + /* DDI E can't be used if DDI A requires 4 lanes */ + if (HAS_DDI(dev) && I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) + return false; + + if (!dev_priv->vbt.int_crt_support) return false; return true; @@ -14098,7 +14470,7 @@ static void intel_setup_outputs(struct drm_device *dev) */ found = I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED; /* WaIgnoreDDIAStrap: skl */ - if (found || IS_SKYLAKE(dev)) + if (found || IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) intel_ddi_init(dev, PORT_A); /* DDI B, C and D detection is indicated by the SFUSE_STRAP @@ -14114,7 +14486,7 @@ static void intel_setup_outputs(struct drm_device *dev) /* * On SKL we don't have a way to detect DDI-E so we rely on VBT. */ - if (IS_SKYLAKE(dev) && + if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) && (dev_priv->vbt.ddi_port_info[PORT_E].supports_dp || dev_priv->vbt.ddi_port_info[PORT_E].supports_dvi || dev_priv->vbt.ddi_port_info[PORT_E].supports_hdmi)) @@ -14129,7 +14501,7 @@ static void intel_setup_outputs(struct drm_device *dev) if (I915_READ(PCH_HDMIB) & SDVO_DETECTED) { /* PCH SDVOB multiplex with HDMIB */ - found = intel_sdvo_init(dev, PCH_SDVOB, true); + found = intel_sdvo_init(dev, PCH_SDVOB, PORT_B); if (!found) intel_hdmi_init(dev, PCH_HDMIB, PORT_B); if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED)) @@ -14147,7 +14519,7 @@ 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)) { + } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { /* * The DP_DETECTED bit is the latched state of the DDC * SDA pin at boot. However since eDP doesn't require DDC @@ -14185,7 +14557,7 @@ static void intel_setup_outputs(struct drm_device *dev) if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) { DRM_DEBUG_KMS("probing SDVOB\n"); - found = intel_sdvo_init(dev, GEN3_SDVOB, true); + found = intel_sdvo_init(dev, GEN3_SDVOB, PORT_B); if (!found && IS_G4X(dev)) { DRM_DEBUG_KMS("probing HDMI on SDVOB\n"); intel_hdmi_init(dev, GEN4_HDMIB, PORT_B); @@ -14199,7 +14571,7 @@ static void intel_setup_outputs(struct drm_device *dev) if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) { DRM_DEBUG_KMS("probing SDVOC\n"); - found = intel_sdvo_init(dev, GEN3_SDVOC, false); + found = intel_sdvo_init(dev, GEN3_SDVOC, PORT_C); } if (!found && (I915_READ(GEN3_SDVOC) & SDVO_DETECTED)) { @@ -14296,7 +14668,7 @@ u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier, * pixels and 32K bytes." */ return min(8192*drm_format_plane_cpp(pixel_format, 0), 32768); - } else if (gen >= 5 && !IS_VALLEYVIEW(dev)) { + } else if (gen >= 5 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) { return 32*1024; } else if (gen >= 4) { if (fb_modifier == I915_FORMAT_MOD_X_TILED) @@ -14400,7 +14772,8 @@ static int intel_framebuffer_init(struct drm_device *dev, } break; case DRM_FORMAT_ABGR8888: - if (!IS_VALLEYVIEW(dev) && INTEL_INFO(dev)->gen < 9) { + if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && + INTEL_INFO(dev)->gen < 9) { DRM_DEBUG("unsupported pixel format: %s\n", drm_get_format_name(mode_cmd->pixel_format)); return -EINVAL; @@ -14416,7 +14789,7 @@ static int intel_framebuffer_init(struct drm_device *dev, } break; case DRM_FORMAT_ABGR2101010: - if (!IS_VALLEYVIEW(dev)) { + if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) { DRM_DEBUG("unsupported pixel format: %s\n", drm_get_format_name(mode_cmd->pixel_format)); return -EINVAL; @@ -14465,8 +14838,9 @@ static int intel_framebuffer_init(struct drm_device *dev, static struct drm_framebuffer * intel_user_framebuffer_create(struct drm_device *dev, struct drm_file *filp, - struct drm_mode_fb_cmd2 *user_mode_cmd) + const struct drm_mode_fb_cmd2 *user_mode_cmd) { + struct drm_framebuffer *fb; struct drm_i915_gem_object *obj; struct drm_mode_fb_cmd2 mode_cmd = *user_mode_cmd; @@ -14475,7 +14849,11 @@ intel_user_framebuffer_create(struct drm_device *dev, if (&obj->base == NULL) return ERR_PTR(-ENOENT); - return intel_framebuffer_create(dev, &mode_cmd, obj); + fb = intel_framebuffer_create(dev, &mode_cmd, obj); + if (IS_ERR(fb)) + drm_gem_object_unreference_unlocked(&obj->base); + + return fb; } #ifndef CONFIG_DRM_FBDEV_EMULATION @@ -14539,7 +14917,7 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.crtc_disable = ironlake_crtc_disable; dev_priv->display.update_primary_plane = ironlake_update_primary_plane; - } else if (IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { dev_priv->display.get_pipe_config = i9xx_get_pipe_config; dev_priv->display.get_initial_plane_config = i9xx_get_initial_plane_config; @@ -14560,7 +14938,7 @@ static void intel_init_display(struct drm_device *dev) } /* Returns the core display clock speed */ - if (IS_SKYLAKE(dev)) + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) dev_priv->display.get_display_clock_speed = skylake_get_display_clock_speed; else if (IS_BROXTON(dev)) @@ -14572,7 +14950,7 @@ static void intel_init_display(struct drm_device *dev) else if (IS_HASWELL(dev)) dev_priv->display.get_display_clock_speed = haswell_get_display_clock_speed; - else if (IS_VALLEYVIEW(dev)) + else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) dev_priv->display.get_display_clock_speed = valleyview_get_display_clock_speed; else if (IS_GEN5(dev)) @@ -14600,9 +14978,6 @@ static void intel_init_display(struct drm_device *dev) else if (IS_I945GM(dev) || IS_845G(dev)) dev_priv->display.get_display_clock_speed = i9xx_misc_get_display_clock_speed; - else if (IS_PINEVIEW(dev)) - dev_priv->display.get_display_clock_speed = - pnv_get_display_clock_speed; else if (IS_I915GM(dev)) dev_priv->display.get_display_clock_speed = i915gm_get_display_clock_speed; @@ -14633,7 +15008,7 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.modeset_calc_cdclk = broadwell_modeset_calc_cdclk; } - } else if (IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { dev_priv->display.modeset_commit_cdclk = valleyview_modeset_commit_cdclk; dev_priv->display.modeset_calc_cdclk = @@ -14849,7 +15224,7 @@ static void i915_disable_vga(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u8 sr1; - u32 vga_reg = i915_vgacntrl_reg(dev); + i915_reg_t vga_reg = i915_vgacntrl_reg(dev); /* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */ vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO); @@ -14965,9 +15340,6 @@ void intel_modeset_init(struct drm_device *dev) i915_disable_vga(dev); intel_setup_outputs(dev); - /* Just in case the BIOS is doing something questionable. */ - intel_fbc_disable(dev_priv); - drm_modeset_lock_all(dev); intel_modeset_setup_hw_state(dev); drm_modeset_unlock_all(dev); @@ -15054,10 +15426,9 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 reg; + i915_reg_t reg = PIPECONF(crtc->config->cpu_transcoder); /* Clear any frame start delays used for debugging left by the BIOS */ - reg = PIPECONF(crtc->config->cpu_transcoder); I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); /* restore vblank interrupts to correct state */ @@ -15124,6 +15495,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, NULL) < 0); crtc->base.state->active = crtc->active; crtc->base.enabled = crtc->active; + crtc->base.state->connector_mask = 0; /* Because we only establish the connector -> encoder -> * crtc links if something is active, this means the @@ -15211,7 +15583,7 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) void i915_redisable_vga_power_on(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - u32 vga_reg = i915_vgacntrl_reg(dev); + i915_reg_t vga_reg = i915_vgacntrl_reg(dev); if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) { DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n"); @@ -15230,10 +15602,12 @@ void i915_redisable_vga(struct drm_device *dev) * level, just check if the power well is enabled instead of trying to * follow the "don't touch the power well if we don't need it" policy * the rest of the driver uses. */ - if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_VGA)) + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_VGA)) return; i915_redisable_vga_power_on(dev); + + intel_display_power_put(dev_priv, POWER_DOMAIN_VGA); } static bool primary_get_hw_state(struct intel_plane *plane) @@ -15250,7 +15624,7 @@ static void readout_plane_state(struct intel_crtc *crtc) struct intel_plane_state *plane_state = to_intel_plane_state(primary->state); - plane_state->visible = + plane_state->visible = crtc->active && primary_get_hw_state(to_intel_plane(primary)); if (plane_state->visible) @@ -15326,7 +15700,21 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) for_each_intel_connector(dev, connector) { if (connector->get_hw_state(connector)) { connector->base.dpms = DRM_MODE_DPMS_ON; - connector->base.encoder = &connector->encoder->base; + + encoder = connector->encoder; + connector->base.encoder = &encoder->base; + + if (encoder->base.crtc && + encoder->base.crtc->state->active) { + /* + * This has to be done during hardware readout + * because anything calling .crtc_disable may + * rely on the connector_mask being accurate. + */ + encoder->base.crtc->state->connector_mask |= + 1 << drm_connector_index(&connector->base); + } + } else { connector->base.dpms = DRM_MODE_DPMS_OFF; connector->base.encoder = NULL; @@ -15411,7 +15799,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev) pll->on = false; } - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) vlv_wm_get_hw_state(dev); else if (IS_GEN9(dev)) skl_wm_get_hw_state(dev); @@ -15507,8 +15895,7 @@ void intel_modeset_gem_init(struct drm_device *dev) mutex_lock(&dev->struct_mutex); ret = intel_pin_and_fence_fb_obj(c->primary, c->primary->fb, - c->primary->state, - NULL, NULL); + c->primary->state); mutex_unlock(&dev->struct_mutex); if (ret) { DRM_ERROR("failed to pin boot fb on pipe %d\n", @@ -15535,7 +15922,7 @@ void intel_connector_unregister(struct intel_connector *intel_connector) void intel_modeset_cleanup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_connector *connector; + struct intel_connector *connector; intel_disable_gt_powersave(dev); @@ -15562,12 +15949,8 @@ void intel_modeset_cleanup(struct drm_device *dev) flush_scheduled_work(); /* destroy the backlight and sysfs files before encoders/connectors */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct intel_connector *intel_connector; - - intel_connector = to_intel_connector(connector); - intel_connector->unregister(intel_connector); - } + for_each_intel_connector(dev, connector) + connector->unregister(connector); drm_mode_config_cleanup(dev); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 78b8ec84d..4f617128e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -389,8 +389,7 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp) * We don't have power sequencer currently. * Pick one that's not used by other ports. */ - list_for_each_entry(encoder, &dev->mode_config.encoder_list, - base.head) { + for_each_intel_encoder(dev, encoder) { struct intel_dp *tmp; if (encoder->type != INTEL_OUTPUT_EDP) @@ -517,7 +516,7 @@ void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv) struct drm_device *dev = dev_priv->dev; struct intel_encoder *encoder; - if (WARN_ON(!IS_VALLEYVIEW(dev))) + if (WARN_ON(!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev))) return; /* @@ -530,7 +529,7 @@ void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv) * should use them always. */ - list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { + for_each_intel_encoder(dev, encoder) { struct intel_dp *intel_dp; if (encoder->type != INTEL_OUTPUT_EDP) @@ -541,7 +540,8 @@ void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv) } } -static u32 _pp_ctrl_reg(struct intel_dp *intel_dp) +static i915_reg_t +_pp_ctrl_reg(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); @@ -553,7 +553,8 @@ static u32 _pp_ctrl_reg(struct intel_dp *intel_dp) return VLV_PIPE_PP_CONTROL(vlv_power_sequencer_pipe(intel_dp)); } -static u32 _pp_stat_reg(struct intel_dp *intel_dp) +static i915_reg_t +_pp_stat_reg(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); @@ -580,9 +581,9 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code, pps_lock(intel_dp); - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { enum pipe pipe = vlv_power_sequencer_pipe(intel_dp); - u32 pp_ctrl_reg, pp_div_reg; + i915_reg_t pp_ctrl_reg, pp_div_reg; u32 pp_div; pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe); @@ -608,7 +609,7 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp) lockdep_assert_held(&dev_priv->pps_mutex); - if (IS_VALLEYVIEW(dev) && + if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && intel_dp->pps_pipe == INVALID_PIPE) return false; @@ -622,7 +623,7 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp) lockdep_assert_held(&dev_priv->pps_mutex); - if (IS_VALLEYVIEW(dev) && + if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && intel_dp->pps_pipe == INVALID_PIPE) return false; @@ -652,7 +653,7 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq) 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; - uint32_t ch_ctl = intel_dp->aux_ch_ctl_reg; + i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg; uint32_t status; bool done; @@ -679,7 +680,7 @@ static uint32_t i9xx_get_aux_clock_divider(struct intel_dp *intel_dp, int index) * The clock divider is based off the hrawclk, and would like to run at * 2MHz. So, take the hrawclk value and divide by 2 and use that */ - return index ? 0 : intel_hrawclk(dev) / 2; + return index ? 0 : DIV_ROUND_CLOSEST(intel_hrawclk(dev), 2); } static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index) @@ -692,10 +693,10 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index) return 0; if (intel_dig_port->port == PORT_A) { - return DIV_ROUND_UP(dev_priv->cdclk_freq, 2000); + return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000); } else { - return DIV_ROUND_UP(intel_pch_rawclk(dev), 2); + return DIV_ROUND_CLOSEST(intel_pch_rawclk(dev), 2); } } @@ -709,7 +710,7 @@ static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index) if (index) return 0; return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000); - } else if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) { + } else if (HAS_PCH_LPT_H(dev_priv)) { /* Workaround for non-ULT HSW */ switch (index) { case 0: return 63; @@ -717,7 +718,7 @@ static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index) default: return 0; } } else { - return index ? 0 : DIV_ROUND_UP(intel_pch_rawclk(dev), 2); + return index ? 0 : DIV_ROUND_CLOSEST(intel_pch_rawclk(dev), 2); } } @@ -750,7 +751,7 @@ static uint32_t i9xx_get_aux_send_ctl(struct intel_dp *intel_dp, else precharge = 5; - if (IS_BROADWELL(dev) && intel_dp->aux_ch_ctl_reg == DPA_AUX_CH_CTL) + if (IS_BROADWELL(dev) && intel_dig_port->port == PORT_A) timeout = DP_AUX_CH_CTL_TIME_OUT_600us; else timeout = DP_AUX_CH_CTL_TIME_OUT_400us; @@ -789,8 +790,7 @@ intel_dp_aux_ch(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; - uint32_t ch_ctl = intel_dp->aux_ch_ctl_reg; - uint32_t ch_data = ch_ctl + 4; + i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg; uint32_t aux_clock_divider; int i, ret, recv_bytes; uint32_t status; @@ -854,7 +854,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, for (try = 0; try < 5; try++) { /* Load the send data into the aux channel data registers */ for (i = 0; i < send_bytes; i += 4) - I915_WRITE(ch_data + i, + I915_WRITE(intel_dp->aux_ch_data_reg[i >> 2], intel_dp_pack_aux(send + i, send_bytes - i)); @@ -914,11 +914,32 @@ done: /* Unload any bytes sent back from the other side */ recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); + + /* + * By BSpec: "Message sizes of 0 or >20 are not allowed." + * We have no idea of what happened so we return -EBUSY so + * drm layer takes care for the necessary retries. + */ + if (recv_bytes == 0 || recv_bytes > 20) { + DRM_DEBUG_KMS("Forbidden recv_bytes = %d on aux transaction\n", + recv_bytes); + /* + * FIXME: This patch was created on top of a series that + * organize the retries at drm level. There EBUSY should + * also take care for 1ms wait before retrying. + * That aux retries re-org is still needed and after that is + * merged we remove this sleep from here. + */ + usleep_range(1000, 1500); + ret = -EBUSY; + goto out; + } + if (recv_bytes > recv_size) recv_bytes = recv_size; for (i = 0; i < recv_bytes; i += 4) - intel_dp_unpack_aux(I915_READ(ch_data + i), + intel_dp_unpack_aux(I915_READ(intel_dp->aux_ch_data_reg[i >> 2]), recv + i, recv_bytes - i); ret = recv_bytes; @@ -1005,96 +1026,206 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) return ret; } -static void -intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) +static i915_reg_t g4x_aux_ctl_reg(struct drm_i915_private *dev_priv, + enum port port) { - struct drm_device *dev = intel_dp_to_dev(intel_dp); - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - enum port port = intel_dig_port->port; - struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port]; - const char *name = NULL; - uint32_t porte_aux_ctl_reg = DPA_AUX_CH_CTL; - int ret; + switch (port) { + case PORT_B: + case PORT_C: + case PORT_D: + return DP_AUX_CH_CTL(port); + default: + MISSING_CASE(port); + return DP_AUX_CH_CTL(PORT_B); + } +} - /* On SKL we don't have Aux for port E so we rely on VBT to set - * a proper alternate aux channel. - */ - if (IS_SKYLAKE(dev) && port == PORT_E) { - switch (info->alternate_aux_channel) { - case DP_AUX_B: - porte_aux_ctl_reg = DPB_AUX_CH_CTL; - break; - case DP_AUX_C: - porte_aux_ctl_reg = DPC_AUX_CH_CTL; - break; - case DP_AUX_D: - porte_aux_ctl_reg = DPD_AUX_CH_CTL; - break; - case DP_AUX_A: - default: - porte_aux_ctl_reg = DPA_AUX_CH_CTL; - } +static i915_reg_t g4x_aux_data_reg(struct drm_i915_private *dev_priv, + enum port port, int index) +{ + switch (port) { + case PORT_B: + case PORT_C: + case PORT_D: + return DP_AUX_CH_DATA(port, index); + default: + MISSING_CASE(port); + return DP_AUX_CH_DATA(PORT_B, index); } +} +static i915_reg_t ilk_aux_ctl_reg(struct drm_i915_private *dev_priv, + enum port port) +{ switch (port) { case PORT_A: - intel_dp->aux_ch_ctl_reg = DPA_AUX_CH_CTL; - name = "DPDDC-A"; - break; + return DP_AUX_CH_CTL(port); case PORT_B: - intel_dp->aux_ch_ctl_reg = PCH_DPB_AUX_CH_CTL; - name = "DPDDC-B"; - break; case PORT_C: - intel_dp->aux_ch_ctl_reg = PCH_DPC_AUX_CH_CTL; - name = "DPDDC-C"; - break; case PORT_D: - intel_dp->aux_ch_ctl_reg = PCH_DPD_AUX_CH_CTL; - name = "DPDDC-D"; - break; - case PORT_E: - intel_dp->aux_ch_ctl_reg = porte_aux_ctl_reg; - name = "DPDDC-E"; - break; + return PCH_DP_AUX_CH_CTL(port); default: - BUG(); + MISSING_CASE(port); + return DP_AUX_CH_CTL(PORT_A); } +} - /* - * The AUX_CTL register is usually DP_CTL + 0x10. - * - * On Haswell and Broadwell though: - * - Both port A DDI_BUF_CTL and DDI_AUX_CTL are on the CPU - * - Port B/C/D AUX channels are on the PCH, DDI_BUF_CTL on the CPU - * - * Skylake moves AUX_CTL back next to DDI_BUF_CTL, on the CPU. - */ - if (!IS_HASWELL(dev) && !IS_BROADWELL(dev) && port != PORT_E) - intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10; +static i915_reg_t ilk_aux_data_reg(struct drm_i915_private *dev_priv, + enum port port, int index) +{ + switch (port) { + case PORT_A: + return DP_AUX_CH_DATA(port, index); + case PORT_B: + case PORT_C: + case PORT_D: + return PCH_DP_AUX_CH_DATA(port, index); + default: + MISSING_CASE(port); + return DP_AUX_CH_DATA(PORT_A, index); + } +} + +/* + * On SKL we don't have Aux for port E so we rely + * on VBT to set a proper alternate aux channel. + */ +static enum port skl_porte_aux_port(struct drm_i915_private *dev_priv) +{ + const struct ddi_vbt_port_info *info = + &dev_priv->vbt.ddi_port_info[PORT_E]; + + switch (info->alternate_aux_channel) { + case DP_AUX_A: + return PORT_A; + case DP_AUX_B: + return PORT_B; + case DP_AUX_C: + return PORT_C; + case DP_AUX_D: + return PORT_D; + default: + MISSING_CASE(info->alternate_aux_channel); + return PORT_A; + } +} + +static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv, + enum port port) +{ + if (port == PORT_E) + port = skl_porte_aux_port(dev_priv); + + switch (port) { + case PORT_A: + case PORT_B: + case PORT_C: + case PORT_D: + return DP_AUX_CH_CTL(port); + default: + MISSING_CASE(port); + return DP_AUX_CH_CTL(PORT_A); + } +} + +static i915_reg_t skl_aux_data_reg(struct drm_i915_private *dev_priv, + enum port port, int index) +{ + if (port == PORT_E) + port = skl_porte_aux_port(dev_priv); + + switch (port) { + case PORT_A: + case PORT_B: + case PORT_C: + case PORT_D: + return DP_AUX_CH_DATA(port, index); + default: + MISSING_CASE(port); + return DP_AUX_CH_DATA(PORT_A, index); + } +} + +static i915_reg_t intel_aux_ctl_reg(struct drm_i915_private *dev_priv, + enum port port) +{ + if (INTEL_INFO(dev_priv)->gen >= 9) + return skl_aux_ctl_reg(dev_priv, port); + else if (HAS_PCH_SPLIT(dev_priv)) + return ilk_aux_ctl_reg(dev_priv, port); + else + return g4x_aux_ctl_reg(dev_priv, port); +} + +static i915_reg_t intel_aux_data_reg(struct drm_i915_private *dev_priv, + enum port port, int index) +{ + if (INTEL_INFO(dev_priv)->gen >= 9) + return skl_aux_data_reg(dev_priv, port, index); + else if (HAS_PCH_SPLIT(dev_priv)) + return ilk_aux_data_reg(dev_priv, port, index); + else + return g4x_aux_data_reg(dev_priv, port, index); +} + +static void intel_aux_reg_init(struct intel_dp *intel_dp) +{ + struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); + enum port port = dp_to_dig_port(intel_dp)->port; + int i; + + intel_dp->aux_ch_ctl_reg = intel_aux_ctl_reg(dev_priv, port); + for (i = 0; i < ARRAY_SIZE(intel_dp->aux_ch_data_reg); i++) + intel_dp->aux_ch_data_reg[i] = intel_aux_data_reg(dev_priv, port, i); +} + +static void +intel_dp_aux_fini(struct intel_dp *intel_dp) +{ + drm_dp_aux_unregister(&intel_dp->aux); + kfree(intel_dp->aux.name); +} + +static int +intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) +{ + struct drm_device *dev = intel_dp_to_dev(intel_dp); + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + enum port port = intel_dig_port->port; + int ret; + + intel_aux_reg_init(intel_dp); + + intel_dp->aux.name = kasprintf(GFP_KERNEL, "DPDDC-%c", port_name(port)); + if (!intel_dp->aux.name) + return -ENOMEM; - intel_dp->aux.name = name; intel_dp->aux.dev = dev->dev; intel_dp->aux.transfer = intel_dp_aux_transfer; - DRM_DEBUG_KMS("registering %s bus for %s\n", name, + DRM_DEBUG_KMS("registering %s bus for %s\n", + intel_dp->aux.name, connector->base.kdev->kobj.name); ret = drm_dp_aux_register(&intel_dp->aux); if (ret < 0) { DRM_ERROR("drm_dp_aux_register() for %s failed (%d)\n", - name, ret); - return; + intel_dp->aux.name, ret); + kfree(intel_dp->aux.name); + return ret; } ret = sysfs_create_link(&connector->base.kdev->kobj, &intel_dp->aux.ddc.dev.kobj, intel_dp->aux.ddc.dev.kobj.name); if (ret < 0) { - DRM_ERROR("sysfs_create_link() for %s failed (%d)\n", name, ret); - drm_dp_aux_unregister(&intel_dp->aux); + DRM_ERROR("sysfs_create_link() for %s failed (%d)\n", + intel_dp->aux.name, ret); + intel_dp_aux_fini(intel_dp); + return ret; } + + return 0; } static void @@ -1186,10 +1317,13 @@ intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates) return (intel_dp_max_link_bw(intel_dp) >> 3) + 1; } -static bool intel_dp_source_supports_hbr2(struct drm_device *dev) +bool intel_dp_source_supports_hbr2(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; + /* WaDisableHBR2:skl */ - if (IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) + if (IS_SKL_REVID(dev, 0, SKL_REVID_B0)) return false; if ((IS_HASWELL(dev) && !IS_HSW_ULX(dev)) || IS_BROADWELL(dev) || @@ -1200,14 +1334,16 @@ static bool intel_dp_source_supports_hbr2(struct drm_device *dev) } static int -intel_dp_source_rates(struct drm_device *dev, const int **source_rates) +intel_dp_source_rates(struct intel_dp *intel_dp, const int **source_rates) { + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; int size; if (IS_BROXTON(dev)) { *source_rates = bxt_rates; size = ARRAY_SIZE(bxt_rates); - } else if (IS_SKYLAKE(dev)) { + } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { *source_rates = skl_rates; size = ARRAY_SIZE(skl_rates); } else { @@ -1216,7 +1352,7 @@ intel_dp_source_rates(struct drm_device *dev, const int **source_rates) } /* This depends on the fact that 5.4 is last value in the array */ - if (!intel_dp_source_supports_hbr2(dev)) + if (!intel_dp_source_supports_hbr2(intel_dp)) size--; return size; @@ -1281,12 +1417,11 @@ static int intersect_rates(const int *source_rates, int source_len, static int intel_dp_common_rates(struct intel_dp *intel_dp, int *common_rates) { - struct drm_device *dev = intel_dp_to_dev(intel_dp); const int *source_rates, *sink_rates; int source_len, sink_len; sink_len = intel_dp_sink_rates(intel_dp, &sink_rates); - source_len = intel_dp_source_rates(dev, &source_rates); + source_len = intel_dp_source_rates(intel_dp, &source_rates); return intersect_rates(source_rates, source_len, sink_rates, sink_len, @@ -1311,7 +1446,6 @@ static void snprintf_int_array(char *str, size_t len, static void intel_dp_print_rates(struct intel_dp *intel_dp) { - struct drm_device *dev = intel_dp_to_dev(intel_dp); const int *source_rates, *sink_rates; int source_len, sink_len, common_len; int common_rates[DP_MAX_SUPPORTED_RATES]; @@ -1320,7 +1454,7 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp) if ((drm_debug & DRM_UT_KMS) == 0) return; - source_len = intel_dp_source_rates(dev, &source_rates); + source_len = intel_dp_source_rates(intel_dp, &source_rates); snprintf_int_array(str, sizeof(str), source_rates, source_len); DRM_DEBUG_KMS("source rates: %s\n", str); @@ -1362,8 +1496,8 @@ int intel_dp_rate_select(struct intel_dp *intel_dp, int rate) return rate_to_index(rate, intel_dp->sink_rates); } -static void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, - uint8_t *link_bw, uint8_t *rate_select) +void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, + uint8_t *link_bw, uint8_t *rate_select) { if (intel_dp->num_sink_rates) { *link_bw = 0; @@ -1423,7 +1557,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, return ret; } - if (!HAS_PCH_SPLIT(dev)) + if (HAS_GMCH_DISPLAY(dev)) intel_gmch_panel_fitting(intel_crtc, pipe_config, intel_connector->panel.fitting_mode); else @@ -1527,7 +1661,7 @@ found: &pipe_config->dp_m2_n2); } - if (IS_SKYLAKE(dev) && is_edp(intel_dp)) + if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) && is_edp(intel_dp)) skl_edp_set_pll_config(pipe_config); else if (IS_BROXTON(dev)) /* handled in ddi */; @@ -1539,37 +1673,6 @@ found: return true; } -static void ironlake_set_pll_cpu_edp(struct intel_dp *intel_dp) -{ - struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc); - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - u32 dpa_ctl; - - DRM_DEBUG_KMS("eDP PLL enable for clock %d\n", - crtc->config->port_clock); - dpa_ctl = I915_READ(DP_A); - dpa_ctl &= ~DP_PLL_FREQ_MASK; - - if (crtc->config->port_clock == 162000) { - /* For a long time we've carried around a ILK-DevA w/a for the - * 160MHz clock. If we're really unlucky, it's still required. - */ - DRM_DEBUG_KMS("160MHz cpu eDP clock, might need ilk devA w/a\n"); - dpa_ctl |= DP_PLL_FREQ_160MHZ; - intel_dp->DP |= DP_PLL_FREQ_160MHZ; - } else { - dpa_ctl |= DP_PLL_FREQ_270MHZ; - intel_dp->DP |= DP_PLL_FREQ_270MHZ; - } - - I915_WRITE(DP_A, dpa_ctl); - - POSTING_READ(DP_A); - udelay(500); -} - void intel_dp_set_link_params(struct intel_dp *intel_dp, const struct intel_crtc_state *pipe_config) { @@ -1614,9 +1717,6 @@ static void intel_dp_prepare(struct intel_encoder *encoder) intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; intel_dp->DP |= DP_PORT_WIDTH(crtc->config->lane_count); - if (crtc->config->has_audio) - intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE; - /* Split out the IBX/CPU vs CPT settings */ if (IS_GEN7(dev) && port == PORT_A) { @@ -1643,7 +1743,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder) I915_WRITE(TRANS_DP_CTL(crtc->pipe), trans_dp); } else { if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) && - crtc->config->limited_color_range) + !IS_CHERRYVIEW(dev) && crtc->config->limited_color_range) intel_dp->DP |= DP_COLOR_RANGE_16_235; if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) @@ -1677,7 +1777,7 @@ static void wait_panel_status(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; + i915_reg_t pp_stat_reg, pp_ctrl_reg; lockdep_assert_held(&dev_priv->pps_mutex); @@ -1767,7 +1867,7 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = dev->dev_private; enum intel_display_power_domain power_domain; u32 pp; - u32 pp_stat_reg, pp_ctrl_reg; + i915_reg_t pp_stat_reg, pp_ctrl_reg; bool need_to_disable = !intel_dp->want_panel_vdd; lockdep_assert_held(&dev_priv->pps_mutex); @@ -1843,7 +1943,7 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp) struct intel_encoder *intel_encoder = &intel_dig_port->base; enum intel_display_power_domain power_domain; u32 pp; - u32 pp_stat_reg, pp_ctrl_reg; + i915_reg_t pp_stat_reg, pp_ctrl_reg; lockdep_assert_held(&dev_priv->pps_mutex); @@ -1930,7 +2030,7 @@ static void edp_panel_on(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; - u32 pp_ctrl_reg; + i915_reg_t pp_ctrl_reg; lockdep_assert_held(&dev_priv->pps_mutex); @@ -1992,7 +2092,7 @@ static void edp_panel_off(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = dev->dev_private; enum intel_display_power_domain power_domain; u32 pp; - u32 pp_ctrl_reg; + i915_reg_t pp_ctrl_reg; lockdep_assert_held(&dev_priv->pps_mutex); @@ -2043,7 +2143,7 @@ static void _intel_edp_backlight_on(struct intel_dp *intel_dp) struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 pp; - u32 pp_ctrl_reg; + i915_reg_t pp_ctrl_reg; /* * If we enable the backlight right away following a panel power @@ -2084,7 +2184,7 @@ static void _intel_edp_backlight_off(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; - u32 pp_ctrl_reg; + i915_reg_t pp_ctrl_reg; if (!is_edp(intel_dp)) return; @@ -2143,27 +2243,61 @@ static void intel_edp_backlight_power(struct intel_connector *connector, _intel_edp_backlight_off(intel_dp); } +static const char *state_string(bool enabled) +{ + return enabled ? "on" : "off"; +} + +static void assert_dp_port(struct intel_dp *intel_dp, bool state) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); + bool cur_state = I915_READ(intel_dp->output_reg) & DP_PORT_EN; + + I915_STATE_WARN(cur_state != state, + "DP port %c state assertion failure (expected %s, current %s)\n", + port_name(dig_port->port), + state_string(state), state_string(cur_state)); +} +#define assert_dp_port_disabled(d) assert_dp_port((d), false) + +static void assert_edp_pll(struct drm_i915_private *dev_priv, bool state) +{ + bool cur_state = I915_READ(DP_A) & DP_PLL_ENABLE; + + I915_STATE_WARN(cur_state != state, + "eDP PLL state assertion failure (expected %s, current %s)\n", + state_string(state), state_string(cur_state)); +} +#define assert_edp_pll_enabled(d) assert_edp_pll((d), true) +#define assert_edp_pll_disabled(d) assert_edp_pll((d), false) + static void ironlake_edp_pll_on(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 = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - u32 dpa_ctl; + struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - assert_pipe_disabled(dev_priv, - to_intel_crtc(crtc)->pipe); + assert_pipe_disabled(dev_priv, crtc->pipe); + assert_dp_port_disabled(intel_dp); + assert_edp_pll_disabled(dev_priv); + + DRM_DEBUG_KMS("enabling eDP PLL for clock %d\n", + crtc->config->port_clock); + + intel_dp->DP &= ~DP_PLL_FREQ_MASK; + + if (crtc->config->port_clock == 162000) + intel_dp->DP |= DP_PLL_FREQ_162MHZ; + else + intel_dp->DP |= DP_PLL_FREQ_270MHZ; + + I915_WRITE(DP_A, intel_dp->DP); + POSTING_READ(DP_A); + udelay(500); - DRM_DEBUG_KMS("\n"); - dpa_ctl = I915_READ(DP_A); - WARN(dpa_ctl & DP_PLL_ENABLE, "dp pll on, should be off\n"); - WARN(dpa_ctl & DP_PORT_EN, "dp port still on, should be off\n"); - - /* We don't adjust intel_dp->DP while tearing down the link, to - * facilitate link retraining (e.g. after hotplug). Hence clear all - * enable bits here to ensure that we don't enable too much. */ - intel_dp->DP &= ~(DP_PORT_EN | DP_AUDIO_OUTPUT_ENABLE); intel_dp->DP |= DP_PLL_ENABLE; + I915_WRITE(DP_A, intel_dp->DP); POSTING_READ(DP_A); udelay(200); @@ -2172,24 +2306,18 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp) static void ironlake_edp_pll_off(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 = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - u32 dpa_ctl; + struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + + assert_pipe_disabled(dev_priv, crtc->pipe); + assert_dp_port_disabled(intel_dp); + assert_edp_pll_enabled(dev_priv); - assert_pipe_disabled(dev_priv, - to_intel_crtc(crtc)->pipe); + DRM_DEBUG_KMS("disabling eDP PLL\n"); - dpa_ctl = I915_READ(DP_A); - WARN((dpa_ctl & DP_PLL_ENABLE) == 0, - "dp pll off, should be on\n"); - WARN(dpa_ctl & DP_PORT_EN, "dp port still on, should be off\n"); + intel_dp->DP &= ~DP_PLL_ENABLE; - /* We can't rely on the value tracked for the DP register in - * intel_dp->DP because link_down must not change that (otherwise link - * re-training will fail. */ - dpa_ctl &= ~DP_PLL_ENABLE; - I915_WRITE(DP_A, dpa_ctl); + I915_WRITE(DP_A, intel_dp->DP); POSTING_READ(DP_A); udelay(200); } @@ -2234,15 +2362,18 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = dev->dev_private; enum intel_display_power_domain power_domain; u32 tmp; + bool ret; power_domain = intel_display_port_power_domain(encoder); - if (!intel_display_power_is_enabled(dev_priv, power_domain)) + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; + ret = false; + tmp = I915_READ(intel_dp->output_reg); if (!(tmp & DP_PORT_EN)) - return false; + goto out; if (IS_GEN7(dev) && port == PORT_A) { *pipe = PORT_TO_PIPE_CPT(tmp); @@ -2253,19 +2384,26 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder, u32 trans_dp = I915_READ(TRANS_DP_CTL(p)); if (TRANS_DP_PIPE_TO_PORT(trans_dp) == port) { *pipe = p; - return true; + ret = true; + + goto out; } } DRM_DEBUG_KMS("No pipe for dp port 0x%x found\n", - intel_dp->output_reg); + i915_mmio_reg_offset(intel_dp->output_reg)); } else if (IS_CHERRYVIEW(dev)) { *pipe = DP_PORT_TO_PIPE_CHV(tmp); } else { *pipe = PORT_TO_PIPE(tmp); } - return true; + ret = true; + +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } static void intel_dp_get_config(struct intel_encoder *encoder, @@ -2310,7 +2448,7 @@ static void intel_dp_get_config(struct intel_encoder *encoder, pipe_config->base.adjusted_mode.flags |= flags; if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) && - tmp & DP_COLOR_RANGE_16_235) + !IS_CHERRYVIEW(dev) && tmp & DP_COLOR_RANGE_16_235) pipe_config->limited_color_range = true; pipe_config->has_dp_encoder = true; @@ -2321,7 +2459,7 @@ static void intel_dp_get_config(struct intel_encoder *encoder, intel_dp_get_m_n(crtc, pipe_config); if (port == PORT_A) { - if ((I915_READ(DP_A) & DP_PLL_FREQ_MASK) == DP_PLL_FREQ_160MHZ) + if ((I915_READ(DP_A) & DP_PLL_FREQ_MASK) == DP_PLL_FREQ_162MHZ) pipe_config->port_clock = 162000; else pipe_config->port_clock = 270000; @@ -2386,6 +2524,8 @@ static void ilk_post_disable_dp(struct intel_encoder *encoder) enum port port = dp_to_dig_port(intel_dp)->port; intel_dp_link_down(intel_dp); + + /* Only ilk+ has port A */ if (port == PORT_A) ironlake_edp_pll_off(intel_dp); } @@ -2545,6 +2685,8 @@ static void intel_dp_enable_port(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_crtc *crtc = + to_intel_crtc(dp_to_dig_port(intel_dp)->base.base.crtc); /* enable with pattern 1 (as per spec) */ _intel_dp_set_link_train(intel_dp, &intel_dp->DP, @@ -2560,6 +2702,8 @@ static void intel_dp_enable_port(struct intel_dp *intel_dp) * fail when the power sequencer is freshly used for this port. */ intel_dp->DP |= DP_PORT_EN; + if (crtc->config->has_audio) + intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE; I915_WRITE(intel_dp->output_reg, intel_dp->DP); POSTING_READ(intel_dp->output_reg); @@ -2572,24 +2716,49 @@ static void intel_enable_dp(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); uint32_t dp_reg = I915_READ(intel_dp->output_reg); + enum port port = dp_to_dig_port(intel_dp)->port; + enum pipe pipe = crtc->pipe; if (WARN_ON(dp_reg & DP_PORT_EN)) return; pps_lock(intel_dp); - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) vlv_init_panel_power_sequencer(intel_dp); + /* + * We get an occasional spurious underrun between the port + * enable and vdd enable, when enabling port A eDP. + * + * FIXME: Not sure if this applies to (PCH) port D eDP as well + */ + if (port == PORT_A) + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); + intel_dp_enable_port(intel_dp); + if (port == PORT_A && IS_GEN5(dev_priv)) { + /* + * Underrun reporting for the other pipe was disabled in + * g4x_pre_enable_dp(). The eDP PLL and port have now been + * enabled, so it's now safe to re-enable underrun reporting. + */ + intel_wait_for_vblank_if_active(dev_priv->dev, !pipe); + intel_set_cpu_fifo_underrun_reporting(dev_priv, !pipe, true); + intel_set_pch_fifo_underrun_reporting(dev_priv, !pipe, true); + } + edp_panel_vdd_on(intel_dp); edp_panel_on(intel_dp); edp_panel_vdd_off(intel_dp, true); + if (port == PORT_A) + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); + pps_unlock(intel_dp); - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { unsigned int lane_mask = 0x0; if (IS_CHERRYVIEW(dev)) @@ -2605,7 +2774,7 @@ static void intel_enable_dp(struct intel_encoder *encoder) if (crtc->config->has_audio) { DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n", - pipe_name(crtc->pipe)); + pipe_name(pipe)); intel_audio_codec_enable(encoder); } } @@ -2628,16 +2797,29 @@ static void vlv_enable_dp(struct intel_encoder *encoder) static void g4x_pre_enable_dp(struct intel_encoder *encoder) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); - struct intel_digital_port *dport = dp_to_dig_port(intel_dp); + enum port port = dp_to_dig_port(intel_dp)->port; + enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe; intel_dp_prepare(encoder); + if (port == PORT_A && IS_GEN5(dev_priv)) { + /* + * We get FIFO underruns on the other pipe when + * enabling the CPU eDP PLL, and when enabling CPU + * eDP port. We could potentially avoid the PLL + * underrun with a vblank wait just prior to enabling + * the PLL, but that doesn't appear to help the port + * enable case. Just sweep it all under the rug. + */ + intel_set_cpu_fifo_underrun_reporting(dev_priv, !pipe, false); + intel_set_pch_fifo_underrun_reporting(dev_priv, !pipe, false); + } + /* Only ilk+ has port A */ - if (dport->port == PORT_A) { - ironlake_set_pll_cpu_edp(intel_dp); + if (port == PORT_A) ironlake_edp_pll_on(intel_dp); - } } static void vlv_detach_power_sequencer(struct intel_dp *intel_dp) @@ -2645,7 +2827,7 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp) struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = intel_dig_port->base.base.dev->dev_private; enum pipe pipe = intel_dp->pps_pipe; - int pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe); + i915_reg_t pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe); edp_panel_vdd_off_sync(intel_dp); @@ -2677,8 +2859,7 @@ static void vlv_steal_power_sequencer(struct drm_device *dev, if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B)) return; - list_for_each_entry(encoder, &dev->mode_config.encoder_list, - base.head) { + for_each_intel_encoder(dev, encoder) { struct intel_dp *intel_dp; enum port port; @@ -3043,7 +3224,7 @@ intel_dp_dpcd_read_wake(struct drm_dp_aux *aux, unsigned int offset, * Fetch AUX CH registers 0x202 - 0x207 which contain * link status information */ -static bool +bool intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]) { return intel_dp_dpcd_read_wake(&intel_dp->aux, @@ -3053,7 +3234,7 @@ intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_ } /* These are source-specific values. */ -static uint8_t +uint8_t intel_dp_voltage_max(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); @@ -3066,7 +3247,7 @@ intel_dp_voltage_max(struct intel_dp *intel_dp) if (dev_priv->edp_low_vswing && port == PORT_A) return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; - } else if (IS_VALLEYVIEW(dev)) + } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; else if (IS_GEN7(dev) && port == PORT_A) return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; @@ -3076,7 +3257,7 @@ intel_dp_voltage_max(struct intel_dp *intel_dp) return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; } -static uint8_t +uint8_t intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) { struct drm_device *dev = intel_dp_to_dev(intel_dp); @@ -3107,7 +3288,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) default: return DP_TRAIN_PRE_EMPH_LEVEL_0; } - } else if (IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: return DP_TRAIN_PRE_EMPH_LEVEL_3; @@ -3418,38 +3599,6 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp) return 0; } -static void -intel_get_adjust_train(struct intel_dp *intel_dp, - const uint8_t link_status[DP_LINK_STATUS_SIZE]) -{ - uint8_t v = 0; - uint8_t p = 0; - int lane; - uint8_t voltage_max; - uint8_t preemph_max; - - for (lane = 0; lane < intel_dp->lane_count; lane++) { - uint8_t this_v = drm_dp_get_adjust_request_voltage(link_status, lane); - uint8_t this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane); - - if (this_v > v) - v = this_v; - if (this_p > p) - p = this_p; - } - - voltage_max = intel_dp_voltage_max(intel_dp); - if (v >= voltage_max) - v = voltage_max | DP_TRAIN_MAX_SWING_REACHED; - - preemph_max = intel_dp_pre_emphasis_max(intel_dp, v); - if (p >= preemph_max) - p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; - - for (lane = 0; lane < 4; lane++) - intel_dp->train_set[lane] = v | p; -} - static uint32_t gen4_signal_levels(uint8_t train_set) { @@ -3547,13 +3696,13 @@ gen7_edp_signal_levels(uint8_t train_set) } } -/* Properly updates "DP" with the correct signal levels. */ -static void -intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) +void +intel_dp_set_signal_levels(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); enum port port = intel_dig_port->port; struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); uint32_t signal_levels, mask = 0; uint8_t train_set = intel_dp->train_set[0]; @@ -3588,74 +3737,27 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT); - *DP = (*DP & ~mask) | signal_levels; -} - -static bool -intel_dp_set_link_train(struct intel_dp *intel_dp, - uint32_t *DP, - uint8_t dp_train_pat) -{ - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_i915_private *dev_priv = - to_i915(intel_dig_port->base.base.dev); - uint8_t buf[sizeof(intel_dp->train_set) + 1]; - int ret, len; - - _intel_dp_set_link_train(intel_dp, DP, dp_train_pat); + intel_dp->DP = (intel_dp->DP & ~mask) | signal_levels; - I915_WRITE(intel_dp->output_reg, *DP); + I915_WRITE(intel_dp->output_reg, intel_dp->DP); POSTING_READ(intel_dp->output_reg); - - buf[0] = 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 = drm_dp_dpcd_write(&intel_dp->aux, 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) -{ - if (!intel_dp->train_set_valid) - 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]) +void +intel_dp_program_link_training_pattern(struct intel_dp *intel_dp, + uint8_t dp_train_pat) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); - int ret; - intel_get_adjust_train(intel_dp, link_status); - intel_dp_set_signal_levels(intel_dp, DP); + _intel_dp_set_link_train(intel_dp, &intel_dp->DP, dp_train_pat); - I915_WRITE(intel_dp->output_reg, *DP); + I915_WRITE(intel_dp->output_reg, intel_dp->DP); POSTING_READ(intel_dp->output_reg); - - ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET, - intel_dp->train_set, intel_dp->lane_count); - - return ret == intel_dp->lane_count; } -static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp) +void intel_dp_set_idle_link_train(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; @@ -3686,232 +3788,6 @@ static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp) DRM_ERROR("Timed out waiting for DP idle patterns\n"); } -/* Enable corresponding port and start training pattern 1 */ -static void -intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp) -{ - struct drm_encoder *encoder = &dp_to_dig_port(intel_dp)->base.base; - struct drm_device *dev = encoder->dev; - int i; - uint8_t voltage; - int voltage_tries, loop_tries; - uint32_t DP = intel_dp->DP; - uint8_t link_config[2]; - uint8_t link_bw, rate_select; - - if (HAS_DDI(dev)) - intel_ddi_prepare_link_retrain(encoder); - - intel_dp_compute_rate(intel_dp, intel_dp->link_rate, - &link_bw, &rate_select); - - /* Write the link configuration data */ - link_config[0] = 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; - drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2); - if (intel_dp->num_sink_rates) - drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET, - &rate_select, 1); - - link_config[0] = 0; - link_config[1] = DP_SET_ANSI_8B10B; - drm_dp_dpcd_write(&intel_dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2); - - 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; - } - - voltage = 0xff; - voltage_tries = 0; - loop_tries = 0; - for (;;) { - uint8_t link_status[DP_LINK_STATUS_SIZE]; - - drm_dp_link_train_clock_recovery_delay(intel_dp->dpcd); - if (!intel_dp_get_link_status(intel_dp, link_status)) { - DRM_ERROR("failed to get link status\n"); - break; - } - - if (drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) { - DRM_DEBUG_KMS("clock recovery OK\n"); - break; - } - - /* - * if we used previously trained voltage and pre-emphasis values - * and we don't get clock recovery, reset link training values - */ - if (intel_dp->train_set_valid) { - DRM_DEBUG_KMS("clock recovery not ok, reset"); - /* clear the flag as we are not reusing train set */ - intel_dp->train_set_valid = false; - 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; - } - continue; - } - - /* Check to see if we've tried the max voltage */ - for (i = 0; i < intel_dp->lane_count; i++) - if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) - break; - if (i == intel_dp->lane_count) { - ++loop_tries; - if (loop_tries == 5) { - DRM_ERROR("too many full retries, give up\n"); - break; - } - intel_dp_reset_link_train(intel_dp, &DP, - DP_TRAINING_PATTERN_1 | - DP_LINK_SCRAMBLING_DISABLE); - voltage_tries = 0; - continue; - } - - /* Check to see if we've tried the same voltage 5 times */ - 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"); - 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; - } - } - - intel_dp->DP = DP; -} - -static void -intel_dp_link_training_channel_equalization(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; - bool channel_eq = false; - int tries, cr_tries; - uint32_t DP = intel_dp->DP; - uint32_t training_pattern = DP_TRAINING_PATTERN_2; - - /* - * Training Pattern 3 for HBR2 or 1.2 devices that support it. - * - * Intel platforms that support HBR2 also support TPS3. TPS3 support is - * also mandatory for downstream devices that support HBR2. - * - * Due to WaDisableHBR2 SKL < B0 is the only exception where TPS3 is - * supported but still not enabled. - */ - if (intel_dp_source_supports_hbr2(dev) && - drm_dp_tps3_supported(intel_dp->dpcd)) - training_pattern = DP_TRAINING_PATTERN_3; - else if (intel_dp->link_rate == 540000) - DRM_ERROR("5.4 Gbps link rate without HBR2/TPS3 support\n"); - - /* channel equalization */ - if (!intel_dp_set_link_train(intel_dp, &DP, - training_pattern | - 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]; - - if (cr_tries > 5) { - DRM_ERROR("failed to train DP, aborting\n"); - 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"); - break; - } - - /* Make sure clock is still ok */ - if (!drm_dp_clock_recovery_ok(link_status, - intel_dp->lane_count)) { - intel_dp->train_set_valid = false; - intel_dp_link_training_clock_recovery(intel_dp); - intel_dp_set_link_train(intel_dp, &DP, - training_pattern | - DP_LINK_SCRAMBLING_DISABLE); - cr_tries++; - continue; - } - - if (drm_dp_channel_eq_ok(link_status, - intel_dp->lane_count)) { - channel_eq = true; - break; - } - - /* Try 5 times, then try clock recovery if that fails */ - if (tries > 5) { - intel_dp->train_set_valid = false; - intel_dp_link_training_clock_recovery(intel_dp); - intel_dp_set_link_train(intel_dp, &DP, - training_pattern | - 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; - } - ++tries; - } - - intel_dp_set_idle_link_train(intel_dp); - - intel_dp->DP = DP; - - if (channel_eq) { - intel_dp->train_set_valid = true; - DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n"); - } -} - -void intel_dp_stop_link_train(struct intel_dp *intel_dp) -{ - intel_dp_set_link_train(intel_dp, &intel_dp->DP, - DP_TRAINING_PATTERN_DISABLE); -} - -void -intel_dp_start_link_train(struct intel_dp *intel_dp) -{ - intel_dp_link_training_clock_recovery(intel_dp); - intel_dp_link_training_channel_equalization(intel_dp); -} - static void intel_dp_link_down(struct intel_dp *intel_dp) { @@ -3954,6 +3830,13 @@ intel_dp_link_down(struct intel_dp *intel_dp) * matching HDMI port to be enabled on transcoder A. */ if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B && port != PORT_A) { + /* + * We get CPU/PCH FIFO underruns on the other pipe when + * doing the workaround. Sweep them under the rug. + */ + intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, false); + intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false); + /* always enable with pattern 1 (as per spec) */ DP &= ~(DP_PIPEB_SELECT | DP_LINK_TRAIN_MASK); DP |= DP_PORT_EN | DP_LINK_TRAIN_PAT_1; @@ -3963,9 +3846,15 @@ intel_dp_link_down(struct intel_dp *intel_dp) DP &= ~DP_PORT_EN; I915_WRITE(intel_dp->output_reg, DP); POSTING_READ(intel_dp->output_reg); + + intel_wait_for_vblank_if_active(dev_priv->dev, PIPE_A); + intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true); + intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true); } msleep(intel_dp->panel_power_down_delay); + + intel_dp->DP = DP; } static bool @@ -4013,7 +3902,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) } DRM_DEBUG_KMS("Display Port TPS3 support: source %s, sink %s\n", - yesno(intel_dp_source_supports_hbr2(dev)), + yesno(intel_dp_source_supports_hbr2(intel_dp)), yesno(drm_dp_tps3_supported(intel_dp->dpcd))); /* Intermediate frequency support */ @@ -4103,9 +3992,12 @@ intel_dp_probe_mst(struct intel_dp *intel_dp) static int intel_dp_sink_crc_stop(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 intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc); u8 buf; int ret = 0; + int count = 0; + int attempts = 10; if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0) { DRM_DEBUG_KMS("Sink CRC couldn't be stopped properly\n"); @@ -4120,7 +4012,22 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp) goto out; } - intel_dp->sink_crc.started = false; + do { + intel_wait_for_vblank(dev, intel_crtc->pipe); + + if (drm_dp_dpcd_readb(&intel_dp->aux, + DP_TEST_SINK_MISC, &buf) < 0) { + ret = -EIO; + goto out; + } + count = buf & DP_TEST_COUNT_MASK; + } while (--attempts && count); + + if (attempts == 0) { + DRM_ERROR("TIMEOUT: Sink CRC counter is not zeroed\n"); + ret = -ETIMEDOUT; + } + out: hsw_enable_ips(intel_crtc); return ret; @@ -4129,27 +4036,26 @@ static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp) static int intel_dp_sink_crc_start(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 intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc); u8 buf; int ret; - if (intel_dp->sink_crc.started) { - ret = intel_dp_sink_crc_stop(intel_dp); - if (ret) - return ret; - } - if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, &buf) < 0) return -EIO; if (!(buf & DP_TEST_CRC_SUPPORTED)) return -ENOTTY; - intel_dp->sink_crc.last_count = buf & DP_TEST_COUNT_MASK; - if (drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK, &buf) < 0) return -EIO; + if (buf & DP_TEST_SINK_START) { + ret = intel_dp_sink_crc_stop(intel_dp); + if (ret) + return ret; + } + hsw_disable_ips(intel_crtc); if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK, @@ -4158,7 +4064,7 @@ static int intel_dp_sink_crc_start(struct intel_dp *intel_dp) return -EIO; } - intel_dp->sink_crc.started = true; + intel_wait_for_vblank(dev, intel_crtc->pipe); return 0; } @@ -4170,7 +4076,6 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc) u8 buf; int count, ret; int attempts = 6; - bool old_equal_new; ret = intel_dp_sink_crc_start(intel_dp); if (ret) @@ -4186,35 +4091,17 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc) } count = buf & DP_TEST_COUNT_MASK; - /* - * Count might be reset during the loop. In this case - * last known count needs to be reset as well. - */ - if (count == 0) - intel_dp->sink_crc.last_count = 0; - - if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) { - ret = -EIO; - goto stop; - } - - old_equal_new = (count == intel_dp->sink_crc.last_count && - !memcmp(intel_dp->sink_crc.last_crc, crc, - 6 * sizeof(u8))); - - } while (--attempts && (count == 0 || old_equal_new)); - - intel_dp->sink_crc.last_count = buf & DP_TEST_COUNT_MASK; - memcpy(intel_dp->sink_crc.last_crc, crc, 6 * sizeof(u8)); + } while (--attempts && count == 0); if (attempts == 0) { - if (old_equal_new) { - DRM_DEBUG_KMS("Unreliable Sink CRC counter: Current returned CRC is identical to the previous one\n"); - } else { - DRM_ERROR("Panel is unable to calculate any CRC after 6 vblanks\n"); - ret = -ETIMEDOUT; - goto stop; - } + DRM_ERROR("Panel is unable to calculate any CRC after 6 vblanks\n"); + ret = -ETIMEDOUT; + goto stop; + } + + if (drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6) < 0) { + ret = -EIO; + goto stop; } stop: @@ -4314,13 +4201,6 @@ static void intel_dp_handle_test_request(struct intel_dp *intel_dp) uint8_t rxdata = 0; int status = 0; - intel_dp->compliance_test_active = 0; - intel_dp->compliance_test_type = 0; - intel_dp->compliance_test_data = 0; - - intel_dp->aux.i2c_nack_count = 0; - intel_dp->aux.i2c_defer_count = 0; - status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_REQUEST, &rxdata, 1); if (status <= 0) { DRM_DEBUG_KMS("Could not read test request from sink\n"); @@ -4436,6 +4316,14 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); + /* + * Clearing compliance test variables to allow capturing + * of values for next automated test request. + */ + intel_dp->compliance_test_active = 0; + intel_dp->compliance_test_type = 0; + intel_dp->compliance_test_data = 0; + if (!intel_encoder->base.crtc) return; @@ -4466,7 +4354,9 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n"); } - if (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count)) { + /* if link training is requested we should perform it always */ + if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) || + (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) { DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", intel_encoder->base.name); intel_dp_start_link_train(intel_dp); @@ -4613,20 +4503,20 @@ static bool g4x_digital_port_connected(struct drm_i915_private *dev_priv, return I915_READ(PORT_HOTPLUG_STAT) & bit; } -static bool vlv_digital_port_connected(struct drm_i915_private *dev_priv, - struct intel_digital_port *port) +static bool gm45_digital_port_connected(struct drm_i915_private *dev_priv, + struct intel_digital_port *port) { u32 bit; switch (port->port) { case PORT_B: - bit = PORTB_HOTPLUG_LIVE_STATUS_VLV; + bit = PORTB_HOTPLUG_LIVE_STATUS_GM45; break; case PORT_C: - bit = PORTC_HOTPLUG_LIVE_STATUS_VLV; + bit = PORTC_HOTPLUG_LIVE_STATUS_GM45; break; case PORT_D: - bit = PORTD_HOTPLUG_LIVE_STATUS_VLV; + bit = PORTD_HOTPLUG_LIVE_STATUS_GM45; break; default: MISSING_CASE(port->port); @@ -4678,47 +4568,12 @@ bool intel_digital_port_connected(struct drm_i915_private *dev_priv, return cpt_digital_port_connected(dev_priv, port); else if (IS_BROXTON(dev_priv)) return bxt_digital_port_connected(dev_priv, port); - else if (IS_VALLEYVIEW(dev_priv)) - return vlv_digital_port_connected(dev_priv, port); + else if (IS_GM45(dev_priv)) + return gm45_digital_port_connected(dev_priv, port); else return g4x_digital_port_connected(dev_priv, port); } -static enum drm_connector_status -ironlake_dp_detect(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 *intel_dig_port = dp_to_dig_port(intel_dp); - - if (!intel_digital_port_connected(dev_priv, intel_dig_port)) - return connector_status_disconnected; - - return intel_dp_detect_dpcd(intel_dp); -} - -static enum drm_connector_status -g4x_dp_detect(struct intel_dp *intel_dp) -{ - struct drm_device *dev = intel_dp_to_dev(intel_dp); - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - - /* Can't disconnect eDP, but you can close the lid... */ - if (is_edp(intel_dp)) { - enum drm_connector_status status; - - status = intel_panel_detect(dev); - if (status == connector_status_unknown) - status = connector_status_connected; - return status; - } - - if (!intel_digital_port_connected(dev->dev_private, intel_dig_port)) - return connector_status_disconnected; - - return intel_dp_detect_dpcd(intel_dp); -} - static struct edid * intel_dp_get_edid(struct intel_dp *intel_dp) { @@ -4791,12 +4646,19 @@ intel_dp_detect(struct drm_connector *connector, bool force) /* Can't disconnect eDP, but you can close the lid... */ if (is_edp(intel_dp)) status = edp_detect(intel_dp); - else if (HAS_PCH_SPLIT(dev)) - status = ironlake_dp_detect(intel_dp); + else if (intel_digital_port_connected(to_i915(dev), + dp_to_dig_port(intel_dp))) + status = intel_dp_detect_dpcd(intel_dp); else - status = g4x_dp_detect(intel_dp); - if (status != connector_status_connected) + status = connector_status_disconnected; + + if (status != connector_status_connected) { + intel_dp->compliance_test_active = 0; + intel_dp->compliance_test_type = 0; + intel_dp->compliance_test_data = 0; + goto out; + } intel_dp_probe_oui(intel_dp); @@ -4810,6 +4672,14 @@ intel_dp_detect(struct drm_connector *connector, bool force) goto out; } + /* + * Clearing NACK and defer counts to get their exact values + * while reading EDID which are required by Compliance tests + * 4.2.2.4 and 4.2.2.5 + */ + intel_dp->aux.i2c_nack_count = 0; + intel_dp->aux.i2c_defer_count = 0; + intel_dp_set_edid(intel_dp); if (intel_encoder->type != INTEL_OUTPUT_EDP) @@ -5014,7 +4884,7 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder) struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); struct intel_dp *intel_dp = &intel_dig_port->dp; - drm_dp_aux_unregister(&intel_dp->aux); + intel_dp_aux_fini(intel_dp); intel_dp_mst_encoder_cleanup(intel_dig_port); if (is_edp(intel_dp)) { cancel_delayed_work_sync(&intel_dp->panel_vdd_work); @@ -5092,7 +4962,7 @@ static void intel_dp_encoder_reset(struct drm_encoder *encoder) * Read out the current power sequencer assignment, * in case the BIOS did something with it. */ - if (IS_VALLEYVIEW(encoder->dev)) + if (IS_VALLEYVIEW(encoder->dev) || IS_CHERRYVIEW(encoder->dev)) vlv_initial_power_sequencer_setup(intel_dp); intel_edp_panel_vdd_sanitize(intel_dp); @@ -5204,25 +5074,6 @@ put_power: return ret; } -/* Return which DP Port should be selected for Transcoder DP control */ -int -intel_trans_dp_port_sel(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct intel_encoder *intel_encoder; - struct intel_dp *intel_dp; - - for_each_encoder_on_crtc(dev, crtc, intel_encoder) { - intel_dp = enc_to_intel_dp(&intel_encoder->base); - - if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT || - intel_encoder->type == INTEL_OUTPUT_EDP) - return intel_dp->output_reg; - } - - return -1; -} - /* check the VBT to see whether the eDP is on another port */ bool intel_dp_is_edp(struct drm_device *dev, enum port port) { @@ -5294,7 +5145,7 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, struct edp_power_seq cur, vbt, spec, *final = &intel_dp->pps_delays; u32 pp_on, pp_off, pp_div = 0, pp_ctl = 0; - int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg = 0; + i915_reg_t pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg; lockdep_assert_held(&dev_priv->pps_mutex); @@ -5416,7 +5267,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; u32 pp_on, pp_off, pp_div, port_sel = 0; int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev); - int pp_on_reg, pp_off_reg, pp_div_reg = 0, pp_ctrl_reg; + i915_reg_t pp_on_reg, pp_off_reg, pp_div_reg, pp_ctrl_reg; enum port port = dp_to_dig_port(intel_dp)->port; const struct edp_power_seq *seq = &intel_dp->pps_delays; @@ -5471,7 +5322,7 @@ 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 (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { port_sel = PANEL_PORT_SELECT_VLV(port); } else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) { if (port == PORT_A) @@ -5578,17 +5429,17 @@ static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate) DRM_ERROR("Unsupported refreshrate type\n"); } } else if (INTEL_INFO(dev)->gen > 6) { - u32 reg = PIPECONF(intel_crtc->config->cpu_transcoder); + i915_reg_t reg = PIPECONF(intel_crtc->config->cpu_transcoder); u32 val; val = I915_READ(reg); if (index > DRRS_HIGH_RR) { - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV; else val |= PIPECONF_EDP_RR_MODE_SWITCH; } else { - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV; else val &= ~PIPECONF_EDP_RR_MODE_SWITCH; @@ -5955,7 +5806,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, } mutex_unlock(&dev->mode_config.mutex); - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { intel_dp->edp_notifier.notifier_call = edp_notify_handler; register_reboot_notifier(&intel_dp->edp_notifier); @@ -5996,14 +5847,14 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, struct drm_device *dev = intel_encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; enum port port = intel_dig_port->port; - int type; + int type, ret; intel_dp->pps_pipe = INVALID_PIPE; /* intel_dp vfuncs */ if (INTEL_INFO(dev)->gen >= 9) intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider; - else if (IS_VALLEYVIEW(dev)) + else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) intel_dp->get_aux_clock_divider = vlv_get_aux_clock_divider; else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider; @@ -6017,6 +5868,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, else intel_dp->get_aux_send_ctl = i9xx_get_aux_send_ctl; + if (HAS_DDI(dev)) + intel_dp->prepare_link_retrain = intel_ddi_prepare_link_retrain; + /* Preserve the current hw state. */ intel_dp->DP = I915_READ(intel_dp->output_reg); intel_dp->attached_connector = intel_connector; @@ -6035,8 +5889,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, intel_encoder->type = INTEL_OUTPUT_EDP; /* eDP only on port B and/or C on vlv/chv */ - if (WARN_ON(IS_VALLEYVIEW(dev) && is_edp(intel_dp) && - port != PORT_B && port != PORT_C)) + if (WARN_ON((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && + is_edp(intel_dp) && port != PORT_B && port != PORT_C)) return false; DRM_DEBUG_KMS("Adding %s connector on port %c\n", @@ -6068,7 +5922,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, break; case PORT_B: intel_encoder->hpd_pin = HPD_PORT_B; - if (IS_BROXTON(dev_priv) && (INTEL_REVID(dev) < BXT_REVID_B0)) + if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) intel_encoder->hpd_pin = HPD_PORT_A; break; case PORT_C: @@ -6087,14 +5941,16 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, if (is_edp(intel_dp)) { pps_lock(intel_dp); intel_dp_init_panel_power_timestamps(intel_dp); - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) vlv_initial_power_sequencer_setup(intel_dp); else intel_dp_init_panel_power_sequencer(dev, intel_dp); pps_unlock(intel_dp); } - intel_dp_aux_init(intel_dp, intel_connector); + ret = intel_dp_aux_init(intel_dp, intel_connector); + if (ret) + goto fail; /* init MST on ports that can support it */ if (HAS_DP_MST(dev) && @@ -6103,20 +5959,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, intel_connector->base.base.id); if (!intel_edp_init_connector(intel_dp, intel_connector)) { - drm_dp_aux_unregister(&intel_dp->aux); - if (is_edp(intel_dp)) { - cancel_delayed_work_sync(&intel_dp->panel_vdd_work); - /* - * vdd might still be enabled do to the delayed vdd off. - * Make sure vdd is actually turned off here. - */ - pps_lock(intel_dp); - edp_panel_vdd_off_sync(intel_dp); - pps_unlock(intel_dp); - } - drm_connector_unregister(connector); - drm_connector_cleanup(connector); - return false; + intel_dp_aux_fini(intel_dp); + intel_dp_mst_encoder_cleanup(intel_dig_port); + goto fail; } intel_dp_add_properties(intel_dp, connector); @@ -6133,10 +5978,27 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, i915_debugfs_connector_add(connector); return true; + +fail: + if (is_edp(intel_dp)) { + cancel_delayed_work_sync(&intel_dp->panel_vdd_work); + /* + * vdd might still be enabled do to the delayed vdd off. + * Make sure vdd is actually turned off here. + */ + pps_lock(intel_dp); + edp_panel_vdd_off_sync(intel_dp); + pps_unlock(intel_dp); + } + drm_connector_unregister(connector); + drm_connector_cleanup(connector); + + return false; } void -intel_dp_init(struct drm_device *dev, int output_reg, enum port port) +intel_dp_init(struct drm_device *dev, + i915_reg_t output_reg, enum port port) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_digital_port *intel_dig_port; @@ -6155,8 +6017,9 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) intel_encoder = &intel_dig_port->base; encoder = &intel_encoder->base; - drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs, - DRM_MODE_ENCODER_TMDS); + if (drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs, + DRM_MODE_ENCODER_TMDS, NULL)) + goto err_encoder_init; intel_encoder->compute_config = intel_dp_compute_config; intel_encoder->disable = intel_disable_dp; @@ -6205,6 +6068,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) err_init_connector: drm_encoder_cleanup(encoder); +err_encoder_init: kfree(intel_connector); err_connector_alloc: kfree(intel_dig_port); @@ -6249,6 +6113,19 @@ void intel_dp_mst_resume(struct drm_device *dev) ret = drm_dp_mst_topology_mgr_resume(&intel_dig_port->dp.mst_mgr); if (ret != 0) { + /* + * For some reason, some laptops can't bring + * their MST docks back up immediately after + * resume and need to wait a short period of + * time before aux transactions with the dock + * become functional again. Until we find a + * proper fix for this, this workaround should + * suffice + */ + msleep(30); + ret = drm_dp_mst_topology_mgr_resume(&intel_dig_port->dp.mst_mgr); + } + if (ret != 0) { intel_dp_check_mst_status(&intel_dig_port->dp); } } diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c new file mode 100644 index 000000000..0b8eefc2a --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c @@ -0,0 +1,342 @@ +/* + * Copyright © 2008-2015 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. + */ + +#include "intel_drv.h" + +static void +intel_get_adjust_train(struct intel_dp *intel_dp, + const uint8_t link_status[DP_LINK_STATUS_SIZE]) +{ + uint8_t v = 0; + uint8_t p = 0; + int lane; + uint8_t voltage_max; + uint8_t preemph_max; + + for (lane = 0; lane < intel_dp->lane_count; lane++) { + uint8_t this_v = drm_dp_get_adjust_request_voltage(link_status, lane); + uint8_t this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane); + + if (this_v > v) + v = this_v; + if (this_p > p) + p = this_p; + } + + voltage_max = intel_dp_voltage_max(intel_dp); + if (v >= voltage_max) + v = voltage_max | DP_TRAIN_MAX_SWING_REACHED; + + preemph_max = intel_dp_pre_emphasis_max(intel_dp, v); + if (p >= preemph_max) + p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + + for (lane = 0; lane < 4; lane++) + intel_dp->train_set[lane] = v | p; +} + +static bool +intel_dp_set_link_train(struct intel_dp *intel_dp, + uint8_t dp_train_pat) +{ + uint8_t buf[sizeof(intel_dp->train_set) + 1]; + int ret, len; + + intel_dp_program_link_training_pattern(intel_dp, dp_train_pat); + + buf[0] = 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 = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_PATTERN_SET, + buf, len); + + return ret == len; +} + +static bool +intel_dp_reset_link_train(struct intel_dp *intel_dp, + uint8_t dp_train_pat) +{ + if (!intel_dp->train_set_valid) + memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set)); + intel_dp_set_signal_levels(intel_dp); + return intel_dp_set_link_train(intel_dp, dp_train_pat); +} + +static bool +intel_dp_update_link_train(struct intel_dp *intel_dp) +{ + int ret; + + intel_dp_set_signal_levels(intel_dp); + + ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET, + intel_dp->train_set, intel_dp->lane_count); + + return ret == intel_dp->lane_count; +} + +/* Enable corresponding port and start training pattern 1 */ +static void +intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp) +{ + int i; + uint8_t voltage; + int voltage_tries, loop_tries; + uint8_t link_config[2]; + uint8_t link_bw, rate_select; + + if (intel_dp->prepare_link_retrain) + intel_dp->prepare_link_retrain(intel_dp); + + intel_dp_compute_rate(intel_dp, intel_dp->link_rate, + &link_bw, &rate_select); + + /* Write the link configuration data */ + link_config[0] = 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; + drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2); + if (intel_dp->num_sink_rates) + drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET, + &rate_select, 1); + + link_config[0] = 0; + link_config[1] = DP_SET_ANSI_8B10B; + drm_dp_dpcd_write(&intel_dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2); + + intel_dp->DP |= DP_PORT_EN; + + /* clock recovery */ + if (!intel_dp_reset_link_train(intel_dp, + DP_TRAINING_PATTERN_1 | + DP_LINK_SCRAMBLING_DISABLE)) { + DRM_ERROR("failed to enable link training\n"); + return; + } + + voltage = 0xff; + voltage_tries = 0; + loop_tries = 0; + for (;;) { + uint8_t link_status[DP_LINK_STATUS_SIZE]; + + drm_dp_link_train_clock_recovery_delay(intel_dp->dpcd); + if (!intel_dp_get_link_status(intel_dp, link_status)) { + DRM_ERROR("failed to get link status\n"); + break; + } + + if (drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) { + DRM_DEBUG_KMS("clock recovery OK\n"); + break; + } + + /* + * if we used previously trained voltage and pre-emphasis values + * and we don't get clock recovery, reset link training values + */ + if (intel_dp->train_set_valid) { + DRM_DEBUG_KMS("clock recovery not ok, reset"); + /* clear the flag as we are not reusing train set */ + intel_dp->train_set_valid = false; + if (!intel_dp_reset_link_train(intel_dp, + DP_TRAINING_PATTERN_1 | + DP_LINK_SCRAMBLING_DISABLE)) { + DRM_ERROR("failed to enable link training\n"); + return; + } + continue; + } + + /* Check to see if we've tried the max voltage */ + for (i = 0; i < intel_dp->lane_count; i++) + if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) + break; + if (i == intel_dp->lane_count) { + ++loop_tries; + if (loop_tries == 5) { + DRM_ERROR("too many full retries, give up\n"); + break; + } + intel_dp_reset_link_train(intel_dp, + DP_TRAINING_PATTERN_1 | + DP_LINK_SCRAMBLING_DISABLE); + voltage_tries = 0; + continue; + } + + /* Check to see if we've tried the same voltage 5 times */ + 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"); + break; + } + } else + voltage_tries = 0; + voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; + + /* Update training set as requested by target */ + intel_get_adjust_train(intel_dp, link_status); + if (!intel_dp_update_link_train(intel_dp)) { + DRM_ERROR("failed to update link training\n"); + break; + } + } +} + +/* + * Pick training pattern for channel equalization. Training Pattern 3 for HBR2 + * or 1.2 devices that support it, Training Pattern 2 otherwise. + */ +static u32 intel_dp_training_pattern(struct intel_dp *intel_dp) +{ + u32 training_pattern = DP_TRAINING_PATTERN_2; + bool source_tps3, sink_tps3; + + /* + * Intel platforms that support HBR2 also support TPS3. TPS3 support is + * also mandatory for downstream devices that support HBR2. However, not + * all sinks follow the spec. + * + * Due to WaDisableHBR2 SKL < B0 is the only exception where TPS3 is + * supported in source but still not enabled. + */ + source_tps3 = intel_dp_source_supports_hbr2(intel_dp); + sink_tps3 = drm_dp_tps3_supported(intel_dp->dpcd); + + if (source_tps3 && sink_tps3) { + training_pattern = DP_TRAINING_PATTERN_3; + } else if (intel_dp->link_rate == 540000) { + if (!source_tps3) + DRM_DEBUG_KMS("5.4 Gbps link rate without source HBR2/TPS3 support\n"); + if (!sink_tps3) + DRM_DEBUG_KMS("5.4 Gbps link rate without sink TPS3 support\n"); + } + + return training_pattern; +} + +static void +intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp) +{ + bool channel_eq = false; + int tries, cr_tries; + u32 training_pattern; + + training_pattern = intel_dp_training_pattern(intel_dp); + + /* channel equalization */ + if (!intel_dp_set_link_train(intel_dp, + training_pattern | + 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]; + + if (cr_tries > 5) { + DRM_ERROR("failed to train DP, aborting\n"); + 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"); + break; + } + + /* Make sure clock is still ok */ + if (!drm_dp_clock_recovery_ok(link_status, + intel_dp->lane_count)) { + intel_dp->train_set_valid = false; + intel_dp_link_training_clock_recovery(intel_dp); + intel_dp_set_link_train(intel_dp, + training_pattern | + DP_LINK_SCRAMBLING_DISABLE); + cr_tries++; + continue; + } + + if (drm_dp_channel_eq_ok(link_status, + intel_dp->lane_count)) { + channel_eq = true; + break; + } + + /* Try 5 times, then try clock recovery if that fails */ + if (tries > 5) { + intel_dp->train_set_valid = false; + intel_dp_link_training_clock_recovery(intel_dp); + intel_dp_set_link_train(intel_dp, + training_pattern | + DP_LINK_SCRAMBLING_DISABLE); + tries = 0; + cr_tries++; + continue; + } + + /* Update training set as requested by target */ + intel_get_adjust_train(intel_dp, link_status); + if (!intel_dp_update_link_train(intel_dp)) { + DRM_ERROR("failed to update link training\n"); + break; + } + ++tries; + } + + intel_dp_set_idle_link_train(intel_dp); + + if (channel_eq) { + intel_dp->train_set_valid = true; + DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n"); + } +} + +void intel_dp_stop_link_train(struct intel_dp *intel_dp) +{ + intel_dp_set_link_train(intel_dp, + DP_TRAINING_PATTERN_DISABLE); +} + +void +intel_dp_start_link_train(struct intel_dp *intel_dp) +{ + intel_dp_link_training_clock_recovery(intel_dp); + intel_dp_link_training_channel_equalization(intel_dp); +} diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 0639275fc..fa0dabf57 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -78,6 +78,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, return false; } + if (drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, found->port)) + pipe_config->has_audio = true; mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, bpp); pipe_config->pbn = mst_pbn; @@ -102,6 +104,11 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder) struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_digital_port *intel_dig_port = intel_mst->primary; struct intel_dp *intel_dp = &intel_dig_port->dp; + struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_crtc *crtc = encoder->base.crtc; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int ret; DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); @@ -112,6 +119,10 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder) if (ret) { DRM_ERROR("failed to update payload %d\n", ret); } + if (intel_crtc->config->has_audio) { + intel_audio_codec_disable(encoder); + intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO); + } } static void intel_mst_post_disable_dp(struct intel_encoder *encoder) @@ -173,20 +184,14 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder) intel_mst->port = found->port; if (intel_dp->active_mst_links == 0) { - enum port port = intel_ddi_get_encoder_port(encoder); + intel_ddi_clk_select(encoder, intel_crtc->config); intel_dp_set_link_params(intel_dp, intel_crtc->config); - /* FIXME: add support for SKL */ - if (INTEL_INFO(dev)->gen < 9) - I915_WRITE(PORT_CLK_SEL(port), - intel_crtc->config->ddi_pll_sel); - intel_ddi_init_dp_buf_reg(&intel_dig_port->base); intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); - intel_dp_start_link_train(intel_dp); intel_dp_stop_link_train(intel_dp); } @@ -214,6 +219,7 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder) struct intel_dp *intel_dp = &intel_dig_port->dp; struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); enum port port = intel_dig_port->port; int ret; @@ -226,6 +232,13 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder) ret = drm_dp_check_act_status(&intel_dp->mst_mgr); ret = drm_dp_update_payload_part2(&intel_dp->mst_mgr); + + if (crtc->config->has_audio) { + DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n", + pipe_name(crtc->pipe)); + intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO); + intel_audio_codec_enable(encoder); + } } static bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder, @@ -251,6 +264,9 @@ static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder, pipe_config->has_dp_encoder = true; + pipe_config->has_audio = + intel_ddi_is_audio_enabled(dev_priv, crtc); + temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); if (temp & TRANS_DDI_PHSYNC) flags |= DRM_MODE_FLAG_PHSYNC; @@ -414,7 +430,10 @@ static void intel_connector_add_to_fbdev(struct intel_connector *connector) { #ifdef CONFIG_DRM_FBDEV_EMULATION struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - drm_fb_helper_add_one_connector(&dev_priv->fbdev->helper, &connector->base); + + if (dev_priv->fbdev) + drm_fb_helper_add_one_connector(&dev_priv->fbdev->helper, + &connector->base); #endif } @@ -422,7 +441,10 @@ static void intel_connector_remove_from_fbdev(struct intel_connector *connector) { #ifdef CONFIG_DRM_FBDEV_EMULATION struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - drm_fb_helper_remove_one_connector(&dev_priv->fbdev->helper, &connector->base); + + if (dev_priv->fbdev) + drm_fb_helper_remove_one_connector(&dev_priv->fbdev->helper, + &connector->base); #endif } @@ -512,7 +534,7 @@ static void intel_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) drm_kms_helper_hotplug_event(dev); } -static struct drm_dp_mst_topology_cbs mst_cbs = { +static const struct drm_dp_mst_topology_cbs mst_cbs = { .add_connector = intel_dp_add_mst_connector, .register_connector = intel_dp_register_mst_connector, .destroy_connector = intel_dp_destroy_mst_connector, @@ -536,7 +558,7 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum intel_mst->primary = intel_dig_port; drm_encoder_init(dev, &intel_encoder->base, &intel_dp_mst_enc_funcs, - DRM_MODE_ENCODER_DPMST); + DRM_MODE_ENCODER_DPMST, NULL); intel_encoder->type = INTEL_OUTPUT_DP_MST; intel_encoder->crtc_mask = 0x7; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 0d00f07b7..df7f3cb66 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -123,8 +123,6 @@ struct intel_framebuffer { struct intel_fbdev { struct drm_fb_helper helper; struct intel_framebuffer *fb; - struct list_head fbdev_list; - struct drm_display_mode *our_mode; int preferred_bpp; }; @@ -250,6 +248,7 @@ struct intel_atomic_state { unsigned int cdclk; bool dpll_set; struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS]; + struct intel_wm_config wm_config; }; struct intel_plane_state { @@ -280,6 +279,9 @@ struct intel_plane_state { int scaler_id; struct drm_intel_sprite_colorkey ckey; + + /* async flip related structures */ + struct drm_i915_gem_request *wait_req; }; struct intel_initial_plane_config { @@ -334,6 +336,21 @@ struct intel_crtc_scaler_state { /* drm_mode->private_flags */ #define I915_MODE_FLAG_INHERITED 1 +struct intel_pipe_wm { + struct intel_wm_level wm[5]; + uint32_t linetime; + bool fbc_wm_enabled; + bool pipe_enabled; + bool sprites_enabled; + bool sprites_scaled; +}; + +struct skl_pipe_wm { + struct skl_wm_level wm[8]; + struct skl_wm_level trans_wm; + uint32_t linetime; +}; + struct intel_crtc_state { struct drm_crtc_state base; @@ -348,7 +365,9 @@ struct intel_crtc_state { #define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */ unsigned long quirks; - bool update_pipe; + bool update_pipe; /* can a fast modeset be performed? */ + bool disable_cxsr; + bool wm_changed; /* watermarks are updated */ /* Pipe source size (ie. panel fitter input size) * All planes will be positioned inside this space, @@ -376,6 +395,9 @@ struct intel_crtc_state { * accordingly. */ bool has_dp_encoder; + /* DSI has special cases */ + bool has_dsi_encoder; + /* Whether we should send NULL infoframes. Required for audio. */ bool has_hdmi_sink; @@ -468,6 +490,20 @@ struct intel_crtc_state { /* w/a for waiting 2 vblanks during crtc enable */ enum pipe hsw_workaround_pipe; + + /* IVB sprite scaling w/a (WaCxSRDisabledForSpriteScaling:ivb) */ + bool disable_lp_wm; + + struct { + /* + * optimal watermarks, programmed post-vblank when this state + * is committed + */ + union { + struct intel_pipe_wm ilk; + struct skl_pipe_wm skl; + } optimal; + } wm; }; struct vlv_wm_state { @@ -479,26 +515,12 @@ struct vlv_wm_state { bool cxsr; }; -struct intel_pipe_wm { - struct intel_wm_level wm[5]; - uint32_t linetime; - bool fbc_wm_enabled; - bool pipe_enabled; - bool sprites_enabled; - bool sprites_scaled; -}; - struct intel_mmio_flip { struct work_struct work; struct drm_i915_private *i915; struct drm_i915_gem_request *req; struct intel_crtc *crtc; -}; - -struct skl_pipe_wm { - struct skl_wm_level wm[8]; - struct skl_wm_level trans_wm; - uint32_t linetime; + unsigned int rotation; }; /* @@ -509,13 +531,9 @@ struct skl_pipe_wm { */ struct intel_crtc_atomic_commit { /* Sleepable operations to perform before commit */ - bool wait_for_flips; bool disable_fbc; bool disable_ips; - bool disable_cxsr; bool pre_disable_primary; - bool update_wm_pre, update_wm_post; - unsigned disabled_planes; /* Sleepable operations to perform after commit */ unsigned fb_bits; @@ -567,9 +585,10 @@ struct intel_crtc { /* per-pipe watermark state */ struct { /* watermarks currently being used */ - struct intel_pipe_wm active; - /* SKL wm values currently in use */ - struct skl_pipe_wm skl_active; + union { + struct intel_pipe_wm ilk; + struct skl_pipe_wm skl; + } active; /* allow CxSR on this pipe */ bool cxsr_allowed; } wm; @@ -677,7 +696,7 @@ struct cxsr_latency { #define intel_fb_obj(x) (x ? to_intel_framebuffer(x)->obj : NULL) struct intel_hdmi { - u32 hdmi_reg; + i915_reg_t hdmi_reg; int ddc_bus; bool limited_color_range; bool color_range_auto; @@ -693,7 +712,8 @@ struct intel_hdmi { void (*set_infoframes)(struct drm_encoder *encoder, bool enable, const struct drm_display_mode *adjusted_mode); - bool (*infoframe_enabled)(struct drm_encoder *encoder); + bool (*infoframe_enabled)(struct drm_encoder *encoder, + const struct intel_crtc_state *pipe_config); }; struct intel_dp_mst_encoder; @@ -719,15 +739,10 @@ enum link_m_n_set { M2_N2 }; -struct sink_crc { - bool started; - u8 last_crc[6]; - int last_count; -}; - struct intel_dp { - uint32_t output_reg; - uint32_t aux_ch_ctl_reg; + i915_reg_t output_reg; + i915_reg_t aux_ch_ctl_reg; + i915_reg_t aux_ch_data_reg[5]; uint32_t DP; int link_rate; uint8_t lane_count; @@ -741,7 +756,6 @@ struct intel_dp { /* sink rates as reported by DP_SUPPORTED_LINK_RATES */ uint8_t num_sink_rates; int sink_rates[DP_MAX_SUPPORTED_RATES]; - struct sink_crc sink_crc; struct drm_dp_aux aux; uint8_t train_set[4]; int panel_power_up_delay; @@ -783,6 +797,10 @@ struct intel_dp { bool has_aux_irq, int send_bytes, uint32_t aux_clock_divider); + + /* This is called before a link training is starterd */ + void (*prepare_link_retrain)(struct intel_dp *intel_dp); + bool train_set_valid; /* Displayport compliance testing */ @@ -799,6 +817,8 @@ struct intel_digital_port { struct intel_hdmi hdmi; enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool); bool release_cl2_override; + /* for communication with audio component; protected by av_mutex */ + const struct drm_connector *audio_connector; }; struct intel_dp_mst_encoder { @@ -942,7 +962,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, enum pipe pipe); void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, enum transcoder pch_transcoder); -void i9xx_check_fifo_underruns(struct drm_i915_private *dev_priv); +void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv); +void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv); /* i915_irq.c */ void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); @@ -973,6 +994,8 @@ void intel_crt_init(struct drm_device *dev); /* intel_ddi.c */ +void intel_ddi_clk_select(struct intel_encoder *encoder, + const struct intel_crtc_state *pipe_config); 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); @@ -987,9 +1010,11 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc); bool intel_ddi_pll_select(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state); void intel_ddi_set_pipe_settings(struct drm_crtc *crtc); -void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder); +void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp); bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); void intel_ddi_fdi_disable(struct drm_crtc *crtc); +bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv, + struct intel_crtc *intel_crtc); void intel_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config); struct intel_encoder * @@ -1055,6 +1080,15 @@ intel_wait_for_vblank(struct drm_device *dev, int pipe) { drm_wait_one_vblank(dev, pipe); } +static inline void +intel_wait_for_vblank_if_active(struct drm_device *dev, int pipe) +{ + const struct intel_crtc *crtc = + to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe)); + + if (crtc->active) + intel_wait_for_vblank(dev, 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, struct intel_digital_port *dport, @@ -1068,9 +1102,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx); int intel_pin_and_fence_fb_obj(struct drm_plane *plane, struct drm_framebuffer *fb, - const struct drm_plane_state *plane_state, - struct intel_engine_cs *pipelined, - struct drm_i915_gem_request **pipelined_request); + const struct drm_plane_state *plane_state); struct drm_framebuffer * __intel_framebuffer_create(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, @@ -1151,7 +1183,10 @@ void broxton_ddi_phy_uninit(struct drm_device *dev); void bxt_enable_dc9(struct drm_i915_private *dev_priv); void bxt_disable_dc9(struct drm_i915_private *dev_priv); void skl_init_cdclk(struct drm_i915_private *dev_priv); +int skl_sanitize_cdclk(struct drm_i915_private *dev_priv); void skl_uninit_cdclk(struct drm_i915_private *dev_priv); +void skl_enable_dc6(struct drm_i915_private *dev_priv); +void skl_disable_dc6(struct drm_i915_private *dev_priv); void intel_dp_get_m_n(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config); void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n); @@ -1172,31 +1207,26 @@ enum intel_display_power_domain intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder); void intel_mode_from_pipe_config(struct drm_display_mode *mode, struct intel_crtc_state *pipe_config); -void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc); void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file); int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state); -unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane, - struct drm_i915_gem_object *obj, - unsigned int plane); +u32 intel_plane_obj_offset(struct intel_plane *intel_plane, + struct drm_i915_gem_object *obj, + unsigned int plane); u32 skl_plane_ctl_format(uint32_t pixel_format); u32 skl_plane_ctl_tiling(uint64_t fb_modifier); u32 skl_plane_ctl_rotation(unsigned int rotation); /* intel_csr.c */ -void intel_csr_ucode_init(struct drm_device *dev); -enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv); -void intel_csr_load_status_set(struct drm_i915_private *dev_priv, - enum csr_state state); -void intel_csr_load_program(struct drm_device *dev); -void intel_csr_ucode_fini(struct drm_device *dev); -void assert_csr_loaded(struct drm_i915_private *dev_priv); +void intel_csr_ucode_init(struct drm_i915_private *); +void intel_csr_load_program(struct drm_i915_private *); +void intel_csr_ucode_fini(struct drm_i915_private *); /* intel_dp.c */ -void intel_dp_init(struct drm_device *dev, int output_reg, enum port port); +void intel_dp_init(struct drm_device *dev, i915_reg_t 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_set_link_params(struct intel_dp *intel_dp, @@ -1234,6 +1264,22 @@ bool intel_digital_port_connected(struct drm_i915_private *dev_priv, struct intel_digital_port *port); void hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config); +void +intel_dp_program_link_training_pattern(struct intel_dp *intel_dp, + uint8_t dp_train_pat); +void +intel_dp_set_signal_levels(struct intel_dp *intel_dp); +void intel_dp_set_idle_link_train(struct intel_dp *intel_dp); +uint8_t +intel_dp_voltage_max(struct intel_dp *intel_dp); +uint8_t +intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing); +void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, + uint8_t *link_bw, uint8_t *rate_select); +bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp); +bool +intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]); + /* intel_dp_mst.c */ int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id); void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port); @@ -1248,7 +1294,7 @@ void intel_dvo_init(struct drm_device *dev); /* legacy fbdev emulation in intel_fbdev.c */ #ifdef CONFIG_DRM_FBDEV_EMULATION extern int intel_fbdev_init(struct drm_device *dev); -extern void intel_fbdev_initial_config(void *data, async_cookie_t cookie); +extern void intel_fbdev_initial_config_async(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, bool synchronous); extern void intel_fbdev_output_poll_changed(struct drm_device *dev); @@ -1259,7 +1305,7 @@ static inline int intel_fbdev_init(struct drm_device *dev) return 0; } -static inline void intel_fbdev_initial_config(void *data, async_cookie_t cookie) +static inline void intel_fbdev_initial_config_async(struct drm_device *dev) { } @@ -1277,9 +1323,11 @@ static inline void intel_fbdev_restore_mode(struct drm_device *dev) #endif /* intel_fbc.c */ -bool intel_fbc_enabled(struct drm_i915_private *dev_priv); -void intel_fbc_update(struct drm_i915_private *dev_priv); +bool intel_fbc_is_active(struct drm_i915_private *dev_priv); +void intel_fbc_deactivate(struct intel_crtc *crtc); +void intel_fbc_update(struct intel_crtc *crtc); void intel_fbc_init(struct drm_i915_private *dev_priv); +void intel_fbc_enable(struct intel_crtc *crtc); void intel_fbc_disable(struct drm_i915_private *dev_priv); void intel_fbc_disable_crtc(struct intel_crtc *crtc); void intel_fbc_invalidate(struct drm_i915_private *dev_priv, @@ -1287,11 +1335,10 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv, enum fb_op_origin origin); void intel_fbc_flush(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits, enum fb_op_origin origin); -const char *intel_no_fbc_reason_str(enum no_fbc_reason reason); void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv); /* intel_hdmi.c */ -void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port); +void intel_hdmi_init(struct drm_device *dev, i915_reg_t 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); @@ -1367,8 +1414,13 @@ void intel_psr_single_frame_update(struct drm_device *dev, /* intel_runtime_pm.c */ int intel_power_domains_init(struct drm_i915_private *); void intel_power_domains_fini(struct drm_i915_private *); -void intel_power_domains_init_hw(struct drm_i915_private *dev_priv); +void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume); +void intel_power_domains_suspend(struct drm_i915_private *dev_priv); +void skl_pw1_misc_io_init(struct drm_i915_private *dev_priv); +void skl_pw1_misc_io_fini(struct drm_i915_private *dev_priv); void intel_runtime_pm_enable(struct drm_i915_private *dev_priv); +const char * +intel_display_power_domain_str(enum intel_display_power_domain domain); bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain); @@ -1376,9 +1428,95 @@ bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain); void intel_display_power_get(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain); +bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv, + enum intel_display_power_domain domain); void intel_display_power_put(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain); + +static inline void +assert_rpm_device_not_suspended(struct drm_i915_private *dev_priv) +{ + WARN_ONCE(dev_priv->pm.suspended, + "Device suspended during HW access\n"); +} + +static inline void +assert_rpm_wakelock_held(struct drm_i915_private *dev_priv) +{ + assert_rpm_device_not_suspended(dev_priv); + /* FIXME: Needs to be converted back to WARN_ONCE, but currently causes + * too much noise. */ + if (!atomic_read(&dev_priv->pm.wakeref_count)) + DRM_DEBUG_DRIVER("RPM wakelock ref not held during HW access"); +} + +static inline int +assert_rpm_atomic_begin(struct drm_i915_private *dev_priv) +{ + int seq = atomic_read(&dev_priv->pm.atomic_seq); + + assert_rpm_wakelock_held(dev_priv); + + return seq; +} + +static inline void +assert_rpm_atomic_end(struct drm_i915_private *dev_priv, int begin_seq) +{ + WARN_ONCE(atomic_read(&dev_priv->pm.atomic_seq) != begin_seq, + "HW access outside of RPM atomic section\n"); +} + +/** + * disable_rpm_wakeref_asserts - disable the RPM assert checks + * @dev_priv: i915 device instance + * + * This function disable asserts that check if we hold an RPM wakelock + * reference, while keeping the device-not-suspended checks still enabled. + * It's meant to be used only in special circumstances where our rule about + * the wakelock refcount wrt. the device power state doesn't hold. According + * to this rule at any point where we access the HW or want to keep the HW in + * an active state we must hold an RPM wakelock reference acquired via one of + * the intel_runtime_pm_get() helpers. Currently there are a few special spots + * where this rule doesn't hold: the IRQ and suspend/resume handlers, the + * forcewake release timer, and the GPU RPS and hangcheck works. All other + * users should avoid using this function. + * + * Any calls to this function must have a symmetric call to + * enable_rpm_wakeref_asserts(). + */ +static inline void +disable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv) +{ + atomic_inc(&dev_priv->pm.wakeref_count); +} + +/** + * enable_rpm_wakeref_asserts - re-enable the RPM assert checks + * @dev_priv: i915 device instance + * + * This function re-enables the RPM assert checks after disabling them with + * disable_rpm_wakeref_asserts. It's meant to be used only in special + * circumstances otherwise its use should be avoided. + * + * Any calls to this function must have a symmetric call to + * disable_rpm_wakeref_asserts(). + */ +static inline void +enable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv) +{ + atomic_dec(&dev_priv->pm.wakeref_count); +} + +/* TODO: convert users of these to rely instead on proper RPM refcounting */ +#define DISABLE_RPM_WAKEREF_ASSERTS(dev_priv) \ + disable_rpm_wakeref_asserts(dev_priv) + +#define ENABLE_RPM_WAKEREF_ASSERTS(dev_priv) \ + enable_rpm_wakeref_asserts(dev_priv) + void intel_runtime_pm_get(struct drm_i915_private *dev_priv); +bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv); void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv); void intel_runtime_pm_put(struct drm_i915_private *dev_priv); @@ -1395,12 +1533,6 @@ void intel_init_clock_gating(struct drm_device *dev); void intel_suspend_hw(struct drm_device *dev); int ilk_wm_max_level(const 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, - uint32_t sprite_height, - int pixel_size, - bool enabled, bool scaled); void intel_init_pm(struct drm_device *dev); void intel_pm_setup(struct drm_device *dev); void intel_gpu_ips_init(struct drm_i915_private *dev_priv); @@ -1428,7 +1560,8 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config); /* intel_sdvo.c */ -bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob); +bool intel_sdvo_init(struct drm_device *dev, + i915_reg_t reg, enum port port); /* intel_sprite.c */ diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 170ae6f48..0193c62a5 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -60,7 +60,8 @@ static void wait_for_dsi_fifo_empty(struct intel_dsi *intel_dsi, enum port port) DRM_ERROR("DPI FIFOs are not empty\n"); } -static void write_data(struct drm_i915_private *dev_priv, u32 reg, +static void write_data(struct drm_i915_private *dev_priv, + i915_reg_t reg, const u8 *data, u32 len) { u32 i, j; @@ -75,7 +76,8 @@ static void write_data(struct drm_i915_private *dev_priv, u32 reg, } } -static void read_data(struct drm_i915_private *dev_priv, u32 reg, +static void read_data(struct drm_i915_private *dev_priv, + i915_reg_t reg, u8 *data, u32 len) { u32 i, j; @@ -98,7 +100,8 @@ static ssize_t intel_dsi_host_transfer(struct mipi_dsi_host *host, struct mipi_dsi_packet packet; ssize_t ret; const u8 *header, *data; - u32 data_reg, data_mask, ctrl_reg, ctrl_mask; + i915_reg_t data_reg, ctrl_reg; + u32 data_mask, ctrl_mask; ret = mipi_dsi_create_packet(&packet, msg); if (ret < 0) @@ -263,16 +266,18 @@ static inline bool is_cmd_mode(struct intel_dsi *intel_dsi) } static bool intel_dsi_compute_config(struct intel_encoder *encoder, - struct intel_crtc_state *config) + struct intel_crtc_state *pipe_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->base.adjusted_mode; + struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; DRM_DEBUG_KMS("\n"); + pipe_config->has_dsi_encoder = true; + if (fixed_mode) intel_fixed_panel_mode(fixed_mode, adjusted_mode); @@ -364,7 +369,7 @@ static void intel_dsi_device_ready(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) vlv_dsi_device_ready(encoder); else if (IS_BROXTON(dev)) bxt_dsi_device_ready(encoder); @@ -377,10 +382,10 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder) struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); enum port port; - u32 temp; - u32 port_ctrl; if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) { + u32 temp; + temp = I915_READ(VLV_CHICKEN_3); temp &= ~PIXEL_OVERLAP_CNT_MASK | intel_dsi->pixel_overlap << @@ -389,8 +394,9 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder) } for_each_dsi_port(port, intel_dsi->ports) { - port_ctrl = IS_BROXTON(dev) ? BXT_MIPI_PORT_CTRL(port) : - MIPI_PORT_CTRL(port); + i915_reg_t port_ctrl = IS_BROXTON(dev) ? + BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port); + u32 temp; temp = I915_READ(port_ctrl); @@ -416,13 +422,13 @@ static void intel_dsi_port_disable(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); enum port port; - u32 temp; - u32 port_ctrl; for_each_dsi_port(port, intel_dsi->ports) { + i915_reg_t port_ctrl = IS_BROXTON(dev) ? + BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port); + u32 temp; + /* de-assert ip_tg_enable signal */ - port_ctrl = IS_BROXTON(dev) ? BXT_MIPI_PORT_CTRL(port) : - MIPI_PORT_CTRL(port); temp = I915_READ(port_ctrl); I915_WRITE(port_ctrl, temp & ~DPI_ENABLE); POSTING_READ(port_ctrl); @@ -458,6 +464,8 @@ static void intel_dsi_enable(struct intel_encoder *encoder) intel_panel_enable_backlight(intel_dsi->attached_connector); } +static void intel_dsi_prepare(struct intel_encoder *intel_encoder); + static void intel_dsi_pre_enable(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; @@ -470,13 +478,16 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder) DRM_DEBUG_KMS("\n"); + intel_dsi_prepare(encoder); + intel_enable_dsi_pll(encoder); + /* Panel Enable over CRC PMIC */ if (intel_dsi->gpio_panel) gpiod_set_value_cansleep(intel_dsi->gpio_panel, 1); msleep(intel_dsi->panel_on_delay); - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { /* * Disable DPOunit clock gating, can stall pipe * and we need DPLL REFA always enabled @@ -580,11 +591,13 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); enum port port; - u32 val; - u32 port_ctrl = 0; DRM_DEBUG_KMS("\n"); for_each_dsi_port(port, intel_dsi->ports) { + /* Common bit for both MIPI Port A & MIPI Port C on VLV/CHV */ + i915_reg_t port_ctrl = IS_BROXTON(dev) ? + BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(PORT_A); + u32 val; I915_WRITE(MIPI_DEVICE_READY(port), DEVICE_READY | ULPS_STATE_ENTER); @@ -598,12 +611,6 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) ULPS_STATE_ENTER); usleep_range(2000, 2500); - if (IS_BROXTON(dev)) - port_ctrl = BXT_MIPI_PORT_CTRL(port); - else if (IS_VALLEYVIEW(dev)) - /* Common bit for both MIPI Port A & MIPI Port C */ - port_ctrl = MIPI_PORT_CTRL(PORT_A); - /* Wait till Clock lanes are in LP-00 state for MIPI Port A * only. MIPI Port C has no similar bit for checking */ @@ -656,40 +663,47 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); struct drm_device *dev = encoder->base.dev; enum intel_display_power_domain power_domain; - u32 dpi_enabled, func, ctrl_reg; enum port port; + bool ret; DRM_DEBUG_KMS("\n"); power_domain = intel_display_port_power_domain(encoder); - if (!intel_display_power_is_enabled(dev_priv, power_domain)) + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; + ret = false; + /* XXX: this only works for one DSI output */ for_each_dsi_port(port, intel_dsi->ports) { + i915_reg_t ctrl_reg = IS_BROXTON(dev) ? + BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port); + u32 dpi_enabled, func; + func = I915_READ(MIPI_DSI_FUNC_PRG(port)); - ctrl_reg = IS_BROXTON(dev) ? BXT_MIPI_PORT_CTRL(port) : - MIPI_PORT_CTRL(port); dpi_enabled = I915_READ(ctrl_reg) & DPI_ENABLE; /* Due to some hardware limitations on BYT, MIPI Port C DPI * Enable bit does not get set. To check whether DSI Port C * was enabled in BIOS, check the Pipe B enable bit */ - if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && - (port == PORT_C)) + if (IS_VALLEYVIEW(dev) && port == PORT_C) dpi_enabled = I915_READ(PIPECONF(PIPE_B)) & PIPECONF_ENABLE; if (dpi_enabled || (func & CMD_MODE_DATA_WIDTH_MASK)) { if (I915_READ(MIPI_DEVICE_READY(port)) & DEVICE_READY) { *pipe = port == PORT_A ? PIPE_A : PIPE_B; - return true; + ret = true; + + goto out; } } } +out: + intel_display_power_put(dev_priv, power_domain); - return false; + return ret; } static void intel_dsi_get_config(struct intel_encoder *encoder, @@ -698,6 +712,8 @@ static void intel_dsi_get_config(struct intel_encoder *encoder, u32 pclk = 0; DRM_DEBUG_KMS("\n"); + pipe_config->has_dsi_encoder = true; + /* * DPLL_MD is not used in case of DSI, reading will get some default value * set dpll_md = 0 @@ -706,7 +722,8 @@ static void intel_dsi_get_config(struct intel_encoder *encoder, if (IS_BROXTON(encoder->base.dev)) pclk = bxt_get_dsi_pclk(encoder, pipe_config->pipe_bpp); - else if (IS_VALLEYVIEW(encoder->base.dev)) + else if (IS_VALLEYVIEW(encoder->base.dev) || + IS_CHERRYVIEW(encoder->base.dev)) pclk = vlv_get_dsi_pclk(encoder, pipe_config->pipe_bpp); if (!pclk) @@ -859,7 +876,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) } for_each_dsi_port(port, intel_dsi->ports) { - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { /* * escape clock divider, 20MHz, shared for A and C. * device ready must be off when doing this! txclkesc? @@ -875,21 +892,12 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) I915_WRITE(MIPI_CTRL(port), tmp | READ_REQUEST_PRIORITY_HIGH); } else if (IS_BROXTON(dev)) { - /* - * FIXME: - * BXT can connect any PIPE to any MIPI port. - * Select the pipe based on the MIPI port read from - * VBT for now. Pick PIPE A for MIPI port A and C - * for port C. - */ + enum pipe pipe = intel_crtc->pipe; + tmp = I915_READ(MIPI_CTRL(port)); tmp &= ~BXT_PIPE_SELECT_MASK; - if (port == PORT_A) - tmp |= BXT_PIPE_SELECT_A; - else if (port == PORT_C) - tmp |= BXT_PIPE_SELECT_C; - + tmp |= BXT_PIPE_SELECT(pipe); I915_WRITE(MIPI_CTRL(port), tmp); } @@ -1025,15 +1033,6 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) } } -static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder) -{ - DRM_DEBUG_KMS("\n"); - - intel_dsi_prepare(encoder); - intel_enable_dsi_pll(encoder); - -} - static enum drm_connector_status intel_dsi_detect(struct drm_connector *connector, bool force) { @@ -1128,7 +1127,7 @@ void intel_dsi_init(struct drm_device *dev) if (!dev_priv->vbt.has_mipi) return; - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { dev_priv->mipi_mmio_base = VLV_MIPI_BASE; } else { DRM_ERROR("Unsupported Mipi device to reg base"); @@ -1151,11 +1150,10 @@ void intel_dsi_init(struct drm_device *dev) connector = &intel_connector->base; - drm_encoder_init(dev, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI); + drm_encoder_init(dev, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI, + NULL); - /* XXX: very likely not all of these are needed */ 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_nop; intel_encoder->disable = intel_dsi_pre_disable; diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index e6cb25239..02551ff22 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -117,7 +117,7 @@ static inline struct intel_dsi_host *to_intel_dsi_host(struct mipi_dsi_host *h) #define for_each_dsi_port(__port, __ports_mask) \ for ((__port) = PORT_A; (__port) < I915_MAX_PORTS; (__port)++) \ - if ((__ports_mask) & (1 << (__port))) + for_each_if ((__ports_mask) & (1 << (__port))) static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder) { diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index a8912aecc..e8113ad65 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -204,6 +204,9 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) struct drm_device *dev = intel_dsi->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + if (dev_priv->vbt.dsi.seq_version >= 3) + data++; + gpio = *data++; /* pull up/down */ @@ -214,6 +217,16 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) goto out; } + if (!IS_VALLEYVIEW(dev_priv)) { + DRM_DEBUG_KMS("GPIO element not supported on this platform\n"); + goto out; + } + + if (dev_priv->vbt.dsi.seq_version >= 3) { + DRM_DEBUG_KMS("GPIO element v3 not supported\n"); + goto out; + } + function = gtable[gpio].function_reg; pad = gtable[gpio].pad_reg; diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index cb3cf3986..fbd2b5181 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -561,7 +561,7 @@ void intel_enable_dsi_pll(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) vlv_enable_dsi_pll(encoder); else if (IS_BROXTON(dev)) bxt_enable_dsi_pll(encoder); @@ -571,7 +571,7 @@ void intel_disable_dsi_pll(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) vlv_disable_dsi_pll(encoder); else if (IS_BROXTON(dev)) bxt_disable_dsi_pll(encoder); @@ -599,6 +599,6 @@ void intel_dsi_reset_clocks(struct intel_encoder *encoder, enum port port) if (IS_BROXTON(dev)) bxt_dsi_reset_clocks(encoder, port); - else if (IS_VALLEYVIEW(dev)) + else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) vlv_dsi_reset_clocks(encoder, port); } diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 8492053e0..286baec97 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -44,6 +44,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = { .type = INTEL_DVO_CHIP_TMDS, .name = "sil164", .dvo_reg = DVOC, + .dvo_srcdim_reg = DVOC_SRCDIM, .slave_addr = SIL164_ADDR, .dev_ops = &sil164_ops, }, @@ -51,6 +52,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = { .type = INTEL_DVO_CHIP_TMDS, .name = "ch7xxx", .dvo_reg = DVOC, + .dvo_srcdim_reg = DVOC_SRCDIM, .slave_addr = CH7xxx_ADDR, .dev_ops = &ch7xxx_ops, }, @@ -58,6 +60,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = { .type = INTEL_DVO_CHIP_TMDS, .name = "ch7xxx", .dvo_reg = DVOC, + .dvo_srcdim_reg = DVOC_SRCDIM, .slave_addr = 0x75, /* For some ch7010 */ .dev_ops = &ch7xxx_ops, }, @@ -65,6 +68,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = { .type = INTEL_DVO_CHIP_LVDS, .name = "ivch", .dvo_reg = DVOA, + .dvo_srcdim_reg = DVOA_SRCDIM, .slave_addr = 0x02, /* Might also be 0x44, 0x84, 0xc4 */ .dev_ops = &ivch_ops, }, @@ -72,6 +76,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = { .type = INTEL_DVO_CHIP_TMDS, .name = "tfp410", .dvo_reg = DVOC, + .dvo_srcdim_reg = DVOC_SRCDIM, .slave_addr = TFP410_ADDR, .dev_ops = &tfp410_ops, }, @@ -79,6 +84,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = { .type = INTEL_DVO_CHIP_LVDS, .name = "ch7017", .dvo_reg = DVOC, + .dvo_srcdim_reg = DVOC_SRCDIM, .slave_addr = 0x75, .gpio = GMBUS_PIN_DPB, .dev_ops = &ch7017_ops, @@ -87,6 +93,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = { .type = INTEL_DVO_CHIP_TMDS, .name = "ns2501", .dvo_reg = DVOB, + .dvo_srcdim_reg = DVOB_SRCDIM, .slave_addr = NS2501_ADDR, .dev_ops = &ns2501_ops, } @@ -171,7 +178,7 @@ static void intel_disable_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); - u32 dvo_reg = intel_dvo->dev.dvo_reg; + i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg; u32 temp = I915_READ(dvo_reg); intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false); @@ -184,7 +191,7 @@ 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; + i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg; u32 temp = I915_READ(dvo_reg); intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, @@ -255,20 +262,8 @@ static void intel_dvo_pre_enable(struct intel_encoder *encoder) struct intel_dvo *intel_dvo = enc_to_dvo(encoder); int pipe = crtc->pipe; u32 dvo_val; - u32 dvo_reg = intel_dvo->dev.dvo_reg, dvo_srcdim_reg; - - switch (dvo_reg) { - case DVOA: - default: - dvo_srcdim_reg = DVOA_SRCDIM; - break; - case DVOB: - dvo_srcdim_reg = DVOB_SRCDIM; - break; - case DVOC: - dvo_srcdim_reg = DVOC_SRCDIM; - break; - } + i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg; + i915_reg_t dvo_srcdim_reg = intel_dvo->dev.dvo_srcdim_reg; /* Save the data order, since I don't know what it should be set to. */ dvo_val = I915_READ(dvo_reg) & @@ -434,7 +429,7 @@ void intel_dvo_init(struct drm_device *dev) intel_encoder = &intel_dvo->base; drm_encoder_init(dev, &intel_encoder->base, - &intel_dvo_enc_funcs, encoder_type); + &intel_dvo_enc_funcs, encoder_type, NULL); intel_encoder->disable = intel_disable_dvo; intel_encoder->enable = intel_enable_dvo; diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index cf47352b7..a1988a486 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -43,7 +43,17 @@ static inline bool fbc_supported(struct drm_i915_private *dev_priv) { - return dev_priv->fbc.enable_fbc != NULL; + return dev_priv->fbc.activate != NULL; +} + +static inline bool fbc_on_pipe_a_only(struct drm_i915_private *dev_priv) +{ + return IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8; +} + +static inline bool fbc_on_plane_a_only(struct drm_i915_private *dev_priv) +{ + return INTEL_INFO(dev_priv)->gen < 4; } /* @@ -59,11 +69,51 @@ static unsigned int get_crtc_fence_y_offset(struct intel_crtc *crtc) return crtc->base.y - crtc->adjusted_y; } -static void i8xx_fbc_disable(struct drm_i915_private *dev_priv) +/* + * For SKL+, the plane source size used by the hardware is based on the value we + * write to the PLANE_SIZE register. For BDW-, the hardware looks at the value + * we wrote to PIPESRC. + */ +static void intel_fbc_get_plane_source_size(struct intel_crtc *crtc, + int *width, int *height) +{ + struct intel_plane_state *plane_state = + to_intel_plane_state(crtc->base.primary->state); + int w, h; + + if (intel_rotation_90_or_270(plane_state->base.rotation)) { + w = drm_rect_height(&plane_state->src) >> 16; + h = drm_rect_width(&plane_state->src) >> 16; + } else { + w = drm_rect_width(&plane_state->src) >> 16; + h = drm_rect_height(&plane_state->src) >> 16; + } + + if (width) + *width = w; + if (height) + *height = h; +} + +static int intel_fbc_calculate_cfb_size(struct intel_crtc *crtc, + struct drm_framebuffer *fb) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + int lines; + + intel_fbc_get_plane_source_size(crtc, NULL, &lines); + if (INTEL_INFO(dev_priv)->gen >= 7) + lines = min(lines, 2048); + + /* Hardware needs the full buffer stride, not just the active area. */ + return lines * fb->pitches[0]; +} + +static void i8xx_fbc_deactivate(struct drm_i915_private *dev_priv) { u32 fbc_ctl; - dev_priv->fbc.enabled = false; + dev_priv->fbc.active = false; /* Disable compression */ fbc_ctl = I915_READ(FBC_CONTROL); @@ -78,11 +128,9 @@ static void i8xx_fbc_disable(struct drm_i915_private *dev_priv) DRM_DEBUG_KMS("FBC idle timed out\n"); return; } - - DRM_DEBUG_KMS("disabled FBC\n"); } -static void i8xx_fbc_enable(struct intel_crtc *crtc) +static void i8xx_fbc_activate(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct drm_framebuffer *fb = crtc->base.primary->fb; @@ -91,10 +139,10 @@ static void i8xx_fbc_enable(struct intel_crtc *crtc) int i; u32 fbc_ctl; - dev_priv->fbc.enabled = true; + dev_priv->fbc.active = true; /* Note: fbc.threshold == 1 for i8xx */ - cfb_pitch = dev_priv->fbc.uncompressed_size / FBC_LL_SIZE; + cfb_pitch = intel_fbc_calculate_cfb_size(crtc, fb) / FBC_LL_SIZE; if (fb->pitches[0] < cfb_pitch) cfb_pitch = fb->pitches[0]; @@ -127,24 +175,21 @@ static void i8xx_fbc_enable(struct intel_crtc *crtc) fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; fbc_ctl |= obj->fence_reg; I915_WRITE(FBC_CONTROL, fbc_ctl); - - DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %c\n", - cfb_pitch, crtc->base.y, plane_name(crtc->plane)); } -static bool i8xx_fbc_enabled(struct drm_i915_private *dev_priv) +static bool i8xx_fbc_is_active(struct drm_i915_private *dev_priv) { return I915_READ(FBC_CONTROL) & FBC_CTL_EN; } -static void g4x_fbc_enable(struct intel_crtc *crtc) +static void g4x_fbc_activate(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct drm_framebuffer *fb = crtc->base.primary->fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); u32 dpfc_ctl; - dev_priv->fbc.enabled = true; + dev_priv->fbc.active = true; dpfc_ctl = DPFC_CTL_PLANE(crtc->plane) | DPFC_SR_EN; if (drm_format_plane_cpp(fb->pixel_format, 0) == 2) @@ -157,38 +202,35 @@ static void g4x_fbc_enable(struct intel_crtc *crtc) /* enable it... */ I915_WRITE(DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); - - DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane)); } -static void g4x_fbc_disable(struct drm_i915_private *dev_priv) +static void g4x_fbc_deactivate(struct drm_i915_private *dev_priv) { u32 dpfc_ctl; - dev_priv->fbc.enabled = false; + dev_priv->fbc.active = false; /* Disable compression */ dpfc_ctl = I915_READ(DPFC_CONTROL); if (dpfc_ctl & DPFC_CTL_EN) { dpfc_ctl &= ~DPFC_CTL_EN; I915_WRITE(DPFC_CONTROL, dpfc_ctl); - - DRM_DEBUG_KMS("disabled FBC\n"); } } -static bool g4x_fbc_enabled(struct drm_i915_private *dev_priv) +static bool g4x_fbc_is_active(struct drm_i915_private *dev_priv) { return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN; } -static void intel_fbc_nuke(struct drm_i915_private *dev_priv) +/* This function forces a CFB recompression through the nuke operation. */ +static void intel_fbc_recompress(struct drm_i915_private *dev_priv) { I915_WRITE(MSG_FBC_REND_STATE, FBC_REND_NUKE); POSTING_READ(MSG_FBC_REND_STATE); } -static void ilk_fbc_enable(struct intel_crtc *crtc) +static void ilk_fbc_activate(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct drm_framebuffer *fb = crtc->base.primary->fb; @@ -197,7 +239,7 @@ static void ilk_fbc_enable(struct intel_crtc *crtc) int threshold = dev_priv->fbc.threshold; unsigned int y_offset; - dev_priv->fbc.enabled = true; + dev_priv->fbc.active = true; dpfc_ctl = DPFC_CTL_PLANE(crtc->plane); if (drm_format_plane_cpp(fb->pixel_format, 0) == 2) @@ -231,33 +273,29 @@ static void ilk_fbc_enable(struct intel_crtc *crtc) I915_WRITE(DPFC_CPU_FENCE_OFFSET, y_offset); } - intel_fbc_nuke(dev_priv); - - DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane)); + intel_fbc_recompress(dev_priv); } -static void ilk_fbc_disable(struct drm_i915_private *dev_priv) +static void ilk_fbc_deactivate(struct drm_i915_private *dev_priv) { u32 dpfc_ctl; - dev_priv->fbc.enabled = false; + dev_priv->fbc.active = false; /* Disable compression */ dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); if (dpfc_ctl & DPFC_CTL_EN) { dpfc_ctl &= ~DPFC_CTL_EN; I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); - - DRM_DEBUG_KMS("disabled FBC\n"); } } -static bool ilk_fbc_enabled(struct drm_i915_private *dev_priv) +static bool ilk_fbc_is_active(struct drm_i915_private *dev_priv) { return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN; } -static void gen7_fbc_enable(struct intel_crtc *crtc) +static void gen7_fbc_activate(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct drm_framebuffer *fb = crtc->base.primary->fb; @@ -265,7 +303,7 @@ static void gen7_fbc_enable(struct intel_crtc *crtc) u32 dpfc_ctl; int threshold = dev_priv->fbc.threshold; - dev_priv->fbc.enabled = true; + dev_priv->fbc.active = true; dpfc_ctl = 0; if (IS_IVYBRIDGE(dev_priv)) @@ -310,155 +348,120 @@ static void gen7_fbc_enable(struct intel_crtc *crtc) SNB_CPU_FENCE_ENABLE | obj->fence_reg); I915_WRITE(DPFC_CPU_FENCE_OFFSET, get_crtc_fence_y_offset(crtc)); - intel_fbc_nuke(dev_priv); - - DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(crtc->plane)); + intel_fbc_recompress(dev_priv); } /** - * intel_fbc_enabled - Is FBC enabled? + * intel_fbc_is_active - Is FBC active? * @dev_priv: i915 device instance * * This function is used to verify the current state of FBC. * FIXME: This should be tracked in the plane config eventually * instead of queried at runtime for most callers. */ -bool intel_fbc_enabled(struct drm_i915_private *dev_priv) +bool intel_fbc_is_active(struct drm_i915_private *dev_priv) { - return dev_priv->fbc.enabled; + return dev_priv->fbc.active; } -static void intel_fbc_enable(struct intel_crtc *crtc, - const struct drm_framebuffer *fb) +static void intel_fbc_activate(const struct drm_framebuffer *fb) { - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct drm_i915_private *dev_priv = fb->dev->dev_private; + struct intel_crtc *crtc = dev_priv->fbc.crtc; - dev_priv->fbc.enable_fbc(crtc); + dev_priv->fbc.activate(crtc); - dev_priv->fbc.crtc = crtc; dev_priv->fbc.fb_id = fb->base.id; dev_priv->fbc.y = crtc->base.y; } static void intel_fbc_work_fn(struct work_struct *__work) { - struct intel_fbc_work *work = - container_of(to_delayed_work(__work), - struct intel_fbc_work, work); - struct drm_i915_private *dev_priv = work->crtc->base.dev->dev_private; - struct drm_framebuffer *crtc_fb = work->crtc->base.primary->fb; + struct drm_i915_private *dev_priv = + container_of(__work, struct drm_i915_private, fbc.work.work); + struct intel_fbc_work *work = &dev_priv->fbc.work; + struct intel_crtc *crtc = dev_priv->fbc.crtc; + int delay_ms = 50; + +retry: + /* Delay the actual enabling to let pageflipping cease and the + * display to settle before starting the compression. Note that + * this delay also serves a second purpose: it allows for a + * vblank to pass after disabling the FBC before we attempt + * to modify the control registers. + * + * A more complicated solution would involve tracking vblanks + * following the termination of the page-flipping sequence + * and indeed performing the enable as a co-routine and not + * waiting synchronously upon the vblank. + * + * WaFbcWaitForVBlankBeforeEnable:ilk,snb + */ + wait_remaining_ms_from_jiffies(work->enable_jiffies, delay_ms); mutex_lock(&dev_priv->fbc.lock); - if (work == dev_priv->fbc.fbc_work) { - /* Double check that we haven't switched fb without cancelling - * the prior work. - */ - if (crtc_fb == work->fb) - intel_fbc_enable(work->crtc, work->fb); - dev_priv->fbc.fbc_work = NULL; + /* Were we cancelled? */ + if (!work->scheduled) + goto out; + + /* Were we delayed again while this function was sleeping? */ + if (time_after(work->enable_jiffies + msecs_to_jiffies(delay_ms), + jiffies)) { + mutex_unlock(&dev_priv->fbc.lock); + goto retry; } - mutex_unlock(&dev_priv->fbc.lock); - kfree(work); + if (crtc->base.primary->fb == work->fb) + intel_fbc_activate(work->fb); + + work->scheduled = false; + +out: + mutex_unlock(&dev_priv->fbc.lock); } static void intel_fbc_cancel_work(struct drm_i915_private *dev_priv) { WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock)); - - if (dev_priv->fbc.fbc_work == NULL) - return; - - DRM_DEBUG_KMS("cancelling pending FBC enable\n"); - - /* Synchronisation is provided by struct_mutex and checking of - * dev_priv->fbc.fbc_work, so we can perform the cancellation - * entirely asynchronously. - */ - if (cancel_delayed_work(&dev_priv->fbc.fbc_work->work)) - /* tasklet was killed before being run, clean up */ - kfree(dev_priv->fbc.fbc_work); - - /* Mark the work as no longer wanted so that if it does - * wake-up (because the work was already running and waiting - * for our mutex), it will discover that is no longer - * necessary to run. - */ - dev_priv->fbc.fbc_work = NULL; + dev_priv->fbc.work.scheduled = false; } -static void intel_fbc_schedule_enable(struct intel_crtc *crtc) +static void intel_fbc_schedule_activation(struct intel_crtc *crtc) { - struct intel_fbc_work *work; struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_fbc_work *work = &dev_priv->fbc.work; WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock)); - intel_fbc_cancel_work(dev_priv); - - work = kzalloc(sizeof(*work), GFP_KERNEL); - if (work == NULL) { - DRM_ERROR("Failed to allocate FBC work structure\n"); - intel_fbc_enable(crtc, crtc->base.primary->fb); - return; - } - - work->crtc = crtc; + /* It is useless to call intel_fbc_cancel_work() in this function since + * we're not releasing fbc.lock, so it won't have an opportunity to grab + * it to discover that it was cancelled. So we just update the expected + * jiffy count. */ work->fb = crtc->base.primary->fb; - INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn); - - dev_priv->fbc.fbc_work = work; + work->scheduled = true; + work->enable_jiffies = jiffies; - /* Delay the actual enabling to let pageflipping cease and the - * display to settle before starting the compression. Note that - * this delay also serves a second purpose: it allows for a - * vblank to pass after disabling the FBC before we attempt - * to modify the control registers. - * - * A more complicated solution would involve tracking vblanks - * following the termination of the page-flipping sequence - * and indeed performing the enable as a co-routine and not - * waiting synchronously upon the vblank. - * - * WaFbcWaitForVBlankBeforeEnable:ilk,snb - */ - schedule_delayed_work(&work->work, msecs_to_jiffies(50)); + schedule_work(&work->work); } -static void __intel_fbc_disable(struct drm_i915_private *dev_priv) +static void __intel_fbc_deactivate(struct drm_i915_private *dev_priv) { WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock)); intel_fbc_cancel_work(dev_priv); - dev_priv->fbc.disable_fbc(dev_priv); - dev_priv->fbc.crtc = NULL; -} - -/** - * intel_fbc_disable - disable FBC - * @dev_priv: i915 device instance - * - * This function disables FBC. - */ -void intel_fbc_disable(struct drm_i915_private *dev_priv) -{ - if (!fbc_supported(dev_priv)) - return; - - mutex_lock(&dev_priv->fbc.lock); - __intel_fbc_disable(dev_priv); - mutex_unlock(&dev_priv->fbc.lock); + if (dev_priv->fbc.active) + dev_priv->fbc.deactivate(dev_priv); } /* - * intel_fbc_disable_crtc - disable FBC if it's associated with crtc + * intel_fbc_deactivate - deactivate FBC if it's associated with crtc * @crtc: the CRTC * - * This function disables FBC if it's associated with the provided CRTC. + * This function deactivates FBC if it's associated with the provided CRTC. */ -void intel_fbc_disable_crtc(struct intel_crtc *crtc) +void intel_fbc_deactivate(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; @@ -467,85 +470,42 @@ void intel_fbc_disable_crtc(struct intel_crtc *crtc) mutex_lock(&dev_priv->fbc.lock); if (dev_priv->fbc.crtc == crtc) - __intel_fbc_disable(dev_priv); + __intel_fbc_deactivate(dev_priv); mutex_unlock(&dev_priv->fbc.lock); } -const char *intel_no_fbc_reason_str(enum no_fbc_reason reason) -{ - switch (reason) { - case FBC_OK: - return "FBC enabled but currently disabled in hardware"; - case FBC_UNSUPPORTED: - return "unsupported by this chipset"; - case FBC_NO_OUTPUT: - return "no output"; - case FBC_STOLEN_TOO_SMALL: - return "not enough stolen memory"; - case FBC_UNSUPPORTED_MODE: - return "mode incompatible with compression"; - case FBC_MODE_TOO_LARGE: - return "mode too large for compression"; - case FBC_BAD_PLANE: - return "FBC unsupported on plane"; - case FBC_NOT_TILED: - return "framebuffer not tiled or fenced"; - case FBC_MULTIPLE_PIPES: - return "more than one pipe active"; - case FBC_MODULE_PARAM: - return "disabled per module param"; - case FBC_CHIP_DEFAULT: - return "disabled per chip default"; - case FBC_ROTATION: - return "rotation unsupported"; - case FBC_IN_DBG_MASTER: - return "Kernel debugger is active"; - case FBC_BAD_STRIDE: - return "framebuffer stride not supported"; - case FBC_PIXEL_RATE: - return "pixel rate is too big"; - case FBC_PIXEL_FORMAT: - return "pixel format is invalid"; - default: - MISSING_CASE(reason); - return "unknown reason"; - } -} - static void set_no_fbc_reason(struct drm_i915_private *dev_priv, - enum no_fbc_reason reason) + const char *reason) { if (dev_priv->fbc.no_fbc_reason == reason) return; dev_priv->fbc.no_fbc_reason = reason; - DRM_DEBUG_KMS("Disabling FBC: %s\n", intel_no_fbc_reason_str(reason)); + DRM_DEBUG_KMS("Disabling FBC: %s\n", reason); } -static struct drm_crtc *intel_fbc_find_crtc(struct drm_i915_private *dev_priv) +static bool crtc_can_fbc(struct intel_crtc *crtc) { - struct drm_crtc *crtc = NULL, *tmp_crtc; - enum pipe pipe; - bool pipe_a_only = false; + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8) - pipe_a_only = true; + if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) + return false; - for_each_pipe(dev_priv, pipe) { - tmp_crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + if (fbc_on_plane_a_only(dev_priv) && crtc->plane != PLANE_A) + return false; - if (intel_crtc_active(tmp_crtc) && - to_intel_plane_state(tmp_crtc->primary->state)->visible) - crtc = tmp_crtc; + return true; +} - if (pipe_a_only) - break; - } +static bool crtc_is_valid(struct intel_crtc *crtc) +{ + if (!intel_crtc_active(&crtc->base)) + return false; - if (!crtc || crtc->primary->fb == NULL) - return NULL; + if (!to_intel_plane_state(crtc->base.primary->state)->visible) + return false; - return crtc; + return true; } static bool multiple_pipes_ok(struct drm_i915_private *dev_priv) @@ -581,7 +541,8 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv, * reserved range size, so it always assumes the maximum (8mb) is used. * If we enable FBC using a CFB on that memory range we'll get FIFO * underruns, even if that range is not reserved by the BIOS. */ - if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv)) + if (IS_BROADWELL(dev_priv) || + IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) end = dev_priv->gtt.stolen_size - 8 * 1024 * 1024; else end = dev_priv->gtt.stolen_usable_size; @@ -617,11 +578,17 @@ again: } } -static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv, int size, - int fb_cpp) +static int intel_fbc_alloc_cfb(struct intel_crtc *crtc) { + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct drm_framebuffer *fb = crtc->base.primary->state->fb; struct drm_mm_node *uninitialized_var(compressed_llb); - int ret; + int size, fb_cpp, ret; + + WARN_ON(drm_mm_node_allocated(&dev_priv->fbc.compressed_fb)); + + size = intel_fbc_calculate_cfb_size(crtc, fb); + fb_cpp = drm_format_plane_cpp(fb->pixel_format, 0); ret = find_compression_threshold(dev_priv, &dev_priv->fbc.compressed_fb, size, fb_cpp); @@ -656,8 +623,6 @@ static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv, int size, dev_priv->mm.stolen_base + compressed_llb->start); } - dev_priv->fbc.uncompressed_size = size; - DRM_DEBUG_KMS("reserved %llu bytes of contiguous stolen space for FBC, threshold: %d\n", dev_priv->fbc.compressed_fb.size, dev_priv->fbc.threshold); @@ -674,18 +639,15 @@ err_llb: static void __intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv) { - if (dev_priv->fbc.uncompressed_size == 0) - return; - - i915_gem_stolen_remove_node(dev_priv, &dev_priv->fbc.compressed_fb); + if (drm_mm_node_allocated(&dev_priv->fbc.compressed_fb)) + i915_gem_stolen_remove_node(dev_priv, + &dev_priv->fbc.compressed_fb); if (dev_priv->fbc.compressed_llb) { i915_gem_stolen_remove_node(dev_priv, dev_priv->fbc.compressed_llb); kfree(dev_priv->fbc.compressed_llb); } - - dev_priv->fbc.uncompressed_size = 0; } void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv) @@ -698,63 +660,6 @@ void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv) mutex_unlock(&dev_priv->fbc.lock); } -/* - * For SKL+, the plane source size used by the hardware is based on the value we - * write to the PLANE_SIZE register. For BDW-, the hardware looks at the value - * we wrote to PIPESRC. - */ -static void intel_fbc_get_plane_source_size(struct intel_crtc *crtc, - int *width, int *height) -{ - struct intel_plane_state *plane_state = - to_intel_plane_state(crtc->base.primary->state); - int w, h; - - if (intel_rotation_90_or_270(plane_state->base.rotation)) { - w = drm_rect_height(&plane_state->src) >> 16; - h = drm_rect_width(&plane_state->src) >> 16; - } else { - w = drm_rect_width(&plane_state->src) >> 16; - h = drm_rect_height(&plane_state->src) >> 16; - } - - if (width) - *width = w; - if (height) - *height = h; -} - -static int intel_fbc_calculate_cfb_size(struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - struct drm_framebuffer *fb = crtc->base.primary->fb; - int lines; - - intel_fbc_get_plane_source_size(crtc, NULL, &lines); - if (INTEL_INFO(dev_priv)->gen >= 7) - lines = min(lines, 2048); - - return lines * fb->pitches[0]; -} - -static int intel_fbc_setup_cfb(struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - struct drm_framebuffer *fb = crtc->base.primary->fb; - int size, cpp; - - size = intel_fbc_calculate_cfb_size(crtc); - cpp = drm_format_plane_cpp(fb->pixel_format, 0); - - if (size <= dev_priv->fbc.uncompressed_size) - return 0; - - /* Release any current block */ - __intel_fbc_cleanup_cfb(dev_priv); - - return intel_fbc_alloc_cfb(dev_priv, size, cpp); -} - static bool stride_is_valid(struct drm_i915_private *dev_priv, unsigned int stride) { @@ -829,87 +734,46 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc) } /** - * __intel_fbc_update - enable/disable FBC as needed, unlocked - * @dev_priv: i915 device instance - * - * Set up the framebuffer compression hardware at mode set time. We - * enable it if possible: - * - plane A only (on pre-965) - * - no pixel mulitply/line duplication - * - no alpha buffer discard - * - no dual wide - * - framebuffer <= max_hdisplay in width, max_vdisplay in height - * - * We can't assume that any compression will take place (worst case), - * so the compressed buffer has to be the same size as the uncompressed - * one. It also must reside (along with the line length buffer) in - * stolen memory. + * __intel_fbc_update - activate/deactivate FBC as needed, unlocked + * @crtc: the CRTC that triggered the update * - * We need to enable/disable FBC on a global basis. + * This function completely reevaluates the status of FBC, then activates, + * deactivates or maintains it on the same state. */ -static void __intel_fbc_update(struct drm_i915_private *dev_priv) +static void __intel_fbc_update(struct intel_crtc *crtc) { - struct drm_crtc *crtc = NULL; - struct intel_crtc *intel_crtc; + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct drm_framebuffer *fb; struct drm_i915_gem_object *obj; const struct drm_display_mode *adjusted_mode; WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock)); - /* disable framebuffer compression in vGPU */ - if (intel_vgpu_active(dev_priv->dev)) - i915.enable_fbc = 0; - - if (i915.enable_fbc < 0) { - set_no_fbc_reason(dev_priv, FBC_CHIP_DEFAULT); + if (!multiple_pipes_ok(dev_priv)) { + set_no_fbc_reason(dev_priv, "more than one pipe active"); goto out_disable; } - if (!i915.enable_fbc) { - set_no_fbc_reason(dev_priv, FBC_MODULE_PARAM); - goto out_disable; - } + if (!dev_priv->fbc.enabled || dev_priv->fbc.crtc != crtc) + return; - /* - * If FBC is already on, we just have to verify that we can - * keep it that way... - * Need to disable if: - * - more than one pipe is active - * - changing FBC params (stride, fence, mode) - * - new fb is too large to fit in compressed buffer - * - going to an unsupported config (interlace, pixel multiply, etc.) - */ - crtc = intel_fbc_find_crtc(dev_priv); - if (!crtc) { - set_no_fbc_reason(dev_priv, FBC_NO_OUTPUT); + if (!crtc_is_valid(crtc)) { + set_no_fbc_reason(dev_priv, "no output"); goto out_disable; } - if (!multiple_pipes_ok(dev_priv)) { - set_no_fbc_reason(dev_priv, FBC_MULTIPLE_PIPES); - goto out_disable; - } - - intel_crtc = to_intel_crtc(crtc); - fb = crtc->primary->fb; + fb = crtc->base.primary->fb; obj = intel_fb_obj(fb); - adjusted_mode = &intel_crtc->config->base.adjusted_mode; + adjusted_mode = &crtc->config->base.adjusted_mode; if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) || (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) { - set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED_MODE); + set_no_fbc_reason(dev_priv, "incompatible mode"); goto out_disable; } - if (!intel_fbc_hw_tracking_covers_screen(intel_crtc)) { - set_no_fbc_reason(dev_priv, FBC_MODE_TOO_LARGE); - goto out_disable; - } - - if ((INTEL_INFO(dev_priv)->gen < 4 || HAS_DDI(dev_priv)) && - intel_crtc->plane != PLANE_A) { - set_no_fbc_reason(dev_priv, FBC_BAD_PLANE); + if (!intel_fbc_hw_tracking_covers_screen(crtc)) { + set_no_fbc_reason(dev_priv, "mode too large for compression"); goto out_disable; } @@ -918,41 +782,46 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv) */ if (obj->tiling_mode != I915_TILING_X || obj->fence_reg == I915_FENCE_REG_NONE) { - set_no_fbc_reason(dev_priv, FBC_NOT_TILED); + set_no_fbc_reason(dev_priv, "framebuffer not tiled or fenced"); goto out_disable; } if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_G4X(dev_priv) && - crtc->primary->state->rotation != BIT(DRM_ROTATE_0)) { - set_no_fbc_reason(dev_priv, FBC_ROTATION); + crtc->base.primary->state->rotation != BIT(DRM_ROTATE_0)) { + set_no_fbc_reason(dev_priv, "rotation unsupported"); goto out_disable; } if (!stride_is_valid(dev_priv, fb->pitches[0])) { - set_no_fbc_reason(dev_priv, FBC_BAD_STRIDE); + set_no_fbc_reason(dev_priv, "framebuffer stride not supported"); goto out_disable; } if (!pixel_format_is_valid(fb)) { - set_no_fbc_reason(dev_priv, FBC_PIXEL_FORMAT); - goto out_disable; - } - - /* If the kernel debugger is active, always disable compression */ - if (in_dbg_master()) { - set_no_fbc_reason(dev_priv, FBC_IN_DBG_MASTER); + set_no_fbc_reason(dev_priv, "pixel format is invalid"); goto out_disable; } /* WaFbcExceedCdClockThreshold:hsw,bdw */ if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) && - ilk_pipe_pixel_rate(intel_crtc->config) >= + ilk_pipe_pixel_rate(crtc->config) >= dev_priv->cdclk_freq * 95 / 100) { - set_no_fbc_reason(dev_priv, FBC_PIXEL_RATE); + set_no_fbc_reason(dev_priv, "pixel rate is too big"); goto out_disable; } - if (intel_fbc_setup_cfb(intel_crtc)) { - set_no_fbc_reason(dev_priv, FBC_STOLEN_TOO_SMALL); + /* It is possible for the required CFB size change without a + * crtc->disable + crtc->enable since it is possible to change the + * stride without triggering a full modeset. Since we try to + * over-allocate the CFB, there's a chance we may keep FBC enabled even + * if this happens, but if we exceed the current CFB size we'll have to + * disable FBC. Notice that it would be possible to disable FBC, wait + * for a frame, free the stolen node, then try to reenable FBC in case + * we didn't get any invalidate/deactivate calls, but this would require + * a lot of tracking just for a specific case. If we conclude it's an + * important case, we can implement it later. */ + if (intel_fbc_calculate_cfb_size(crtc, fb) > + dev_priv->fbc.compressed_fb.size * dev_priv->fbc.threshold) { + set_no_fbc_reason(dev_priv, "CFB requirements changed"); goto out_disable; } @@ -961,12 +830,13 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv) * cannot be unpinned (and have its GTT offset and fence revoked) * without first being decoupled from the scanout and FBC disabled. */ - if (dev_priv->fbc.crtc == intel_crtc && + if (dev_priv->fbc.crtc == crtc && dev_priv->fbc.fb_id == fb->base.id && - dev_priv->fbc.y == crtc->y) + dev_priv->fbc.y == crtc->base.y && + dev_priv->fbc.active) return; - if (intel_fbc_enabled(dev_priv)) { + if (intel_fbc_is_active(dev_priv)) { /* We update FBC along two paths, after changing fb/crtc * configuration (modeswitching) and after page-flipping * finishes. For the latter, we know that not only did @@ -990,36 +860,37 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv) * disabling paths we do need to wait for a vblank at * some point. And we wait before enabling FBC anyway. */ - DRM_DEBUG_KMS("disabling active FBC for update\n"); - __intel_fbc_disable(dev_priv); + DRM_DEBUG_KMS("deactivating FBC for update\n"); + __intel_fbc_deactivate(dev_priv); } - intel_fbc_schedule_enable(intel_crtc); - dev_priv->fbc.no_fbc_reason = FBC_OK; + intel_fbc_schedule_activation(crtc); + dev_priv->fbc.no_fbc_reason = "FBC enabled (not necessarily active)"; return; out_disable: /* Multiple disables should be harmless */ - if (intel_fbc_enabled(dev_priv)) { - DRM_DEBUG_KMS("unsupported config, disabling FBC\n"); - __intel_fbc_disable(dev_priv); + if (intel_fbc_is_active(dev_priv)) { + DRM_DEBUG_KMS("unsupported config, deactivating FBC\n"); + __intel_fbc_deactivate(dev_priv); } - __intel_fbc_cleanup_cfb(dev_priv); } /* - * intel_fbc_update - enable/disable FBC as needed - * @dev_priv: i915 device instance + * intel_fbc_update - activate/deactivate FBC as needed + * @crtc: the CRTC that triggered the update * - * This function reevaluates the overall state and enables or disables FBC. + * This function reevaluates the overall state and activates or deactivates FBC. */ -void intel_fbc_update(struct drm_i915_private *dev_priv) +void intel_fbc_update(struct intel_crtc *crtc) { + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + if (!fbc_supported(dev_priv)) return; mutex_lock(&dev_priv->fbc.lock); - __intel_fbc_update(dev_priv); + __intel_fbc_update(crtc); mutex_unlock(&dev_priv->fbc.lock); } @@ -1039,16 +910,13 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv, if (dev_priv->fbc.enabled) fbc_bits = INTEL_FRONTBUFFER_PRIMARY(dev_priv->fbc.crtc->pipe); - else if (dev_priv->fbc.fbc_work) - fbc_bits = INTEL_FRONTBUFFER_PRIMARY( - dev_priv->fbc.fbc_work->crtc->pipe); else fbc_bits = dev_priv->fbc.possible_framebuffer_bits; dev_priv->fbc.busy_bits |= (fbc_bits & frontbuffer_bits); if (dev_priv->fbc.busy_bits) - __intel_fbc_disable(dev_priv); + __intel_fbc_deactivate(dev_priv); mutex_unlock(&dev_priv->fbc.lock); } @@ -1066,11 +934,136 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, dev_priv->fbc.busy_bits &= ~frontbuffer_bits; - if (!dev_priv->fbc.busy_bits) { + if (!dev_priv->fbc.busy_bits && dev_priv->fbc.enabled) { + if (origin != ORIGIN_FLIP && dev_priv->fbc.active) { + intel_fbc_recompress(dev_priv); + } else { + __intel_fbc_deactivate(dev_priv); + __intel_fbc_update(dev_priv->fbc.crtc); + } + } + + mutex_unlock(&dev_priv->fbc.lock); +} + +/** + * intel_fbc_enable: tries to enable FBC on the CRTC + * @crtc: the CRTC + * + * This function checks if it's possible to enable FBC on the following CRTC, + * then enables it. Notice that it doesn't activate FBC. + */ +void intel_fbc_enable(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + + if (!fbc_supported(dev_priv)) + return; + + mutex_lock(&dev_priv->fbc.lock); + + if (dev_priv->fbc.enabled) { + WARN_ON(dev_priv->fbc.crtc == crtc); + goto out; + } + + WARN_ON(dev_priv->fbc.active); + WARN_ON(dev_priv->fbc.crtc != NULL); + + if (intel_vgpu_active(dev_priv->dev)) { + set_no_fbc_reason(dev_priv, "VGPU is active"); + goto out; + } + + if (i915.enable_fbc < 0) { + set_no_fbc_reason(dev_priv, "disabled per chip default"); + goto out; + } + + if (!i915.enable_fbc) { + set_no_fbc_reason(dev_priv, "disabled per module param"); + goto out; + } + + if (!crtc_can_fbc(crtc)) { + set_no_fbc_reason(dev_priv, "no enabled pipes can have FBC"); + goto out; + } + + if (intel_fbc_alloc_cfb(crtc)) { + set_no_fbc_reason(dev_priv, "not enough stolen memory"); + goto out; + } + + DRM_DEBUG_KMS("Enabling FBC on pipe %c\n", pipe_name(crtc->pipe)); + dev_priv->fbc.no_fbc_reason = "FBC enabled but not active yet\n"; + + dev_priv->fbc.enabled = true; + dev_priv->fbc.crtc = crtc; +out: + mutex_unlock(&dev_priv->fbc.lock); +} + +/** + * __intel_fbc_disable - disable FBC + * @dev_priv: i915 device instance + * + * This is the low level function that actually disables FBC. Callers should + * grab the FBC lock. + */ +static void __intel_fbc_disable(struct drm_i915_private *dev_priv) +{ + struct intel_crtc *crtc = dev_priv->fbc.crtc; + + WARN_ON(!mutex_is_locked(&dev_priv->fbc.lock)); + WARN_ON(!dev_priv->fbc.enabled); + WARN_ON(dev_priv->fbc.active); + assert_pipe_disabled(dev_priv, crtc->pipe); + + DRM_DEBUG_KMS("Disabling FBC on pipe %c\n", pipe_name(crtc->pipe)); + + __intel_fbc_cleanup_cfb(dev_priv); + + dev_priv->fbc.enabled = false; + dev_priv->fbc.crtc = NULL; +} + +/** + * intel_fbc_disable_crtc - disable FBC if it's associated with crtc + * @crtc: the CRTC + * + * This function disables FBC if it's associated with the provided CRTC. + */ +void intel_fbc_disable_crtc(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + + if (!fbc_supported(dev_priv)) + return; + + mutex_lock(&dev_priv->fbc.lock); + if (dev_priv->fbc.crtc == crtc) { + WARN_ON(!dev_priv->fbc.enabled); + WARN_ON(dev_priv->fbc.active); __intel_fbc_disable(dev_priv); - __intel_fbc_update(dev_priv); } + mutex_unlock(&dev_priv->fbc.lock); +} +/** + * intel_fbc_disable - globally disable FBC + * @dev_priv: i915 device instance + * + * This function disables FBC regardless of which CRTC is associated with it. + */ +void intel_fbc_disable(struct drm_i915_private *dev_priv) +{ + if (!fbc_supported(dev_priv)) + return; + + mutex_lock(&dev_priv->fbc.lock); + if (dev_priv->fbc.enabled) + __intel_fbc_disable(dev_priv); mutex_unlock(&dev_priv->fbc.lock); } @@ -1084,11 +1077,14 @@ void intel_fbc_init(struct drm_i915_private *dev_priv) { enum pipe pipe; + INIT_WORK(&dev_priv->fbc.work.work, intel_fbc_work_fn); mutex_init(&dev_priv->fbc.lock); + dev_priv->fbc.enabled = false; + dev_priv->fbc.active = false; + dev_priv->fbc.work.scheduled = false; if (!HAS_FBC(dev_priv)) { - dev_priv->fbc.enabled = false; - dev_priv->fbc.no_fbc_reason = FBC_UNSUPPORTED; + dev_priv->fbc.no_fbc_reason = "unsupported by this chipset"; return; } @@ -1096,30 +1092,34 @@ void intel_fbc_init(struct drm_i915_private *dev_priv) dev_priv->fbc.possible_framebuffer_bits |= INTEL_FRONTBUFFER_PRIMARY(pipe); - if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8) + if (fbc_on_pipe_a_only(dev_priv)) break; } if (INTEL_INFO(dev_priv)->gen >= 7) { - dev_priv->fbc.fbc_enabled = ilk_fbc_enabled; - dev_priv->fbc.enable_fbc = gen7_fbc_enable; - dev_priv->fbc.disable_fbc = ilk_fbc_disable; + dev_priv->fbc.is_active = ilk_fbc_is_active; + dev_priv->fbc.activate = gen7_fbc_activate; + dev_priv->fbc.deactivate = ilk_fbc_deactivate; } else if (INTEL_INFO(dev_priv)->gen >= 5) { - dev_priv->fbc.fbc_enabled = ilk_fbc_enabled; - dev_priv->fbc.enable_fbc = ilk_fbc_enable; - dev_priv->fbc.disable_fbc = ilk_fbc_disable; + dev_priv->fbc.is_active = ilk_fbc_is_active; + dev_priv->fbc.activate = ilk_fbc_activate; + dev_priv->fbc.deactivate = ilk_fbc_deactivate; } else if (IS_GM45(dev_priv)) { - dev_priv->fbc.fbc_enabled = g4x_fbc_enabled; - dev_priv->fbc.enable_fbc = g4x_fbc_enable; - dev_priv->fbc.disable_fbc = g4x_fbc_disable; + dev_priv->fbc.is_active = g4x_fbc_is_active; + dev_priv->fbc.activate = g4x_fbc_activate; + dev_priv->fbc.deactivate = g4x_fbc_deactivate; } else { - dev_priv->fbc.fbc_enabled = i8xx_fbc_enabled; - dev_priv->fbc.enable_fbc = i8xx_fbc_enable; - dev_priv->fbc.disable_fbc = i8xx_fbc_disable; + dev_priv->fbc.is_active = i8xx_fbc_is_active; + dev_priv->fbc.activate = i8xx_fbc_activate; + dev_priv->fbc.deactivate = i8xx_fbc_deactivate; /* This value was pulled out of someone's hat */ I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT); } - dev_priv->fbc.enabled = dev_priv->fbc.fbc_enabled(dev_priv); + /* We still don't have any sort of hardware state readout for FBC, so + * deactivate it in case the BIOS activated it to make sure software + * matches the hardware state. */ + if (dev_priv->fbc.is_active(dev_priv)) + dev_priv->fbc.deactivate(dev_priv); } diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 4fd5fdfef..bea75cafc 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -119,7 +119,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper, { struct intel_fbdev *ifbdev = container_of(helper, struct intel_fbdev, helper); - struct drm_framebuffer *fb; + struct drm_framebuffer *fb = NULL; struct drm_device *dev = helper->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct drm_mode_fb_cmd2 mode_cmd = {}; @@ -138,6 +138,8 @@ static int intelfb_alloc(struct drm_fb_helper *helper, mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); + mutex_lock(&dev->struct_mutex); + size = mode_cmd.pitches[0] * mode_cmd.height; size = PAGE_ALIGN(size); @@ -156,26 +158,21 @@ static int intelfb_alloc(struct drm_fb_helper *helper, fb = __intel_framebuffer_create(dev, &mode_cmd, obj); if (IS_ERR(fb)) { + drm_gem_object_unreference(&obj->base); ret = PTR_ERR(fb); - goto out_unref; + goto out; } - /* Flush everything out, we'll be doing GTT only from now on */ - ret = intel_pin_and_fence_fb_obj(NULL, fb, NULL, NULL, NULL); - if (ret) { - DRM_ERROR("failed to pin obj: %d\n", ret); - goto out_fb; - } + mutex_unlock(&dev->struct_mutex); ifbdev->fb = to_intel_framebuffer(fb); return 0; -out_fb: - drm_framebuffer_remove(fb); -out_unref: - drm_gem_object_unreference(&obj->base); out: + mutex_unlock(&dev->struct_mutex); + if (!IS_ERR_OR_NULL(fb)) + drm_framebuffer_unreference(fb); return ret; } @@ -193,8 +190,6 @@ static int intelfb_create(struct drm_fb_helper *helper, int size, ret; bool prealloc = false; - mutex_lock(&dev->struct_mutex); - if (intel_fb && (sizes->fb_width > intel_fb->base.width || sizes->fb_height > intel_fb->base.height)) { @@ -209,7 +204,7 @@ static int intelfb_create(struct drm_fb_helper *helper, DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n"); ret = intelfb_alloc(helper, sizes); if (ret) - goto out_unlock; + return ret; intel_fb = ifbdev->fb; } else { DRM_DEBUG_KMS("re-using BIOS fb\n"); @@ -221,8 +216,19 @@ static int intelfb_create(struct drm_fb_helper *helper, obj = intel_fb->obj; size = obj->base.size; + mutex_lock(&dev->struct_mutex); + + /* Pin the GGTT vma for our access via info->screen_base. + * This also validates that any existing fb inherited from the + * BIOS is suitable for own access. + */ + ret = intel_pin_and_fence_fb_obj(NULL, &ifbdev->fb->base, NULL); + if (ret) + goto out_unlock; + info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { + DRM_ERROR("Failed to allocate fb_info\n"); ret = PTR_ERR(info); goto out_unpin; } @@ -249,6 +255,7 @@ static int intelfb_create(struct drm_fb_helper *helper, ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj), size); if (!info->screen_base) { + DRM_ERROR("Failed to remap framebuffer into virtual memory\n"); ret = -ENOSPC; goto out_destroy_fbi; } @@ -281,7 +288,6 @@ out_destroy_fbi: drm_fb_helper_release_fbi(helper); out_unpin: i915_gem_object_ggtt_unpin(obj); - drm_gem_object_unreference(&obj->base); out_unlock: mutex_unlock(&dev->struct_mutex); return ret; @@ -520,14 +526,20 @@ static const struct drm_fb_helper_funcs intel_fb_helper_funcs = { static void intel_fbdev_destroy(struct drm_device *dev, struct intel_fbdev *ifbdev) { + /* We rely on the object-free to release the VMA pinning for + * the info->screen_base mmaping. Leaking the VMA is simpler than + * trying to rectify all the possible error paths leading here. + */ drm_fb_helper_unregister_fbi(&ifbdev->helper); drm_fb_helper_release_fbi(&ifbdev->helper); drm_fb_helper_fini(&ifbdev->helper); - drm_framebuffer_unregister_private(&ifbdev->fb->base); - drm_framebuffer_remove(&ifbdev->fb->base); + if (ifbdev->fb) { + drm_framebuffer_unregister_private(&ifbdev->fb->base); + drm_framebuffer_remove(&ifbdev->fb->base); + } } /* @@ -702,13 +714,20 @@ int intel_fbdev_init(struct drm_device *dev) return 0; } -void intel_fbdev_initial_config(void *data, async_cookie_t cookie) +static void intel_fbdev_initial_config(void *data, async_cookie_t cookie) { struct drm_i915_private *dev_priv = data; struct intel_fbdev *ifbdev = dev_priv->fbdev; /* Due to peculiar init order wrt to hpd handling this is separate. */ - drm_fb_helper_initial_config(&ifbdev->helper, ifbdev->preferred_bpp); + if (drm_fb_helper_initial_config(&ifbdev->helper, + ifbdev->preferred_bpp)) + intel_fbdev_fini(dev_priv->dev); +} + +void intel_fbdev_initial_config_async(struct drm_device *dev) +{ + async_schedule(intel_fbdev_initial_config, to_i915(dev)); } void intel_fbdev_fini(struct drm_device *dev) @@ -719,7 +738,8 @@ void intel_fbdev_fini(struct drm_device *dev) flush_work(&dev_priv->fbdev_suspend_work); - async_synchronize_full(); + if (!current_is_async()) + async_synchronize_full(); intel_fbdev_destroy(dev, dev_priv->fbdev); kfree(dev_priv->fbdev); dev_priv->fbdev = NULL; diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c index 54daa66c6..bda526660 100644 --- a/drivers/gpu/drm/i915/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c @@ -84,38 +84,21 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev) return true; } -/** - * i9xx_check_fifo_underruns - check for fifo underruns - * @dev_priv: i915 device instance - * - * This function checks for fifo underruns on GMCH platforms. This needs to be - * done manually on modeset to make sure that we catch all underruns since they - * do not generate an interrupt by themselves on these platforms. - */ -void i9xx_check_fifo_underruns(struct drm_i915_private *dev_priv) +static void i9xx_check_fifo_underruns(struct intel_crtc *crtc) { - struct intel_crtc *crtc; - - spin_lock_irq(&dev_priv->irq_lock); - - for_each_intel_crtc(dev_priv->dev, crtc) { - u32 reg = PIPESTAT(crtc->pipe); - u32 pipestat; - - if (crtc->cpu_fifo_underrun_disabled) - continue; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + i915_reg_t reg = PIPESTAT(crtc->pipe); + u32 pipestat = I915_READ(reg) & 0xffff0000; - pipestat = I915_READ(reg) & 0xffff0000; - if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0) - continue; + assert_spin_locked(&dev_priv->irq_lock); - I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS); - POSTING_READ(reg); + if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0) + return; - DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe)); - } + I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS); + POSTING_READ(reg); - spin_unlock_irq(&dev_priv->irq_lock); + DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe)); } static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev, @@ -123,7 +106,7 @@ static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev, bool enable, bool old) { struct drm_i915_private *dev_priv = dev->dev_private; - u32 reg = PIPESTAT(pipe); + i915_reg_t reg = PIPESTAT(pipe); u32 pipestat = I915_READ(reg) & 0xffff0000; assert_spin_locked(&dev_priv->irq_lock); @@ -145,9 +128,26 @@ static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev, DE_PIPEB_FIFO_UNDERRUN; if (enable) - ironlake_enable_display_irq(dev_priv, bit); + ilk_enable_display_irq(dev_priv, bit); else - ironlake_disable_display_irq(dev_priv, bit); + ilk_disable_display_irq(dev_priv, bit); +} + +static void ivybridge_check_fifo_underruns(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + uint32_t err_int = I915_READ(GEN7_ERR_INT); + + assert_spin_locked(&dev_priv->irq_lock); + + if ((err_int & ERR_INT_FIFO_UNDERRUN(pipe)) == 0) + return; + + I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe)); + POSTING_READ(GEN7_ERR_INT); + + DRM_ERROR("fifo underrun on pipe %c\n", pipe_name(pipe)); } static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev, @@ -161,9 +161,9 @@ static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev, if (!ivb_can_enable_err_int(dev)) return; - ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB); + ilk_enable_display_irq(dev_priv, DE_ERR_INT_IVB); } else { - ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB); + ilk_disable_display_irq(dev_priv, DE_ERR_INT_IVB); if (old && I915_READ(GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) { @@ -178,14 +178,10 @@ static void broadwell_set_fifo_underrun_reporting(struct drm_device *dev, { 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; + bdw_enable_pipe_irq(dev_priv, 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)); + bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN); } static void ibx_set_fifo_underrun_reporting(struct drm_device *dev, @@ -202,6 +198,24 @@ static void ibx_set_fifo_underrun_reporting(struct drm_device *dev, ibx_disable_display_interrupt(dev_priv, bit); } +static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum transcoder pch_transcoder = (enum transcoder) crtc->pipe; + uint32_t serr_int = I915_READ(SERR_INT); + + assert_spin_locked(&dev_priv->irq_lock); + + if ((serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) == 0) + return; + + I915_WRITE(SERR_INT, SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)); + POSTING_READ(SERR_INT); + + DRM_ERROR("pch fifo underrun on pch transcoder %c\n", + transcoder_name(pch_transcoder)); +} + static void cpt_set_fifo_underrun_reporting(struct drm_device *dev, enum transcoder pch_transcoder, bool enable, bool old) @@ -375,3 +389,56 @@ void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, DRM_ERROR("PCH transcoder %c FIFO underrun\n", transcoder_name(pch_transcoder)); } + +/** + * intel_check_cpu_fifo_underruns - check for CPU fifo underruns immediately + * @dev_priv: i915 device instance + * + * Check for CPU fifo underruns immediately. Useful on IVB/HSW where the shared + * error interrupt may have been disabled, and so CPU fifo underruns won't + * necessarily raise an interrupt, and on GMCH platforms where underruns never + * raise an interrupt. + */ +void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv) +{ + struct intel_crtc *crtc; + + spin_lock_irq(&dev_priv->irq_lock); + + for_each_intel_crtc(dev_priv->dev, crtc) { + if (crtc->cpu_fifo_underrun_disabled) + continue; + + if (HAS_GMCH_DISPLAY(dev_priv)) + i9xx_check_fifo_underruns(crtc); + else if (IS_GEN7(dev_priv)) + ivybridge_check_fifo_underruns(crtc); + } + + spin_unlock_irq(&dev_priv->irq_lock); +} + +/** + * intel_check_pch_fifo_underruns - check for PCH fifo underruns immediately + * @dev_priv: i915 device instance + * + * Check for PCH fifo underruns immediately. Useful on CPT/PPT where the shared + * error interrupt may have been disabled, and so PCH fifo underruns won't + * necessarily raise an interrupt. + */ +void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv) +{ + struct intel_crtc *crtc; + + spin_lock_irq(&dev_priv->irq_lock); + + for_each_intel_crtc(dev_priv->dev, crtc) { + if (crtc->pch_fifo_underrun_disabled) + continue; + + if (HAS_PCH_CPT(dev_priv)) + cpt_check_pch_fifo_underruns(crtc); + } + + spin_unlock_irq(&dev_priv->irq_lock); +} diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index 081d5f648..822952235 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -42,8 +42,6 @@ struct i915_guc_client { uint32_t wq_offset; uint32_t wq_size; - - spinlock_t wq_lock; /* Protects all data below */ uint32_t wq_tail; /* GuC submission statistics & status */ @@ -76,11 +74,17 @@ struct intel_guc_fw { uint16_t guc_fw_minor_wanted; uint16_t guc_fw_major_found; uint16_t guc_fw_minor_found; + + uint32_t header_size; + uint32_t header_offset; + uint32_t rsa_size; + uint32_t rsa_offset; + uint32_t ucode_size; + uint32_t ucode_offset; }; struct intel_guc { struct intel_guc_fw guc_fw; - uint32_t log_flags; struct drm_i915_gem_object *log_obj; @@ -89,8 +93,6 @@ struct intel_guc { struct i915_guc_client *execbuf_client; - spinlock_t host2guc_lock; /* Protects all data below */ - DECLARE_BITMAP(doorbell_bitmap, GUC_MAX_DOORBELLS); uint32_t db_cacheline; /* Cyclic counter mod pagesize */ diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index 593d2f585..40b2ea572 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h @@ -122,6 +122,78 @@ #define GUC_CTL_MAX_DWORDS (GUC_CTL_RSRVD + 1) +/** + * DOC: GuC Firmware Layout + * + * The GuC firmware layout looks like this: + * + * +-------------------------------+ + * | guc_css_header | + * | contains major/minor version | + * +-------------------------------+ + * | uCode | + * +-------------------------------+ + * | RSA signature | + * +-------------------------------+ + * | modulus key | + * +-------------------------------+ + * | exponent val | + * +-------------------------------+ + * + * The firmware may or may not have modulus key and exponent data. The header, + * uCode and RSA signature are must-have components that will be used by driver. + * Length of each components, which is all in dwords, can be found in header. + * In the case that modulus and exponent are not present in fw, a.k.a truncated + * image, the length value still appears in header. + * + * Driver will do some basic fw size validation based on the following rules: + * + * 1. Header, uCode and RSA are must-have components. + * 2. All firmware components, if they present, are in the sequence illustrated + * in the layout table above. + * 3. Length info of each component can be found in header, in dwords. + * 4. Modulus and exponent key are not required by driver. They may not appear + * in fw. So driver will load a truncated firmware in this case. + */ + +struct guc_css_header { + uint32_t module_type; + /* header_size includes all non-uCode bits, including css_header, rsa + * key, modulus key and exponent data. */ + uint32_t header_size_dw; + uint32_t header_version; + uint32_t module_id; + uint32_t module_vendor; + union { + struct { + uint8_t day; + uint8_t month; + uint16_t year; + }; + uint32_t date; + }; + uint32_t size_dw; /* uCode plus header_size_dw */ + uint32_t key_size_dw; + uint32_t modulus_size_dw; + uint32_t exponent_size_dw; + union { + struct { + uint8_t hour; + uint8_t min; + uint16_t sec; + }; + uint32_t time; + }; + + char username[8]; + char buildnumber[12]; + uint32_t device_id; + uint32_t guc_sw_version; + uint32_t prod_preprod_fw; + uint32_t reserved[12]; + uint32_t header_info; +} __packed; + struct guc_doorbell_info { u32 db_status; u32 cookie; diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 7e5b4f386..e27f82382 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -31,7 +31,7 @@ #include "intel_guc.h" /** - * DOC: GuC + * DOC: GuC-specific firmware loader * * intel_guc: * Top level structure of guc. It handles firmware loading and manages client @@ -208,16 +208,6 @@ static inline bool guc_ucode_response(struct drm_i915_private *dev_priv, /* * Transfer the firmware image to RAM for execution by the microcontroller. * - * GuC Firmware layout: - * +-------------------------------+ ---- - * | CSS header | 128B - * | contains major/minor version | - * +-------------------------------+ ---- - * | uCode | - * +-------------------------------+ ---- - * | RSA signature | 256B - * +-------------------------------+ ---- - * * Architecturally, the DMA engine is bidirectional, and can potentially even * transfer between GTT locations. This functionality is left out of the API * for now as there is no need for it. @@ -225,33 +215,29 @@ static inline bool guc_ucode_response(struct drm_i915_private *dev_priv, * Note that GuC needs the CSS header plus uKernel code to be copied by the * DMA engine in one operation, whereas the RSA signature is loaded via MMIO. */ - -#define UOS_CSS_HEADER_OFFSET 0 -#define UOS_VER_MINOR_OFFSET 0x44 -#define UOS_VER_MAJOR_OFFSET 0x46 -#define UOS_CSS_HEADER_SIZE 0x80 -#define UOS_RSA_SIG_SIZE 0x100 - static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv) { struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; struct drm_i915_gem_object *fw_obj = guc_fw->guc_fw_obj; unsigned long offset; struct sg_table *sg = fw_obj->pages; - u32 status, ucode_size, rsa[UOS_RSA_SIG_SIZE / sizeof(u32)]; + u32 status, rsa[UOS_RSA_SCRATCH_MAX_COUNT]; int i, ret = 0; - /* uCode size, also is where RSA signature starts */ - offset = ucode_size = guc_fw->guc_fw_size - UOS_RSA_SIG_SIZE; - I915_WRITE(DMA_COPY_SIZE, ucode_size); + /* where RSA signature starts */ + offset = guc_fw->rsa_offset; /* Copy RSA signature from the fw image to HW for verification */ - sg_pcopy_to_buffer(sg->sgl, sg->nents, rsa, UOS_RSA_SIG_SIZE, offset); - for (i = 0; i < UOS_RSA_SIG_SIZE / sizeof(u32); i++) + sg_pcopy_to_buffer(sg->sgl, sg->nents, rsa, sizeof(rsa), offset); + for (i = 0; i < UOS_RSA_SCRATCH_MAX_COUNT; i++) I915_WRITE(UOS_RSA_SCRATCH(i), rsa[i]); + /* The header plus uCode will be copied to WOPCM via DMA, excluding any + * other components */ + I915_WRITE(DMA_COPY_SIZE, guc_fw->header_size + guc_fw->ucode_size); + /* Set the source address for the new blob */ - offset = i915_gem_obj_ggtt_offset(fw_obj); + offset = i915_gem_obj_ggtt_offset(fw_obj) + guc_fw->header_offset; I915_WRITE(DMA_ADDR_0_LOW, lower_32_bits(offset)); I915_WRITE(DMA_ADDR_0_HIGH, upper_32_bits(offset) & 0xFFFF); @@ -322,8 +308,8 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE); /* WaDisableMinuteIaClockGating:skl,bxt */ - if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) || - (IS_BROXTON(dev) && INTEL_REVID(dev) == BXT_REVID_A0)) { + if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) || + IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { I915_WRITE(GUC_SHIM_CONTROL, (I915_READ(GUC_SHIM_CONTROL) & ~GUC_ENABLE_MIA_CLOCK_GATING)); } @@ -378,6 +364,9 @@ int intel_guc_ucode_load(struct drm_device *dev) struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; int err = 0; + if (!i915.enable_guc_submission) + return 0; + DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n", intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status), intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); @@ -457,10 +446,8 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) { struct drm_i915_gem_object *obj; const struct firmware *fw; - const u8 *css_header; - const size_t minsize = UOS_CSS_HEADER_SIZE + UOS_RSA_SIG_SIZE; - const size_t maxsize = GUC_WOPCM_SIZE_VALUE + UOS_RSA_SIG_SIZE - - 0x8000; /* 32k reserved (8K stack + 24k context) */ + struct guc_css_header *css; + size_t size; int err; DRM_DEBUG_DRIVER("before requesting firmware: GuC fw fetch status %s\n", @@ -474,12 +461,52 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) DRM_DEBUG_DRIVER("fetch GuC fw from %s succeeded, fw %p\n", guc_fw->guc_fw_path, fw); - DRM_DEBUG_DRIVER("firmware file size %zu (minimum %zu, maximum %zu)\n", - fw->size, minsize, maxsize); - /* Check the size of the blob befoe examining buffer contents */ - if (fw->size < minsize || fw->size > maxsize) + /* Check the size of the blob before examining buffer contents */ + if (fw->size < sizeof(struct guc_css_header)) { + DRM_ERROR("Firmware header is missing\n"); goto fail; + } + + css = (struct guc_css_header *)fw->data; + + /* Firmware bits always start from header */ + guc_fw->header_offset = 0; + guc_fw->header_size = (css->header_size_dw - css->modulus_size_dw - + css->key_size_dw - css->exponent_size_dw) * sizeof(u32); + + if (guc_fw->header_size != sizeof(struct guc_css_header)) { + DRM_ERROR("CSS header definition mismatch\n"); + goto fail; + } + + /* then, uCode */ + guc_fw->ucode_offset = guc_fw->header_offset + guc_fw->header_size; + guc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32); + + /* now RSA */ + if (css->key_size_dw != UOS_RSA_SCRATCH_MAX_COUNT) { + DRM_ERROR("RSA key size is bad\n"); + goto fail; + } + guc_fw->rsa_offset = guc_fw->ucode_offset + guc_fw->ucode_size; + guc_fw->rsa_size = css->key_size_dw * sizeof(u32); + + /* At least, it should have header, uCode and RSA. Size of all three. */ + size = guc_fw->header_size + guc_fw->ucode_size + guc_fw->rsa_size; + if (fw->size < size) { + DRM_ERROR("Missing firmware components\n"); + goto fail; + } + + /* Header and uCode will be loaded to WOPCM. Size of the two. */ + size = guc_fw->header_size + guc_fw->ucode_size; + + /* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */ + if (size > GUC_WOPCM_SIZE_VALUE - 0x8000) { + DRM_ERROR("Firmware is too large to fit in WOPCM\n"); + goto fail; + } /* * The GuC firmware image has the version number embedded at a well-known @@ -487,9 +514,8 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) * TWO bytes each (i.e. u16), although all pointers and offsets are defined * in terms of bytes (u8). */ - css_header = fw->data + UOS_CSS_HEADER_OFFSET; - guc_fw->guc_fw_major_found = *(u16 *)(css_header + UOS_VER_MAJOR_OFFSET); - guc_fw->guc_fw_minor_found = *(u16 *)(css_header + UOS_VER_MINOR_OFFSET); + guc_fw->guc_fw_major_found = css->guc_sw_version >> 16; + guc_fw->guc_fw_minor_found = css->guc_sw_version & 0xFFFF; if (guc_fw->guc_fw_major_found != guc_fw->guc_fw_major_wanted || guc_fw->guc_fw_minor_found < guc_fw->guc_fw_minor_wanted) { @@ -566,6 +592,9 @@ void intel_guc_ucode_init(struct drm_device *dev) fw_path = ""; /* unknown device */ } + if (!i915.enable_guc_submission) + return; + guc_fw->guc_dev = dev; guc_fw->guc_fw_path = fw_path; guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index e6c035b0f..616108c4b 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -78,7 +78,7 @@ static u32 g4x_infoframe_index(enum hdmi_infoframe_type type) case HDMI_INFOFRAME_TYPE_VENDOR: return VIDEO_DIP_SELECT_VENDOR; default: - DRM_DEBUG_DRIVER("unknown info frame type %d\n", type); + MISSING_CASE(type); return 0; } } @@ -93,7 +93,7 @@ static u32 g4x_infoframe_enable(enum hdmi_infoframe_type type) case HDMI_INFOFRAME_TYPE_VENDOR: return VIDEO_DIP_ENABLE_VENDOR; default: - DRM_DEBUG_DRIVER("unknown info frame type %d\n", type); + MISSING_CASE(type); return 0; } } @@ -108,15 +108,16 @@ static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type) case HDMI_INFOFRAME_TYPE_VENDOR: return VIDEO_DIP_ENABLE_VS_HSW; default: - DRM_DEBUG_DRIVER("unknown info frame type %d\n", type); + MISSING_CASE(type); return 0; } } -static u32 hsw_dip_data_reg(struct drm_i915_private *dev_priv, - enum transcoder cpu_transcoder, - enum hdmi_infoframe_type type, - int i) +static i915_reg_t +hsw_dip_data_reg(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder, + enum hdmi_infoframe_type type, + int i) { switch (type) { case HDMI_INFOFRAME_TYPE_AVI: @@ -126,8 +127,8 @@ static u32 hsw_dip_data_reg(struct drm_i915_private *dev_priv, case HDMI_INFOFRAME_TYPE_VENDOR: return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder, i); default: - DRM_DEBUG_DRIVER("unknown info frame type %d\n", type); - return 0; + MISSING_CASE(type); + return INVALID_MMIO_REG; } } @@ -168,10 +169,10 @@ static void g4x_write_infoframe(struct drm_encoder *encoder, POSTING_READ(VIDEO_DIP_CTL); } -static bool g4x_infoframe_enabled(struct drm_encoder *encoder) +static bool g4x_infoframe_enabled(struct drm_encoder *encoder, + const struct intel_crtc_state *pipe_config) { - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(encoder->dev); struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); u32 val = I915_READ(VIDEO_DIP_CTL); @@ -193,8 +194,9 @@ static void ibx_write_infoframe(struct drm_encoder *encoder, 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); - int i, reg = TVIDEO_DIP_CTL(intel_crtc->pipe); + i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); + int i; WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); @@ -223,13 +225,13 @@ static void ibx_write_infoframe(struct drm_encoder *encoder, POSTING_READ(reg); } -static bool ibx_infoframe_enabled(struct drm_encoder *encoder) +static bool ibx_infoframe_enabled(struct drm_encoder *encoder, + const struct intel_crtc_state *pipe_config) { - 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 drm_i915_private *dev_priv = to_i915(encoder->dev); struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); - int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); + enum pipe pipe = to_intel_crtc(pipe_config->base.crtc)->pipe; + i915_reg_t reg = TVIDEO_DIP_CTL(pipe); u32 val = I915_READ(reg); if ((val & VIDEO_DIP_ENABLE) == 0) @@ -251,8 +253,9 @@ static void cpt_write_infoframe(struct drm_encoder *encoder, 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); - int i, reg = TVIDEO_DIP_CTL(intel_crtc->pipe); + i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); + int i; WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); @@ -284,13 +287,12 @@ static void cpt_write_infoframe(struct drm_encoder *encoder, POSTING_READ(reg); } -static bool cpt_infoframe_enabled(struct drm_encoder *encoder) +static bool cpt_infoframe_enabled(struct drm_encoder *encoder, + const struct intel_crtc_state *pipe_config) { - 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); - int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); - u32 val = I915_READ(reg); + struct drm_i915_private *dev_priv = to_i915(encoder->dev); + enum pipe pipe = to_intel_crtc(pipe_config->base.crtc)->pipe; + u32 val = I915_READ(TVIDEO_DIP_CTL(pipe)); if ((val & VIDEO_DIP_ENABLE) == 0) return false; @@ -308,8 +310,9 @@ static void vlv_write_infoframe(struct drm_encoder *encoder, 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); - int i, reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); + i915_reg_t reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); + int i; WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); @@ -338,14 +341,13 @@ static void vlv_write_infoframe(struct drm_encoder *encoder, POSTING_READ(reg); } -static bool vlv_infoframe_enabled(struct drm_encoder *encoder) +static bool vlv_infoframe_enabled(struct drm_encoder *encoder, + const struct intel_crtc_state *pipe_config) { - 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 drm_i915_private *dev_priv = to_i915(encoder->dev); struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); - int reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); - u32 val = I915_READ(reg); + enum pipe pipe = to_intel_crtc(pipe_config->base.crtc)->pipe; + u32 val = I915_READ(VLV_TVIDEO_DIP_CTL(pipe)); if ((val & VIDEO_DIP_ENABLE) == 0) return false; @@ -367,14 +369,12 @@ static void hsw_write_infoframe(struct drm_encoder *encoder, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; - u32 ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder); - u32 data_reg; + i915_reg_t ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder); + i915_reg_t data_reg; int i; u32 val = I915_READ(ctl_reg); data_reg = hsw_dip_data_reg(dev_priv, cpu_transcoder, type, 0); - if (data_reg == 0) - return; val &= ~hsw_infoframe_enable(type); I915_WRITE(ctl_reg, val); @@ -396,13 +396,11 @@ static void hsw_write_infoframe(struct drm_encoder *encoder, POSTING_READ(ctl_reg); } -static bool hsw_infoframe_enabled(struct drm_encoder *encoder) +static bool hsw_infoframe_enabled(struct drm_encoder *encoder, + const struct intel_crtc_state *pipe_config) { - 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); - u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config->cpu_transcoder); - u32 val = I915_READ(ctl_reg); + struct drm_i915_private *dev_priv = to_i915(encoder->dev); + u32 val = I915_READ(HSW_TVIDEO_DIP_CTL(pipe_config->cpu_transcoder)); return val & (VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_AVI_HSW | VIDEO_DIP_ENABLE_GCP_HSW | VIDEO_DIP_ENABLE_VS_HSW | @@ -513,7 +511,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder, struct drm_i915_private *dev_priv = encoder->dev->dev_private; struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi; - u32 reg = VIDEO_DIP_CTL; + i915_reg_t reg = VIDEO_DIP_CTL; u32 val = I915_READ(reg); u32 port = VIDEO_DIP_PORT(intel_dig_port->port); @@ -633,11 +631,12 @@ static bool intel_hdmi_set_gcp_infoframe(struct drm_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->dev->dev_private; struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); - u32 reg, val = 0; + i915_reg_t reg; + u32 val = 0; if (HAS_DDI(dev_priv)) reg = HSW_TVIDEO_DIP_GCP(crtc->config->cpu_transcoder); - else if (IS_VALLEYVIEW(dev_priv)) + else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) reg = VLV_TVIDEO_DIP_GCP(crtc->pipe); else if (HAS_PCH_SPLIT(dev_priv->dev)) reg = TVIDEO_DIP_GCP(crtc->pipe); @@ -666,7 +665,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder, struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi; - u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); + i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); u32 port = VIDEO_DIP_PORT(intel_dig_port->port); @@ -717,7 +716,7 @@ static void cpt_set_infoframes(struct drm_encoder *encoder, struct drm_i915_private *dev_priv = encoder->dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); - u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); + i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); assert_hdmi_port_disabled(intel_hdmi); @@ -760,7 +759,7 @@ static void vlv_set_infoframes(struct drm_encoder *encoder, struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); - u32 reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); + i915_reg_t reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); u32 port = VIDEO_DIP_PORT(intel_dig_port->port); @@ -811,7 +810,7 @@ static void hsw_set_infoframes(struct drm_encoder *encoder, struct drm_i915_private *dev_priv = encoder->dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); - u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config->cpu_transcoder); + i915_reg_t reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config->cpu_transcoder); u32 val = I915_READ(reg); assert_hdmi_port_disabled(intel_hdmi); @@ -881,15 +880,18 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder, struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); enum intel_display_power_domain power_domain; u32 tmp; + bool ret; power_domain = intel_display_port_power_domain(encoder); - if (!intel_display_power_is_enabled(dev_priv, power_domain)) + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; + ret = false; + tmp = I915_READ(intel_hdmi->hdmi_reg); if (!(tmp & SDVO_ENABLE)) - return false; + goto out; if (HAS_PCH_CPT(dev)) *pipe = PORT_TO_PIPE_CPT(tmp); @@ -898,7 +900,12 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder, else *pipe = PORT_TO_PIPE(tmp); - return true; + ret = true; + +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } static void intel_hdmi_get_config(struct intel_encoder *encoder, @@ -925,7 +932,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, if (tmp & HDMI_MODE_SELECT_HDMI) pipe_config->has_hdmi_sink = true; - if (intel_hdmi->infoframe_enabled(&encoder->base)) + if (intel_hdmi->infoframe_enabled(&encoder->base, pipe_config)) pipe_config->has_infoframe = true; if (tmp & SDVO_AUDIO_ENABLE) @@ -1108,6 +1115,13 @@ static void intel_disable_hdmi(struct intel_encoder *encoder) * matching DP port to be enabled on transcoder A. */ if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B) { + /* + * We get CPU/PCH FIFO underruns on the other pipe when + * doing the workaround. Sweep them under the rug. + */ + intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, false); + intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false); + temp &= ~SDVO_PIPE_B_SELECT; temp |= SDVO_ENABLE; /* @@ -1122,6 +1136,10 @@ static void intel_disable_hdmi(struct intel_encoder *encoder) temp &= ~SDVO_ENABLE; I915_WRITE(intel_hdmi->hdmi_reg, temp); POSTING_READ(intel_hdmi->hdmi_reg); + + intel_wait_for_vblank_if_active(dev_priv->dev, PIPE_A); + intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true); + intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true); } intel_hdmi->set_infoframes(&encoder->base, false, NULL); @@ -1338,14 +1356,15 @@ intel_hdmi_set_edid(struct drm_connector *connector, bool force) struct edid *edid = NULL; bool connected = false; - intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); + if (force) { + intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); - if (force) edid = drm_get_edid(connector, intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus)); - intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); + intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); + } to_intel_connector(connector)->detect_edid = edid; if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { @@ -2040,7 +2059,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, * On BXT A0/A1, sw needs to activate DDIA HPD logic and * interrupts to check the external panel connection. */ - if (IS_BROXTON(dev_priv) && (INTEL_REVID(dev) < BXT_REVID_B0)) + if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) intel_encoder->hpd_pin = HPD_PORT_A; else intel_encoder->hpd_pin = HPD_PORT_B; @@ -2088,7 +2107,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, BUG(); } - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { intel_hdmi->write_infoframe = vlv_write_infoframe; intel_hdmi->set_infoframes = vlv_set_infoframes; intel_hdmi->infoframe_enabled = vlv_infoframe_enabled; @@ -2132,7 +2151,8 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, } } -void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) +void intel_hdmi_init(struct drm_device *dev, + i915_reg_t hdmi_reg, enum port port) { struct intel_digital_port *intel_dig_port; struct intel_encoder *intel_encoder; @@ -2151,7 +2171,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) intel_encoder = &intel_dig_port->base; drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs, - DRM_MODE_ENCODER_TMDS); + DRM_MODE_ENCODER_TMDS, NULL); intel_encoder->compute_config = intel_hdmi_compute_config; if (HAS_PCH_SPLIT(dev)) { @@ -2203,7 +2223,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) intel_dig_port->port = port; intel_dig_port->hdmi.hdmi_reg = hdmi_reg; - intel_dig_port->dp.output_reg = 0; + intel_dig_port->dp.output_reg = INVALID_MMIO_REG; intel_hdmi_init_connector(intel_dig_port, intel_connector); } diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c index d7a6437d9..bee673005 100644 --- a/drivers/gpu/drm/i915/intel_hotplug.c +++ b/drivers/gpu/drm/i915/intel_hotplug.c @@ -407,7 +407,7 @@ void intel_hpd_irq_handler(struct drm_device *dev, * hotplug bits itself. So only WARN about unexpected * interrupts on saner platforms. */ - WARN_ONCE(INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev), + WARN_ONCE(!HAS_GMCH_DISPLAY(dev), "Received HPD interrupt on pin %d although disabled\n", i); continue; } diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index f3bee54c4..52fbe530f 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -36,7 +36,7 @@ struct gmbus_pin { const char *name; - int reg; + i915_reg_t reg; }; /* Map gmbus pin pairs to names and registers. */ @@ -63,9 +63,9 @@ static const struct gmbus_pin gmbus_pins_skl[] = { }; static const struct gmbus_pin gmbus_pins_bxt[] = { - [GMBUS_PIN_1_BXT] = { "dpb", PCH_GPIOB }, - [GMBUS_PIN_2_BXT] = { "dpc", PCH_GPIOC }, - [GMBUS_PIN_3_BXT] = { "misc", PCH_GPIOD }, + [GMBUS_PIN_1_BXT] = { "dpb", GPIOB }, + [GMBUS_PIN_2_BXT] = { "dpc", GPIOC }, + [GMBUS_PIN_3_BXT] = { "misc", GPIOD }, }; /* pin is expected to be valid */ @@ -74,7 +74,7 @@ static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *dev_priv, { if (IS_BROXTON(dev_priv)) return &gmbus_pins_bxt[pin]; - else if (IS_SKYLAKE(dev_priv)) + else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) return &gmbus_pins_skl[pin]; else if (IS_BROADWELL(dev_priv)) return &gmbus_pins_bdw[pin]; @@ -89,14 +89,15 @@ bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv, if (IS_BROXTON(dev_priv)) size = ARRAY_SIZE(gmbus_pins_bxt); - else if (IS_SKYLAKE(dev_priv)) + else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) size = ARRAY_SIZE(gmbus_pins_skl); else if (IS_BROADWELL(dev_priv)) size = ARRAY_SIZE(gmbus_pins_bdw); else size = ARRAY_SIZE(gmbus_pins); - return pin < size && get_gmbus_pin(dev_priv, pin)->reg; + return pin < size && + i915_mmio_reg_valid(get_gmbus_pin(dev_priv, pin)->reg); } /* Intel GPIO access functions */ @@ -240,9 +241,8 @@ intel_gpio_setup(struct intel_gmbus *bus, unsigned int pin) algo = &bus->bit_algo; - bus->gpio_reg = dev_priv->gpio_mmio_base + - get_gmbus_pin(dev_priv, pin)->reg; - + bus->gpio_reg = _MMIO(dev_priv->gpio_mmio_base + + i915_mmio_reg_offset(get_gmbus_pin(dev_priv, pin)->reg)); bus->adapter.algo_data = algo; algo->setsda = set_data; algo->setscl = set_clock; @@ -472,9 +472,7 @@ gmbus_xfer_index_read(struct drm_i915_private *dev_priv, struct i2c_msg *msgs) } static int -gmbus_xfer(struct i2c_adapter *adapter, - struct i2c_msg *msgs, - int num) +do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) { struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus, @@ -483,14 +481,6 @@ gmbus_xfer(struct i2c_adapter *adapter, int i = 0, inc, try = 0; int ret = 0; - intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); - mutex_lock(&dev_priv->gmbus_mutex); - - if (bus->force_bit) { - ret = i2c_bit_algo.master_xfer(adapter, msgs, num); - goto out; - } - retry: I915_WRITE(GMBUS0, bus->reg0); @@ -505,17 +495,13 @@ retry: ret = gmbus_xfer_write(dev_priv, &msgs[i]); } + if (!ret) + ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_WAIT_PHASE, + GMBUS_HW_WAIT_EN); if (ret == -ETIMEDOUT) goto timeout; - if (ret == -ENXIO) - goto clear_err; - - ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_WAIT_PHASE, - GMBUS_HW_WAIT_EN); - if (ret == -ENXIO) + else if (ret) goto clear_err; - if (ret) - goto timeout; } /* Generate a STOP condition on the bus. Note that gmbus can't generata @@ -589,13 +575,34 @@ timeout: bus->adapter.name, bus->reg0 & 0xff); I915_WRITE(GMBUS0, 0); - /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */ + /* + * Hardware may not support GMBUS over these pins? Try GPIO bitbanging + * instead. Use EAGAIN to have i2c core retry. + */ bus->force_bit = 1; - ret = i2c_bit_algo.master_xfer(adapter, msgs, num); + ret = -EAGAIN; out: - mutex_unlock(&dev_priv->gmbus_mutex); + return ret; +} +static int +gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) +{ + struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus, + adapter); + struct drm_i915_private *dev_priv = bus->dev_priv; + int ret; + + intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); + mutex_lock(&dev_priv->gmbus_mutex); + + if (bus->force_bit) + ret = i2c_bit_algo.master_xfer(adapter, msgs, num); + else + ret = do_gmbus_xfer(adapter, msgs, num); + + mutex_unlock(&dev_priv->gmbus_mutex); intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); return ret; @@ -628,12 +635,13 @@ int intel_setup_gmbus(struct drm_device *dev) if (HAS_PCH_NOP(dev)) return 0; - else if (HAS_PCH_SPLIT(dev)) - dev_priv->gpio_mmio_base = PCH_GPIOA - GPIOA; - else if (IS_VALLEYVIEW(dev)) + + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) dev_priv->gpio_mmio_base = VLV_DISPLAY_BASE; - else - dev_priv->gpio_mmio_base = 0; + else if (!HAS_GMCH_DISPLAY(dev_priv)) + dev_priv->gpio_mmio_base = + i915_mmio_reg_offset(PCH_GPIOA) - + i915_mmio_reg_offset(GPIOA); mutex_init(&dev_priv->gmbus_mutex); init_waitqueue_head(&dev_priv->gmbus_wait_queue); @@ -656,6 +664,12 @@ int intel_setup_gmbus(struct drm_device *dev) bus->adapter.algo = &gmbus_algorithm; + /* + * We wish to retry with bit banging + * after a timed out GMBUS attempt. + */ + bus->adapter.retries = 1; + /* By default use a conservative clock rate */ bus->reg0 = pin | GMBUS_RATE_100KHZ; diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index d69547a65..f1fa756c5 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -190,16 +190,21 @@ #define GEN8_CTX_L3LLC_COHERENT (1<<5) #define GEN8_CTX_PRIVILEGE (1<<8) -#define ASSIGN_CTX_PDP(ppgtt, reg_state, n) { \ +#define ASSIGN_CTX_REG(reg_state, pos, reg, val) do { \ + (reg_state)[(pos)+0] = i915_mmio_reg_offset(reg); \ + (reg_state)[(pos)+1] = (val); \ +} while (0) + +#define ASSIGN_CTX_PDP(ppgtt, reg_state, n) do { \ const u64 _addr = i915_page_dir_dma_addr((ppgtt), (n)); \ reg_state[CTX_PDP ## n ## _UDW+1] = upper_32_bits(_addr); \ reg_state[CTX_PDP ## n ## _LDW+1] = lower_32_bits(_addr); \ -} +} while (0) -#define ASSIGN_CTX_PML4(ppgtt, reg_state) { \ +#define ASSIGN_CTX_PML4(ppgtt, reg_state) do { \ reg_state[CTX_PDP0_UDW + 1] = upper_32_bits(px_dma(&ppgtt->pml4)); \ reg_state[CTX_PDP0_LDW + 1] = lower_32_bits(px_dma(&ppgtt->pml4)); \ -} +} while (0) enum { ADVANCED_CONTEXT = 0, @@ -284,8 +289,8 @@ static bool disable_lite_restore_wa(struct intel_engine_cs *ring) { struct drm_device *dev = ring->dev; - return ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) || - (IS_BROXTON(dev) && INTEL_REVID(dev) == BXT_REVID_A0)) && + return (IS_SKL_REVID(dev, 0, SKL_REVID_B0) || + IS_BXT_REVID(dev, 0, BXT_REVID_A1)) && (ring->id == VCS || ring->id == VCS2); } @@ -367,7 +372,7 @@ static int execlists_update_context(struct drm_i915_gem_request *rq) WARN_ON(!i915_gem_obj_is_pinned(ctx_obj)); WARN_ON(!i915_gem_obj_is_pinned(rb_obj)); - page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); + page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN); reg_state = kmap_atomic(page); reg_state[CTX_RING_TAIL+1] = rq->tail; @@ -921,7 +926,7 @@ int intel_execlists_submission(struct i915_execbuffer_params *params, intel_logical_ring_emit(ringbuf, MI_NOOP); intel_logical_ring_emit(ringbuf, MI_LOAD_REGISTER_IMM(1)); - intel_logical_ring_emit(ringbuf, INSTPM); + intel_logical_ring_emit_reg(ringbuf, INSTPM); intel_logical_ring_emit(ringbuf, instp_mask << 16 | instp_mode); intel_logical_ring_advance(ringbuf); @@ -1096,7 +1101,7 @@ static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req) intel_logical_ring_emit(ringbuf, MI_LOAD_REGISTER_IMM(w->count)); for (i = 0; i < w->count; i++) { - intel_logical_ring_emit(ringbuf, w->reg[i].addr); + intel_logical_ring_emit_reg(ringbuf, w->reg[i].addr); intel_logical_ring_emit(ringbuf, w->reg[i].value); } intel_logical_ring_emit(ringbuf, MI_NOOP); @@ -1120,6 +1125,8 @@ static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req) batch[__index] = (cmd); \ } while (0) +#define wa_ctx_emit_reg(batch, index, reg) \ + wa_ctx_emit((batch), (index), i915_mmio_reg_offset(reg)) /* * In this WA we need to set GEN8_L3SQCREG4[21:21] and reset it after @@ -1149,17 +1156,17 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *ring, * this batch updates GEN8_L3SQCREG4 with default value we need to * set this bit here to retain the WA during flush. */ - if (IS_SKYLAKE(ring->dev) && INTEL_REVID(ring->dev) <= SKL_REVID_E0) + if (IS_SKL_REVID(ring->dev, 0, SKL_REVID_E0)) l3sqc4_flush |= GEN8_LQSC_RO_PERF_DIS; wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8 | MI_SRM_LRM_GLOBAL_GTT)); - wa_ctx_emit(batch, index, GEN8_L3SQCREG4); + wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4); wa_ctx_emit(batch, index, ring->scratch.gtt_offset + 256); wa_ctx_emit(batch, index, 0); wa_ctx_emit(batch, index, MI_LOAD_REGISTER_IMM(1)); - wa_ctx_emit(batch, index, GEN8_L3SQCREG4); + wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4); wa_ctx_emit(batch, index, l3sqc4_flush); wa_ctx_emit(batch, index, GFX_OP_PIPE_CONTROL(6)); @@ -1172,7 +1179,7 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *ring, wa_ctx_emit(batch, index, (MI_LOAD_REGISTER_MEM_GEN8 | MI_SRM_LRM_GLOBAL_GTT)); - wa_ctx_emit(batch, index, GEN8_L3SQCREG4); + wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4); wa_ctx_emit(batch, index, ring->scratch.gtt_offset + 256); wa_ctx_emit(batch, index, 0); @@ -1314,8 +1321,8 @@ static int gen9_init_indirectctx_bb(struct intel_engine_cs *ring, uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS); /* WaDisableCtxRestoreArbitration:skl,bxt */ - if ((IS_SKYLAKE(dev) && (INTEL_REVID(dev) <= SKL_REVID_D0)) || - (IS_BROXTON(dev) && (INTEL_REVID(dev) == BXT_REVID_A0))) + if (IS_SKL_REVID(dev, 0, SKL_REVID_D0) || + IS_BXT_REVID(dev, 0, BXT_REVID_A1)) wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_DISABLE); /* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt */ @@ -1340,18 +1347,18 @@ static int gen9_init_perctx_bb(struct intel_engine_cs *ring, uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS); /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */ - if ((IS_SKYLAKE(dev) && (INTEL_REVID(dev) <= SKL_REVID_B0)) || - (IS_BROXTON(dev) && (INTEL_REVID(dev) == BXT_REVID_A0))) { + if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) || + IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { wa_ctx_emit(batch, index, MI_LOAD_REGISTER_IMM(1)); - wa_ctx_emit(batch, index, GEN9_SLICE_COMMON_ECO_CHICKEN0); + wa_ctx_emit_reg(batch, index, GEN9_SLICE_COMMON_ECO_CHICKEN0); wa_ctx_emit(batch, index, _MASKED_BIT_ENABLE(DISABLE_PIXEL_MASK_CAMMING)); wa_ctx_emit(batch, index, MI_NOOP); } /* WaDisableCtxRestoreArbitration:skl,bxt */ - if ((IS_SKYLAKE(dev) && (INTEL_REVID(dev) <= SKL_REVID_D0)) || - (IS_BROXTON(dev) && (INTEL_REVID(dev) == BXT_REVID_A0))) + if (IS_SKL_REVID(dev, 0, SKL_REVID_D0) || + IS_BXT_REVID(dev, 0, BXT_REVID_A1)) wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_ENABLE); wa_ctx_emit(batch, index, MI_BATCH_BUFFER_END); @@ -1418,7 +1425,7 @@ static int intel_init_workaround_bb(struct intel_engine_cs *ring) return ret; } - page = i915_gem_object_get_page(wa_ctx->obj, 0); + page = i915_gem_object_get_dirty_page(wa_ctx->obj, 0); batch = kmap_atomic(page); offset = 0; @@ -1472,12 +1479,6 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring) I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask)); I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff); - if (ring->status_page.obj) { - I915_WRITE(RING_HWS_PGA(ring->mmio_base), - (u32)ring->status_page.gfx_addr); - POSTING_READ(RING_HWS_PGA(ring->mmio_base)); - } - I915_WRITE(RING_MODE_GEN7(ring), _MASKED_BIT_DISABLE(GFX_REPLAY_MODE) | _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE)); @@ -1562,9 +1563,9 @@ static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) for (i = GEN8_LEGACY_PDPES - 1; i >= 0; i--) { const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i); - intel_logical_ring_emit(ringbuf, GEN8_RING_PDP_UDW(ring, i)); + intel_logical_ring_emit_reg(ringbuf, GEN8_RING_PDP_UDW(ring, i)); intel_logical_ring_emit(ringbuf, upper_32_bits(pd_daddr)); - intel_logical_ring_emit(ringbuf, GEN8_RING_PDP_LDW(ring, i)); + intel_logical_ring_emit_reg(ringbuf, GEN8_RING_PDP_LDW(ring, i)); intel_logical_ring_emit(ringbuf, lower_32_bits(pd_daddr)); } @@ -1894,8 +1895,10 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *ring) dev_priv = ring->dev->dev_private; - intel_logical_ring_stop(ring); - WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0); + if (ring->buffer) { + intel_logical_ring_stop(ring); + WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0); + } if (ring->cleanup) ring->cleanup(ring); @@ -1909,6 +1912,7 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *ring) } lrc_destroy_wa_ctx_obj(ring); + ring->dev = NULL; } static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *ring) @@ -1924,17 +1928,18 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rin i915_gem_batch_pool_init(dev, &ring->batch_pool); init_waitqueue_head(&ring->irq_queue); + INIT_LIST_HEAD(&ring->buffers); INIT_LIST_HEAD(&ring->execlist_queue); INIT_LIST_HEAD(&ring->execlist_retired_req_list); spin_lock_init(&ring->execlist_lock); ret = i915_cmd_parser_init_ring(ring); if (ret) - return ret; + goto error; ret = intel_lr_context_deferred_alloc(ring->default_context, ring); if (ret) - return ret; + goto error; /* As this is the default context, always pin it */ ret = intel_lr_context_do_pin( @@ -1945,9 +1950,13 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rin DRM_ERROR( "Failed to pin and map ringbuffer %s: %d\n", ring->name, ret); - return ret; + goto error; } + return 0; + +error: + intel_logical_ring_cleanup(ring); return ret; } @@ -1973,7 +1982,7 @@ static int logical_render_ring_init(struct drm_device *dev) ring->init_hw = gen8_init_render_ring; ring->init_context = gen8_init_rcs_context; ring->cleanup = intel_fini_pipe_control; - if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) { + if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { ring->get_seqno = bxt_a_get_seqno; ring->set_seqno = bxt_a_set_seqno; } else { @@ -2025,7 +2034,7 @@ static int logical_bsd_ring_init(struct drm_device *dev) GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; ring->init_hw = gen8_init_common_ring; - if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) { + if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { ring->get_seqno = bxt_a_get_seqno; ring->set_seqno = bxt_a_set_seqno; } else { @@ -2080,7 +2089,7 @@ static int logical_blt_ring_init(struct drm_device *dev) GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT; ring->init_hw = gen8_init_common_ring; - if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) { + if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { ring->get_seqno = bxt_a_get_seqno; ring->set_seqno = bxt_a_set_seqno; } else { @@ -2110,7 +2119,7 @@ static int logical_vebox_ring_init(struct drm_device *dev) GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT; ring->init_hw = gen8_init_common_ring; - if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0) { + if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { ring->get_seqno = bxt_a_get_seqno; ring->set_seqno = bxt_a_set_seqno; } else { @@ -2256,7 +2265,7 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o /* The second page of the context object contains some fields which must * be set up prior to the first execution. */ - page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); + page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN); reg_state = kmap_atomic(page); /* A context is actually a big batch buffer with several MI_LOAD_REGISTER_IMM @@ -2264,46 +2273,31 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o * only for the first context restore: on a subsequent save, the GPU will * recreate this batchbuffer with new values (including all the missing * MI_LOAD_REGISTER_IMM commands that we are not initializing here). */ - if (ring->id == RCS) - reg_state[CTX_LRI_HEADER_0] = MI_LOAD_REGISTER_IMM(14); - else - reg_state[CTX_LRI_HEADER_0] = MI_LOAD_REGISTER_IMM(11); - reg_state[CTX_LRI_HEADER_0] |= MI_LRI_FORCE_POSTED; - reg_state[CTX_CONTEXT_CONTROL] = RING_CONTEXT_CONTROL(ring); - reg_state[CTX_CONTEXT_CONTROL+1] = - _MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH | - CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT | - CTX_CTRL_RS_CTX_ENABLE); - reg_state[CTX_RING_HEAD] = RING_HEAD(ring->mmio_base); - reg_state[CTX_RING_HEAD+1] = 0; - reg_state[CTX_RING_TAIL] = RING_TAIL(ring->mmio_base); - reg_state[CTX_RING_TAIL+1] = 0; - reg_state[CTX_RING_BUFFER_START] = RING_START(ring->mmio_base); + reg_state[CTX_LRI_HEADER_0] = + MI_LOAD_REGISTER_IMM(ring->id == RCS ? 14 : 11) | MI_LRI_FORCE_POSTED; + ASSIGN_CTX_REG(reg_state, CTX_CONTEXT_CONTROL, RING_CONTEXT_CONTROL(ring), + _MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH | + CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT | + CTX_CTRL_RS_CTX_ENABLE)); + ASSIGN_CTX_REG(reg_state, CTX_RING_HEAD, RING_HEAD(ring->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_RING_TAIL, RING_TAIL(ring->mmio_base), 0); /* Ring buffer start address is not known until the buffer is pinned. * It is written to the context image in execlists_update_context() */ - reg_state[CTX_RING_BUFFER_CONTROL] = RING_CTL(ring->mmio_base); - reg_state[CTX_RING_BUFFER_CONTROL+1] = - ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID; - reg_state[CTX_BB_HEAD_U] = ring->mmio_base + 0x168; - reg_state[CTX_BB_HEAD_U+1] = 0; - reg_state[CTX_BB_HEAD_L] = ring->mmio_base + 0x140; - reg_state[CTX_BB_HEAD_L+1] = 0; - reg_state[CTX_BB_STATE] = ring->mmio_base + 0x110; - reg_state[CTX_BB_STATE+1] = (1<<5); - reg_state[CTX_SECOND_BB_HEAD_U] = ring->mmio_base + 0x11c; - reg_state[CTX_SECOND_BB_HEAD_U+1] = 0; - reg_state[CTX_SECOND_BB_HEAD_L] = ring->mmio_base + 0x114; - reg_state[CTX_SECOND_BB_HEAD_L+1] = 0; - reg_state[CTX_SECOND_BB_STATE] = ring->mmio_base + 0x118; - reg_state[CTX_SECOND_BB_STATE+1] = 0; + ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_START, RING_START(ring->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_CONTROL, RING_CTL(ring->mmio_base), + ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID); + ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_U, RING_BBADDR_UDW(ring->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_L, RING_BBADDR(ring->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_BB_STATE, RING_BBSTATE(ring->mmio_base), + RING_BB_PPGTT); + ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_HEAD_U, RING_SBBADDR_UDW(ring->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_HEAD_L, RING_SBBADDR(ring->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_STATE, RING_SBBSTATE(ring->mmio_base), 0); if (ring->id == RCS) { - reg_state[CTX_BB_PER_CTX_PTR] = ring->mmio_base + 0x1c0; - reg_state[CTX_BB_PER_CTX_PTR+1] = 0; - reg_state[CTX_RCS_INDIRECT_CTX] = ring->mmio_base + 0x1c4; - reg_state[CTX_RCS_INDIRECT_CTX+1] = 0; - reg_state[CTX_RCS_INDIRECT_CTX_OFFSET] = ring->mmio_base + 0x1c8; - reg_state[CTX_RCS_INDIRECT_CTX_OFFSET+1] = 0; + ASSIGN_CTX_REG(reg_state, CTX_BB_PER_CTX_PTR, RING_BB_PER_CTX_PTR(ring->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX, RING_INDIRECT_CTX(ring->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX_OFFSET, RING_INDIRECT_CTX_OFFSET(ring->mmio_base), 0); if (ring->wa_ctx.obj) { struct i915_ctx_workarounds *wa_ctx = &ring->wa_ctx; uint32_t ggtt_offset = i915_gem_obj_ggtt_offset(wa_ctx->obj); @@ -2320,18 +2314,17 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o 0x01; } } - reg_state[CTX_LRI_HEADER_1] = MI_LOAD_REGISTER_IMM(9); - reg_state[CTX_LRI_HEADER_1] |= MI_LRI_FORCE_POSTED; - reg_state[CTX_CTX_TIMESTAMP] = ring->mmio_base + 0x3a8; - reg_state[CTX_CTX_TIMESTAMP+1] = 0; - reg_state[CTX_PDP3_UDW] = GEN8_RING_PDP_UDW(ring, 3); - reg_state[CTX_PDP3_LDW] = GEN8_RING_PDP_LDW(ring, 3); - reg_state[CTX_PDP2_UDW] = GEN8_RING_PDP_UDW(ring, 2); - reg_state[CTX_PDP2_LDW] = GEN8_RING_PDP_LDW(ring, 2); - reg_state[CTX_PDP1_UDW] = GEN8_RING_PDP_UDW(ring, 1); - reg_state[CTX_PDP1_LDW] = GEN8_RING_PDP_LDW(ring, 1); - reg_state[CTX_PDP0_UDW] = GEN8_RING_PDP_UDW(ring, 0); - reg_state[CTX_PDP0_LDW] = GEN8_RING_PDP_LDW(ring, 0); + reg_state[CTX_LRI_HEADER_1] = MI_LOAD_REGISTER_IMM(9) | MI_LRI_FORCE_POSTED; + ASSIGN_CTX_REG(reg_state, CTX_CTX_TIMESTAMP, RING_CTX_TIMESTAMP(ring->mmio_base), 0); + /* PDP values well be assigned later if needed */ + ASSIGN_CTX_REG(reg_state, CTX_PDP3_UDW, GEN8_RING_PDP_UDW(ring, 3), 0); + ASSIGN_CTX_REG(reg_state, CTX_PDP3_LDW, GEN8_RING_PDP_LDW(ring, 3), 0); + ASSIGN_CTX_REG(reg_state, CTX_PDP2_UDW, GEN8_RING_PDP_UDW(ring, 2), 0); + ASSIGN_CTX_REG(reg_state, CTX_PDP2_LDW, GEN8_RING_PDP_LDW(ring, 2), 0); + ASSIGN_CTX_REG(reg_state, CTX_PDP1_UDW, GEN8_RING_PDP_UDW(ring, 1), 0); + ASSIGN_CTX_REG(reg_state, CTX_PDP1_LDW, GEN8_RING_PDP_LDW(ring, 1), 0); + ASSIGN_CTX_REG(reg_state, CTX_PDP0_UDW, GEN8_RING_PDP_UDW(ring, 0), 0); + ASSIGN_CTX_REG(reg_state, CTX_PDP0_LDW, GEN8_RING_PDP_LDW(ring, 0), 0); if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) { /* 64b PPGTT (48bit canonical) @@ -2353,14 +2346,11 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o if (ring->id == RCS) { reg_state[CTX_LRI_HEADER_2] = MI_LOAD_REGISTER_IMM(1); - reg_state[CTX_R_PWR_CLK_STATE] = GEN8_R_PWR_CLK_STATE; - reg_state[CTX_R_PWR_CLK_STATE+1] = make_rpcs(dev); + ASSIGN_CTX_REG(reg_state, CTX_R_PWR_CLK_STATE, GEN8_R_PWR_CLK_STATE, + make_rpcs(dev)); } kunmap_atomic(reg_state); - - ctx_obj->dirty = 1; - set_page_dirty(page); i915_gem_object_unpin_pages(ctx_obj); return 0; @@ -2544,7 +2534,7 @@ void intel_lr_context_reset(struct drm_device *dev, WARN(1, "Failed get_pages for context obj\n"); continue; } - page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); + page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN); reg_state = kmap_atomic(page); reg_state[CTX_RING_HEAD+1] = 0; diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 4e60d54ba..0b821b917 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -29,16 +29,16 @@ #define GEN8_CSB_PTR_MASK 0x07 /* Execlists regs */ -#define RING_ELSP(ring) ((ring)->mmio_base+0x230) -#define RING_EXECLIST_STATUS_LO(ring) ((ring)->mmio_base+0x234) -#define RING_EXECLIST_STATUS_HI(ring) ((ring)->mmio_base+0x234 + 4) -#define RING_CONTEXT_CONTROL(ring) ((ring)->mmio_base+0x244) +#define RING_ELSP(ring) _MMIO((ring)->mmio_base + 0x230) +#define RING_EXECLIST_STATUS_LO(ring) _MMIO((ring)->mmio_base + 0x234) +#define RING_EXECLIST_STATUS_HI(ring) _MMIO((ring)->mmio_base + 0x234 + 4) +#define RING_CONTEXT_CONTROL(ring) _MMIO((ring)->mmio_base + 0x244) #define CTX_CTRL_INHIBIT_SYN_CTX_SWITCH (1 << 3) #define CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT (1 << 0) #define CTX_CTRL_RS_CTX_ENABLE (1 << 1) -#define RING_CONTEXT_STATUS_BUF_LO(ring, i) ((ring)->mmio_base+0x370 + (i) * 8) -#define RING_CONTEXT_STATUS_BUF_HI(ring, i) ((ring)->mmio_base+0x370 + (i) * 8 + 4) -#define RING_CONTEXT_STATUS_PTR(ring) ((ring)->mmio_base+0x3a0) +#define RING_CONTEXT_STATUS_BUF_LO(ring, i) _MMIO((ring)->mmio_base + 0x370 + (i) * 8) +#define RING_CONTEXT_STATUS_BUF_HI(ring, i) _MMIO((ring)->mmio_base + 0x370 + (i) * 8 + 4) +#define RING_CONTEXT_STATUS_PTR(ring) _MMIO((ring)->mmio_base + 0x3a0) /* Logical Rings */ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request); @@ -70,6 +70,11 @@ static inline void intel_logical_ring_emit(struct intel_ringbuffer *ringbuf, iowrite32(data, ringbuf->virtual_start + ringbuf->tail); ringbuf->tail += 4; } +static inline void intel_logical_ring_emit_reg(struct intel_ringbuffer *ringbuf, + i915_reg_t reg) +{ + intel_logical_ring_emit(ringbuf, i915_mmio_reg_offset(reg)); +} /* Logical Ring Contexts */ diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 7f39b8ad8..bc04d8d29 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -51,7 +51,7 @@ struct intel_lvds_encoder { struct intel_encoder base; bool is_dual_link; - u32 reg; + i915_reg_t reg; u32 a3_power; struct intel_lvds_connector *attached_connector; @@ -75,22 +75,30 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder, struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); enum intel_display_power_domain power_domain; u32 tmp; + bool ret; power_domain = intel_display_port_power_domain(encoder); - if (!intel_display_power_is_enabled(dev_priv, power_domain)) + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; + ret = false; + tmp = I915_READ(lvds_encoder->reg); if (!(tmp & LVDS_PORT_EN)) - return false; + goto out; if (HAS_PCH_CPT(dev)) *pipe = PORT_TO_PIPE_CPT(tmp); else *pipe = PORT_TO_PIPE(tmp); - return true; + ret = true; + +out: + intel_display_power_put(dev_priv, power_domain); + + return ret; } static void intel_lvds_get_config(struct intel_encoder *encoder, @@ -210,7 +218,7 @@ static void intel_enable_lvds(struct intel_encoder *encoder) struct intel_connector *intel_connector = &lvds_encoder->attached_connector->base; struct drm_i915_private *dev_priv = dev->dev_private; - u32 ctl_reg, stat_reg; + i915_reg_t ctl_reg, stat_reg; if (HAS_PCH_SPLIT(dev)) { ctl_reg = PCH_PP_CONTROL; @@ -235,7 +243,7 @@ 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 drm_i915_private *dev_priv = dev->dev_private; - u32 ctl_reg, stat_reg; + i915_reg_t ctl_reg, stat_reg; if (HAS_PCH_SPLIT(dev)) { ctl_reg = PCH_PP_CONTROL; @@ -939,7 +947,7 @@ void intel_lvds_init(struct drm_device *dev) struct drm_display_mode *downclock_mode = NULL; struct edid *edid; struct drm_crtc *crtc; - u32 lvds_reg; + i915_reg_t lvds_reg; u32 lvds; int pipe; u8 pin; @@ -1025,7 +1033,7 @@ void intel_lvds_init(struct drm_device *dev) DRM_MODE_CONNECTOR_LVDS); drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs, - DRM_MODE_ENCODER_LVDS); + DRM_MODE_ENCODER_LVDS, NULL); intel_encoder->enable = intel_enable_lvds; intel_encoder->pre_enable = intel_pre_enable_lvds; @@ -1164,8 +1172,7 @@ out: DRM_DEBUG_KMS("detected %s-link lvds configuration\n", lvds_encoder->is_dual_link ? "dual" : "single"); - lvds_encoder->a3_power = I915_READ(lvds_encoder->reg) & - LVDS_A3_POWER_MASK; + lvds_encoder->a3_power = lvds & LVDS_A3_POWER_MASK; lvds_connector->lid_notifier.notifier_call = intel_lid_notify; if (acpi_lid_notifier_register(&lvds_connector->lid_notifier)) { diff --git a/drivers/gpu/drm/i915/intel_mocs.c b/drivers/gpu/drm/i915/intel_mocs.c index 6d3c6c0a5..fed7bea19 100644 --- a/drivers/gpu/drm/i915/intel_mocs.c +++ b/drivers/gpu/drm/i915/intel_mocs.c @@ -143,7 +143,7 @@ static bool get_mocs_settings(struct drm_device *dev, { bool result = false; - if (IS_SKYLAKE(dev)) { + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { table->size = ARRAY_SIZE(skylake_mocs_table); table->table = skylake_mocs_table; result = true; @@ -159,11 +159,30 @@ static bool get_mocs_settings(struct drm_device *dev, return result; } +static i915_reg_t mocs_register(enum intel_ring_id ring, int index) +{ + switch (ring) { + case RCS: + return GEN9_GFX_MOCS(index); + case VCS: + return GEN9_MFX0_MOCS(index); + case BCS: + return GEN9_BLT_MOCS(index); + case VECS: + return GEN9_VEBOX_MOCS(index); + case VCS2: + return GEN9_MFX1_MOCS(index); + default: + MISSING_CASE(ring); + return INVALID_MMIO_REG; + } +} + /** * emit_mocs_control_table() - emit the mocs control table * @req: Request to set up the MOCS table for. * @table: The values to program into the control regs. - * @reg_base: The base for the engine that needs to be programmed. + * @ring: The engine for whom to emit the registers. * * This function simply emits a MI_LOAD_REGISTER_IMM command for the * given table starting at the given address. @@ -172,7 +191,7 @@ static bool get_mocs_settings(struct drm_device *dev, */ static int emit_mocs_control_table(struct drm_i915_gem_request *req, const struct drm_i915_mocs_table *table, - u32 reg_base) + enum intel_ring_id ring) { struct intel_ringbuffer *ringbuf = req->ringbuf; unsigned int index; @@ -191,7 +210,7 @@ static int emit_mocs_control_table(struct drm_i915_gem_request *req, MI_LOAD_REGISTER_IMM(GEN9_NUM_MOCS_ENTRIES)); for (index = 0; index < table->size; index++) { - intel_logical_ring_emit(ringbuf, reg_base + index * 4); + intel_logical_ring_emit_reg(ringbuf, mocs_register(ring, index)); intel_logical_ring_emit(ringbuf, table->table[index].control_value); } @@ -205,7 +224,7 @@ static int emit_mocs_control_table(struct drm_i915_gem_request *req, * that value to all the used entries. */ for (; index < GEN9_NUM_MOCS_ENTRIES; index++) { - intel_logical_ring_emit(ringbuf, reg_base + index * 4); + intel_logical_ring_emit_reg(ringbuf, mocs_register(ring, index)); intel_logical_ring_emit(ringbuf, table->table[0].control_value); } @@ -253,7 +272,7 @@ static int emit_mocs_l3cc_table(struct drm_i915_gem_request *req, value = (table->table[count].l3cc_value & 0xffff) | ((table->table[count + 1].l3cc_value & 0xffff) << 16); - intel_logical_ring_emit(ringbuf, GEN9_LNCFCMOCS0 + i * 4); + intel_logical_ring_emit_reg(ringbuf, GEN9_LNCFCMOCS(i)); intel_logical_ring_emit(ringbuf, value); } @@ -270,7 +289,7 @@ static int emit_mocs_l3cc_table(struct drm_i915_gem_request *req, * they are reserved by the hardware. */ for (; i < GEN9_NUM_MOCS_ENTRIES / 2; i++) { - intel_logical_ring_emit(ringbuf, GEN9_LNCFCMOCS0 + i * 4); + intel_logical_ring_emit_reg(ringbuf, GEN9_LNCFCMOCS(i)); intel_logical_ring_emit(ringbuf, value); value = filler; @@ -304,26 +323,16 @@ int intel_rcs_context_init_mocs(struct drm_i915_gem_request *req) int ret; if (get_mocs_settings(req->ring->dev, &t)) { - /* Program the control registers */ - ret = emit_mocs_control_table(req, &t, GEN9_GFX_MOCS_0); - if (ret) - return ret; - - ret = emit_mocs_control_table(req, &t, GEN9_MFX0_MOCS_0); - if (ret) - return ret; + struct drm_i915_private *dev_priv = req->i915; + struct intel_engine_cs *ring; + enum intel_ring_id ring_id; - ret = emit_mocs_control_table(req, &t, GEN9_MFX1_MOCS_0); - if (ret) - return ret; - - ret = emit_mocs_control_table(req, &t, GEN9_VEBOX_MOCS_0); - if (ret) - return ret; - - ret = emit_mocs_control_table(req, &t, GEN9_BLT_MOCS_0); - if (ret) - return ret; + /* Program the control registers */ + for_each_ring(ring, dev_priv, ring_id) { + ret = emit_mocs_control_table(req, &t, ring_id); + if (ret) + return ret; + } /* Now program the l3cc registers */ ret = emit_mocs_l3cc_table(req, &t); diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 6dc13c02c..c15718b48 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -26,6 +26,7 @@ */ #include <linux/acpi.h> +#include <linux/dmi.h> #include <acpi/video.h> #include <drm/drmP.h> @@ -46,6 +47,7 @@ #define OPREGION_SWSCI_OFFSET 0x200 #define OPREGION_ASLE_OFFSET 0x300 #define OPREGION_VBT_OFFSET 0x400 +#define OPREGION_ASLE_EXT_OFFSET 0x1C00 #define OPREGION_SIGNATURE "IntelGraphicsMem" #define MBOX_ACPI (1<<0) @@ -120,7 +122,16 @@ struct opregion_asle { u64 fdss; u32 fdsp; u32 stat; - u8 rsvd[70]; + u64 rvda; /* Physical address of raw vbt data */ + u32 rvds; /* Size of raw vbt data */ + u8 rsvd[58]; +} __packed; + +/* OpRegion mailbox #5: ASLE ext */ +struct opregion_asle_ext { + u32 phed; /* Panel Header */ + u8 bddc[256]; /* Panel EDID */ + u8 rsvd[764]; } __packed; /* Driver readiness indicator */ @@ -411,7 +422,7 @@ int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state) static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_connector *intel_connector; + struct intel_connector *connector; struct opregion_asle *asle = dev_priv->opregion.asle; DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp); @@ -435,8 +446,8 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) * only one). */ DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp); - list_for_each_entry(intel_connector, &dev->mode_config.connector_list, base.head) - intel_panel_set_backlight_acpi(intel_connector, bclp, 255); + for_each_intel_connector(dev, connector) + intel_panel_set_backlight_acpi(connector, bclp, 255); asle->cblv = DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID; drm_modeset_unlock(&dev->mode_config.connection_mutex); @@ -682,7 +693,7 @@ static void intel_didl_outputs(struct drm_device *dev) } if (!acpi_video_bus) { - DRM_ERROR("No ACPI video bus found\n"); + DRM_DEBUG_KMS("No ACPI video bus found\n"); return; } @@ -826,6 +837,10 @@ void intel_opregion_fini(struct drm_device *dev) /* just clear all opregion memory pointers now */ memunmap(opregion->header); + if (opregion->rvda) { + memunmap(opregion->rvda); + opregion->rvda = NULL; + } opregion->header = NULL; opregion->acpi = NULL; opregion->swsci = NULL; @@ -894,6 +909,25 @@ static void swsci_setup(struct drm_device *dev) static inline void swsci_setup(struct drm_device *dev) {} #endif /* CONFIG_ACPI */ +static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id) +{ + DRM_DEBUG_KMS("Falling back to manually reading VBT from " + "VBIOS ROM for %s\n", id->ident); + return 1; +} + +static const struct dmi_system_id intel_no_opregion_vbt[] = { + { + .callback = intel_no_opregion_vbt_callback, + .ident = "ThinkCentre A57", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"), + }, + }, + { } +}; + int intel_opregion_setup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -907,6 +941,7 @@ int intel_opregion_setup(struct drm_device *dev) BUILD_BUG_ON(sizeof(struct opregion_acpi) != 0x100); BUILD_BUG_ON(sizeof(struct opregion_swsci) != 0x100); BUILD_BUG_ON(sizeof(struct opregion_asle) != 0x100); + BUILD_BUG_ON(sizeof(struct opregion_asle_ext) != 0x400); pci_read_config_dword(dev->pdev, PCI_ASLS, &asls); DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls); @@ -931,8 +966,6 @@ int intel_opregion_setup(struct drm_device *dev) goto err_out; } opregion->header = base; - opregion->vbt = base + OPREGION_VBT_OFFSET; - opregion->lid_state = base + ACPI_CLID; mboxes = opregion->header->mboxes; @@ -946,6 +979,7 @@ int intel_opregion_setup(struct drm_device *dev) opregion->swsci = base + OPREGION_SWSCI_OFFSET; swsci_setup(dev); } + if (mboxes & MBOX_ASLE) { DRM_DEBUG_DRIVER("ASLE supported\n"); opregion->asle = base + OPREGION_ASLE_OFFSET; @@ -953,6 +987,37 @@ int intel_opregion_setup(struct drm_device *dev) opregion->asle->ardy = ASLE_ARDY_NOT_READY; } + if (mboxes & MBOX_ASLE_EXT) + DRM_DEBUG_DRIVER("ASLE extension supported\n"); + + if (!dmi_check_system(intel_no_opregion_vbt)) { + const void *vbt = NULL; + u32 vbt_size = 0; + + if (opregion->header->opregion_ver >= 2 && opregion->asle && + opregion->asle->rvda && opregion->asle->rvds) { + opregion->rvda = memremap(opregion->asle->rvda, + opregion->asle->rvds, + MEMREMAP_WB); + vbt = opregion->rvda; + vbt_size = opregion->asle->rvds; + } + + if (intel_bios_is_valid_vbt(vbt, vbt_size)) { + DRM_DEBUG_KMS("Found valid VBT in ACPI OpRegion (RVDA)\n"); + opregion->vbt = vbt; + opregion->vbt_size = vbt_size; + } else { + vbt = base + OPREGION_VBT_OFFSET; + vbt_size = OPREGION_ASLE_EXT_OFFSET - OPREGION_VBT_OFFSET; + if (intel_bios_is_valid_vbt(vbt, vbt_size)) { + DRM_DEBUG_KMS("Found valid VBT in ACPI OpRegion (Mailbox #4)\n"); + opregion->vbt = vbt; + opregion->vbt_size = vbt_size; + } + } + } + return 0; err_out: diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 444542696..76f1980a7 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -749,7 +749,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, if (ret != 0) return ret; - ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL, NULL, + ret = i915_gem_object_pin_to_display_plane(new_bo, 0, &i915_ggtt_view_normal); if (ret != 0) return ret; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index a24df35e1..21ee6477b 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -461,8 +461,7 @@ static inline u32 scale_hw_to_user(struct intel_connector *connector, static u32 intel_panel_compute_brightness(struct intel_connector *connector, u32 val) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; WARN_ON(panel->backlight.max == 0); @@ -480,45 +479,40 @@ static u32 intel_panel_compute_brightness(struct intel_connector *connector, static u32 lpt_get_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK; } static u32 pch_get_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; } static u32 i9xx_get_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 val; val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; - if (INTEL_INFO(dev)->gen < 4) + if (INTEL_INFO(dev_priv)->gen < 4) val >>= 1; if (panel->backlight.combination_mode) { u8 lbpc; - pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); + pci_read_config_byte(dev_priv->dev->pdev, PCI_LBPC, &lbpc); val *= lbpc; } return val; } -static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe) +static u32 _vlv_get_backlight(struct drm_i915_private *dev_priv, enum pipe pipe) { - struct drm_i915_private *dev_priv = dev->dev_private; - if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B)) return 0; @@ -527,17 +521,16 @@ static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe) static u32 vlv_get_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); enum pipe pipe = intel_get_pipe_from_connector(connector); - return _vlv_get_backlight(dev, pipe); + return _vlv_get_backlight(dev_priv, pipe); } static u32 bxt_get_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - struct drm_i915_private *dev_priv = dev->dev_private; return I915_READ(BXT_BLC_PWM_DUTY(panel->backlight.controller)); } @@ -553,8 +546,7 @@ static u32 pwm_get_backlight(struct intel_connector *connector) static u32 intel_panel_get_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 val = 0; @@ -573,16 +565,14 @@ static u32 intel_panel_get_backlight(struct intel_connector *connector) static void lpt_set_backlight(struct intel_connector *connector, u32 level) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK; I915_WRITE(BLC_PWM_PCH_CTL2, val | level); } static void pch_set_backlight(struct intel_connector *connector, u32 level) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); u32 tmp; tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; @@ -591,8 +581,7 @@ static void pch_set_backlight(struct intel_connector *connector, u32 level) static void i9xx_set_backlight(struct intel_connector *connector, u32 level) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 tmp, mask; @@ -603,10 +592,10 @@ static void i9xx_set_backlight(struct intel_connector *connector, u32 level) lbpc = level * 0xfe / panel->backlight.max + 1; level /= lbpc; - pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc); + pci_write_config_byte(dev_priv->dev->pdev, PCI_LBPC, lbpc); } - if (IS_GEN4(dev)) { + if (IS_GEN4(dev_priv)) { mask = BACKLIGHT_DUTY_CYCLE_MASK; } else { level <<= 1; @@ -619,8 +608,7 @@ static void i9xx_set_backlight(struct intel_connector *connector, u32 level) static void vlv_set_backlight(struct intel_connector *connector, u32 level) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); enum pipe pipe = intel_get_pipe_from_connector(connector); u32 tmp; @@ -633,8 +621,7 @@ static void vlv_set_backlight(struct intel_connector *connector, u32 level) static void bxt_set_backlight(struct intel_connector *connector, u32 level) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; I915_WRITE(BXT_BLC_PWM_DUTY(panel->backlight.controller), level); @@ -663,8 +650,7 @@ intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level) static void intel_panel_set_backlight(struct intel_connector *connector, u32 user_level, u32 user_max) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 hw_level; @@ -690,8 +676,7 @@ static void intel_panel_set_backlight(struct intel_connector *connector, void intel_panel_set_backlight_acpi(struct intel_connector *connector, u32 user_level, u32 user_max) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); u32 hw_level; @@ -726,8 +711,7 @@ void intel_panel_set_backlight_acpi(struct intel_connector *connector, static void lpt_disable_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); u32 tmp; intel_panel_actually_set_backlight(connector, 0); @@ -752,8 +736,7 @@ static void lpt_disable_backlight(struct intel_connector *connector) static void pch_disable_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); u32 tmp; intel_panel_actually_set_backlight(connector, 0); @@ -772,8 +755,7 @@ static void i9xx_disable_backlight(struct intel_connector *connector) static void i965_disable_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); u32 tmp; intel_panel_actually_set_backlight(connector, 0); @@ -784,8 +766,7 @@ static void i965_disable_backlight(struct intel_connector *connector) static void vlv_disable_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); enum pipe pipe = intel_get_pipe_from_connector(connector); u32 tmp; @@ -800,8 +781,7 @@ static void vlv_disable_backlight(struct intel_connector *connector) static void bxt_disable_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 tmp, val; @@ -830,8 +810,7 @@ static void pwm_disable_backlight(struct intel_connector *connector) void intel_panel_disable_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; if (!panel->backlight.present) @@ -843,7 +822,7 @@ void intel_panel_disable_backlight(struct intel_connector *connector) * backlight. This will leave the backlight on unnecessarily when * another client is not activated. */ - if (dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) { + if (dev_priv->dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) { DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n"); return; } @@ -860,8 +839,7 @@ void intel_panel_disable_backlight(struct intel_connector *connector) static void lpt_enable_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 pch_ctl1, pch_ctl2; @@ -893,8 +871,7 @@ static void lpt_enable_backlight(struct intel_connector *connector) static void pch_enable_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); enum transcoder cpu_transcoder = @@ -940,8 +917,7 @@ static void pch_enable_backlight(struct intel_connector *connector) static void i9xx_enable_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 ctl, freq; @@ -958,7 +934,7 @@ static void i9xx_enable_backlight(struct intel_connector *connector) ctl = freq << 17; if (panel->backlight.combination_mode) ctl |= BLM_LEGACY_MODE; - if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm) + if (IS_PINEVIEW(dev_priv) && panel->backlight.active_low_pwm) ctl |= BLM_POLARITY_PNV; I915_WRITE(BLC_PWM_CTL, ctl); @@ -972,14 +948,13 @@ static void i9xx_enable_backlight(struct intel_connector *connector) * 855gm only, but checking for gen2 is safe, as 855gm is the only gen2 * that has backlight. */ - if (IS_GEN2(dev)) + if (IS_GEN2(dev_priv)) I915_WRITE(BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE); } static void i965_enable_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); u32 ctl, ctl2, freq; @@ -1012,8 +987,7 @@ static void i965_enable_backlight(struct intel_connector *connector) static void vlv_enable_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); u32 ctl, ctl2; @@ -1044,8 +1018,7 @@ static void vlv_enable_backlight(struct intel_connector *connector) static void bxt_enable_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); u32 pwm_ctl, val; @@ -1102,8 +1075,7 @@ static void pwm_enable_backlight(struct intel_connector *connector) void intel_panel_enable_backlight(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; enum pipe pipe = intel_get_pipe_from_connector(connector); @@ -1264,14 +1236,21 @@ static void intel_backlight_device_unregister(struct intel_connector *connector) #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */ /* + * BXT: PWM clock frequency = 19.2 MHz. + */ +static u32 bxt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) +{ + return KHz(19200) / pwm_freq_hz; +} + +/* * SPT: This value represents the period of the PWM stream in clock periods * multiplied by 16 (default increment) or 128 (alternate increment selected in * SCHICKEN_1 bit 0). PWM clock is 24 MHz. */ static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); u32 mul, clock; if (I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY) @@ -1291,8 +1270,7 @@ static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); u32 mul, clock; if (I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY) @@ -1300,7 +1278,7 @@ static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) else mul = 128; - if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) + if (HAS_PCH_LPT_H(dev_priv)) clock = MHz(135); /* LPT:H */ else clock = MHz(24); /* LPT:LP */ @@ -1335,22 +1313,28 @@ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) int clock; if (IS_PINEVIEW(dev)) - clock = intel_hrawclk(dev); + clock = MHz(intel_hrawclk(dev)); else - clock = 1000 * dev_priv->display.get_display_clock_speed(dev); + clock = 1000 * dev_priv->cdclk_freq; return clock / (pwm_freq_hz * 32); } /* * Gen4: This value represents the period of the PWM stream in display core - * clocks multiplied by 128. + * clocks ([DevCTG] HRAW clocks) multiplied by 128. + * */ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - int clock = 1000 * dev_priv->display.get_display_clock_speed(dev); + int clock; + + if (IS_G4X(dev_priv)) + clock = MHz(intel_hrawclk(dev)); + else + clock = 1000 * dev_priv->cdclk_freq; return clock / (pwm_freq_hz * 128); } @@ -1379,20 +1363,23 @@ static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) static u32 get_backlight_max_vbt(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz; u32 pwm; - if (!pwm_freq_hz) { - DRM_DEBUG_KMS("backlight frequency not specified in VBT\n"); + if (!panel->backlight.hz_to_pwm) { + DRM_DEBUG_KMS("backlight frequency conversion not supported\n"); return 0; } - if (!panel->backlight.hz_to_pwm) { - DRM_DEBUG_KMS("backlight frequency setting from VBT currently not supported on this platform\n"); - return 0; + if (pwm_freq_hz) { + DRM_DEBUG_KMS("VBT defined backlight frequency %u Hz\n", + pwm_freq_hz); + } else { + pwm_freq_hz = 200; + DRM_DEBUG_KMS("default backlight frequency %u Hz\n", + pwm_freq_hz); } pwm = panel->backlight.hz_to_pwm(connector, pwm_freq_hz); @@ -1401,8 +1388,6 @@ static u32 get_backlight_max_vbt(struct intel_connector *connector) return 0; } - DRM_DEBUG_KMS("backlight frequency %u Hz from VBT\n", pwm_freq_hz); - return pwm; } @@ -1411,8 +1396,7 @@ static u32 get_backlight_max_vbt(struct intel_connector *connector) */ static u32 get_backlight_min_vbt(struct intel_connector *connector) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; int min; @@ -1437,8 +1421,7 @@ static u32 get_backlight_min_vbt(struct intel_connector *connector) static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 pch_ctl1, pch_ctl2, val; @@ -1467,8 +1450,7 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus static int pch_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 cpu_ctl2, pch_ctl1, pch_ctl2, val; @@ -1498,17 +1480,16 @@ static int pch_setup_backlight(struct intel_connector *connector, enum pipe unus static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 ctl, val; ctl = I915_READ(BLC_PWM_CTL); - if (IS_GEN2(dev) || IS_I915GM(dev) || IS_I945GM(dev)) + if (IS_GEN2(dev_priv) || IS_I915GM(dev_priv) || IS_I945GM(dev_priv)) panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE; - if (IS_PINEVIEW(dev)) + if (IS_PINEVIEW(dev_priv)) panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV; panel->backlight.max = ctl >> 17; @@ -1536,8 +1517,7 @@ static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unu static int i965_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 ctl, ctl2, val; @@ -1570,8 +1550,7 @@ static int i965_setup_backlight(struct intel_connector *connector, enum pipe unu static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 ctl, ctl2, val; @@ -1592,7 +1571,7 @@ static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe panel->backlight.min = get_backlight_min_vbt(connector); - val = _vlv_get_backlight(dev, pipe); + val = _vlv_get_backlight(dev_priv, pipe); panel->backlight.level = intel_panel_compute_brightness(connector, val); panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && @@ -1604,8 +1583,7 @@ static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe static int bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 pwm_ctl, val; @@ -1683,8 +1661,7 @@ static int pwm_setup_backlight(struct intel_connector *connector, int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe) { - struct drm_device *dev = connector->dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->dev); struct intel_connector *intel_connector = to_intel_connector(connector); struct intel_panel *panel = &intel_connector->panel; int ret; @@ -1739,35 +1716,35 @@ void intel_panel_destroy_backlight(struct drm_connector *connector) static void intel_panel_init_backlight_funcs(struct intel_panel *panel) { - struct intel_connector *intel_connector = + struct intel_connector *connector = container_of(panel, struct intel_connector, panel); - struct drm_device *dev = intel_connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - if (IS_BROXTON(dev)) { + if (IS_BROXTON(dev_priv)) { panel->backlight.setup = bxt_setup_backlight; panel->backlight.enable = bxt_enable_backlight; panel->backlight.disable = bxt_disable_backlight; panel->backlight.set = bxt_set_backlight; panel->backlight.get = bxt_get_backlight; - } else if (HAS_PCH_LPT(dev) || HAS_PCH_SPT(dev)) { + panel->backlight.hz_to_pwm = bxt_hz_to_pwm; + } else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_SPT(dev_priv)) { panel->backlight.setup = lpt_setup_backlight; panel->backlight.enable = lpt_enable_backlight; panel->backlight.disable = lpt_disable_backlight; panel->backlight.set = lpt_set_backlight; panel->backlight.get = lpt_get_backlight; - if (HAS_PCH_LPT(dev)) + if (HAS_PCH_LPT(dev_priv)) panel->backlight.hz_to_pwm = lpt_hz_to_pwm; else panel->backlight.hz_to_pwm = spt_hz_to_pwm; - } else if (HAS_PCH_SPLIT(dev)) { + } else if (HAS_PCH_SPLIT(dev_priv)) { panel->backlight.setup = pch_setup_backlight; panel->backlight.enable = pch_enable_backlight; panel->backlight.disable = pch_disable_backlight; panel->backlight.set = pch_set_backlight; panel->backlight.get = pch_get_backlight; panel->backlight.hz_to_pwm = pch_hz_to_pwm; - } else if (IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { if (dev_priv->vbt.has_mipi) { panel->backlight.setup = pwm_setup_backlight; panel->backlight.enable = pwm_enable_backlight; @@ -1782,7 +1759,7 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel) panel->backlight.get = vlv_get_backlight; panel->backlight.hz_to_pwm = vlv_hz_to_pwm; } - } else if (IS_GEN4(dev)) { + } else if (IS_GEN4(dev_priv)) { panel->backlight.setup = i965_setup_backlight; panel->backlight.enable = i965_enable_backlight; panel->backlight.disable = i965_disable_backlight; @@ -1828,7 +1805,7 @@ void intel_backlight_register(struct drm_device *dev) { struct intel_connector *connector; - list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) + for_each_intel_connector(dev, connector) intel_backlight_device_register(connector); } @@ -1836,6 +1813,6 @@ void intel_backlight_unregister(struct drm_device *dev) { struct intel_connector *connector; - list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) + for_each_intel_connector(dev, connector) intel_backlight_device_unregister(connector); } diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f091ad12d..b28c29f20 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -66,6 +66,14 @@ static void bxt_init_clock_gating(struct drm_device *dev) */ I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) | GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ); + + /* + * Wa: Backlight PWM may stop in the asserted state, causing backlight + * to stay fully on. + */ + if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) + I915_WRITE(GEN9_CLKGATE_DIS_0, I915_READ(GEN9_CLKGATE_DIS_0) | + PWM1_GATING_DIS | PWM2_GATING_DIS); } static void i915_pineview_get_mem_freq(struct drm_device *dev) @@ -283,7 +291,7 @@ void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable) struct drm_device *dev = dev_priv->dev; u32 val; - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { I915_WRITE(FW_BLC_SELF_VLV, enable ? FW_CSPWRDWNEN : 0); POSTING_READ(FW_BLC_SELF_VLV); dev_priv->wm.vlv.cxsr = enable; @@ -1708,13 +1716,6 @@ static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels, return DIV_ROUND_UP(pri_val * 64, horiz_pixels * bytes_per_pixel) + 2; } -struct skl_pipe_wm_parameters { - bool active; - uint32_t pipe_htotal; - uint32_t pixel_rate; /* in KHz */ - struct intel_plane_wm_parameters plane[I915_MAX_PLANES]; -}; - struct ilk_wm_maximums { uint16_t pri; uint16_t spr; @@ -1722,13 +1723,6 @@ struct ilk_wm_maximums { uint16_t fbc; }; -/* used in computing the new watermarks state */ -struct intel_wm_config { - unsigned int num_pipes_active; - bool sprites_enabled; - bool sprites_scaled; -}; - /* * For both WM_PIPE and WM_LP. * mem_value must be in 0.1us units. @@ -1789,16 +1783,20 @@ static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate, const struct intel_plane_state *pstate, uint32_t mem_value) { - int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0; + /* + * We treat the cursor plane as always-on for the purposes of watermark + * calculation. Until we have two-stage watermark programming merged, + * this is necessary to avoid flickering. + */ + int cpp = 4; + int width = pstate->visible ? pstate->base.crtc_w : 64; - if (!cstate->base.active || !pstate->visible) + if (!cstate->base.active) return 0; return ilk_wm_method2(ilk_pipe_pixel_rate(cstate), cstate->base.adjusted_mode.crtc_htotal, - drm_rect_width(&pstate->dst), - bpp, - mem_value); + width, cpp, mem_value); } /* Only for WM_LP. */ @@ -1979,9 +1977,11 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv, const struct intel_crtc *intel_crtc, int level, struct intel_crtc_state *cstate, + struct intel_plane_state *pristate, + struct intel_plane_state *sprstate, + struct intel_plane_state *curstate, struct intel_wm_level *result) { - struct intel_plane *intel_plane; uint16_t pri_latency = dev_priv->wm.pri_latency[level]; uint16_t spr_latency = dev_priv->wm.spr_latency[level]; uint16_t cur_latency = dev_priv->wm.cur_latency[level]; @@ -1993,29 +1993,11 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv, cur_latency *= 5; } - for_each_intel_plane_on_crtc(dev_priv->dev, intel_crtc, intel_plane) { - struct intel_plane_state *pstate = - to_intel_plane_state(intel_plane->base.state); - - switch (intel_plane->base.type) { - case DRM_PLANE_TYPE_PRIMARY: - result->pri_val = ilk_compute_pri_wm(cstate, pstate, - pri_latency, - level); - result->fbc_val = ilk_compute_fbc_wm(cstate, pstate, - result->pri_val); - break; - case DRM_PLANE_TYPE_OVERLAY: - result->spr_val = ilk_compute_spr_wm(cstate, pstate, - spr_latency); - break; - case DRM_PLANE_TYPE_CURSOR: - result->cur_val = ilk_compute_cur_wm(cstate, pstate, - cur_latency); - break; - } - } - + result->pri_val = ilk_compute_pri_wm(cstate, pristate, + pri_latency, level); + result->spr_val = ilk_compute_spr_wm(cstate, sprstate, spr_latency); + result->cur_val = ilk_compute_cur_wm(cstate, curstate, cur_latency); + result->fbc_val = ilk_compute_fbc_wm(cstate, pristate, result->pri_val); result->enable = true; } @@ -2274,34 +2256,19 @@ static void skl_setup_wm_latency(struct drm_device *dev) intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency); } -static void ilk_compute_wm_config(struct drm_device *dev, - struct intel_wm_config *config) -{ - struct intel_crtc *intel_crtc; - - /* Compute the currently _active_ config */ - for_each_intel_crtc(dev, intel_crtc) { - const struct intel_pipe_wm *wm = &intel_crtc->wm.active; - - if (!wm->pipe_enabled) - continue; - - config->sprites_enabled |= wm->sprites_enabled; - config->sprites_scaled |= wm->sprites_scaled; - config->num_pipes_active++; - } -} - /* Compute new watermarks for the pipe */ -static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate, - struct intel_pipe_wm *pipe_wm) +static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, + struct drm_atomic_state *state) { - struct drm_crtc *crtc = cstate->base.crtc; - struct drm_device *dev = crtc->dev; + struct intel_pipe_wm *pipe_wm; + struct drm_device *dev = intel_crtc->base.dev; const struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *cstate = NULL; struct intel_plane *intel_plane; + struct drm_plane_state *ps; + struct intel_plane_state *pristate = NULL; struct intel_plane_state *sprstate = NULL; + struct intel_plane_state *curstate = NULL; int level, max_level = ilk_wm_max_level(dev); /* LP0 watermark maximums depend on this pipe alone */ struct intel_wm_config config = { @@ -2309,11 +2276,24 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate, }; struct ilk_wm_maximums max; + cstate = intel_atomic_get_crtc_state(state, intel_crtc); + if (IS_ERR(cstate)) + return PTR_ERR(cstate); + + pipe_wm = &cstate->wm.optimal.ilk; + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { - if (intel_plane->base.type == DRM_PLANE_TYPE_OVERLAY) { - sprstate = to_intel_plane_state(intel_plane->base.state); - break; - } + ps = drm_atomic_get_plane_state(state, + &intel_plane->base); + if (IS_ERR(ps)) + return PTR_ERR(ps); + + if (intel_plane->base.type == DRM_PLANE_TYPE_PRIMARY) + pristate = to_intel_plane_state(ps); + else if (intel_plane->base.type == DRM_PLANE_TYPE_OVERLAY) + sprstate = to_intel_plane_state(ps); + else if (intel_plane->base.type == DRM_PLANE_TYPE_CURSOR) + curstate = to_intel_plane_state(ps); } config.sprites_enabled = sprstate->visible; @@ -2322,7 +2302,7 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate, drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16); pipe_wm->pipe_enabled = cstate->base.active; - pipe_wm->sprites_enabled = sprstate->visible; + pipe_wm->sprites_enabled = config.sprites_enabled; pipe_wm->sprites_scaled = config.sprites_scaled; /* ILK/SNB: LP2+ watermarks only w/o sprites */ @@ -2333,24 +2313,27 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate, if (config.sprites_scaled) max_level = 0; - ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate, &pipe_wm->wm[0]); + ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate, + pristate, sprstate, curstate, &pipe_wm->wm[0]); if (IS_HASWELL(dev) || IS_BROADWELL(dev)) - pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc); + pipe_wm->linetime = hsw_compute_linetime_wm(dev, + &intel_crtc->base); /* LP0 watermarks always use 1/2 DDB partitioning */ ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max); /* At least LP0 must be valid */ if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0])) - return false; + return -EINVAL; ilk_compute_wm_reg_maximums(dev, 1, &max); for (level = 1; level <= max_level; level++) { struct intel_wm_level wm = {}; - ilk_compute_wm_level(dev_priv, intel_crtc, level, cstate, &wm); + ilk_compute_wm_level(dev_priv, intel_crtc, level, cstate, + pristate, sprstate, curstate, &wm); /* * Disable any watermark level that exceeds the @@ -2363,7 +2346,7 @@ static bool intel_compute_pipe_wm(struct intel_crtc_state *cstate, pipe_wm->wm[level] = wm; } - return true; + return 0; } /* @@ -2378,7 +2361,9 @@ static void ilk_merge_wm_level(struct drm_device *dev, ret_wm->enable = true; for_each_intel_crtc(dev, intel_crtc) { - const struct intel_pipe_wm *active = &intel_crtc->wm.active; + const struct intel_crtc_state *cstate = + to_intel_crtc_state(intel_crtc->base.state); + const struct intel_pipe_wm *active = &cstate->wm.optimal.ilk; const struct intel_wm_level *wm = &active->wm[level]; if (!active->pipe_enabled) @@ -2449,7 +2434,7 @@ static void ilk_wm_merge(struct drm_device *dev, * enabled sometime later. */ if (IS_GEN5(dev) && !merged->fbc_wm_enabled && - intel_fbc_enabled(dev_priv)) { + intel_fbc_is_active(dev_priv)) { for (level = 2; level <= max_level; level++) { struct intel_wm_level *wm = &merged->wm[level]; @@ -2526,14 +2511,15 @@ static void ilk_compute_wm_results(struct drm_device *dev, /* LP0 register values */ for_each_intel_crtc(dev, intel_crtc) { + const struct intel_crtc_state *cstate = + to_intel_crtc_state(intel_crtc->base.state); enum pipe pipe = intel_crtc->pipe; - const struct intel_wm_level *r = - &intel_crtc->wm.active.wm[0]; + const struct intel_wm_level *r = &cstate->wm.optimal.ilk.wm[0]; if (WARN_ON(!r->enable)) continue; - results->wm_linetime[pipe] = intel_crtc->wm.active.linetime; + results->wm_linetime[pipe] = cstate->wm.optimal.ilk.linetime; results->wm_pipe[pipe] = (r->pri_val << WM0_PIPE_PLANE_SHIFT) | @@ -2755,18 +2741,40 @@ static bool ilk_disable_lp_wm(struct drm_device *dev) #define SKL_DDB_SIZE 896 /* in blocks */ #define BXT_DDB_SIZE 512 +/* + * Return the index of a plane in the SKL DDB and wm result arrays. Primary + * plane is always in slot 0, cursor is always in slot I915_MAX_PLANES-1, and + * other universal planes are in indices 1..n. Note that this may leave unused + * indices between the top "sprite" plane and the cursor. + */ +static int +skl_wm_plane_id(const struct intel_plane *plane) +{ + switch (plane->base.type) { + case DRM_PLANE_TYPE_PRIMARY: + return 0; + case DRM_PLANE_TYPE_CURSOR: + return PLANE_CURSOR; + case DRM_PLANE_TYPE_OVERLAY: + return plane->plane + 1; + default: + MISSING_CASE(plane->base.type); + return plane->plane; + } +} + static void skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, - struct drm_crtc *for_crtc, + const struct intel_crtc_state *cstate, const struct intel_wm_config *config, - const struct skl_pipe_wm_parameters *params, struct skl_ddb_entry *alloc /* out */) { + struct drm_crtc *for_crtc = cstate->base.crtc; struct drm_crtc *crtc; unsigned int pipe_size, ddb_size; int nth_active_pipe; - if (!params->active) { + if (!cstate->base.active) { alloc->start = 0; alloc->end = 0; return; @@ -2821,7 +2829,10 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, memset(ddb, 0, sizeof(*ddb)); for_each_pipe(dev_priv, pipe) { - if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) + enum intel_display_power_domain power_domain; + + power_domain = POWER_DOMAIN_PIPE(pipe); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) continue; for_each_plane(dev_priv, pipe, plane) { @@ -2833,23 +2844,35 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, val = I915_READ(CUR_BUF_CFG(pipe)); skl_ddb_entry_init_from_hw(&ddb->plane[pipe][PLANE_CURSOR], val); + + intel_display_power_put(dev_priv, power_domain); } } static unsigned int -skl_plane_relative_data_rate(const struct intel_plane_wm_parameters *p, int y) +skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, + const struct drm_plane_state *pstate, + int y) { + struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); + struct drm_framebuffer *fb = pstate->fb; /* for planar format */ - if (p->y_bytes_per_pixel) { + if (fb->pixel_format == DRM_FORMAT_NV12) { if (y) /* y-plane data rate */ - return p->horiz_pixels * p->vert_pixels * p->y_bytes_per_pixel; + return intel_crtc->config->pipe_src_w * + intel_crtc->config->pipe_src_h * + drm_format_plane_cpp(fb->pixel_format, 0); else /* uv-plane data rate */ - return (p->horiz_pixels/2) * (p->vert_pixels/2) * p->bytes_per_pixel; + return (intel_crtc->config->pipe_src_w/2) * + (intel_crtc->config->pipe_src_h/2) * + drm_format_plane_cpp(fb->pixel_format, 1); } /* for packed formats */ - return p->horiz_pixels * p->vert_pixels * p->bytes_per_pixel; + return intel_crtc->config->pipe_src_w * + intel_crtc->config->pipe_src_h * + drm_format_plane_cpp(fb->pixel_format, 0); } /* @@ -2858,46 +2881,55 @@ skl_plane_relative_data_rate(const struct intel_plane_wm_parameters *p, int y) * 3 * 4096 * 8192 * 4 < 2^32 */ static unsigned int -skl_get_total_relative_data_rate(struct intel_crtc *intel_crtc, - const struct skl_pipe_wm_parameters *params) +skl_get_total_relative_data_rate(const struct intel_crtc_state *cstate) { + struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); + struct drm_device *dev = intel_crtc->base.dev; + const struct intel_plane *intel_plane; unsigned int total_data_rate = 0; - int plane; - for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) { - const struct intel_plane_wm_parameters *p; + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { + const struct drm_plane_state *pstate = intel_plane->base.state; - p = ¶ms->plane[plane]; - if (!p->enabled) + if (pstate->fb == NULL) continue; - total_data_rate += skl_plane_relative_data_rate(p, 0); /* packed/uv */ - if (p->y_bytes_per_pixel) { - total_data_rate += skl_plane_relative_data_rate(p, 1); /* y-plane */ - } + if (intel_plane->base.type == DRM_PLANE_TYPE_CURSOR) + continue; + + /* packed/uv */ + total_data_rate += skl_plane_relative_data_rate(cstate, + pstate, + 0); + + if (pstate->fb->pixel_format == DRM_FORMAT_NV12) + /* y-plane */ + total_data_rate += skl_plane_relative_data_rate(cstate, + pstate, + 1); } return total_data_rate; } static void -skl_allocate_pipe_ddb(struct drm_crtc *crtc, - const struct intel_wm_config *config, - const struct skl_pipe_wm_parameters *params, +skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, struct skl_ddb_allocation *ddb /* out */) { + struct drm_crtc *crtc = cstate->base.crtc; struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_wm_config *config = &dev_priv->wm.config; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_plane *intel_plane; enum pipe pipe = intel_crtc->pipe; struct skl_ddb_entry *alloc = &ddb->pipe[pipe]; uint16_t alloc_size, start, cursor_blocks; uint16_t minimum[I915_MAX_PLANES]; uint16_t y_minimum[I915_MAX_PLANES]; unsigned int total_data_rate; - int plane; - skl_ddb_get_pipe_allocation_limits(dev, crtc, config, params, alloc); + skl_ddb_get_pipe_allocation_limits(dev, cstate, config, alloc); alloc_size = skl_ddb_entry_size(alloc); if (alloc_size == 0) { memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); @@ -2914,17 +2946,20 @@ skl_allocate_pipe_ddb(struct drm_crtc *crtc, alloc->end -= cursor_blocks; /* 1. Allocate the mininum required blocks for each active plane */ - for_each_plane(dev_priv, pipe, plane) { - const struct intel_plane_wm_parameters *p; + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { + struct drm_plane *plane = &intel_plane->base; + struct drm_framebuffer *fb = plane->state->fb; + int id = skl_wm_plane_id(intel_plane); - p = ¶ms->plane[plane]; - if (!p->enabled) + if (fb == NULL) + continue; + if (plane->type == DRM_PLANE_TYPE_CURSOR) continue; - minimum[plane] = 8; - alloc_size -= minimum[plane]; - y_minimum[plane] = p->y_bytes_per_pixel ? 8 : 0; - alloc_size -= y_minimum[plane]; + minimum[id] = 8; + alloc_size -= minimum[id]; + y_minimum[id] = (fb->pixel_format == DRM_FORMAT_NV12) ? 8 : 0; + alloc_size -= y_minimum[id]; } /* @@ -2933,45 +2968,50 @@ skl_allocate_pipe_ddb(struct drm_crtc *crtc, * * FIXME: we may not allocate every single block here. */ - total_data_rate = skl_get_total_relative_data_rate(intel_crtc, params); + total_data_rate = skl_get_total_relative_data_rate(cstate); start = alloc->start; - for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) { - const struct intel_plane_wm_parameters *p; + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { + struct drm_plane *plane = &intel_plane->base; + struct drm_plane_state *pstate = intel_plane->base.state; unsigned int data_rate, y_data_rate; uint16_t plane_blocks, y_plane_blocks = 0; + int id = skl_wm_plane_id(intel_plane); - p = ¶ms->plane[plane]; - if (!p->enabled) + if (pstate->fb == NULL) + continue; + if (plane->type == DRM_PLANE_TYPE_CURSOR) continue; - data_rate = skl_plane_relative_data_rate(p, 0); + data_rate = skl_plane_relative_data_rate(cstate, pstate, 0); /* * allocation for (packed formats) or (uv-plane part of planar format): * promote the expression to 64 bits to avoid overflowing, the * result is < available as data_rate / total_data_rate < 1 */ - plane_blocks = minimum[plane]; + plane_blocks = minimum[id]; plane_blocks += div_u64((uint64_t)alloc_size * data_rate, total_data_rate); - ddb->plane[pipe][plane].start = start; - ddb->plane[pipe][plane].end = start + plane_blocks; + ddb->plane[pipe][id].start = start; + ddb->plane[pipe][id].end = start + plane_blocks; start += plane_blocks; /* * allocation for y_plane part of planar format: */ - if (p->y_bytes_per_pixel) { - y_data_rate = skl_plane_relative_data_rate(p, 1); - y_plane_blocks = y_minimum[plane]; + if (pstate->fb->pixel_format == DRM_FORMAT_NV12) { + y_data_rate = skl_plane_relative_data_rate(cstate, + pstate, + 1); + y_plane_blocks = y_minimum[id]; y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate, total_data_rate); - ddb->y_plane[pipe][plane].start = start; - ddb->y_plane[pipe][plane].end = start + y_plane_blocks; + ddb->y_plane[pipe][id].start = start; + ddb->y_plane[pipe][id].end = start + y_plane_blocks; start += y_plane_blocks; } @@ -3041,104 +3081,27 @@ static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb, struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; const struct skl_ddb_allocation *cur_ddb = &dev_priv->wm.skl_hw.ddb; - enum pipe pipe = intel_crtc->pipe; - - if (memcmp(new_ddb->plane[pipe], cur_ddb->plane[pipe], - sizeof(new_ddb->plane[pipe]))) - return true; - if (memcmp(&new_ddb->plane[pipe][PLANE_CURSOR], &cur_ddb->plane[pipe][PLANE_CURSOR], - sizeof(new_ddb->plane[pipe][PLANE_CURSOR]))) + /* + * If ddb allocation of pipes changed, it may require recalculation of + * watermarks + */ + if (memcmp(new_ddb->pipe, cur_ddb->pipe, sizeof(new_ddb->pipe))) return true; return false; } -static void skl_compute_wm_global_parameters(struct drm_device *dev, - struct intel_wm_config *config) -{ - struct drm_crtc *crtc; - struct drm_plane *plane; - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) - config->num_pipes_active += to_intel_crtc(crtc)->active; - - /* FIXME: I don't think we need those two global parameters on SKL */ - list_for_each_entry(plane, &dev->mode_config.plane_list, head) { - struct intel_plane *intel_plane = to_intel_plane(plane); - - config->sprites_enabled |= intel_plane->wm.enabled; - config->sprites_scaled |= intel_plane->wm.scaled; - } -} - -static void skl_compute_wm_pipe_parameters(struct drm_crtc *crtc, - struct skl_pipe_wm_parameters *p) -{ - struct drm_device *dev = crtc->dev; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; - struct drm_plane *plane; - struct drm_framebuffer *fb; - int i = 1; /* Index for sprite planes start */ - - p->active = intel_crtc->active; - if (p->active) { - p->pipe_htotal = intel_crtc->config->base.adjusted_mode.crtc_htotal; - p->pixel_rate = skl_pipe_pixel_rate(intel_crtc->config); - - fb = crtc->primary->state->fb; - /* For planar: Bpp is for uv plane, y_Bpp is for y plane */ - if (fb) { - p->plane[0].enabled = true; - p->plane[0].bytes_per_pixel = fb->pixel_format == DRM_FORMAT_NV12 ? - drm_format_plane_cpp(fb->pixel_format, 1) : - drm_format_plane_cpp(fb->pixel_format, 0); - p->plane[0].y_bytes_per_pixel = fb->pixel_format == DRM_FORMAT_NV12 ? - drm_format_plane_cpp(fb->pixel_format, 0) : 0; - p->plane[0].tiling = fb->modifier[0]; - } else { - p->plane[0].enabled = false; - p->plane[0].bytes_per_pixel = 0; - p->plane[0].y_bytes_per_pixel = 0; - p->plane[0].tiling = DRM_FORMAT_MOD_NONE; - } - p->plane[0].horiz_pixels = intel_crtc->config->pipe_src_w; - p->plane[0].vert_pixels = intel_crtc->config->pipe_src_h; - p->plane[0].rotation = crtc->primary->state->rotation; - - fb = crtc->cursor->state->fb; - p->plane[PLANE_CURSOR].y_bytes_per_pixel = 0; - if (fb) { - p->plane[PLANE_CURSOR].enabled = true; - p->plane[PLANE_CURSOR].bytes_per_pixel = fb->bits_per_pixel / 8; - p->plane[PLANE_CURSOR].horiz_pixels = crtc->cursor->state->crtc_w; - p->plane[PLANE_CURSOR].vert_pixels = crtc->cursor->state->crtc_h; - } else { - p->plane[PLANE_CURSOR].enabled = false; - p->plane[PLANE_CURSOR].bytes_per_pixel = 0; - p->plane[PLANE_CURSOR].horiz_pixels = 64; - p->plane[PLANE_CURSOR].vert_pixels = 64; - } - } - - list_for_each_entry(plane, &dev->mode_config.plane_list, head) { - struct intel_plane *intel_plane = to_intel_plane(plane); - - if (intel_plane->pipe == pipe && - plane->type == DRM_PLANE_TYPE_OVERLAY) - p->plane[i++] = intel_plane->wm; - } -} - static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, - struct skl_pipe_wm_parameters *p, - struct intel_plane_wm_parameters *p_params, + struct intel_crtc_state *cstate, + struct intel_plane *intel_plane, uint16_t ddb_allocation, int level, uint16_t *out_blocks, /* out */ uint8_t *out_lines /* out */) { + struct drm_plane *plane = &intel_plane->base; + struct drm_framebuffer *fb = plane->state->fb; uint32_t latency = dev_priv->wm.skl_latency[level]; uint32_t method1, method2; uint32_t plane_bytes_per_line, plane_blocks_per_line; @@ -3146,31 +3109,33 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint32_t selected_result; uint8_t bytes_per_pixel; - if (latency == 0 || !p->active || !p_params->enabled) + if (latency == 0 || !cstate->base.active || !fb) return false; - bytes_per_pixel = p_params->y_bytes_per_pixel ? - p_params->y_bytes_per_pixel : - p_params->bytes_per_pixel; - method1 = skl_wm_method1(p->pixel_rate, + bytes_per_pixel = drm_format_plane_cpp(fb->pixel_format, 0); + method1 = skl_wm_method1(skl_pipe_pixel_rate(cstate), bytes_per_pixel, latency); - method2 = skl_wm_method2(p->pixel_rate, - p->pipe_htotal, - p_params->horiz_pixels, + method2 = skl_wm_method2(skl_pipe_pixel_rate(cstate), + cstate->base.adjusted_mode.crtc_htotal, + cstate->pipe_src_w, bytes_per_pixel, - p_params->tiling, + fb->modifier[0], latency); - plane_bytes_per_line = p_params->horiz_pixels * bytes_per_pixel; + plane_bytes_per_line = cstate->pipe_src_w * bytes_per_pixel; plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); - if (p_params->tiling == I915_FORMAT_MOD_Y_TILED || - p_params->tiling == I915_FORMAT_MOD_Yf_TILED) { + if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || + fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { uint32_t min_scanlines = 4; uint32_t y_tile_minimum; - if (intel_rotation_90_or_270(p_params->rotation)) { - switch (p_params->bytes_per_pixel) { + if (intel_rotation_90_or_270(plane->state->rotation)) { + int bpp = (fb->pixel_format == DRM_FORMAT_NV12) ? + drm_format_plane_cpp(fb->pixel_format, 1) : + drm_format_plane_cpp(fb->pixel_format, 0); + + switch (bpp) { case 1: min_scanlines = 16; break; @@ -3194,8 +3159,8 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, res_lines = DIV_ROUND_UP(selected_result, plane_blocks_per_line); if (level >= 1 && level <= 7) { - if (p_params->tiling == I915_FORMAT_MOD_Y_TILED || - p_params->tiling == I915_FORMAT_MOD_Yf_TILED) + if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || + fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) res_lines += 4; else res_blocks++; @@ -3212,84 +3177,80 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, static void skl_compute_wm_level(const struct drm_i915_private *dev_priv, struct skl_ddb_allocation *ddb, - struct skl_pipe_wm_parameters *p, - enum pipe pipe, + struct intel_crtc_state *cstate, int level, - int num_planes, struct skl_wm_level *result) { + struct drm_device *dev = dev_priv->dev; + struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); + struct intel_plane *intel_plane; uint16_t ddb_blocks; - int i; + enum pipe pipe = intel_crtc->pipe; + + for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { + int i = skl_wm_plane_id(intel_plane); - for (i = 0; i < num_planes; i++) { ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]); result->plane_en[i] = skl_compute_plane_wm(dev_priv, - p, &p->plane[i], + cstate, + intel_plane, ddb_blocks, level, &result->plane_res_b[i], &result->plane_res_l[i]); } - - ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][PLANE_CURSOR]); - result->plane_en[PLANE_CURSOR] = skl_compute_plane_wm(dev_priv, p, - &p->plane[PLANE_CURSOR], - ddb_blocks, level, - &result->plane_res_b[PLANE_CURSOR], - &result->plane_res_l[PLANE_CURSOR]); } static uint32_t -skl_compute_linetime_wm(struct drm_crtc *crtc, struct skl_pipe_wm_parameters *p) +skl_compute_linetime_wm(struct intel_crtc_state *cstate) { - if (!to_intel_crtc(crtc)->active) + if (!cstate->base.active) return 0; - if (WARN_ON(p->pixel_rate == 0)) + if (WARN_ON(skl_pipe_pixel_rate(cstate) == 0)) return 0; - return DIV_ROUND_UP(8 * p->pipe_htotal * 1000, p->pixel_rate); + return DIV_ROUND_UP(8 * cstate->base.adjusted_mode.crtc_htotal * 1000, + skl_pipe_pixel_rate(cstate)); } -static void skl_compute_transition_wm(struct drm_crtc *crtc, - struct skl_pipe_wm_parameters *params, +static void skl_compute_transition_wm(struct intel_crtc_state *cstate, struct skl_wm_level *trans_wm /* out */) { + struct drm_crtc *crtc = cstate->base.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int i; + struct intel_plane *intel_plane; - if (!params->active) + if (!cstate->base.active) return; /* Until we know more, just disable transition WMs */ - for (i = 0; i < intel_num_planes(intel_crtc); i++) + for_each_intel_plane_on_crtc(crtc->dev, intel_crtc, intel_plane) { + int i = skl_wm_plane_id(intel_plane); + trans_wm->plane_en[i] = false; - trans_wm->plane_en[PLANE_CURSOR] = false; + } } -static void skl_compute_pipe_wm(struct drm_crtc *crtc, +static void skl_compute_pipe_wm(struct intel_crtc_state *cstate, struct skl_ddb_allocation *ddb, - struct skl_pipe_wm_parameters *params, struct skl_pipe_wm *pipe_wm) { - struct drm_device *dev = crtc->dev; + struct drm_device *dev = cstate->base.crtc->dev; const struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int level, max_level = ilk_wm_max_level(dev); for (level = 0; level <= max_level; level++) { - skl_compute_wm_level(dev_priv, ddb, params, intel_crtc->pipe, - level, intel_num_planes(intel_crtc), - &pipe_wm->wm[level]); + skl_compute_wm_level(dev_priv, ddb, cstate, + level, &pipe_wm->wm[level]); } - pipe_wm->linetime = skl_compute_linetime_wm(crtc, params); + pipe_wm->linetime = skl_compute_linetime_wm(cstate); - skl_compute_transition_wm(crtc, params, &pipe_wm->trans_wm); + skl_compute_transition_wm(cstate, &pipe_wm->trans_wm); } static void skl_compute_wm_results(struct drm_device *dev, - struct skl_pipe_wm_parameters *p, struct skl_pipe_wm *p_wm, struct skl_wm_values *r, struct intel_crtc *intel_crtc) @@ -3346,7 +3307,8 @@ static void skl_compute_wm_results(struct drm_device *dev, r->wm_linetime[pipe] = p_wm->linetime; } -static void skl_ddb_entry_write(struct drm_i915_private *dev_priv, uint32_t reg, +static void skl_ddb_entry_write(struct drm_i915_private *dev_priv, + i915_reg_t reg, const struct skl_ddb_entry *entry) { if (entry->end) @@ -3361,7 +3323,7 @@ static void skl_write_wm_values(struct drm_i915_private *dev_priv, struct drm_device *dev = dev_priv->dev; struct intel_crtc *crtc; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { + for_each_intel_crtc(dev, crtc) { int i, level, max_level = ilk_wm_max_level(dev); enum pipe pipe = crtc->pipe; @@ -3533,28 +3495,25 @@ static void skl_flush_wm_values(struct drm_i915_private *dev_priv, } static bool skl_update_pipe_wm(struct drm_crtc *crtc, - struct skl_pipe_wm_parameters *params, - struct intel_wm_config *config, struct skl_ddb_allocation *ddb, /* out */ struct skl_pipe_wm *pipe_wm /* out */) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); - skl_compute_wm_pipe_parameters(crtc, params); - skl_allocate_pipe_ddb(crtc, config, params, ddb); - skl_compute_pipe_wm(crtc, ddb, params, pipe_wm); + skl_allocate_pipe_ddb(cstate, ddb); + skl_compute_pipe_wm(cstate, ddb, pipe_wm); - if (!memcmp(&intel_crtc->wm.skl_active, pipe_wm, sizeof(*pipe_wm))) + if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm))) return false; - intel_crtc->wm.skl_active = *pipe_wm; + intel_crtc->wm.active.skl = *pipe_wm; return true; } static void skl_update_other_pipe_wm(struct drm_device *dev, struct drm_crtc *crtc, - struct intel_wm_config *config, struct skl_wm_values *r) { struct intel_crtc *intel_crtc; @@ -3573,9 +3532,7 @@ static void skl_update_other_pipe_wm(struct drm_device *dev, * Otherwise, because of this_crtc being freshly enabled/disabled, the * other active pipes need new DDB allocation and WM values. */ - list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, - base.head) { - struct skl_pipe_wm_parameters params = {}; + for_each_intel_crtc(dev, intel_crtc) { struct skl_pipe_wm pipe_wm = {}; bool wm_changed; @@ -3586,7 +3543,6 @@ static void skl_update_other_pipe_wm(struct drm_device *dev, continue; wm_changed = skl_update_pipe_wm(&intel_crtc->base, - ¶ms, config, &r->ddb, &pipe_wm); /* @@ -3596,7 +3552,7 @@ static void skl_update_other_pipe_wm(struct drm_device *dev, */ WARN_ON(!wm_changed); - skl_compute_wm_results(dev, ¶ms, &pipe_wm, r, intel_crtc); + skl_compute_wm_results(dev, &pipe_wm, r, intel_crtc); r->dirty[intel_crtc->pipe] = true; } } @@ -3626,10 +3582,9 @@ static void skl_update_wm(struct drm_crtc *crtc) 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 skl_pipe_wm_parameters params = {}; struct skl_wm_values *results = &dev_priv->wm.skl_results; - struct skl_pipe_wm pipe_wm = {}; - struct intel_wm_config config = {}; + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); + struct skl_pipe_wm *pipe_wm = &cstate->wm.optimal.skl; /* Clear all dirty flags */ @@ -3637,16 +3592,13 @@ static void skl_update_wm(struct drm_crtc *crtc) skl_clear_wm(results, intel_crtc->pipe); - skl_compute_wm_global_parameters(dev, &config); - - if (!skl_update_pipe_wm(crtc, ¶ms, &config, - &results->ddb, &pipe_wm)) + if (!skl_update_pipe_wm(crtc, &results->ddb, pipe_wm)) return; - skl_compute_wm_results(dev, ¶ms, &pipe_wm, results, intel_crtc); + skl_compute_wm_results(dev, pipe_wm, results, intel_crtc); results->dirty[intel_crtc->pipe] = true; - skl_update_other_pipe_wm(dev, crtc, &config, results); + skl_update_other_pipe_wm(dev, crtc, results); skl_write_wm_values(dev_priv, results); skl_flush_wm_values(dev_priv, results); @@ -3654,71 +3606,23 @@ static void skl_update_wm(struct drm_crtc *crtc) dev_priv->wm.skl_hw = *results; } -static void -skl_update_sprite_wm(struct drm_plane *plane, struct drm_crtc *crtc, - uint32_t sprite_width, uint32_t sprite_height, - int pixel_size, bool enabled, bool scaled) +static void ilk_program_watermarks(struct drm_i915_private *dev_priv) { - struct intel_plane *intel_plane = to_intel_plane(plane); - struct drm_framebuffer *fb = plane->state->fb; - - intel_plane->wm.enabled = enabled; - intel_plane->wm.scaled = scaled; - intel_plane->wm.horiz_pixels = sprite_width; - intel_plane->wm.vert_pixels = sprite_height; - intel_plane->wm.tiling = DRM_FORMAT_MOD_NONE; - - /* For planar: Bpp is for UV plane, y_Bpp is for Y plane */ - intel_plane->wm.bytes_per_pixel = - (fb && fb->pixel_format == DRM_FORMAT_NV12) ? - drm_format_plane_cpp(plane->state->fb->pixel_format, 1) : pixel_size; - intel_plane->wm.y_bytes_per_pixel = - (fb && fb->pixel_format == DRM_FORMAT_NV12) ? - drm_format_plane_cpp(plane->state->fb->pixel_format, 0) : 0; - - /* - * Framebuffer can be NULL on plane disable, but it does not - * matter for watermarks if we assume no tiling in that case. - */ - if (fb) - intel_plane->wm.tiling = fb->modifier[0]; - intel_plane->wm.rotation = plane->state->rotation; - - skl_update_wm(crtc); -} - -static void ilk_update_wm(struct drm_crtc *crtc) -{ - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_device *dev = dev_priv->dev; + struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm; struct ilk_wm_maximums max; + struct intel_wm_config *config = &dev_priv->wm.config; struct ilk_wm_values 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 = {}; - - WARN_ON(cstate->base.active != intel_crtc->active); - intel_compute_pipe_wm(cstate, &pipe_wm); - - if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm))) - return; - - intel_crtc->wm.active = pipe_wm; - - ilk_compute_wm_config(dev, &config); - - ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max); - ilk_wm_merge(dev, &config, &max, &lp_wm_1_2); + ilk_compute_wm_maximums(dev, 1, config, INTEL_DDB_PART_1_2, &max); + ilk_wm_merge(dev, config, &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, &config, &max, &lp_wm_5_6); + 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, config, &max, &lp_wm_5_6); best_lp_wm = ilk_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6); } else { @@ -3733,14 +3637,13 @@ static void ilk_update_wm(struct drm_crtc *crtc) ilk_write_wm_values(dev_priv, &results); } -static void -ilk_update_sprite_wm(struct drm_plane *plane, - struct drm_crtc *crtc, - uint32_t sprite_width, uint32_t sprite_height, - int pixel_size, bool enabled, bool scaled) +static void ilk_update_wm(struct drm_crtc *crtc) { - struct drm_device *dev = plane->dev; - struct intel_plane *intel_plane = to_intel_plane(plane); + struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); + + WARN_ON(cstate->base.active != intel_crtc->active); /* * IVB workaround: must disable low power watermarks for at least @@ -3749,10 +3652,14 @@ ilk_update_sprite_wm(struct drm_plane *plane, * * WaCxSRDisabledForSpriteScaling:ivb */ - if (IS_IVYBRIDGE(dev) && scaled && ilk_disable_lp_wm(dev)) - intel_wait_for_vblank(dev, intel_plane->pipe); + if (cstate->disable_lp_wm) { + ilk_disable_lp_wm(crtc->dev); + intel_wait_for_vblank(crtc->dev, intel_crtc->pipe); + } + + intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk; - ilk_update_wm(crtc); + ilk_program_watermarks(dev_priv); } static void skl_pipe_wm_active_state(uint32_t val, @@ -3805,7 +3712,8 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; struct skl_wm_values *hw = &dev_priv->wm.skl_hw; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct skl_pipe_wm *active = &intel_crtc->wm.skl_active; + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); + struct skl_pipe_wm *active = &cstate->wm.optimal.skl; enum pipe pipe = intel_crtc->pipe; int level, i, max_level; uint32_t temp; @@ -3849,6 +3757,8 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc) temp = hw->plane_trans[pipe][PLANE_CURSOR]; skl_pipe_wm_active_state(temp, active, true, true, i, 0); + + intel_crtc->wm.active.skl = *active; } void skl_wm_get_hw_state(struct drm_device *dev) @@ -3868,9 +3778,10 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; struct ilk_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; + struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); + struct intel_pipe_wm *active = &cstate->wm.optimal.ilk; enum pipe pipe = intel_crtc->pipe; - static const unsigned int wm0_pipe_reg[] = { + static const i915_reg_t wm0_pipe_reg[] = { [PIPE_A] = WM0_PIPEA_ILK, [PIPE_B] = WM0_PIPEB_ILK, [PIPE_C] = WM0_PIPEC_IVB, @@ -3907,6 +3818,8 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) for (level = 0; level <= max_level; level++) active->wm[level].enable = true; } + + intel_crtc->wm.active.ilk = *active; } #define _FW_WM(value, plane) \ @@ -4132,21 +4045,6 @@ void intel_update_watermarks(struct drm_crtc *crtc) dev_priv->display.update_wm(crtc); } -void intel_update_sprite_watermarks(struct drm_plane *plane, - struct drm_crtc *crtc, - uint32_t sprite_width, - uint32_t sprite_height, - int pixel_size, - bool enabled, bool scaled) -{ - struct drm_i915_private *dev_priv = plane->dev->dev_private; - - if (dev_priv->display.update_sprite_wm) - dev_priv->display.update_sprite_wm(plane, crtc, - sprite_width, sprite_height, - pixel_size, enabled, scaled); -} - /** * Lock protecting IPS related data structures */ @@ -4414,7 +4312,7 @@ static void gen6_set_rps(struct drm_device *dev, u8 val) struct drm_i915_private *dev_priv = dev->dev_private; /* WaGsvDisableTurbo: Workaround to disable turbo on BXT A* */ - if (IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) + if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) return; WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); @@ -4515,7 +4413,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv) mutex_lock(&dev_priv->rps.hw_lock); if (dev_priv->rps.enabled) { - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) vlv_set_rps_idle(dev_priv); else gen6_set_rps(dev_priv->dev, dev_priv->rps.idle_freq); @@ -4568,7 +4466,7 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv, void intel_set_rps(struct drm_device *dev, u8 val) { - if (IS_VALLEYVIEW(dev)) + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) valleyview_set_rps(dev, val); else gen6_set_rps(dev, val); @@ -4612,7 +4510,7 @@ static void valleyview_disable_rps(struct drm_device *dev) static void intel_print_rc6_info(struct drm_device *dev, u32 mode) { - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { if (mode & (GEN7_RC_CTL_TO_MODE | GEN6_RC_CTL_EI_MODE(1))) mode = GEN6_RC_CTL_RC6_ENABLE; else @@ -4689,7 +4587,8 @@ static void gen6_init_rps_frequencies(struct drm_device *dev) dev_priv->rps.max_freq = dev_priv->rps.rp0_freq; dev_priv->rps.efficient_freq = dev_priv->rps.rp1_freq; - if (IS_HASWELL(dev) || IS_BROADWELL(dev) || IS_SKYLAKE(dev)) { + if (IS_HASWELL(dev) || IS_BROADWELL(dev) || + IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { ret = sandybridge_pcode_read(dev_priv, HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL, &ddcc_status); @@ -4701,7 +4600,7 @@ static void gen6_init_rps_frequencies(struct drm_device *dev) dev_priv->rps.max_freq); } - if (IS_SKYLAKE(dev)) { + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { /* Store the frequency values in 16.66 MHZ units, which is the natural hardware unit for SKL */ dev_priv->rps.rp0_freq *= GEN9_FREQ_SCALER; @@ -4738,7 +4637,7 @@ static void gen9_enable_rps(struct drm_device *dev) gen6_init_rps_frequencies(dev); /* WaGsvDisableTurbo: Workaround to disable turbo on BXT A* */ - if (IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) { + if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); return; } @@ -4806,8 +4705,8 @@ static void gen9_enable_rc6(struct drm_device *dev) DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off"); /* WaRsUseTimeoutMode */ - if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_D0) || - (IS_BROXTON(dev) && INTEL_REVID(dev) <= BXT_REVID_A0)) { + if (IS_SKL_REVID(dev, 0, SKL_REVID_D0) || + IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us */ I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | GEN7_RC_CTL_TO_MODE | @@ -5055,7 +4954,7 @@ static void __gen6_update_ring_freq(struct drm_device *dev) /* convert DDR frequency from units of 266.6MHz to bandwidth */ min_ring_freq = mult_frac(min_ring_freq, 8, 3); - if (IS_SKYLAKE(dev)) { + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { /* Convert GT frequency to 50 HZ units */ min_gpu_freq = dev_priv->rps.min_freq / GEN9_FREQ_SCALER; max_gpu_freq = dev_priv->rps.max_freq / GEN9_FREQ_SCALER; @@ -5073,7 +4972,7 @@ static void __gen6_update_ring_freq(struct drm_device *dev) int diff = max_gpu_freq - gpu_freq; unsigned int ia_freq = 0, ring_freq = 0; - if (IS_SKYLAKE(dev)) { + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { /* * ring_freq = 2 * GT. ring_freq is in 100MHz units * No floor required for ring frequency on SKL. @@ -5208,7 +5107,17 @@ static int valleyview_rps_rpe_freq(struct drm_i915_private *dev_priv) static int valleyview_rps_min_freq(struct drm_i915_private *dev_priv) { - return vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM) & 0xff; + u32 val; + + val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM) & 0xff; + /* + * According to the BYT Punit GPU turbo HAS 1.1.6.3 the minimum value + * for the minimum frequency in GPLL mode is 0xc1. Contrary to this on + * a BYT-M B0 the above register contains 0xbf. Moreover when setting + * a frequency Punit will not allow values below 0xc0. Clamp it 0xc0 + * to make sure it matches what Punit accepts. + */ + return max_t(u32, val, 0xc0); } /* Check that the pctx buffer wasn't move under us. */ @@ -6113,7 +6022,17 @@ static void intel_init_emon(struct drm_device *dev) void intel_init_gt_powersave(struct drm_device *dev) { + struct drm_i915_private *dev_priv = dev->dev_private; + i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6); + /* + * RPM depends on RC6 to save restore the GT HW context, so make RC6 a + * requirement. + */ + if (!i915.enable_rc6) { + DRM_INFO("RC6 disabled, disabling runtime PM support\n"); + intel_runtime_pm_get(dev_priv); + } if (IS_CHERRYVIEW(dev)) cherryview_init_gt_powersave(dev); @@ -6123,10 +6042,15 @@ void intel_init_gt_powersave(struct drm_device *dev) void intel_cleanup_gt_powersave(struct drm_device *dev) { + struct drm_i915_private *dev_priv = dev->dev_private; + if (IS_CHERRYVIEW(dev)) return; else if (IS_VALLEYVIEW(dev)) valleyview_cleanup_gt_powersave(dev); + + if (!i915.enable_rc6) + intel_runtime_pm_put(dev_priv); } static void gen6_suspend_rps(struct drm_device *dev) @@ -6201,7 +6125,7 @@ static void intel_gen6_powersave_work(struct work_struct *work) } else if (INTEL_INFO(dev)->gen >= 9) { gen9_enable_rc6(dev); gen9_enable_rps(dev); - if (IS_SKYLAKE(dev)) + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) __gen6_update_ring_freq(dev); } else if (IS_BROADWELL(dev)) { gen8_enable_rps(dev); @@ -7057,7 +6981,6 @@ void intel_init_pm(struct drm_device *dev) dev_priv->display.init_clock_gating = bxt_init_clock_gating; dev_priv->display.update_wm = skl_update_wm; - dev_priv->display.update_sprite_wm = skl_update_sprite_wm; } else if (HAS_PCH_SPLIT(dev)) { ilk_setup_wm_latency(dev); @@ -7066,7 +6989,7 @@ void intel_init_pm(struct drm_device *dev) (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] && dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) { dev_priv->display.update_wm = ilk_update_wm; - dev_priv->display.update_sprite_wm = ilk_update_sprite_wm; + dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm; } else { DRM_DEBUG_KMS("Failed to read display plane latency. " "Disable CxSR\n"); @@ -7331,4 +7254,6 @@ void intel_pm_setup(struct drm_device *dev) INIT_LIST_HEAD(&dev_priv->rps.mmioflips.link); dev_priv->pm.suspended = false; + atomic_set(&dev_priv->pm.wakeref_count, 0); + atomic_set(&dev_priv->pm.atomic_seq, 0); } diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 213581c21..9ccff3011 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -80,7 +80,7 @@ static void intel_psr_write_vsc(struct intel_dp *intel_dp, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc); enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; - u32 ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder); + i915_reg_t ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder); uint32_t *data = (uint32_t *) vsc_psr; unsigned int i; @@ -151,13 +151,31 @@ static void vlv_psr_enable_sink(struct intel_dp *intel_dp) DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE); } +static i915_reg_t psr_aux_ctl_reg(struct drm_i915_private *dev_priv, + enum port port) +{ + if (INTEL_INFO(dev_priv)->gen >= 9) + return DP_AUX_CH_CTL(port); + else + return EDP_PSR_AUX_CTL; +} + +static i915_reg_t psr_aux_data_reg(struct drm_i915_private *dev_priv, + enum port port, int index) +{ + if (INTEL_INFO(dev_priv)->gen >= 9) + return DP_AUX_CH_DATA(port, index); + else + return EDP_PSR_AUX_DATA(index); +} + static void hsw_psr_enable_sink(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; uint32_t aux_clock_divider; - uint32_t aux_data_reg, aux_ctl_reg; + i915_reg_t aux_ctl_reg; int precharge = 0x3; static const uint8_t aux_msg[] = { [0] = DP_AUX_NATIVE_WRITE << 4, @@ -166,29 +184,24 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) [3] = 1 - 1, [4] = DP_SET_POWER_D0, }; + enum port port = dig_port->port; int i; BUILD_BUG_ON(sizeof(aux_msg) > 20); aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, 0); - drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, - DP_PSR_ENABLE & ~DP_PSR_MAIN_LINK_ACTIVE); - /* Enable AUX frame sync at sink */ if (dev_priv->psr.aux_frame_sync) drm_dp_dpcd_writeb(&intel_dp->aux, DP_SINK_DEVICE_AUX_FRAME_SYNC_CONF, DP_AUX_FRAME_SYNC_ENABLE); - aux_data_reg = (INTEL_INFO(dev)->gen >= 9) ? - DPA_AUX_CH_DATA1 : EDP_PSR_AUX_DATA1(dev); - aux_ctl_reg = (INTEL_INFO(dev)->gen >= 9) ? - DPA_AUX_CH_CTL : EDP_PSR_AUX_CTL(dev); + aux_ctl_reg = psr_aux_ctl_reg(dev_priv, port); /* Setup AUX registers */ for (i = 0; i < sizeof(aux_msg); i += 4) - I915_WRITE(aux_data_reg + i, + I915_WRITE(psr_aux_data_reg(dev_priv, port, i >> 2), intel_dp_pack_aux(&aux_msg[i], sizeof(aux_msg) - i)); if (INTEL_INFO(dev)->gen >= 9) { @@ -254,30 +267,20 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = dev->dev_private; uint32_t max_sleep_time = 0x1f; - /* Lately it was identified that depending on panel idle frame count - * calculated at HW can be off by 1. So let's use what came - * from VBT + 1. - * There are also other cases where panel demands at least 4 - * but VBT is not being set. To cover these 2 cases lets use - * at least 5 when VBT isn't set to be on the safest side. + /* + * Let's respect VBT in case VBT asks a higher idle_frame value. + * Let's use 6 as the minimum to cover all known cases including + * the off-by-one issue that HW has in some cases. Also there are + * cases where sink should be able to train + * with the 5 or 6 idle patterns. */ - uint32_t idle_frames = dev_priv->vbt.psr.idle_frames ? - dev_priv->vbt.psr.idle_frames + 1 : 5; + uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); 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) { - /* It doesn't mean we shouldn't send TPS patters, so let's - send the minimal TP1 possible and skip TP2. */ - val |= EDP_PSR_TP1_TIME_100us; - val |= EDP_PSR_TP2_TP3_TIME_0us; - val |= EDP_PSR_SKIP_AUX_EXIT; - /* Sink should be able to train with the 5 or 6 idle patterns */ - idle_frames += 4; - } - I915_WRITE(EDP_PSR_CTL(dev), val | - (IS_BROADWELL(dev) ? 0 : link_entry_time) | + if (IS_HASWELL(dev)) + val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES; + + I915_WRITE(EDP_PSR_CTL, val | max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT | idle_frames << EDP_PSR_IDLE_FRAME_SHIFT | EDP_PSR_ENABLE); @@ -324,8 +327,8 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) return false; } - if (!IS_VALLEYVIEW(dev) && ((dev_priv->vbt.psr.full_link) || - (dig_port->port != PORT_A))) { + if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && + ((dev_priv->vbt.psr.full_link) || (dig_port->port != PORT_A))) { DRM_DEBUG_KMS("PSR condition failed: Link Standby requested/needed but not supported on this platform\n"); return false; } @@ -340,7 +343,7 @@ static void intel_psr_activate(struct intel_dp *intel_dp) struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - WARN_ON(I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE); + WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); WARN_ON(dev_priv->psr.active); lockdep_assert_held(&dev_priv->psr.lock); @@ -403,9 +406,14 @@ void intel_psr_enable(struct intel_dp *intel_dp) skl_psr_setup_su_vsc(intel_dp); } - /* Avoid continuous PSR exit by masking memup and hpd */ - I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP | - EDP_PSR_DEBUG_MASK_HPD); + /* + * Per Spec: Avoid continuous PSR exit by masking MEMUP and HPD. + * Also mask LPSP to avoid dependency on other drivers that + * might block runtime_pm besides preventing other hw tracking + * issues now we can rely on frontbuffer tracking. + */ + I915_WRITE(EDP_PSR_DEBUG_CTL, EDP_PSR_DEBUG_MASK_MEMUP | + EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP); /* Enable PSR on the panel */ hsw_psr_enable_sink(intel_dp); @@ -427,6 +435,19 @@ void intel_psr_enable(struct intel_dp *intel_dp) vlv_psr_enable_source(intel_dp); } + /* + * FIXME: Activation should happen immediately since this function + * is just called after pipe is fully trained and enabled. + * However on every platform we face issues when first activation + * follows a modeset so quickly. + * - On VLV/CHV we get bank screen on first activation + * - On HSW/BDW we get a recoverable frozen screen until next + * exit-activate sequence. + */ + if (INTEL_INFO(dev)->gen < 9) + schedule_delayed_work(&dev_priv->psr.work, + msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5)); + dev_priv->psr.enabled = intel_dp; unlock: mutex_unlock(&dev_priv->psr.lock); @@ -466,17 +487,17 @@ static void hsw_psr_disable(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = dev->dev_private; if (dev_priv->psr.active) { - 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"); dev_priv->psr.active = false; } else { - WARN_ON(I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE); + WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); } } @@ -498,11 +519,15 @@ void intel_psr_disable(struct intel_dp *intel_dp) return; } + /* Disable PSR on Source */ if (HAS_DDI(dev)) hsw_psr_disable(intel_dp); else vlv_psr_disable(intel_dp); + /* Disable PSR on Sink */ + drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0); + dev_priv->psr.enabled = NULL; mutex_unlock(&dev_priv->psr.lock); @@ -523,7 +548,7 @@ static void intel_psr_work(struct work_struct *work) * and be ready for re-enable. */ if (HAS_DDI(dev_priv->dev)) { - if (wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev_priv->dev)) & + if (wait_for((I915_READ(EDP_PSR_STATUS_CTL) & EDP_PSR_STATUS_STATE_MASK) == 0, 50)) { DRM_ERROR("Timed out waiting for PSR Idle for re-enable\n"); return; @@ -566,11 +591,11 @@ static void intel_psr_exit(struct drm_device *dev) return; if (HAS_DDI(dev)) { - val = I915_READ(EDP_PSR_CTL(dev)); + val = I915_READ(EDP_PSR_CTL); WARN_ON(!(val & EDP_PSR_ENABLE)); - I915_WRITE(EDP_PSR_CTL(dev), val & ~EDP_PSR_ENABLE); + I915_WRITE(EDP_PSR_CTL, val & ~EDP_PSR_ENABLE); } else { val = I915_READ(VLV_PSRCTL(pipe)); @@ -620,7 +645,7 @@ void intel_psr_single_frame_update(struct drm_device *dev, * Single frame update is already supported on BDW+ but it requires * many W/A and it isn't really needed. */ - if (!IS_VALLEYVIEW(dev)) + if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) return; mutex_lock(&dev_priv->psr.lock); @@ -700,7 +725,6 @@ void intel_psr_flush(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; enum pipe pipe; - int delay_ms = HAS_DDI(dev) ? 100 : 500; mutex_lock(&dev_priv->psr.lock); if (!dev_priv->psr.enabled) { @@ -714,29 +738,14 @@ void intel_psr_flush(struct drm_device *dev, frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe); dev_priv->psr.busy_frontbuffer_bits &= ~frontbuffer_bits; - if (HAS_DDI(dev)) { - /* - * By definition every flush should mean invalidate + flush, - * however on core platforms let's minimize the - * disable/re-enable so we can avoid the invalidate when flip - * originated the flush. - */ - if (frontbuffer_bits && origin != ORIGIN_FLIP) - intel_psr_exit(dev); - } else { - /* - * On Valleyview and Cherryview we don't use hardware tracking - * so any plane updates or cursor moves don't result in a PSR - * invalidating. Which means we need to manually fake this in - * software for all flushes. - */ - if (frontbuffer_bits) - intel_psr_exit(dev); - } + /* By definition flush = invalidate + flush */ + if (frontbuffer_bits) + intel_psr_exit(dev); if (!dev_priv->psr.active && !dev_priv->psr.busy_frontbuffer_bits) - schedule_delayed_work(&dev_priv->psr.work, - msecs_to_jiffies(delay_ms)); + if (!work_busy(&dev_priv->psr.work.work)) + schedule_delayed_work(&dev_priv->psr.work, + msecs_to_jiffies(100)); mutex_unlock(&dev_priv->psr.lock); } @@ -751,6 +760,9 @@ void intel_psr_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + dev_priv->psr_mmio_base = IS_HASWELL(dev_priv) ? + HSW_EDP_PSR_BASE : BDW_EDP_PSR_BASE; + INIT_DELAYED_WORK(&dev_priv->psr.work, intel_psr_work); mutex_init(&dev_priv->psr.lock); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index f6b2a814e..40c6aff57 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -27,29 +27,13 @@ * */ +#include <linux/log2.h> #include <drm/drmP.h> #include "i915_drv.h" #include <drm/i915_drm.h> #include "i915_trace.h" #include "intel_drv.h" -bool -intel_ring_initialized(struct intel_engine_cs *ring) -{ - struct drm_device *dev = ring->dev; - - if (!dev) - return false; - - if (i915.enable_execlists) { - struct intel_context *dctx = ring->default_context; - struct intel_ringbuffer *ringbuf = dctx->engine[ring->id].ringbuf; - - return ringbuf->obj; - } else - return ring->buffer && ring->buffer->obj; -} - int __intel_ring_space(int head, int tail, int size) { int space = head - tail; @@ -483,7 +467,7 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *ring) { struct drm_device *dev = ring->dev; struct drm_i915_private *dev_priv = ring->dev->dev_private; - u32 mmio = 0; + i915_reg_t mmio; /* The ring status page addresses are no longer next to the rest of * the ring registers as of gen7. @@ -526,7 +510,7 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *ring) * invalidating the TLB? */ if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) { - u32 reg = RING_INSTPM(ring->mmio_base); + i915_reg_t reg = RING_INSTPM(ring->mmio_base); /* ring should be idle before issuing a sync flush*/ WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0); @@ -735,7 +719,7 @@ static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count)); for (i = 0; i < w->count; i++) { - intel_ring_emit(ring, w->reg[i].addr); + intel_ring_emit_reg(ring, w->reg[i].addr); intel_ring_emit(ring, w->reg[i].value); } intel_ring_emit(ring, MI_NOOP); @@ -768,7 +752,8 @@ static int intel_rcs_ctx_init(struct drm_i915_gem_request *req) } static int wa_add(struct drm_i915_private *dev_priv, - const u32 addr, const u32 mask, const u32 val) + i915_reg_t addr, + const u32 mask, const u32 val) { const u32 idx = dev_priv->workarounds.count; @@ -926,17 +911,15 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring) WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); - if ((IS_SKYLAKE(dev) && (INTEL_REVID(dev) == SKL_REVID_A0 || - INTEL_REVID(dev) == SKL_REVID_B0)) || - (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)) { - /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */ + /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */ + if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) || + IS_BXT_REVID(dev, 0, BXT_REVID_A1)) WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, GEN9_DG_MIRROR_FIX_ENABLE); - } - if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) || - (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)) { - /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */ + /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */ + if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) || + IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1, GEN9_RHWO_OPTIMIZATION_DISABLE); /* @@ -946,12 +929,10 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring) */ } - if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) >= SKL_REVID_C0) || - IS_BROXTON(dev)) { - /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt */ + /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt */ + if (IS_SKL_REVID(dev, SKL_REVID_C0, REVID_FOREVER) || IS_BROXTON(dev)) WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, GEN9_ENABLE_YV12_BUGFIX); - } /* Wa4x4STCOptimizationDisable:skl,bxt */ /* WaDisablePartialResolveInVc:skl,bxt */ @@ -963,24 +944,22 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring) GEN9_CCS_TLB_PREFETCH_ENABLE); /* WaDisableMaskBasedCammingInRCC:skl,bxt */ - if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) == SKL_REVID_C0) || - (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)) + if (IS_SKL_REVID(dev, SKL_REVID_C0, SKL_REVID_C0) || + IS_BXT_REVID(dev, 0, BXT_REVID_A1)) WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, PIXEL_MASK_CAMMING_DISABLE); /* WaForceContextSaveRestoreNonCoherent:skl,bxt */ tmp = HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT; - if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) == SKL_REVID_F0) || - (IS_BROXTON(dev) && INTEL_REVID(dev) >= BXT_REVID_B0)) + if (IS_SKL_REVID(dev, SKL_REVID_F0, SKL_REVID_F0) || + IS_BXT_REVID(dev, BXT_REVID_B0, REVID_FOREVER)) tmp |= HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE; WA_SET_BIT_MASKED(HDC_CHICKEN0, tmp); /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt */ - if (IS_SKYLAKE(dev) || - (IS_BROXTON(dev) && INTEL_REVID(dev) <= BXT_REVID_B0)) { + if (IS_SKYLAKE(dev) || IS_BXT_REVID(dev, 0, BXT_REVID_B0)) WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, GEN8_SAMPLER_POWER_BYPASS_DIS); - } /* WaDisableSTUnitPowerOptimization:skl,bxt */ WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE); @@ -1002,7 +981,7 @@ static int skl_tune_iz_hashing(struct intel_engine_cs *ring) * Only consider slices where one, and only one, subslice has 7 * EUs */ - if (hweight8(dev_priv->info.subslice_7eu[i]) != 1) + if (!is_power_of_2(dev_priv->info.subslice_7eu[i])) continue; /* @@ -1040,11 +1019,7 @@ static int skl_init_workarounds(struct intel_engine_cs *ring) if (ret) return ret; - if (INTEL_REVID(dev) <= SKL_REVID_D0) { - /* WaDisableHDCInvalidation:skl */ - I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | - BDW_DISABLE_HDC_INVALIDATION); - + if (IS_SKL_REVID(dev, 0, SKL_REVID_D0)) { /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */ I915_WRITE(FF_SLICE_CS_CHICKEN2, _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE)); @@ -1053,23 +1028,23 @@ static int skl_init_workarounds(struct intel_engine_cs *ring) /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes * involving this register should also be added to WA batch as required. */ - if (INTEL_REVID(dev) <= SKL_REVID_E0) + if (IS_SKL_REVID(dev, 0, SKL_REVID_E0)) /* WaDisableLSQCROPERFforOCL:skl */ I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | GEN8_LQSC_RO_PERF_DIS); /* WaEnableGapsTsvCreditFix:skl */ - if (IS_SKYLAKE(dev) && (INTEL_REVID(dev) >= SKL_REVID_C0)) { + if (IS_SKL_REVID(dev, SKL_REVID_C0, REVID_FOREVER)) { I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE)); } /* WaDisablePowerCompilerClockGating:skl */ - if (INTEL_REVID(dev) == SKL_REVID_B0) + if (IS_SKL_REVID(dev, SKL_REVID_B0, SKL_REVID_B0)) WA_SET_BIT_MASKED(HIZ_CHICKEN, BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE); - if (INTEL_REVID(dev) <= SKL_REVID_D0) { + if (IS_SKL_REVID(dev, 0, SKL_REVID_F0)) { /* *Use Force Non-Coherent whenever executing a 3D context. This * is a workaround for a possible hang in the unlikely event @@ -1078,21 +1053,23 @@ static int skl_init_workarounds(struct intel_engine_cs *ring) /* WaForceEnableNonCoherent:skl */ WA_SET_BIT_MASKED(HDC_CHICKEN0, HDC_FORCE_NON_COHERENT); + + /* WaDisableHDCInvalidation:skl */ + I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | + BDW_DISABLE_HDC_INVALIDATION); } - if (INTEL_REVID(dev) == SKL_REVID_C0 || - INTEL_REVID(dev) == SKL_REVID_D0) - /* WaBarrierPerformanceFixDisable:skl */ + /* WaBarrierPerformanceFixDisable:skl */ + if (IS_SKL_REVID(dev, SKL_REVID_C0, SKL_REVID_D0)) WA_SET_BIT_MASKED(HDC_CHICKEN0, HDC_FENCE_DEST_SLM_DISABLE | HDC_BARRIER_PERFORMANCE_DISABLE); /* WaDisableSbeCacheDispatchPortSharing:skl */ - if (INTEL_REVID(dev) <= SKL_REVID_F0) { + if (IS_SKL_REVID(dev, 0, SKL_REVID_F0)) WA_SET_BIT_MASKED( GEN7_HALF_SLICE_CHICKEN1, GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); - } return skl_tune_iz_hashing(ring); } @@ -1109,11 +1086,11 @@ static int bxt_init_workarounds(struct intel_engine_cs *ring) /* WaStoreMultiplePTEenable:bxt */ /* This is a requirement according to Hardware specification */ - if (INTEL_REVID(dev) == BXT_REVID_A0) + if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF); /* WaSetClckGatingDisableMedia:bxt */ - if (INTEL_REVID(dev) == BXT_REVID_A0) { + if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) & ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE)); } @@ -1123,7 +1100,7 @@ static int bxt_init_workarounds(struct intel_engine_cs *ring) STALL_DOP_GATING_DISABLE); /* WaDisableSbeCacheDispatchPortSharing:bxt */ - if (INTEL_REVID(dev) <= BXT_REVID_B0) { + if (IS_BXT_REVID(dev, 0, BXT_REVID_B0)) { WA_SET_BIT_MASKED( GEN7_HALF_SLICE_CHICKEN1, GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); @@ -1321,11 +1298,13 @@ static int gen6_signal(struct drm_i915_gem_request *signaller_req, return ret; for_each_ring(useless, dev_priv, i) { - u32 mbox_reg = signaller->semaphore.mbox.signal[i]; - if (mbox_reg != GEN6_NOSYNC) { + i915_reg_t mbox_reg = signaller->semaphore.mbox.signal[i]; + + if (i915_mmio_reg_valid(mbox_reg)) { u32 seqno = i915_gem_request_get_seqno(signaller_req); + intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit(signaller, mbox_reg); + intel_ring_emit_reg(signaller, mbox_reg); intel_ring_emit(signaller, seqno); } } @@ -2006,11 +1985,35 @@ static int init_phys_status_page(struct intel_engine_cs *ring) void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf) { - iounmap(ringbuf->virtual_start); + if (HAS_LLC(ringbuf->obj->base.dev) && !ringbuf->obj->stolen) + vunmap(ringbuf->virtual_start); + else + iounmap(ringbuf->virtual_start); ringbuf->virtual_start = NULL; i915_gem_object_ggtt_unpin(ringbuf->obj); } +static u32 *vmap_obj(struct drm_i915_gem_object *obj) +{ + struct sg_page_iter sg_iter; + struct page **pages; + void *addr; + int i; + + pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages)); + if (pages == NULL) + return NULL; + + i = 0; + for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) + pages[i++] = sg_page_iter_page(&sg_iter); + + addr = vmap(pages, i, 0, PAGE_KERNEL); + drm_free_large(pages); + + return addr; +} + int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, struct intel_ringbuffer *ringbuf) { @@ -2018,21 +2021,39 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, struct drm_i915_gem_object *obj = ringbuf->obj; int ret; - ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE); - if (ret) - return ret; + if (HAS_LLC(dev_priv) && !obj->stolen) { + ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, 0); + if (ret) + return ret; - ret = i915_gem_object_set_to_gtt_domain(obj, true); - if (ret) { - i915_gem_object_ggtt_unpin(obj); - return ret; - } + ret = i915_gem_object_set_to_cpu_domain(obj, true); + if (ret) { + i915_gem_object_ggtt_unpin(obj); + return ret; + } - ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base + - i915_gem_obj_ggtt_offset(obj), ringbuf->size); - if (ringbuf->virtual_start == NULL) { - i915_gem_object_ggtt_unpin(obj); - return -EINVAL; + ringbuf->virtual_start = vmap_obj(obj); + if (ringbuf->virtual_start == NULL) { + i915_gem_object_ggtt_unpin(obj); + return -ENOMEM; + } + } else { + ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE); + if (ret) + return ret; + + ret = i915_gem_object_set_to_gtt_domain(obj, true); + if (ret) { + i915_gem_object_ggtt_unpin(obj); + return ret; + } + + ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base + + i915_gem_obj_ggtt_offset(obj), ringbuf->size); + if (ringbuf->virtual_start == NULL) { + i915_gem_object_ggtt_unpin(obj); + return -EINVAL; + } } return 0; @@ -2072,10 +2093,14 @@ intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size) int ret; ring = kzalloc(sizeof(*ring), GFP_KERNEL); - if (ring == NULL) + if (ring == NULL) { + DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s\n", + engine->name); return ERR_PTR(-ENOMEM); + } ring->ring = engine; + list_add(&ring->link, &engine->buffers); ring->size = size; /* Workaround an erratum on the i830 which causes a hang if @@ -2091,8 +2116,9 @@ intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size) ret = intel_alloc_ringbuffer_obj(engine->dev, ring); if (ret) { - DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", - engine->name, ret); + DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s: %d\n", + engine->name, ret); + list_del(&ring->link); kfree(ring); return ERR_PTR(ret); } @@ -2104,6 +2130,7 @@ void intel_ringbuffer_free(struct intel_ringbuffer *ring) { intel_destroy_ringbuffer_obj(ring); + list_del(&ring->link); kfree(ring); } @@ -2119,14 +2146,17 @@ static int intel_init_ring_buffer(struct drm_device *dev, INIT_LIST_HEAD(&ring->active_list); INIT_LIST_HEAD(&ring->request_list); INIT_LIST_HEAD(&ring->execlist_queue); + INIT_LIST_HEAD(&ring->buffers); i915_gem_batch_pool_init(dev, &ring->batch_pool); memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno)); init_waitqueue_head(&ring->irq_queue); ringbuf = intel_engine_create_ringbuffer(ring, 32 * PAGE_SIZE); - if (IS_ERR(ringbuf)) - return PTR_ERR(ringbuf); + if (IS_ERR(ringbuf)) { + ret = PTR_ERR(ringbuf); + goto error; + } ring->buffer = ringbuf; if (I915_NEED_GFX_HWS(dev)) { @@ -2155,8 +2185,7 @@ static int intel_init_ring_buffer(struct drm_device *dev, return 0; error: - intel_ringbuffer_free(ringbuf); - ring->buffer = NULL; + intel_cleanup_ring_buffer(ring); return ret; } @@ -2169,12 +2198,14 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) dev_priv = to_i915(ring->dev); - intel_stop_ring_buffer(ring); - WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0); + if (ring->buffer) { + intel_stop_ring_buffer(ring); + WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0); - intel_unpin_ringbuffer_obj(ring->buffer); - intel_ringbuffer_free(ring->buffer); - ring->buffer = NULL; + intel_unpin_ringbuffer_obj(ring->buffer); + intel_ringbuffer_free(ring->buffer); + ring->buffer = NULL; + } if (ring->cleanup) ring->cleanup(ring); @@ -2183,6 +2214,7 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) i915_cmd_parser_fini_ring(ring); i915_gem_batch_pool_fini(&ring->batch_pool); + ring->dev = NULL; } static int ring_wait_for_space(struct intel_engine_cs *ring, int n) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 49fa41dc0..49574ffe5 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -100,6 +100,7 @@ struct intel_ringbuffer { void __iomem *virtual_start; struct intel_engine_cs *ring; + struct list_head link; u32 head; u32 tail; @@ -157,6 +158,7 @@ struct intel_engine_cs { u32 mmio_base; struct drm_device *dev; struct intel_ringbuffer *buffer; + struct list_head buffers; /* * A pool of objects to use as shadow copies of client batch buffers @@ -247,7 +249,7 @@ struct intel_engine_cs { /* our mbox written by others */ u32 wait[I915_NUM_RINGS]; /* mboxes this ring signals to */ - u32 signal[I915_NUM_RINGS]; + i915_reg_t signal[I915_NUM_RINGS]; } mbox; u64 signal_ggtt[I915_NUM_RINGS]; }; @@ -348,7 +350,11 @@ struct intel_engine_cs { u32 (*get_cmd_length_mask)(u32 cmd_header); }; -bool intel_ring_initialized(struct intel_engine_cs *ring); +static inline bool +intel_ring_initialized(struct intel_engine_cs *ring) +{ + return ring->dev != NULL; +} static inline unsigned intel_ring_flag(struct intel_engine_cs *ring) @@ -441,6 +447,11 @@ static inline void intel_ring_emit(struct intel_engine_cs *ring, iowrite32(data, ringbuf->virtual_start + ringbuf->tail); ringbuf->tail += 4; } +static inline void intel_ring_emit_reg(struct intel_engine_cs *ring, + i915_reg_t reg) +{ + intel_ring_emit(ring, i915_mmio_reg_offset(reg)); +} static inline void intel_ring_advance(struct intel_engine_cs *ring) { struct intel_ringbuffer *ringbuf = ring->buffer; diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 7e23d65c9..4f43d9b32 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -49,25 +49,88 @@ * present for a given platform. */ -#define GEN9_ENABLE_DC5(dev) 0 -#define SKL_ENABLE_DC6(dev) IS_SKYLAKE(dev) - #define for_each_power_well(i, power_well, domain_mask, power_domains) \ for (i = 0; \ i < (power_domains)->power_well_count && \ ((power_well) = &(power_domains)->power_wells[i]); \ i++) \ - if ((power_well)->domains & (domain_mask)) + for_each_if ((power_well)->domains & (domain_mask)) #define for_each_power_well_rev(i, power_well, domain_mask, power_domains) \ for (i = (power_domains)->power_well_count - 1; \ i >= 0 && ((power_well) = &(power_domains)->power_wells[i]);\ i--) \ - if ((power_well)->domains & (domain_mask)) + for_each_if ((power_well)->domains & (domain_mask)) bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, int power_well_id); +const char * +intel_display_power_domain_str(enum intel_display_power_domain domain) +{ + switch (domain) { + case POWER_DOMAIN_PIPE_A: + return "PIPE_A"; + case POWER_DOMAIN_PIPE_B: + return "PIPE_B"; + case POWER_DOMAIN_PIPE_C: + return "PIPE_C"; + case POWER_DOMAIN_PIPE_A_PANEL_FITTER: + return "PIPE_A_PANEL_FITTER"; + case POWER_DOMAIN_PIPE_B_PANEL_FITTER: + return "PIPE_B_PANEL_FITTER"; + case POWER_DOMAIN_PIPE_C_PANEL_FITTER: + return "PIPE_C_PANEL_FITTER"; + case POWER_DOMAIN_TRANSCODER_A: + return "TRANSCODER_A"; + case POWER_DOMAIN_TRANSCODER_B: + return "TRANSCODER_B"; + case POWER_DOMAIN_TRANSCODER_C: + return "TRANSCODER_C"; + case POWER_DOMAIN_TRANSCODER_EDP: + return "TRANSCODER_EDP"; + case POWER_DOMAIN_PORT_DDI_A_LANES: + return "PORT_DDI_A_LANES"; + case POWER_DOMAIN_PORT_DDI_B_LANES: + return "PORT_DDI_B_LANES"; + case POWER_DOMAIN_PORT_DDI_C_LANES: + return "PORT_DDI_C_LANES"; + case POWER_DOMAIN_PORT_DDI_D_LANES: + return "PORT_DDI_D_LANES"; + case POWER_DOMAIN_PORT_DDI_E_LANES: + return "PORT_DDI_E_LANES"; + case POWER_DOMAIN_PORT_DSI: + return "PORT_DSI"; + case POWER_DOMAIN_PORT_CRT: + return "PORT_CRT"; + case POWER_DOMAIN_PORT_OTHER: + return "PORT_OTHER"; + case POWER_DOMAIN_VGA: + return "VGA"; + case POWER_DOMAIN_AUDIO: + return "AUDIO"; + case POWER_DOMAIN_PLLS: + return "PLLS"; + case POWER_DOMAIN_AUX_A: + return "AUX_A"; + case POWER_DOMAIN_AUX_B: + return "AUX_B"; + case POWER_DOMAIN_AUX_C: + return "AUX_C"; + case POWER_DOMAIN_AUX_D: + return "AUX_D"; + case POWER_DOMAIN_GMBUS: + return "GMBUS"; + case POWER_DOMAIN_INIT: + return "INIT"; + case POWER_DOMAIN_MODESET: + return "MODESET"; + default: + MISSING_CASE(domain); + return "?"; + } +} + static void intel_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { @@ -244,12 +307,6 @@ static void skl_power_well_post_enable(struct drm_i915_private *dev_priv, gen8_irq_power_well_post_enable(dev_priv, 1 << PIPE_C | 1 << PIPE_B); } - - if (power_well->data == SKL_DISP_PW_1) { - if (!dev_priv->power_domains.initializing) - intel_prepare_ddi(dev); - gen8_irq_power_well_post_enable(dev_priv, 1 << PIPE_A); - } } static void hsw_set_power_well(struct drm_i915_private *dev_priv, @@ -292,58 +349,38 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv, BIT(POWER_DOMAIN_TRANSCODER_C) | \ BIT(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ BIT(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \ - BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_E_2_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_D_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_E_LANES) | \ BIT(POWER_DOMAIN_AUX_B) | \ BIT(POWER_DOMAIN_AUX_C) | \ BIT(POWER_DOMAIN_AUX_D) | \ BIT(POWER_DOMAIN_AUDIO) | \ BIT(POWER_DOMAIN_VGA) | \ BIT(POWER_DOMAIN_INIT)) -#define SKL_DISPLAY_POWERWELL_1_POWER_DOMAINS ( \ - SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ - BIT(POWER_DOMAIN_PLLS) | \ - BIT(POWER_DOMAIN_PIPE_A) | \ - BIT(POWER_DOMAIN_TRANSCODER_EDP) | \ - BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER) | \ - BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) | \ - BIT(POWER_DOMAIN_AUX_A) | \ - BIT(POWER_DOMAIN_INIT)) #define SKL_DISPLAY_DDI_A_E_POWER_DOMAINS ( \ - BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_E_2_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_A_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_E_LANES) | \ BIT(POWER_DOMAIN_INIT)) #define SKL_DISPLAY_DDI_B_POWER_DOMAINS ( \ - BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \ BIT(POWER_DOMAIN_INIT)) #define SKL_DISPLAY_DDI_C_POWER_DOMAINS ( \ - BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \ BIT(POWER_DOMAIN_INIT)) #define SKL_DISPLAY_DDI_D_POWER_DOMAINS ( \ - BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_D_LANES) | \ BIT(POWER_DOMAIN_INIT)) -#define SKL_DISPLAY_MISC_IO_POWER_DOMAINS ( \ - SKL_DISPLAY_POWERWELL_1_POWER_DOMAINS | \ - BIT(POWER_DOMAIN_PLLS) | \ +#define SKL_DISPLAY_DC_OFF_POWER_DOMAINS ( \ + SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ + BIT(POWER_DOMAIN_MODESET) | \ + BIT(POWER_DOMAIN_AUX_A) | \ BIT(POWER_DOMAIN_INIT)) #define SKL_DISPLAY_ALWAYS_ON_POWER_DOMAINS ( \ - (POWER_DOMAIN_MASK & ~(SKL_DISPLAY_POWERWELL_1_POWER_DOMAINS | \ + (POWER_DOMAIN_MASK & ~( \ SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ - SKL_DISPLAY_DDI_A_E_POWER_DOMAINS | \ - SKL_DISPLAY_DDI_B_POWER_DOMAINS | \ - SKL_DISPLAY_DDI_C_POWER_DOMAINS | \ - SKL_DISPLAY_DDI_D_POWER_DOMAINS | \ - SKL_DISPLAY_MISC_IO_POWER_DOMAINS)) | \ + SKL_DISPLAY_DC_OFF_POWER_DOMAINS)) | \ BIT(POWER_DOMAIN_INIT)) #define BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS ( \ @@ -354,10 +391,8 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv, BIT(POWER_DOMAIN_TRANSCODER_C) | \ BIT(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ BIT(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \ - BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \ BIT(POWER_DOMAIN_AUX_B) | \ BIT(POWER_DOMAIN_AUX_C) | \ BIT(POWER_DOMAIN_AUDIO) | \ @@ -369,11 +404,15 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv, BIT(POWER_DOMAIN_PIPE_A) | \ BIT(POWER_DOMAIN_TRANSCODER_EDP) | \ BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER) | \ - BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_A_LANES) | \ BIT(POWER_DOMAIN_AUX_A) | \ BIT(POWER_DOMAIN_PLLS) | \ BIT(POWER_DOMAIN_INIT)) +#define BXT_DISPLAY_DC_OFF_POWER_DOMAINS ( \ + BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ + BIT(POWER_DOMAIN_MODESET) | \ + BIT(POWER_DOMAIN_AUX_A) | \ + BIT(POWER_DOMAIN_INIT)) #define BXT_DISPLAY_ALWAYS_ON_POWER_DOMAINS ( \ (POWER_DOMAIN_MASK & ~(BXT_DISPLAY_POWERWELL_1_POWER_DOMAINS | \ BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS)) | \ @@ -417,46 +456,119 @@ static void assert_can_disable_dc9(struct drm_i915_private *dev_priv) */ } -void bxt_enable_dc9(struct drm_i915_private *dev_priv) +static void gen9_set_dc_state_debugmask_memory_up( + struct drm_i915_private *dev_priv) { uint32_t val; + /* The below bit doesn't need to be cleared ever afterwards */ + val = I915_READ(DC_STATE_DEBUG); + if (!(val & DC_STATE_DEBUG_MASK_MEMORY_UP)) { + val |= DC_STATE_DEBUG_MASK_MEMORY_UP; + I915_WRITE(DC_STATE_DEBUG, val); + POSTING_READ(DC_STATE_DEBUG); + } +} + +static void gen9_write_dc_state(struct drm_i915_private *dev_priv, + u32 state) +{ + int rewrites = 0; + int rereads = 0; + u32 v; + + I915_WRITE(DC_STATE_EN, state); + + /* It has been observed that disabling the dc6 state sometimes + * doesn't stick and dmc keeps returning old value. Make sure + * the write really sticks enough times and also force rewrite until + * we are confident that state is exactly what we want. + */ + do { + v = I915_READ(DC_STATE_EN); + + if (v != state) { + I915_WRITE(DC_STATE_EN, state); + rewrites++; + rereads = 0; + } else if (rereads++ > 5) { + break; + } + + } while (rewrites < 100); + + if (v != state) + DRM_ERROR("Writing dc state to 0x%x failed, now 0x%x\n", + state, v); + + /* Most of the times we need one retry, avoid spam */ + if (rewrites > 1) + DRM_DEBUG_KMS("Rewrote dc state to 0x%x %d times\n", + state, rewrites); +} + +static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state) +{ + uint32_t val; + uint32_t mask; + + mask = DC_STATE_EN_UPTO_DC5; + if (IS_BROXTON(dev_priv)) + mask |= DC_STATE_EN_DC9; + else + mask |= DC_STATE_EN_UPTO_DC6; + + WARN_ON_ONCE(state & ~mask); + + if (i915.enable_dc == 0) + state = DC_STATE_DISABLE; + else if (i915.enable_dc == 1 && state > DC_STATE_EN_UPTO_DC5) + state = DC_STATE_EN_UPTO_DC5; + + if (state & DC_STATE_EN_UPTO_DC5_DC6_MASK) + gen9_set_dc_state_debugmask_memory_up(dev_priv); + + val = I915_READ(DC_STATE_EN); + DRM_DEBUG_KMS("Setting DC state from %02x to %02x\n", + val & mask, state); + + /* Check if DMC is ignoring our DC state requests */ + if ((val & mask) != dev_priv->csr.dc_state) + DRM_ERROR("DC state mismatch (0x%x -> 0x%x)\n", + dev_priv->csr.dc_state, val & mask); + + val &= ~mask; + val |= state; + + gen9_write_dc_state(dev_priv, val); + + dev_priv->csr.dc_state = val & mask; +} + +void bxt_enable_dc9(struct drm_i915_private *dev_priv) +{ assert_can_enable_dc9(dev_priv); DRM_DEBUG_KMS("Enabling DC9\n"); - val = I915_READ(DC_STATE_EN); - val |= DC_STATE_EN_DC9; - I915_WRITE(DC_STATE_EN, val); - POSTING_READ(DC_STATE_EN); + gen9_set_dc_state(dev_priv, DC_STATE_EN_DC9); } void bxt_disable_dc9(struct drm_i915_private *dev_priv) { - uint32_t val; - assert_can_disable_dc9(dev_priv); DRM_DEBUG_KMS("Disabling DC9\n"); - val = I915_READ(DC_STATE_EN); - val &= ~DC_STATE_EN_DC9; - I915_WRITE(DC_STATE_EN, val); - POSTING_READ(DC_STATE_EN); + gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); } -static void gen9_set_dc_state_debugmask_memory_up( - struct drm_i915_private *dev_priv) +static void assert_csr_loaded(struct drm_i915_private *dev_priv) { - uint32_t val; - - /* The below bit doesn't need to be cleared ever afterwards */ - val = I915_READ(DC_STATE_DEBUG); - if (!(val & DC_STATE_DEBUG_MASK_MEMORY_UP)) { - val |= DC_STATE_DEBUG_MASK_MEMORY_UP; - I915_WRITE(DC_STATE_DEBUG, val); - POSTING_READ(DC_STATE_DEBUG); - } + WARN_ONCE(!I915_READ(CSR_PROGRAM(0)), + "CSR program storage start is NULL\n"); + WARN_ONCE(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n"); + WARN_ONCE(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n"); } static void assert_can_enable_dc5(struct drm_i915_private *dev_priv) @@ -471,16 +583,13 @@ static void assert_can_enable_dc5(struct drm_i915_private *dev_priv) WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5), "DC5 already programmed to be enabled.\n"); - WARN_ONCE(dev_priv->pm.suspended, - "DC5 cannot be enabled, if platform is runtime-suspended.\n"); + assert_rpm_wakelock_held(dev_priv); assert_csr_loaded(dev_priv); } static void assert_can_disable_dc5(struct drm_i915_private *dev_priv) { - bool pg2_enabled = intel_display_power_well_is_enabled(dev_priv, - SKL_DISP_PW_2); /* * During initialization, the firmware may not be loaded yet. * We still want to make sure that the DC enabling flag is cleared. @@ -488,40 +597,16 @@ static void assert_can_disable_dc5(struct drm_i915_private *dev_priv) if (dev_priv->power_domains.initializing) return; - WARN_ONCE(!pg2_enabled, "PG2 not enabled to disable DC5.\n"); - WARN_ONCE(dev_priv->pm.suspended, - "Disabling of DC5 while platform is runtime-suspended should never happen.\n"); + assert_rpm_wakelock_held(dev_priv); } static void gen9_enable_dc5(struct drm_i915_private *dev_priv) { - uint32_t val; - assert_can_enable_dc5(dev_priv); DRM_DEBUG_KMS("Enabling DC5\n"); - gen9_set_dc_state_debugmask_memory_up(dev_priv); - - val = I915_READ(DC_STATE_EN); - val &= ~DC_STATE_EN_UPTO_DC5_DC6_MASK; - val |= DC_STATE_EN_UPTO_DC5; - I915_WRITE(DC_STATE_EN, val); - POSTING_READ(DC_STATE_EN); -} - -static void gen9_disable_dc5(struct drm_i915_private *dev_priv) -{ - uint32_t val; - - assert_can_disable_dc5(dev_priv); - - DRM_DEBUG_KMS("Disabling DC5\n"); - - val = I915_READ(DC_STATE_EN); - val &= ~DC_STATE_EN_UPTO_DC5; - I915_WRITE(DC_STATE_EN, val); - POSTING_READ(DC_STATE_EN); + gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC5); } static void assert_can_enable_dc6(struct drm_i915_private *dev_priv) @@ -547,40 +632,37 @@ static void assert_can_disable_dc6(struct drm_i915_private *dev_priv) if (dev_priv->power_domains.initializing) return; - assert_csr_loaded(dev_priv); WARN_ONCE(!(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6), "DC6 already programmed to be disabled.\n"); } -static void skl_enable_dc6(struct drm_i915_private *dev_priv) +static void gen9_disable_dc5_dc6(struct drm_i915_private *dev_priv) { - uint32_t val; + assert_can_disable_dc5(dev_priv); + + if (IS_SKYLAKE(dev_priv) && i915.enable_dc != 0 && i915.enable_dc != 1) + assert_can_disable_dc6(dev_priv); + gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); +} + +void skl_enable_dc6(struct drm_i915_private *dev_priv) +{ assert_can_enable_dc6(dev_priv); DRM_DEBUG_KMS("Enabling DC6\n"); - gen9_set_dc_state_debugmask_memory_up(dev_priv); + gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6); - val = I915_READ(DC_STATE_EN); - val &= ~DC_STATE_EN_UPTO_DC5_DC6_MASK; - val |= DC_STATE_EN_UPTO_DC6; - I915_WRITE(DC_STATE_EN, val); - POSTING_READ(DC_STATE_EN); } -static void skl_disable_dc6(struct drm_i915_private *dev_priv) +void skl_disable_dc6(struct drm_i915_private *dev_priv) { - uint32_t val; - assert_can_disable_dc6(dev_priv); DRM_DEBUG_KMS("Disabling DC6\n"); - val = I915_READ(DC_STATE_EN); - val &= ~DC_STATE_EN_UPTO_DC6; - I915_WRITE(DC_STATE_EN, val); - POSTING_READ(DC_STATE_EN); + gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); } static void skl_set_power_well(struct drm_i915_private *dev_priv, @@ -630,20 +712,16 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv, !I915_READ(HSW_PWR_WELL_BIOS), "Invalid for power well status to be enabled, unless done by the BIOS, \ when request is to disable!\n"); - if ((GEN9_ENABLE_DC5(dev) || SKL_ENABLE_DC6(dev)) && - power_well->data == SKL_DISP_PW_2) { - if (SKL_ENABLE_DC6(dev)) { - skl_disable_dc6(dev_priv); - /* - * DDI buffer programming unnecessary during driver-load/resume - * as it's already done during modeset initialization then. - * It's also invalid here as encoder list is still uninitialized. - */ - if (!dev_priv->power_domains.initializing) - intel_prepare_ddi(dev); - } else { - gen9_disable_dc5(dev_priv); - } + if (power_well->data == SKL_DISP_PW_2) { + /* + * DDI buffer programming unnecessary during + * driver-load/resume as it's already done + * during modeset initialization then. It's + * also invalid here as encoder list is still + * uninitialized. + */ + if (!dev_priv->power_domains.initializing) + intel_prepare_ddi(dev); } I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask); } @@ -658,34 +736,9 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv, } } else { if (enable_requested) { - if (IS_SKYLAKE(dev) && - (power_well->data == SKL_DISP_PW_1) && - (intel_csr_load_status_get(dev_priv) == FW_LOADED)) - DRM_DEBUG_KMS("Not Disabling PW1, dmc will handle\n"); - else { - I915_WRITE(HSW_PWR_WELL_DRIVER, tmp & ~req_mask); - POSTING_READ(HSW_PWR_WELL_DRIVER); - DRM_DEBUG_KMS("Disabling %s\n", power_well->name); - } - - if ((GEN9_ENABLE_DC5(dev) || SKL_ENABLE_DC6(dev)) && - power_well->data == SKL_DISP_PW_2) { - enum csr_state state; - /* TODO: wait for a completion event or - * similar here instead of busy - * waiting using wait_for function. - */ - wait_for((state = intel_csr_load_status_get(dev_priv)) != - FW_UNINITIALIZED, 1000); - if (state != FW_LOADED) - DRM_DEBUG("CSR firmware not ready (%d)\n", - state); - else - if (SKL_ENABLE_DC6(dev)) - skl_enable_dc6(dev_priv); - else - gen9_enable_dc5(dev_priv); - } + I915_WRITE(HSW_PWR_WELL_DRIVER, tmp & ~req_mask); + POSTING_READ(HSW_PWR_WELL_DRIVER); + DRM_DEBUG_KMS("Disabling %s\n", power_well->name); } } @@ -760,6 +813,41 @@ static void skl_power_well_disable(struct drm_i915_private *dev_priv, skl_set_power_well(dev_priv, power_well, false); } +static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + return (I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0; +} + +static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + gen9_disable_dc5_dc6(dev_priv); +} + +static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + if (IS_SKYLAKE(dev_priv) && i915.enable_dc != 0 && i915.enable_dc != 1) + skl_enable_dc6(dev_priv); + else + gen9_enable_dc5(dev_priv); +} + +static void gen9_dc_off_power_well_sync_hw(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + if (power_well->count > 0) { + gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); + } else { + if (IS_SKYLAKE(dev_priv) && i915.enable_dc != 0 && + i915.enable_dc != 1) + gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6); + else + gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC5); + } +} + static void i9xx_always_on_power_well_noop(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { @@ -974,10 +1062,12 @@ static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_pr int power_well_id) { struct i915_power_domains *power_domains = &dev_priv->power_domains; - struct i915_power_well *power_well; int i; - for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) { + for (i = 0; i < power_domains->power_well_count; i++) { + struct i915_power_well *power_well; + + power_well = &power_domains->power_wells[i]; if (power_well->data == power_well_id) return power_well; } @@ -1397,6 +1487,22 @@ static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv, chv_set_pipe_power_well(dev_priv, power_well, false); } +static void +__intel_display_power_get_domain(struct drm_i915_private *dev_priv, + enum intel_display_power_domain domain) +{ + struct i915_power_domains *power_domains = &dev_priv->power_domains; + struct i915_power_well *power_well; + int i; + + for_each_power_well(i, power_well, BIT(domain), power_domains) { + if (!power_well->count++) + intel_power_well_enable(dev_priv, power_well); + } + + power_domains->domain_use_count[domain]++; +} + /** * intel_display_power_get - grab a power domain reference * @dev_priv: i915 device instance @@ -1412,24 +1518,53 @@ static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv, void intel_display_power_get(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain) { - struct i915_power_domains *power_domains; - struct i915_power_well *power_well; - int i; + struct i915_power_domains *power_domains = &dev_priv->power_domains; intel_runtime_pm_get(dev_priv); - power_domains = &dev_priv->power_domains; + mutex_lock(&power_domains->lock); + + __intel_display_power_get_domain(dev_priv, domain); + + mutex_unlock(&power_domains->lock); +} + +/** + * intel_display_power_get_if_enabled - grab a reference for an enabled display power domain + * @dev_priv: i915 device instance + * @domain: power domain to reference + * + * This function grabs a power domain reference for @domain and ensures that the + * power domain and all its parents are powered up. Therefore users should only + * grab a reference to the innermost power domain they need. + * + * Any power domain reference obtained by this function must have a symmetric + * call to intel_display_power_put() to release the reference again. + */ +bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv, + enum intel_display_power_domain domain) +{ + struct i915_power_domains *power_domains = &dev_priv->power_domains; + bool is_enabled; + + if (!intel_runtime_pm_get_if_in_use(dev_priv)) + return false; mutex_lock(&power_domains->lock); - for_each_power_well(i, power_well, BIT(domain), power_domains) { - if (!power_well->count++) - intel_power_well_enable(dev_priv, power_well); + if (__intel_display_power_is_enabled(dev_priv, domain)) { + __intel_display_power_get_domain(dev_priv, domain); + is_enabled = true; + } else { + is_enabled = false; } - power_domains->domain_use_count[domain]++; - mutex_unlock(&power_domains->lock); + + if (!is_enabled) + intel_runtime_pm_put(dev_priv); + + return is_enabled; } /** @@ -1452,13 +1587,17 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, mutex_lock(&power_domains->lock); - WARN_ON(!power_domains->domain_use_count[domain]); + WARN(!power_domains->domain_use_count[domain], + "Use count on domain %s is already zero\n", + intel_display_power_domain_str(domain)); power_domains->domain_use_count[domain]--; for_each_power_well_rev(i, power_well, BIT(domain), power_domains) { - WARN_ON(!power_well->count); + WARN(!power_well->count, + "Use count on power well %s is already zero", + power_well->name); - if (!--power_well->count && i915.disable_power_well) + if (!--power_well->count) intel_power_well_disable(dev_priv, power_well); } @@ -1470,14 +1609,10 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, #define HSW_ALWAYS_ON_POWER_DOMAINS ( \ BIT(POWER_DOMAIN_PIPE_A) | \ BIT(POWER_DOMAIN_TRANSCODER_EDP) | \ - BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_A_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_D_LANES) | \ BIT(POWER_DOMAIN_PORT_CRT) | \ BIT(POWER_DOMAIN_PLLS) | \ BIT(POWER_DOMAIN_AUX_A) | \ @@ -1501,49 +1636,42 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, #define VLV_DISPLAY_POWER_DOMAINS POWER_DOMAIN_MASK #define VLV_DPIO_CMN_BC_POWER_DOMAINS ( \ - BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \ BIT(POWER_DOMAIN_PORT_CRT) | \ BIT(POWER_DOMAIN_AUX_B) | \ BIT(POWER_DOMAIN_AUX_C) | \ BIT(POWER_DOMAIN_INIT)) #define VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS ( \ - BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \ BIT(POWER_DOMAIN_AUX_B) | \ BIT(POWER_DOMAIN_INIT)) #define VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS ( \ - BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \ BIT(POWER_DOMAIN_AUX_B) | \ BIT(POWER_DOMAIN_INIT)) #define VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS ( \ - BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \ BIT(POWER_DOMAIN_AUX_C) | \ BIT(POWER_DOMAIN_INIT)) #define VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS ( \ - BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \ BIT(POWER_DOMAIN_AUX_C) | \ BIT(POWER_DOMAIN_INIT)) #define CHV_DPIO_CMN_BC_POWER_DOMAINS ( \ - BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_B_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_C_LANES) | \ BIT(POWER_DOMAIN_AUX_B) | \ BIT(POWER_DOMAIN_AUX_C) | \ BIT(POWER_DOMAIN_INIT)) #define CHV_DPIO_CMN_D_POWER_DOMAINS ( \ - BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \ - BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_D_LANES) | \ BIT(POWER_DOMAIN_AUX_D) | \ BIT(POWER_DOMAIN_INIT)) @@ -1591,6 +1719,13 @@ static const struct i915_power_well_ops skl_power_well_ops = { .is_enabled = skl_power_well_enabled, }; +static const struct i915_power_well_ops gen9_dc_off_power_well_ops = { + .sync_hw = gen9_dc_off_power_well_sync_hw, + .enable = gen9_dc_off_power_well_enable, + .disable = gen9_dc_off_power_well_disable, + .is_enabled = gen9_dc_off_power_well_enabled, +}; + static struct i915_power_well hsw_power_wells[] = { { .name = "always-on", @@ -1646,6 +1781,7 @@ static struct i915_power_well vlv_power_wells[] = { .always_on = 1, .domains = VLV_ALWAYS_ON_POWER_DOMAINS, .ops = &i9xx_always_on_power_well_ops, + .data = PUNIT_POWER_WELL_ALWAYS_ON, }, { .name = "display", @@ -1747,20 +1883,29 @@ static struct i915_power_well skl_power_wells[] = { .always_on = 1, .domains = SKL_DISPLAY_ALWAYS_ON_POWER_DOMAINS, .ops = &i9xx_always_on_power_well_ops, + .data = SKL_DISP_PW_ALWAYS_ON, }, { .name = "power well 1", - .domains = SKL_DISPLAY_POWERWELL_1_POWER_DOMAINS, + /* Handled by the DMC firmware */ + .domains = 0, .ops = &skl_power_well_ops, .data = SKL_DISP_PW_1, }, { .name = "MISC IO power well", - .domains = SKL_DISPLAY_MISC_IO_POWER_DOMAINS, + /* Handled by the DMC firmware */ + .domains = 0, .ops = &skl_power_well_ops, .data = SKL_DISP_PW_MISC_IO, }, { + .name = "DC off", + .domains = SKL_DISPLAY_DC_OFF_POWER_DOMAINS, + .ops = &gen9_dc_off_power_well_ops, + .data = SKL_DISP_PW_DC_OFF, + }, + { .name = "power well 2", .domains = SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS, .ops = &skl_power_well_ops, @@ -1792,6 +1937,34 @@ static struct i915_power_well skl_power_wells[] = { }, }; +void skl_pw1_misc_io_init(struct drm_i915_private *dev_priv) +{ + struct i915_power_well *well; + + if (!IS_SKYLAKE(dev_priv)) + return; + + well = lookup_power_well(dev_priv, SKL_DISP_PW_1); + intel_power_well_enable(dev_priv, well); + + well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO); + intel_power_well_enable(dev_priv, well); +} + +void skl_pw1_misc_io_fini(struct drm_i915_private *dev_priv) +{ + struct i915_power_well *well; + + if (!IS_SKYLAKE(dev_priv)) + return; + + well = lookup_power_well(dev_priv, SKL_DISP_PW_1); + intel_power_well_disable(dev_priv, well); + + well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO); + intel_power_well_disable(dev_priv, well); +} + static struct i915_power_well bxt_power_wells[] = { { .name = "always-on", @@ -1806,11 +1979,17 @@ static struct i915_power_well bxt_power_wells[] = { .data = SKL_DISP_PW_1, }, { + .name = "DC off", + .domains = BXT_DISPLAY_DC_OFF_POWER_DOMAINS, + .ops = &gen9_dc_off_power_well_ops, + .data = SKL_DISP_PW_DC_OFF, + }, + { .name = "power well 2", .domains = BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS, .ops = &skl_power_well_ops, .data = SKL_DISP_PW_2, - } + }, }; static int @@ -1820,7 +1999,7 @@ sanitize_disable_power_well_option(const struct drm_i915_private *dev_priv, if (disable_power_well >= 0) return !!disable_power_well; - if (IS_SKYLAKE(dev_priv)) { + if (IS_BROXTON(dev_priv)) { DRM_DEBUG_KMS("Disabling display power well support\n"); return 0; } @@ -1859,7 +2038,7 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv) set_power_wells(power_domains, hsw_power_wells); } else if (IS_BROADWELL(dev_priv->dev)) { set_power_wells(power_domains, bdw_power_wells); - } else if (IS_SKYLAKE(dev_priv->dev)) { + } else if (IS_SKYLAKE(dev_priv->dev) || IS_KABYLAKE(dev_priv->dev)) { set_power_wells(power_domains, skl_power_wells); } else if (IS_BROXTON(dev_priv->dev)) { set_power_wells(power_domains, bxt_power_wells); @@ -1874,21 +2053,6 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv) return 0; } -static void intel_runtime_pm_disable(struct drm_i915_private *dev_priv) -{ - struct drm_device *dev = dev_priv->dev; - struct device *device = &dev->pdev->dev; - - if (!HAS_RUNTIME_PM(dev)) - return; - - if (!intel_enable_rc6(dev)) - return; - - /* Make sure we're not suspended first. */ - pm_runtime_get_sync(device); -} - /** * intel_power_domains_fini - finalizes the power domain structures * @dev_priv: i915 device instance @@ -1899,15 +2063,32 @@ static void intel_runtime_pm_disable(struct drm_i915_private *dev_priv) */ void intel_power_domains_fini(struct drm_i915_private *dev_priv) { - intel_runtime_pm_disable(dev_priv); + struct device *device = &dev_priv->dev->pdev->dev; - /* The i915.ko module is still not prepared to be loaded when + /* + * 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. */ + * we're going to unload/reload. + * The following also reacquires the RPM reference the core passed + * to the driver during loading, which is dropped in + * intel_runtime_pm_enable(). We have to hand back the control of the + * device to the core with this reference held. + */ intel_display_set_init_power(dev_priv, true); + + /* Remove the refcount we took to keep power well support disabled. */ + if (!i915.disable_power_well) + intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); + + /* + * Remove the refcount we took in intel_runtime_pm_enable() in case + * the platform doesn't support runtime PM. + */ + if (!HAS_RUNTIME_PM(dev_priv)) + pm_runtime_put(device); } -static void intel_power_domains_resume(struct drm_i915_private *dev_priv) +static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv) { struct i915_power_domains *power_domains = &dev_priv->power_domains; struct i915_power_well *power_well; @@ -1922,6 +2103,47 @@ static void intel_power_domains_resume(struct drm_i915_private *dev_priv) mutex_unlock(&power_domains->lock); } +static void skl_display_core_init(struct drm_i915_private *dev_priv, + bool resume) +{ + struct i915_power_domains *power_domains = &dev_priv->power_domains; + uint32_t val; + + gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); + + /* enable PCH reset handshake */ + val = I915_READ(HSW_NDE_RSTWRN_OPT); + I915_WRITE(HSW_NDE_RSTWRN_OPT, val | RESET_PCH_HANDSHAKE_ENABLE); + + /* enable PG1 and Misc I/O */ + mutex_lock(&power_domains->lock); + skl_pw1_misc_io_init(dev_priv); + mutex_unlock(&power_domains->lock); + + if (!resume) + return; + + skl_init_cdclk(dev_priv); + + if (dev_priv->csr.dmc_payload) + intel_csr_load_program(dev_priv); +} + +static void skl_display_core_uninit(struct drm_i915_private *dev_priv) +{ + struct i915_power_domains *power_domains = &dev_priv->power_domains; + + gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); + + skl_uninit_cdclk(dev_priv); + + /* The spec doesn't call for removing the reset handshake flag */ + /* disable PG1 and Misc I/O */ + mutex_lock(&power_domains->lock); + skl_pw1_misc_io_fini(dev_priv); + mutex_unlock(&power_domains->lock); +} + static void chv_phy_control_init(struct drm_i915_private *dev_priv) { struct i915_power_well *cmn_bc = @@ -2044,14 +2266,16 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv) * This function initializes the hardware power domain state and enables all * power domains using intel_display_set_init_power(). */ -void intel_power_domains_init_hw(struct drm_i915_private *dev_priv) +void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume) { struct drm_device *dev = dev_priv->dev; struct i915_power_domains *power_domains = &dev_priv->power_domains; power_domains->initializing = true; - if (IS_CHERRYVIEW(dev)) { + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { + skl_display_core_init(dev_priv, resume); + } else if (IS_CHERRYVIEW(dev)) { mutex_lock(&power_domains->lock); chv_phy_control_init(dev_priv); mutex_unlock(&power_domains->lock); @@ -2063,11 +2287,34 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv) /* For now, we need the power well to be always enabled. */ intel_display_set_init_power(dev_priv, true); - intel_power_domains_resume(dev_priv); + /* Disable power support if the user asked so. */ + if (!i915.disable_power_well) + intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); + intel_power_domains_sync_hw(dev_priv); power_domains->initializing = false; } /** + * intel_power_domains_suspend - suspend power domain state + * @dev_priv: i915 device instance + * + * This function prepares the hardware power domain state before entering + * system suspend. It must be paired with intel_power_domains_init_hw(). + */ +void intel_power_domains_suspend(struct drm_i915_private *dev_priv) +{ + /* + * Even if power well support was disabled we still want to disable + * power wells while we are system suspended. + */ + if (!i915.disable_power_well) + intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); + + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) + skl_display_core_uninit(dev_priv); +} + +/** * intel_runtime_pm_get - grab a runtime pm reference * @dev_priv: i915 device instance * @@ -2082,11 +2329,45 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv) struct drm_device *dev = dev_priv->dev; struct device *device = &dev->pdev->dev; - if (!HAS_RUNTIME_PM(dev)) - return; - pm_runtime_get_sync(device); - WARN(dev_priv->pm.suspended, "Device still suspended.\n"); + + atomic_inc(&dev_priv->pm.wakeref_count); + assert_rpm_wakelock_held(dev_priv); +} + +/** + * intel_runtime_pm_get_if_in_use - grab a runtime pm reference if device in use + * @dev_priv: i915 device instance + * + * This function grabs a device-level runtime pm reference if the device is + * already in use and ensures that it is powered up. + * + * Any runtime pm reference obtained by this function must have a symmetric + * call to intel_runtime_pm_put() to release the reference again. + */ +bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + struct device *device = &dev->pdev->dev; + + if (IS_ENABLED(CONFIG_PM)) { + int ret = pm_runtime_get_if_in_use(device); + + /* + * In cases runtime PM is disabled by the RPM core and we get + * an -EINVAL return value we are not supposed to call this + * function, since the power state is undefined. This applies + * atm to the late/early system suspend/resume handlers. + */ + WARN_ON_ONCE(ret < 0); + if (ret <= 0) + return false; + } + + atomic_inc(&dev_priv->pm.wakeref_count); + assert_rpm_wakelock_held(dev_priv); + + return true; } /** @@ -2111,11 +2392,10 @@ void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv) struct drm_device *dev = dev_priv->dev; struct device *device = &dev->pdev->dev; - if (!HAS_RUNTIME_PM(dev)) - return; - - WARN(dev_priv->pm.suspended, "Getting nosync-ref while suspended.\n"); + assert_rpm_wakelock_held(dev_priv); pm_runtime_get_noresume(device); + + atomic_inc(&dev_priv->pm.wakeref_count); } /** @@ -2131,8 +2411,9 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv) struct drm_device *dev = dev_priv->dev; struct device *device = &dev->pdev->dev; - if (!HAS_RUNTIME_PM(dev)) - return; + assert_rpm_wakelock_held(dev_priv); + if (atomic_dec_and_test(&dev_priv->pm.wakeref_count)) + atomic_inc(&dev_priv->pm.atomic_seq); pm_runtime_mark_last_busy(device); pm_runtime_put_autosuspend(device); @@ -2153,22 +2434,27 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv) struct drm_device *dev = dev_priv->dev; struct device *device = &dev->pdev->dev; - if (!HAS_RUNTIME_PM(dev)) - return; + pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */ + pm_runtime_mark_last_busy(device); /* - * RPM depends on RC6 to save restore the GT HW context, so make RC6 a - * requirement. + * Take a permanent reference to disable the RPM functionality and drop + * it only when unloading the driver. Use the low level get/put helpers, + * so the driver's own RPM reference tracking asserts also work on + * platforms without RPM support. */ - if (!intel_enable_rc6(dev)) { - DRM_INFO("RC6 disabled, disabling runtime PM support\n"); - return; + if (!HAS_RUNTIME_PM(dev)) { + pm_runtime_dont_use_autosuspend(device); + pm_runtime_get_sync(device); + } else { + pm_runtime_use_autosuspend(device); } - pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */ - pm_runtime_mark_last_busy(device); - pm_runtime_use_autosuspend(device); - + /* + * The core calls the driver load handler with an RPM reference held. + * We drop that here and will reacquire it during unloading in + * intel_power_domains_fini(). + */ pm_runtime_put_autosuspend(device); } diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index c42b636c2..2e1da060b 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -74,7 +74,7 @@ struct intel_sdvo { struct i2c_adapter ddc; /* Register for the SDVO device: SDVOB or SDVOC */ - uint32_t sdvo_reg; + i915_reg_t sdvo_reg; /* Active outputs controlled by this SDVO output */ uint16_t controlled_output; @@ -120,8 +120,7 @@ struct intel_sdvo { */ bool is_tv; - /* On different gens SDVOB is at different places. */ - bool is_sdvob; + enum port port; /* This is for current tv format name */ int tv_format_index; @@ -245,7 +244,7 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val) u32 bval = val, cval = val; int i; - if (intel_sdvo->sdvo_reg == PCH_SDVOB) { + if (HAS_PCH_SPLIT(dev_priv)) { I915_WRITE(intel_sdvo->sdvo_reg, val); POSTING_READ(intel_sdvo->sdvo_reg); /* @@ -259,7 +258,7 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val) return; } - if (intel_sdvo->sdvo_reg == GEN3_SDVOB) + if (intel_sdvo->port == PORT_B) cval = I915_READ(GEN3_SDVOC); else bval = I915_READ(GEN3_SDVOB); @@ -422,7 +421,7 @@ static const struct _sdvo_cmd_name { SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_DATA), }; -#define SDVO_NAME(svdo) ((svdo)->is_sdvob ? "SDVOB" : "SDVOC") +#define SDVO_NAME(svdo) ((svdo)->port == PORT_B ? "SDVOB" : "SDVOC") static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd, const void *args, int args_len) @@ -1282,14 +1281,10 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder) sdvox |= SDVO_BORDER_ENABLE; } else { sdvox = I915_READ(intel_sdvo->sdvo_reg); - switch (intel_sdvo->sdvo_reg) { - case GEN3_SDVOB: + if (intel_sdvo->port == PORT_B) sdvox &= SDVOB_PRESERVE_MASK; - break; - case GEN3_SDVOC: + else sdvox &= SDVOC_PRESERVE_MASK; - break; - } sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; } @@ -1464,12 +1459,23 @@ static void intel_disable_sdvo(struct intel_encoder *encoder) * matching DP port to be enabled on transcoder A. */ if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B) { + /* + * We get CPU/PCH FIFO underruns on the other pipe when + * doing the workaround. Sweep them under the rug. + */ + intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, false); + intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false); + temp &= ~SDVO_PIPE_B_SELECT; temp |= SDVO_ENABLE; intel_sdvo_write_sdvox(intel_sdvo, temp); temp &= ~SDVO_ENABLE; intel_sdvo_write_sdvox(intel_sdvo, temp); + + intel_wait_for_vblank_if_active(dev_priv->dev, PIPE_A); + intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true); + intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true); } } @@ -2251,7 +2257,7 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv, { struct sdvo_device_mapping *mapping; - if (sdvo->is_sdvob) + if (sdvo->port == PORT_B) mapping = &(dev_priv->sdvo_mappings[0]); else mapping = &(dev_priv->sdvo_mappings[1]); @@ -2269,7 +2275,7 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, struct sdvo_device_mapping *mapping; u8 pin; - if (sdvo->is_sdvob) + if (sdvo->port == PORT_B) mapping = &dev_priv->sdvo_mappings[0]; else mapping = &dev_priv->sdvo_mappings[1]; @@ -2307,7 +2313,7 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, struct intel_sdvo *sdvo) struct drm_i915_private *dev_priv = dev->dev_private; struct sdvo_device_mapping *my_mapping, *other_mapping; - if (sdvo->is_sdvob) { + if (sdvo->port == PORT_B) { my_mapping = &dev_priv->sdvo_mappings[0]; other_mapping = &dev_priv->sdvo_mappings[1]; } else { @@ -2332,7 +2338,7 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, struct intel_sdvo *sdvo) /* No SDVO device info is found for another DVO port, * so use mapping assumption we had before BIOS parsing. */ - if (sdvo->is_sdvob) + if (sdvo->port == PORT_B) return 0x70; else return 0x72; @@ -2939,18 +2945,31 @@ intel_sdvo_init_ddc_proxy(struct intel_sdvo *sdvo, return i2c_add_adapter(&sdvo->ddc) == 0; } -bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) +static void assert_sdvo_port_valid(const struct drm_i915_private *dev_priv, + enum port port) +{ + if (HAS_PCH_SPLIT(dev_priv)) + WARN_ON(port != PORT_B); + else + WARN_ON(port != PORT_B && port != PORT_C); +} + +bool intel_sdvo_init(struct drm_device *dev, + i915_reg_t sdvo_reg, enum port port) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *intel_encoder; struct intel_sdvo *intel_sdvo; int i; + + assert_sdvo_port_valid(dev_priv, port); + intel_sdvo = kzalloc(sizeof(*intel_sdvo), GFP_KERNEL); if (!intel_sdvo) return false; intel_sdvo->sdvo_reg = sdvo_reg; - intel_sdvo->is_sdvob = is_sdvob; + intel_sdvo->port = port; intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, intel_sdvo) >> 1; intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo); if (!intel_sdvo_init_ddc_proxy(intel_sdvo, dev)) @@ -2959,7 +2978,8 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) /* encoder type will be decided later */ intel_encoder = &intel_sdvo->base; intel_encoder->type = INTEL_OUTPUT_SDVO; - drm_encoder_init(dev, &intel_encoder->base, &intel_sdvo_enc_funcs, 0); + drm_encoder_init(dev, &intel_encoder->base, &intel_sdvo_enc_funcs, 0, + NULL); /* Read the regs to test if we can talk to the device */ for (i = 0; i < 0x40; i++) { @@ -3000,8 +3020,10 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) * hotplug lines. */ if (intel_sdvo->hotplug_active) { - intel_encoder->hpd_pin = - intel_sdvo->is_sdvob ? HPD_SDVO_B : HPD_SDVO_C; + if (intel_sdvo->port == PORT_B) + intel_encoder->hpd_pin = HPD_SDVO_B; + else + intel_encoder->hpd_pin = HPD_SDVO_C; } /* diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 56dc132e8..4ff7a1f41 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -192,10 +192,9 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, const int pipe = intel_plane->pipe; const int plane = intel_plane->plane + 1; u32 plane_ctl, stride_div, stride; - int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); const struct drm_intel_sprite_colorkey *key = &to_intel_plane_state(drm_plane->state)->ckey; - unsigned long surf_addr; + u32 surf_addr; u32 tile_height, plane_offset, plane_size; unsigned int rotation; int x_offset, y_offset; @@ -212,10 +211,6 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, rotation = drm_plane->state->rotation; plane_ctl |= skl_plane_ctl_rotation(rotation); - intel_update_sprite_watermarks(drm_plane, crtc, src_w, src_h, - pixel_size, true, - src_w != crtc_w || src_h != crtc_h); - stride_div = intel_fb_stride_alignment(dev, fb->modifier[0], fb->pixel_format); @@ -297,8 +292,6 @@ skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) I915_WRITE(PLANE_SURF(pipe, plane), 0); POSTING_READ(PLANE_SURF(pipe, plane)); - - intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false); } static void @@ -541,10 +534,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, if (IS_HASWELL(dev) || IS_BROADWELL(dev)) sprctl |= SPRITE_PIPE_CSC_ENABLE; - intel_update_sprite_watermarks(plane, crtc, src_w, src_h, pixel_size, - true, - src_w != crtc_w || src_h != crtc_h); - /* Sizes are 0 based */ src_w--; src_h--; @@ -678,10 +667,6 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, if (IS_GEN6(dev)) dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */ - intel_update_sprite_watermarks(plane, crtc, src_w, src_h, - pixel_size, true, - src_w != crtc_w || src_h != crtc_h); - /* Sizes are 0 based */ src_w--; src_h--; @@ -832,8 +817,8 @@ intel_check_sprite_plane(struct drm_plane *plane, hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale); if (hscale < 0) { DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n"); - drm_rect_debug_print(src, true); - drm_rect_debug_print(dst, false); + drm_rect_debug_print("src: ", src, true); + drm_rect_debug_print("dst: ", dst, false); return hscale; } @@ -841,8 +826,8 @@ intel_check_sprite_plane(struct drm_plane *plane, vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale); if (vscale < 0) { DRM_DEBUG_KMS("Vertical scaling factor out of limits\n"); - drm_rect_debug_print(src, true); - drm_rect_debug_print(dst, false); + drm_rect_debug_print("src: ", src, true); + drm_rect_debug_print("dst: ", dst, false); return vscale; } @@ -938,9 +923,6 @@ intel_commit_sprite_plane(struct drm_plane *plane, crtc = crtc ? crtc : plane->crtc; - if (!crtc->state->active) - return; - if (state->visible) { intel_plane->update_plane(plane, crtc, fb, state->dst.x1, state->dst.y1, @@ -969,7 +951,7 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data, if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) return -EINVAL; - if (IS_VALLEYVIEW(dev) && + if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && set->flags & I915_SET_COLORKEY_DESTINATION) return -EINVAL; @@ -1104,7 +1086,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) intel_plane->max_downscale = 1; } - if (IS_VALLEYVIEW(dev)) { + if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { intel_plane->update_plane = vlv_update_plane; intel_plane->disable_plane = vlv_disable_plane; @@ -1141,7 +1123,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs, &intel_plane_funcs, plane_formats, num_plane_formats, - DRM_PLANE_TYPE_OVERLAY); + DRM_PLANE_TYPE_OVERLAY, NULL); if (ret) { kfree(intel_plane); goto out; diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 6bea78944..948cbff6c 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1645,7 +1645,7 @@ intel_tv_init(struct drm_device *dev) DRM_MODE_CONNECTOR_SVIDEO); drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs, - DRM_MODE_ENCODER_TVDAC); + DRM_MODE_ENCODER_TVDAC, NULL); intel_encoder->compute_config = intel_tv_compute_config; intel_encoder->get_config = intel_tv_get_config; diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 43cba129a..277e60ae0 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -29,19 +29,7 @@ #define FORCEWAKE_ACK_TIMEOUT_MS 50 -#define __raw_i915_read8(dev_priv__, reg__) readb((dev_priv__)->regs + (reg__)) -#define __raw_i915_write8(dev_priv__, reg__, val__) writeb(val__, (dev_priv__)->regs + (reg__)) - -#define __raw_i915_read16(dev_priv__, reg__) readw((dev_priv__)->regs + (reg__)) -#define __raw_i915_write16(dev_priv__, reg__, val__) writew(val__, (dev_priv__)->regs + (reg__)) - -#define __raw_i915_read32(dev_priv__, reg__) readl((dev_priv__)->regs + (reg__)) -#define __raw_i915_write32(dev_priv__, reg__, val__) writel(val__, (dev_priv__)->regs + (reg__)) - -#define __raw_i915_read64(dev_priv__, reg__) readq((dev_priv__)->regs + (reg__)) -#define __raw_i915_write64(dev_priv__, reg__, val__) writeq(val__, (dev_priv__)->regs + (reg__)) - -#define __raw_posting_read(dev_priv__, reg__) (void)__raw_i915_read32(dev_priv__, reg__) +#define __raw_posting_read(dev_priv__, reg__) (void)__raw_i915_read32((dev_priv__), (reg__)) static const char * const forcewake_domain_names[] = { "render", @@ -62,17 +50,10 @@ intel_uncore_forcewake_domain_to_str(const enum forcewake_domain_id id) return "unknown"; } -static void -assert_device_not_suspended(struct drm_i915_private *dev_priv) -{ - WARN_ONCE(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended, - "Device suspended\n"); -} - static inline void fw_domain_reset(const struct intel_uncore_forcewake_domain *d) { - WARN_ON(d->reg_set == 0); + WARN_ON(!i915_mmio_reg_valid(d->reg_set)); __raw_i915_write32(d->i915, d->reg_set, d->val_reset); } @@ -118,7 +99,7 @@ static inline void fw_domain_posting_read(const struct intel_uncore_forcewake_domain *d) { /* something from same cacheline, but not from the set register */ - if (d->reg_post) + if (i915_mmio_reg_valid(d->reg_post)) __raw_posting_read(d->i915, d->reg_post); } @@ -248,7 +229,7 @@ static void intel_uncore_fw_release_timer(unsigned long arg) struct intel_uncore_forcewake_domain *domain = (void *)arg; unsigned long irqflags; - assert_device_not_suspended(domain->i915); + assert_rpm_device_not_suspended(domain->i915); spin_lock_irqsave(&domain->i915->uncore.lock, irqflags); if (WARN_ON(domain->wake_count == 0)) @@ -423,7 +404,7 @@ void intel_uncore_forcewake_get(struct drm_i915_private *dev_priv, if (!dev_priv->uncore.funcs.force_wake_get) return; - WARN_ON(dev_priv->pm.suspended); + assert_rpm_wakelock_held(dev_priv); spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); __intel_uncore_forcewake_get(dev_priv, fw_domains); @@ -525,8 +506,7 @@ void assert_forcewakes_inactive(struct drm_i915_private *dev_priv) } /* We give fast paths for the really cool registers */ -#define NEEDS_FORCE_WAKE(reg) \ - ((reg) < 0x40000 && (reg) != FORCEWAKE) +#define NEEDS_FORCE_WAKE(reg) ((reg) < 0x40000) #define REG_RANGE(reg, start, end) ((reg) >= (start) && (reg) < (end)) @@ -589,7 +569,7 @@ void assert_forcewakes_inactive(struct drm_i915_private *dev_priv) REG_RANGE((reg), 0x9400, 0x9800) #define FORCEWAKE_GEN9_BLITTER_RANGE_OFFSET(reg) \ - ((reg) < 0x40000 &&\ + ((reg) < 0x40000 && \ !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg) && \ !FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg) && \ !FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg) && \ @@ -605,8 +585,8 @@ ilk_dummy_write(struct drm_i915_private *dev_priv) } static void -hsw_unclaimed_reg_debug(struct drm_i915_private *dev_priv, u32 reg, bool read, - bool before) +hsw_unclaimed_reg_debug(struct drm_i915_private *dev_priv, + i915_reg_t reg, bool read, bool before) { const char *op = read ? "reading" : "writing to"; const char *when = before ? "before" : "after"; @@ -616,7 +596,7 @@ hsw_unclaimed_reg_debug(struct drm_i915_private *dev_priv, u32 reg, bool read, if (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM) { WARN(1, "Unclaimed register detected %s %s register 0x%x\n", - when, op, reg); + when, op, i915_mmio_reg_offset(reg)); __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM); i915.mmio_debug--; /* Only report the first N failures */ } @@ -641,7 +621,7 @@ hsw_unclaimed_reg_detect(struct drm_i915_private *dev_priv) #define GEN2_READ_HEADER(x) \ u##x val = 0; \ - assert_device_not_suspended(dev_priv); + assert_rpm_wakelock_held(dev_priv); #define GEN2_READ_FOOTER \ trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \ @@ -649,7 +629,7 @@ hsw_unclaimed_reg_detect(struct drm_i915_private *dev_priv) #define __gen2_read(x) \ static u##x \ -gen2_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ +gen2_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ GEN2_READ_HEADER(x); \ val = __raw_i915_read##x(dev_priv, reg); \ GEN2_READ_FOOTER; \ @@ -657,7 +637,7 @@ gen2_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ #define __gen5_read(x) \ static u##x \ -gen5_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ +gen5_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ GEN2_READ_HEADER(x); \ ilk_dummy_write(dev_priv); \ val = __raw_i915_read##x(dev_priv, reg); \ @@ -680,9 +660,10 @@ __gen2_read(64) #undef GEN2_READ_HEADER #define GEN6_READ_HEADER(x) \ + u32 offset = i915_mmio_reg_offset(reg); \ unsigned long irqflags; \ u##x val = 0; \ - assert_device_not_suspended(dev_priv); \ + assert_rpm_wakelock_held(dev_priv); \ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags) #define GEN6_READ_FOOTER \ @@ -714,20 +695,12 @@ static inline void __force_wake_get(struct drm_i915_private *dev_priv, dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); } -#define __vgpu_read(x) \ -static u##x \ -vgpu_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ - GEN6_READ_HEADER(x); \ - val = __raw_i915_read##x(dev_priv, reg); \ - GEN6_READ_FOOTER; \ -} - #define __gen6_read(x) \ static u##x \ -gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ +gen6_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ GEN6_READ_HEADER(x); \ hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \ - if (NEEDS_FORCE_WAKE(reg)) \ + if (NEEDS_FORCE_WAKE(offset)) \ __force_wake_get(dev_priv, FORCEWAKE_RENDER); \ val = __raw_i915_read##x(dev_priv, reg); \ hsw_unclaimed_reg_debug(dev_priv, reg, true, false); \ @@ -736,47 +709,56 @@ gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ #define __vlv_read(x) \ static u##x \ -vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ +vlv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ + enum forcewake_domains fw_engine = 0; \ GEN6_READ_HEADER(x); \ - if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg)) \ - __force_wake_get(dev_priv, FORCEWAKE_RENDER); \ - else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)) \ - __force_wake_get(dev_priv, FORCEWAKE_MEDIA); \ + if (!NEEDS_FORCE_WAKE(offset)) \ + fw_engine = 0; \ + else if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(offset)) \ + fw_engine = FORCEWAKE_RENDER; \ + else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(offset)) \ + fw_engine = FORCEWAKE_MEDIA; \ + if (fw_engine) \ + __force_wake_get(dev_priv, fw_engine); \ val = __raw_i915_read##x(dev_priv, reg); \ GEN6_READ_FOOTER; \ } #define __chv_read(x) \ static u##x \ -chv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ +chv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ + enum forcewake_domains fw_engine = 0; \ GEN6_READ_HEADER(x); \ - if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) \ - __force_wake_get(dev_priv, FORCEWAKE_RENDER); \ - else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) \ - __force_wake_get(dev_priv, FORCEWAKE_MEDIA); \ - else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) \ - __force_wake_get(dev_priv, \ - FORCEWAKE_RENDER | FORCEWAKE_MEDIA); \ + if (!NEEDS_FORCE_WAKE(offset)) \ + fw_engine = 0; \ + else if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(offset)) \ + fw_engine = FORCEWAKE_RENDER; \ + else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(offset)) \ + fw_engine = FORCEWAKE_MEDIA; \ + else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \ + fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \ + if (fw_engine) \ + __force_wake_get(dev_priv, fw_engine); \ val = __raw_i915_read##x(dev_priv, reg); \ GEN6_READ_FOOTER; \ } #define SKL_NEEDS_FORCE_WAKE(reg) \ - ((reg) < 0x40000 && !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg)) + ((reg) < 0x40000 && !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg)) #define __gen9_read(x) \ static u##x \ -gen9_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ +gen9_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ enum forcewake_domains fw_engine; \ GEN6_READ_HEADER(x); \ hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \ - if (!SKL_NEEDS_FORCE_WAKE(reg)) \ + if (!SKL_NEEDS_FORCE_WAKE(offset)) \ fw_engine = 0; \ - else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) \ + else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \ fw_engine = FORCEWAKE_RENDER; \ - else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg)) \ + else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(offset)) \ fw_engine = FORCEWAKE_MEDIA; \ - else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg)) \ + else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(offset)) \ fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \ else \ fw_engine = FORCEWAKE_BLITTER; \ @@ -787,10 +769,6 @@ gen9_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \ GEN6_READ_FOOTER; \ } -__vgpu_read(8) -__vgpu_read(16) -__vgpu_read(32) -__vgpu_read(64) __gen9_read(8) __gen9_read(16) __gen9_read(32) @@ -812,19 +790,46 @@ __gen6_read(64) #undef __chv_read #undef __vlv_read #undef __gen6_read -#undef __vgpu_read #undef GEN6_READ_FOOTER #undef GEN6_READ_HEADER +#define VGPU_READ_HEADER(x) \ + unsigned long irqflags; \ + u##x val = 0; \ + assert_rpm_device_not_suspended(dev_priv); \ + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags) + +#define VGPU_READ_FOOTER \ + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \ + trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \ + return val + +#define __vgpu_read(x) \ +static u##x \ +vgpu_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ + VGPU_READ_HEADER(x); \ + val = __raw_i915_read##x(dev_priv, reg); \ + VGPU_READ_FOOTER; \ +} + +__vgpu_read(8) +__vgpu_read(16) +__vgpu_read(32) +__vgpu_read(64) + +#undef __vgpu_read +#undef VGPU_READ_FOOTER +#undef VGPU_READ_HEADER + #define GEN2_WRITE_HEADER \ trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \ - assert_device_not_suspended(dev_priv); \ + assert_rpm_wakelock_held(dev_priv); \ #define GEN2_WRITE_FOOTER #define __gen2_write(x) \ static void \ -gen2_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ +gen2_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ GEN2_WRITE_HEADER; \ __raw_i915_write##x(dev_priv, reg, val); \ GEN2_WRITE_FOOTER; \ @@ -832,7 +837,7 @@ gen2_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace #define __gen5_write(x) \ static void \ -gen5_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ +gen5_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ GEN2_WRITE_HEADER; \ ilk_dummy_write(dev_priv); \ __raw_i915_write##x(dev_priv, reg, val); \ @@ -855,9 +860,10 @@ __gen2_write(64) #undef GEN2_WRITE_HEADER #define GEN6_WRITE_HEADER \ + u32 offset = i915_mmio_reg_offset(reg); \ unsigned long irqflags; \ trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \ - assert_device_not_suspended(dev_priv); \ + assert_rpm_wakelock_held(dev_priv); \ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags) #define GEN6_WRITE_FOOTER \ @@ -865,10 +871,10 @@ __gen2_write(64) #define __gen6_write(x) \ static void \ -gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ +gen6_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ u32 __fifo_ret = 0; \ GEN6_WRITE_HEADER; \ - if (NEEDS_FORCE_WAKE(reg)) { \ + if (NEEDS_FORCE_WAKE(offset)) { \ __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ } \ __raw_i915_write##x(dev_priv, reg, val); \ @@ -880,10 +886,10 @@ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace #define __hsw_write(x) \ static void \ -hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ +hsw_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ u32 __fifo_ret = 0; \ GEN6_WRITE_HEADER; \ - if (NEEDS_FORCE_WAKE(reg)) { \ + if (NEEDS_FORCE_WAKE(offset)) { \ __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ } \ hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \ @@ -896,15 +902,7 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) GEN6_WRITE_FOOTER; \ } -#define __vgpu_write(x) \ -static void vgpu_write##x(struct drm_i915_private *dev_priv, \ - off_t reg, u##x val, bool trace) { \ - GEN6_WRITE_HEADER; \ - __raw_i915_write##x(dev_priv, reg, val); \ - GEN6_WRITE_FOOTER; \ -} - -static const u32 gen8_shadowed_regs[] = { +static const i915_reg_t gen8_shadowed_regs[] = { FORCEWAKE_MT, GEN6_RPNSWREQ, GEN6_RC_VIDEO_FREQ, @@ -915,11 +913,12 @@ static const u32 gen8_shadowed_regs[] = { /* TODO: Other registers are not yet used */ }; -static bool is_gen8_shadowed(struct drm_i915_private *dev_priv, u32 reg) +static bool is_gen8_shadowed(struct drm_i915_private *dev_priv, + i915_reg_t reg) { int i; for (i = 0; i < ARRAY_SIZE(gen8_shadowed_regs); i++) - if (reg == gen8_shadowed_regs[i]) + if (i915_mmio_reg_equal(reg, gen8_shadowed_regs[i])) return true; return false; @@ -927,10 +926,10 @@ static bool is_gen8_shadowed(struct drm_i915_private *dev_priv, u32 reg) #define __gen8_write(x) \ static void \ -gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ +gen8_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ GEN6_WRITE_HEADER; \ hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \ - if (reg < 0x40000 && !is_gen8_shadowed(dev_priv, reg)) \ + if (NEEDS_FORCE_WAKE(offset) && !is_gen8_shadowed(dev_priv, reg)) \ __force_wake_get(dev_priv, FORCEWAKE_RENDER); \ __raw_i915_write##x(dev_priv, reg, val); \ hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \ @@ -940,22 +939,25 @@ gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace #define __chv_write(x) \ static void \ -chv_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \ - bool shadowed = is_gen8_shadowed(dev_priv, reg); \ +chv_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ + enum forcewake_domains fw_engine = 0; \ GEN6_WRITE_HEADER; \ - if (!shadowed) { \ - if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) \ - __force_wake_get(dev_priv, FORCEWAKE_RENDER); \ - else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) \ - __force_wake_get(dev_priv, FORCEWAKE_MEDIA); \ - else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) \ - __force_wake_get(dev_priv, FORCEWAKE_RENDER | FORCEWAKE_MEDIA); \ - } \ + if (!NEEDS_FORCE_WAKE(offset) || \ + is_gen8_shadowed(dev_priv, reg)) \ + fw_engine = 0; \ + else if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(offset)) \ + fw_engine = FORCEWAKE_RENDER; \ + else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(offset)) \ + fw_engine = FORCEWAKE_MEDIA; \ + else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \ + fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \ + if (fw_engine) \ + __force_wake_get(dev_priv, fw_engine); \ __raw_i915_write##x(dev_priv, reg, val); \ GEN6_WRITE_FOOTER; \ } -static const u32 gen9_shadowed_regs[] = { +static const i915_reg_t gen9_shadowed_regs[] = { RING_TAIL(RENDER_RING_BASE), RING_TAIL(GEN6_BSD_RING_BASE), RING_TAIL(VEBOX_RING_BASE), @@ -968,11 +970,12 @@ static const u32 gen9_shadowed_regs[] = { /* TODO: Other registers are not yet used */ }; -static bool is_gen9_shadowed(struct drm_i915_private *dev_priv, u32 reg) +static bool is_gen9_shadowed(struct drm_i915_private *dev_priv, + i915_reg_t reg) { int i; for (i = 0; i < ARRAY_SIZE(gen9_shadowed_regs); i++) - if (reg == gen9_shadowed_regs[i]) + if (i915_mmio_reg_equal(reg, gen9_shadowed_regs[i])) return true; return false; @@ -980,19 +983,19 @@ static bool is_gen9_shadowed(struct drm_i915_private *dev_priv, u32 reg) #define __gen9_write(x) \ static void \ -gen9_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, \ +gen9_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, \ bool trace) { \ enum forcewake_domains fw_engine; \ GEN6_WRITE_HEADER; \ hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \ - if (!SKL_NEEDS_FORCE_WAKE(reg) || \ + if (!SKL_NEEDS_FORCE_WAKE(offset) || \ is_gen9_shadowed(dev_priv, reg)) \ fw_engine = 0; \ - else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg)) \ + else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \ fw_engine = FORCEWAKE_RENDER; \ - else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg)) \ + else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(offset)) \ fw_engine = FORCEWAKE_MEDIA; \ - else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg)) \ + else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(offset)) \ fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \ else \ fw_engine = FORCEWAKE_BLITTER; \ @@ -1024,20 +1027,41 @@ __gen6_write(8) __gen6_write(16) __gen6_write(32) __gen6_write(64) -__vgpu_write(8) -__vgpu_write(16) -__vgpu_write(32) -__vgpu_write(64) #undef __gen9_write #undef __chv_write #undef __gen8_write #undef __hsw_write #undef __gen6_write -#undef __vgpu_write #undef GEN6_WRITE_FOOTER #undef GEN6_WRITE_HEADER +#define VGPU_WRITE_HEADER \ + unsigned long irqflags; \ + trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \ + assert_rpm_device_not_suspended(dev_priv); \ + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags) + +#define VGPU_WRITE_FOOTER \ + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags) + +#define __vgpu_write(x) \ +static void vgpu_write##x(struct drm_i915_private *dev_priv, \ + i915_reg_t reg, u##x val, bool trace) { \ + VGPU_WRITE_HEADER; \ + __raw_i915_write##x(dev_priv, reg, val); \ + VGPU_WRITE_FOOTER; \ +} + +__vgpu_write(8) +__vgpu_write(16) +__vgpu_write(32) +__vgpu_write(64) + +#undef __vgpu_write +#undef VGPU_WRITE_FOOTER +#undef VGPU_WRITE_HEADER + #define ASSIGN_WRITE_MMIO_VFUNCS(x) \ do { \ dev_priv->uncore.funcs.mmio_writeb = x##_write8; \ @@ -1057,7 +1081,8 @@ do { \ static void fw_domain_init(struct drm_i915_private *dev_priv, enum forcewake_domain_id domain_id, - u32 reg_set, u32 reg_ack) + i915_reg_t reg_set, + i915_reg_t reg_ack) { struct intel_uncore_forcewake_domain *d; @@ -1083,12 +1108,10 @@ static void fw_domain_init(struct drm_i915_private *dev_priv, d->val_clear = _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL); } - if (IS_VALLEYVIEW(dev_priv)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) d->reg_post = FORCEWAKE_ACK_VLV; else if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv) || IS_GEN8(dev_priv)) d->reg_post = ECOBUS; - else - d->reg_post = 0; d->i915 = dev_priv; d->id = domain_id; @@ -1118,7 +1141,7 @@ static void intel_uncore_fw_domains_init(struct drm_device *dev) FORCEWAKE_ACK_BLITTER_GEN9); fw_domain_init(dev_priv, FW_DOMAIN_ID_MEDIA, FORCEWAKE_MEDIA_GEN9, FORCEWAKE_ACK_MEDIA_GEN9); - } else if (IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { dev_priv->uncore.funcs.force_wake_get = fw_domains_get; if (!IS_CHERRYVIEW(dev)) dev_priv->uncore.funcs.force_wake_put = @@ -1262,12 +1285,14 @@ void intel_uncore_fini(struct drm_device *dev) #define GEN_RANGE(l, h) GENMASK(h, l) static const struct register_whitelist { - uint64_t offset; + i915_reg_t offset_ldw, offset_udw; uint32_t size; /* supported gens, 0x10 for 4, 0x30 for 4 and 5, etc. */ uint32_t gen_bitmask; } whitelist[] = { - { RING_TIMESTAMP(RENDER_RING_BASE), 8, GEN_RANGE(4, 9) }, + { .offset_ldw = RING_TIMESTAMP(RENDER_RING_BASE), + .offset_udw = RING_TIMESTAMP_UDW(RENDER_RING_BASE), + .size = 8, .gen_bitmask = GEN_RANGE(4, 9) }, }; int i915_reg_read_ioctl(struct drm_device *dev, @@ -1277,11 +1302,11 @@ int i915_reg_read_ioctl(struct drm_device *dev, struct drm_i915_reg_read *reg = data; struct register_whitelist const *entry = whitelist; unsigned size; - u64 offset; + i915_reg_t offset_ldw, offset_udw; int i, ret = 0; for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) { - if (entry->offset == (reg->offset & -entry->size) && + if (i915_mmio_reg_offset(entry->offset_ldw) == (reg->offset & -entry->size) && (1 << INTEL_INFO(dev)->gen & entry->gen_bitmask)) break; } @@ -1293,27 +1318,28 @@ int i915_reg_read_ioctl(struct drm_device *dev, * be naturally aligned (and those that are not so aligned merely * limit the available flags for that register). */ - offset = entry->offset; + offset_ldw = entry->offset_ldw; + offset_udw = entry->offset_udw; size = entry->size; - size |= reg->offset ^ offset; + size |= reg->offset ^ i915_mmio_reg_offset(offset_ldw); intel_runtime_pm_get(dev_priv); switch (size) { case 8 | 1: - reg->val = I915_READ64_2x32(offset, offset+4); + reg->val = I915_READ64_2x32(offset_ldw, offset_udw); break; case 8: - reg->val = I915_READ64(offset); + reg->val = I915_READ64(offset_ldw); break; case 4: - reg->val = I915_READ(offset); + reg->val = I915_READ(offset_ldw); break; case 2: - reg->val = I915_READ16(offset); + reg->val = I915_READ16(offset_ldw); break; case 1: - reg->val = I915_READ8(offset); + reg->val = I915_READ8(offset_ldw); break; default: ret = -EINVAL; @@ -1470,7 +1496,7 @@ static int gen6_do_reset(struct drm_device *dev) } static int wait_for_register(struct drm_i915_private *dev_priv, - const u32 reg, + i915_reg_t reg, const u32 mask, const u32 value, const unsigned long timeout_ms) |