diff options
113 files changed, 2588 insertions, 1549 deletions
diff --git a/drivers/gpu/drm/i915/.gitignore b/drivers/gpu/drm/i915/.gitignore new file mode 100644 index 000000000000..cff45d81f42f --- /dev/null +++ b/drivers/gpu/drm/i915/.gitignore @@ -0,0 +1 @@ +header_test_*.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 30bf3301ea24..fbcb0904f4a8 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -32,10 +32,13 @@ CFLAGS_intel_fbdev.o = $(call cc-disable-warning, override-init) subdir-ccflags-y += \ $(call as-instr,movntdqa (%eax)$(comma)%xmm0,-DCONFIG_AS_MOVNTDQA) +# Extra header tests +include $(src)/Makefile.header-test + # Please keep these build lists sorted! # core driver code -i915-y := i915_drv.o \ +i915-y += i915_drv.o \ i915_irq.o \ i915_memcpy.o \ i915_mm.o \ @@ -57,17 +60,6 @@ i915-$(CONFIG_COMPAT) += i915_ioc32.o i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o intel_pipe_crc.o i915-$(CONFIG_PERF_EVENTS) += i915_pmu.o -# Test the headers are compilable as standalone units -i915-$(CONFIG_DRM_I915_WERROR) += \ - test_i915_active_types_standalone.o \ - test_i915_gem_context_types_standalone.o \ - test_i915_priolist_types_standalone.o \ - test_i915_scheduler_types_standalone.o \ - test_i915_timeline_types_standalone.o \ - test_intel_context_types_standalone.o \ - test_intel_engine_types_standalone.o \ - test_intel_workarounds_types_standalone.o - # GEM code i915-y += \ i915_active.o \ diff --git a/drivers/gpu/drm/i915/Makefile.header-test b/drivers/gpu/drm/i915/Makefile.header-test new file mode 100644 index 000000000000..c1c391816fa7 --- /dev/null +++ b/drivers/gpu/drm/i915/Makefile.header-test @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: MIT +# Copyright © 2019 Intel Corporation + +# Test the headers are compilable as standalone units +header_test := \ + i915_active_types.h \ + i915_gem_context_types.h \ + i915_priolist_types.h \ + i915_scheduler_types.h \ + i915_timeline_types.h \ + intel_atomic_plane.h \ + intel_audio.h \ + intel_cdclk.h \ + intel_color.h \ + intel_connector.h \ + intel_context_types.h \ + intel_crt.h \ + intel_csr.h \ + intel_ddi.h \ + intel_dp.h \ + intel_dvo.h \ + intel_engine_types.h \ + intel_fbc.h \ + intel_fbdev.h \ + intel_frontbuffer.h \ + intel_hdcp.h \ + intel_hdmi.h \ + intel_lspcon.h \ + intel_lvds.h \ + intel_panel.h \ + intel_pipe_crc.h \ + intel_pm.h \ + intel_psr.h \ + intel_sdvo.h \ + intel_sprite.h \ + intel_tv.h \ + intel_workarounds_types.h + +quiet_cmd_header_test = HDRTEST $@ + cmd_header_test = echo "\#include \"$(<F)\"" > $@ + +header_test_%.c: %.h + $(call cmd,header_test) + +i915-$(CONFIG_DRM_I915_WERROR) += $(foreach h,$(header_test),$(patsubst %.h,header_test_%.o,$(h))) + +clean-files += $(foreach h,$(header_test),$(patsubst %.h,header_test_%.c,$(h))) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 4dd2d9ae3202..b88c62ea664d 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -26,14 +26,21 @@ * */ -#include <linux/sort.h> #include <linux/sched/mm.h> +#include <linux/sort.h> + #include <drm/drm_debugfs.h> #include <drm/drm_fourcc.h> -#include "intel_drv.h" -#include "intel_guc_submission.h" #include "i915_reset.h" +#include "intel_dp.h" +#include "intel_drv.h" +#include "intel_fbc.h" +#include "intel_guc_submission.h" +#include "intel_hdcp.h" +#include "intel_hdmi.h" +#include "intel_pm.h" +#include "intel_psr.h" static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node) { @@ -4815,6 +4822,8 @@ static int i915_dsc_fec_support_show(struct seq_file *m, void *data) yesno(crtc_state->dsc_params.compression_enable)); seq_printf(m, "DSC_Sink_Support: %s\n", yesno(drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd))); + seq_printf(m, "Force_DSC_Enable: %s\n", + yesno(intel_dp->force_dsc_en)); if (!intel_dp_is_edp(intel_dp)) seq_printf(m, "FEC_Sink_Support: %s\n", yesno(drm_dp_sink_supports_fec(intel_dp->fec_capable))); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 0bbf3f5db5fc..1ad88e6d7c04 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -48,12 +48,19 @@ #include <drm/i915_drm.h> #include "i915_drv.h" -#include "i915_trace.h" #include "i915_pmu.h" -#include "i915_reset.h" #include "i915_query.h" +#include "i915_reset.h" +#include "i915_trace.h" #include "i915_vgpu.h" +#include "intel_audio.h" +#include "intel_cdclk.h" +#include "intel_csr.h" +#include "intel_dp.h" #include "intel_drv.h" +#include "intel_fbdev.h" +#include "intel_pm.h" +#include "intel_sprite.h" #include "intel_uc.h" #include "intel_workarounds.h" @@ -1907,6 +1914,13 @@ void i915_driver_unload(struct drm_device *dev) i915_driver_unregister(dev_priv); + /* + * After unregistering the device to prevent any new users, cancel + * all in-flight requests so that we can quickly unbind the active + * resources. + */ + i915_gem_set_wedged(dev_priv); + /* Flush any external code that still may be under the RCU lock */ synchronize_rcu(); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4af815c3c02d..35d0782c077e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -66,13 +66,14 @@ #include "intel_device_info.h" #include "intel_display.h" #include "intel_dpll_mgr.h" +#include "intel_frontbuffer.h" #include "intel_lrc.h" #include "intel_opregion.h" #include "intel_ringbuffer.h" +#include "intel_uc.h" #include "intel_uncore.h" #include "intel_wopcm.h" #include "intel_workarounds.h" -#include "intel_uc.h" #include "i915_gem.h" #include "i915_gem_context.h" @@ -375,14 +376,6 @@ enum i915_cache_level { #define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */ -enum fb_op_origin { - ORIGIN_GTT, - ORIGIN_CPU, - ORIGIN_CS, - ORIGIN_FLIP, - ORIGIN_DIRTYFB, -}; - struct intel_fbc { /* This is always the inner lock when overlapping with struct_mutex and * it's the outer lock when overlapping with stolen_lock. */ @@ -2002,7 +1995,6 @@ struct drm_i915_private { /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ struct { - void (*resume)(struct drm_i915_private *); void (*cleanup_engine)(struct intel_engine_cs *engine); struct i915_gt_timelines { @@ -2917,6 +2909,7 @@ static inline void i915_gem_drain_workqueue(struct drm_i915_private *i915) int pass = 2; do { rcu_barrier(); + i915_gem_drain_freed_objects(i915); drain_workqueue(i915->wq); } while (--pass); } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index bf594a5e88bc..0a818a60ad31 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -50,6 +50,7 @@ #include "intel_drv.h" #include "intel_frontbuffer.h" #include "intel_mocs.h" +#include "intel_pm.h" #include "intel_workarounds.h" static void i915_gem_flush_free_objects(struct drm_i915_private *i915); @@ -3841,16 +3842,16 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, return vma; } -static __always_inline unsigned int __busy_read_flag(unsigned int id) +static __always_inline u32 __busy_read_flag(u8 id) { - if (id == I915_ENGINE_CLASS_INVALID) - return 0xffff0000; + if (id == (u8)I915_ENGINE_CLASS_INVALID) + return 0xffff0000u; GEM_BUG_ON(id >= 16); - return 0x10000 << id; + return 0x10000u << id; } -static __always_inline unsigned int __busy_write_id(unsigned int id) +static __always_inline u32 __busy_write_id(u8 id) { /* * The uABI guarantees an active writer is also amongst the read @@ -3861,15 +3862,14 @@ static __always_inline unsigned int __busy_write_id(unsigned int id) * last_read - hence we always set both read and write busy for * last_write. */ - if (id == I915_ENGINE_CLASS_INVALID) - return 0xffffffff; + if (id == (u8)I915_ENGINE_CLASS_INVALID) + return 0xffffffffu; return (id + 1) | __busy_read_flag(id); } static __always_inline unsigned int -__busy_set_if_active(const struct dma_fence *fence, - unsigned int (*flag)(unsigned int id)) +__busy_set_if_active(const struct dma_fence *fence, u32 (*flag)(u8 id)) { const struct i915_request *rq; @@ -3889,6 +3889,8 @@ __busy_set_if_active(const struct dma_fence *fence, if (i915_request_completed(rq)) return 0; + /* Beware type-expansion follies! */ + BUILD_BUG_ON(!typecheck(u8, rq->engine->uabi_class)); return flag(rq->engine->uabi_class); } @@ -4511,7 +4513,7 @@ void i915_gem_resume(struct drm_i915_private *i915) * guarantee that the context image is complete. So let's just reset * it and start again. */ - i915->gt.resume(i915); + intel_gt_resume(i915); if (i915_gem_init_hw(i915)) goto err_wedged; @@ -4851,13 +4853,10 @@ int i915_gem_init(struct drm_i915_private *dev_priv) dev_priv->mm.unordered_timeline = dma_fence_context_alloc(1); - if (HAS_LOGICAL_RING_CONTEXTS(dev_priv)) { - dev_priv->gt.resume = intel_lr_context_resume; + if (HAS_LOGICAL_RING_CONTEXTS(dev_priv)) dev_priv->gt.cleanup_engine = intel_logical_ring_cleanup; - } else { - dev_priv->gt.resume = intel_legacy_submission_resume; + else dev_priv->gt.cleanup_engine = intel_engine_cleanup; - } i915_timelines_init(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index fe7ddb1f59e1..7fc34ab6df87 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -562,7 +562,7 @@ static void init_contexts(struct drm_i915_private *i915) static bool needs_preempt_context(struct drm_i915_private *i915) { - return HAS_LOGICAL_RING_PREEMPTION(i915); + return HAS_EXECLISTS(i915); } int i915_gem_contexts_init(struct drm_i915_private *dev_priv) @@ -1028,6 +1028,7 @@ static int emit_ppgtt_update(struct i915_request *rq, void *data) { struct i915_hw_ppgtt *ppgtt = rq->gem_context->ppgtt; struct intel_engine_cs *engine = rq->engine; + u32 base = engine->mmio_base; u32 *cs; int i; @@ -1040,9 +1041,9 @@ static int emit_ppgtt_update(struct i915_request *rq, void *data) *cs++ = MI_LOAD_REGISTER_IMM(2); - *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_UDW(engine, 0)); + *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_UDW(base, 0)); *cs++ = upper_32_bits(pd_daddr); - *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_LDW(engine, 0)); + *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_LDW(base, 0)); *cs++ = lower_32_bits(pd_daddr); *cs++ = MI_NOOP; @@ -1056,9 +1057,9 @@ static int emit_ppgtt_update(struct i915_request *rq, void *data) for (i = GEN8_3LVL_PDPES; i--; ) { const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i); - *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_UDW(engine, i)); + *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_UDW(base, i)); *cs++ = upper_32_bits(pd_daddr); - *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_LDW(engine, i)); + *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_LDW(base, i)); *cs++ = lower_32_bits(pd_daddr); } *cs++ = MI_NOOP; @@ -1166,7 +1167,7 @@ static int gen8_modify_rpcs(struct intel_context *ce, struct intel_sseu sseu) { struct drm_i915_private *i915 = ce->engine->i915; - struct i915_request *rq, *prev; + struct i915_request *rq; intel_wakeref_t wakeref; int ret; @@ -1191,16 +1192,7 @@ gen8_modify_rpcs(struct intel_context *ce, struct intel_sseu sseu) } /* Queue this switch after all other activity by this context. */ - prev = i915_active_request_raw(&ce->ring->timeline->last_request, - &i915->drm.struct_mutex); - if (prev && !i915_request_completed(prev)) { - ret = i915_request_await_dma_fence(rq, &prev->fence); - if (ret < 0) - goto out_add; - } - - /* Order all following requests to be after. */ - ret = i915_timeline_set_barrier(ce->ring->timeline, rq); + ret = i915_active_request_set(&ce->ring->timeline->last_request, rq); if (ret) goto out_add; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 736c845eb77f..8f460cc4cc1f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1228,7 +1228,7 @@ static int gen8_init_scratch(struct i915_address_space *vm) vm->scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, - PTE_READ_ONLY); + vm->has_read_only); vm->scratch_pt = alloc_pt(vm); if (IS_ERR(vm->scratch_pt)) { @@ -1548,8 +1548,13 @@ static struct i915_hw_ppgtt *gen8_ppgtt_create(struct drm_i915_private *i915) ppgtt_init(i915, ppgtt); - /* From bdw, there is support for read-only pages in the PPGTT. */ - ppgtt->vm.has_read_only = true; + /* + * From bdw, there is hw support for read-only pages in the PPGTT. + * + * Gen11 has HSDES#:1807136187 unresolved. Disable ro support + * for now. + */ + ppgtt->vm.has_read_only = INTEL_GEN(i915) != 11; /* There are only few exceptions for gen >=6. chv and bxt. * And we are not sure about the latter so play safe for now. diff --git a/drivers/gpu/drm/i915/i915_globals.c b/drivers/gpu/drm/i915/i915_globals.c index 2f5c72e2a9d1..81e5c2ce336b 100644 --- a/drivers/gpu/drm/i915/i915_globals.c +++ b/drivers/gpu/drm/i915/i915_globals.c @@ -17,6 +17,33 @@ static LIST_HEAD(globals); +static atomic_t active; +static atomic_t epoch; +static struct park_work { + struct rcu_work work; + int epoch; +} park; + +static void i915_globals_shrink(void) +{ + struct i915_global *global; + + /* + * kmem_cache_shrink() discards empty slabs and reorders partially + * filled slabs to prioritise allocating from the mostly full slabs, + * with the aim of reducing fragmentation. + */ + list_for_each_entry(global, &globals, link) + global->shrink(); +} + +static void __i915_globals_park(struct work_struct *work) +{ + /* Confirm nothing woke up in the last grace period */ + if (park.epoch == atomic_read(&epoch)) + i915_globals_shrink(); +} + void __init i915_global_register(struct i915_global *global) { GEM_BUG_ON(!global->shrink); @@ -57,44 +84,12 @@ int __init i915_globals_init(void) } } + INIT_RCU_WORK(&park.work, __i915_globals_park); return 0; } -static void i915_globals_shrink(void) -{ - struct i915_global *global; - - /* - * kmem_cache_shrink() discards empty slabs and reorders partially - * filled slabs to prioritise allocating from the mostly full slabs, - * with the aim of reducing fragmentation. - */ - list_for_each_entry(global, &globals, link) - global->shrink(); -} - -static atomic_t active; -static atomic_t epoch; -struct park_work { - struct rcu_work work; - int epoch; -}; - -static void __i915_globals_park(struct work_struct *work) -{ - struct park_work *wrk = container_of(work, typeof(*wrk), work.work); - - /* Confirm nothing woke up in the last grace period */ - if (wrk->epoch == atomic_read(&epoch)) - i915_globals_shrink(); - - kfree(wrk); -} - void i915_globals_park(void) { - struct park_work *wrk; - /* * Defer shrinking the global slab caches (and other work) until * after a RCU grace period has completed with no activity. This @@ -107,13 +102,8 @@ void i915_globals_park(void) if (!atomic_dec_and_test(&active)) return; - wrk = kmalloc(sizeof(*wrk), GFP_KERNEL); - if (!wrk) - return; - - wrk->epoch = atomic_inc_return(&epoch); - INIT_RCU_WORK(&wrk->work, __i915_globals_park); - queue_rcu_work(system_wq, &wrk->work); + park.epoch = atomic_inc_return(&epoch); + queue_rcu_work(system_wq, &park.work); } void i915_globals_unpark(void) @@ -125,8 +115,8 @@ void i915_globals_unpark(void) void __exit i915_globals_exit(void) { /* Flush any residual park_work */ - rcu_barrier(); - flush_scheduled_work(); + atomic_inc(&epoch); + flush_rcu_work(&park.work); __i915_globals_cleanup(); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index c65d45bc63ee..43b68fdc8967 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1215,20 +1215,23 @@ static void error_record_engine_registers(struct i915_gpu_state *error, ee->vm_info.gfx_mode = I915_READ(RING_MODE_GEN7(engine)); - if (IS_GEN(dev_priv, 6)) + if (IS_GEN(dev_priv, 6)) { ee->vm_info.pp_dir_base = ENGINE_READ(engine, RING_PP_DIR_BASE_READ); - else if (IS_GEN(dev_priv, 7)) + } else if (IS_GEN(dev_priv, 7)) { ee->vm_info.pp_dir_base = - ENGINE_READ(engine, RING_PP_DIR_BASE); - else if (INTEL_GEN(dev_priv) >= 8) + ENGINE_READ(engine, RING_PP_DIR_BASE); + } else if (INTEL_GEN(dev_priv) >= 8) { + u32 base = engine->mmio_base; + for (i = 0; i < 4; i++) { ee->vm_info.pdp[i] = - I915_READ(GEN8_RING_PDP_UDW(engine, i)); + I915_READ(GEN8_RING_PDP_UDW(base, i)); ee->vm_info.pdp[i] <<= 32; ee->vm_info.pdp[i] |= - I915_READ(GEN8_RING_PDP_LDW(engine, i)); + I915_READ(GEN8_RING_PDP_LDW(base, i)); } + } } } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index aa107a78cb36..d934545445e1 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -28,16 +28,19 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include <linux/sysrq.h> -#include <linux/slab.h> -#include <linux/cpuidle.h> #include <linux/circ_buf.h> -#include <drm/drm_irq.h> +#include <linux/cpuidle.h> +#include <linux/slab.h> +#include <linux/sysrq.h> + #include <drm/drm_drv.h> +#include <drm/drm_irq.h> #include <drm/i915_drm.h> + #include "i915_drv.h" #include "i915_trace.h" #include "intel_drv.h" +#include "intel_psr.h" /** * DOC: interrupt handling @@ -366,24 +369,41 @@ static i915_reg_t gen6_pm_iir(struct drm_i915_private *dev_priv) return INTEL_GEN(dev_priv) >= 8 ? GEN8_GT_IIR(2) : GEN6_PMIIR; } -static i915_reg_t gen6_pm_imr(struct drm_i915_private *dev_priv) +static void write_pm_imr(struct drm_i915_private *dev_priv) { - if (INTEL_GEN(dev_priv) >= 11) - return GEN11_GPM_WGBOXPERF_INTR_MASK; - else if (INTEL_GEN(dev_priv) >= 8) - return GEN8_GT_IMR(2); - else - return GEN6_PMIMR; + i915_reg_t reg; + u32 mask = dev_priv->pm_imr; + + if (INTEL_GEN(dev_priv) >= 11) { + reg = GEN11_GPM_WGBOXPERF_INTR_MASK; + /* pm is in upper half */ + mask = mask << 16; + } else if (INTEL_GEN(dev_priv) >= 8) { + reg = GEN8_GT_IMR(2); + } else { + reg = GEN6_PMIMR; + } + + I915_WRITE(reg, mask); + POSTING_READ(reg); } -static i915_reg_t gen6_pm_ier(struct drm_i915_private *dev_priv) +static void write_pm_ier(struct drm_i915_private *dev_priv) { - if (INTEL_GEN(dev_priv) >= 11) - return GEN11_GPM_WGBOXPERF_INTR_ENABLE; - else if (INTEL_GEN(dev_priv) >= 8) - return GEN8_GT_IER(2); - else - return GEN6_PMIER; + i915_reg_t reg; + u32 mask = dev_priv->pm_ier; + + if (INTEL_GEN(dev_priv) >= 11) { + reg = GEN11_GPM_WGBOXPERF_INTR_ENABLE; + /* pm is in upper half */ + mask = mask << 16; + } else if (INTEL_GEN(dev_priv) >= 8) { + reg = GEN8_GT_IER(2); + } else { + reg = GEN6_PMIER; + } + + I915_WRITE(reg, mask); } /** @@ -408,8 +428,7 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv, if (new_val != dev_priv->pm_imr) { dev_priv->pm_imr = new_val; - I915_WRITE(gen6_pm_imr(dev_priv), dev_priv->pm_imr); - POSTING_READ(gen6_pm_imr(dev_priv)); + write_pm_imr(dev_priv); } } @@ -450,7 +469,7 @@ static void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, u32 enable_mas lockdep_assert_held(&dev_priv->irq_lock); dev_priv->pm_ier |= enable_mask; - I915_WRITE(gen6_pm_ier(dev_priv), dev_priv->pm_ier); + write_pm_ier(dev_priv); gen6_unmask_pm_irq(dev_priv, enable_mask); /* unmask_pm_irq provides an implicit barrier (POSTING_READ) */ } @@ -461,7 +480,7 @@ static void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, u32 disable_m dev_priv->pm_ier &= ~disable_mask; __gen6_mask_pm_irq(dev_priv, disable_mask); - I915_WRITE(gen6_pm_ier(dev_priv), dev_priv->pm_ier); + write_pm_ier(dev_priv); /* though a barrier is missing here, but don't really need a one */ } @@ -1793,6 +1812,25 @@ static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, /* The RPS events need forcewake, so we add them to a work queue and mask their * IMR bits until the work is done. Other interrupts can be processed without * the work queue. */ +static void gen11_rps_irq_handler(struct drm_i915_private *i915, u32 pm_iir) +{ + struct intel_rps *rps = &i915->gt_pm.rps; + const u32 events = i915->pm_rps_events & pm_iir; + + lockdep_assert_held(&i915->irq_lock); + + if (unlikely(!events)) + return; + + gen6_mask_pm_irq(i915, events); + + if (!rps->interrupts_enabled) + return; + + rps->pm_iir |= events; + schedule_work(&rps->work); +} + static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) { struct intel_rps *rps = &dev_priv->gt_pm.rps; @@ -2946,7 +2984,7 @@ gen11_other_irq_handler(struct drm_i915_private * const i915, const u8 instance, const u16 iir) { if (instance == OTHER_GTPM_INSTANCE) - return gen6_rps_irq_handler(i915, iir); + return gen11_rps_irq_handler(i915, iir); WARN_ONCE(1, "unhandled other interrupt instance=0x%x, iir=0x%x\n", instance, iir); @@ -3003,14 +3041,8 @@ gen11_gt_bank_handler(struct drm_i915_private * const i915, intr_dw = raw_reg_read(regs, GEN11_GT_INTR_DW(bank)); - if (unlikely(!intr_dw)) { - DRM_ERROR("GT_INTR_DW%u blank!\n", bank); - return; - } - for_each_set_bit(bit, &intr_dw, 32) { - const u32 ident = gen11_gt_engine_identity(i915, - bank, bit); + const u32 ident = gen11_gt_engine_identity(i915, bank, bit); gen11_gt_identity_handler(i915, ident); } @@ -4623,6 +4655,10 @@ void intel_irq_init(struct drm_i915_private *dev_priv) GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT); + /* We share the register with other engine */ + if (INTEL_GEN(dev_priv) > 9) + GEM_WARN_ON(dev_priv->pm_rps_events & 0xffff0000); + rps->pm_intrmsk_mbz = 0; /* diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 6ffb85ddac53..f893c2cbce15 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -31,6 +31,7 @@ #include "i915_drv.h" #include "i915_globals.h" #include "i915_selftest.h" +#include "intel_fbdev.h" #define PLATFORM(x) .platform = (x) #define GEN(x) .gen = (x), .gen_mask = BIT((x) - 1) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 00e03560c4e7..c1c0f7ab03e9 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -439,8 +439,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define RING_PP_DIR_DCLV(base) _MMIO((base) + 0x220) #define PP_DIR_DCLV_2G 0xffffffff -#define GEN8_RING_PDP_UDW(engine, n) _MMIO((engine)->mmio_base + 0x270 + (n) * 8 + 4) -#define GEN8_RING_PDP_LDW(engine, n) _MMIO((engine)->mmio_base + 0x270 + (n) * 8) +#define GEN8_RING_PDP_UDW(base, n) _MMIO((base) + 0x270 + (n) * 8 + 4) +#define GEN8_RING_PDP_LDW(base, n) _MMIO((base) + 0x270 + (n) * 8) #define GEN8_R_PWR_CLK_STATE _MMIO(0x20C8) #define GEN8_RPCS_ENABLE (1 << 31) @@ -2446,8 +2446,10 @@ enum i915_power_well_id { #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 RESET_CTL_CAT_ERROR REG_BIT(2) +#define RESET_CTL_READY_TO_RESET REG_BIT(1) +#define RESET_CTL_REQUEST_RESET REG_BIT(0) + #define RING_SEMA_WAIT_POLL(base) _MMIO((base) + 0x24c) #define HSW_GTT_CACHE_EN _MMIO(0x4024) @@ -4209,42 +4211,6 @@ enum { #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) -#define _PSRCTLB (VLV_DISPLAY_BASE + 0x61090) -#define VLV_EDP_PSR_ENABLE (1 << 0) -#define VLV_EDP_PSR_RESET (1 << 1) -#define VLV_EDP_PSR_MODE_MASK (7 << 2) -#define VLV_EDP_PSR_MODE_HW_TIMER (1 << 3) -#define VLV_EDP_PSR_MODE_SW_TIMER (1 << 2) -#define VLV_EDP_PSR_SINGLE_FRAME_UPDATE (1 << 7) -#define VLV_EDP_PSR_ACTIVE_ENTRY (1 << 8) -#define VLV_EDP_PSR_SRC_TRANSMITTER_STATE (1 << 9) -#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) _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) _MMIO_PIPE(pipe, _VSCSDPA, _VSCSDPB) - -#define _PSRSTATA (VLV_DISPLAY_BASE + 0x60094) -#define _PSRSTATB (VLV_DISPLAY_BASE + 0x61094) -#define VLV_EDP_PSR_LAST_STATE_MASK (7 << 3) -#define VLV_EDP_PSR_CURR_STATE_MASK 7 -#define VLV_EDP_PSR_DISABLED (0 << 0) -#define VLV_EDP_PSR_INACTIVE (1 << 0) -#define VLV_EDP_PSR_IN_TRANS_TO_ACTIVE (2 << 0) -#define VLV_EDP_PSR_ACTIVE_NORFB_UP (3 << 0) -#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) _MMIO_PIPE(pipe, _PSRSTATA, _PSRSTATB) - /* HSW+ eDP PSR registers */ #define HSW_EDP_PSR_BASE 0x64800 #define BDW_EDP_PSR_BASE 0x6f800 @@ -8723,8 +8689,9 @@ enum { #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 GEN9_RENDER_PG_ENABLE REG_BIT(0) +#define GEN9_MEDIA_PG_ENABLE REG_BIT(1) +#define GEN11_MEDIA_SAMPLER_PG_ENABLE REG_BIT(2) #define GEN8_PUSHBUS_CONTROL _MMIO(0xA248) #define GEN8_PUSHBUS_ENABLE _MMIO(0xA250) #define GEN8_PUSHBUS_SHIFT _MMIO(0xA25C) @@ -8739,6 +8706,11 @@ enum { #define GEN6_PMIER _MMIO(0x4402C) #define GEN6_PM_MBOX_EVENT (1 << 25) #define GEN6_PM_THERMAL_EVENT (1 << 24) + +/* + * For Gen11 these are in the upper word of the GPM_WGBOXPERF + * registers. Shifting is handled on accessing the imr and ier. + */ #define GEN6_PM_RP_DOWN_TIMEOUT (1 << 6) #define GEN6_PM_RP_UP_THRESHOLD (1 << 5) #define GEN6_PM_RP_DOWN_THRESHOLD (1 << 4) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 82094b9f5ba7..b836721d3b13 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -29,10 +29,11 @@ #include <linux/sched/clock.h> #include <linux/sched/signal.h> -#include "i915_drv.h" #include "i915_active.h" +#include "i915_drv.h" #include "i915_globals.h" #include "i915_reset.h" +#include "intel_pm.h" struct execute_cb { struct list_head link; @@ -100,6 +101,7 @@ static void i915_fence_release(struct dma_fence *fence) * caught trying to reuse dead objects. */ i915_sw_fence_fini(&rq->submit); + i915_sw_fence_fini(&rq->semaphore); kmem_cache_free(global.slab_requests, rq); } @@ -551,6 +553,36 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) return NOTIFY_DONE; } +static int __i915_sw_fence_call +semaphore_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) +{ + struct i915_request *request = + container_of(fence, typeof(*request), semaphore); + + switch (state) { + case FENCE_COMPLETE: + /* + * We only check a small portion of our dependencies + * and so cannot guarantee that there remains no + * semaphore chain across all. Instead of opting + * for the full NOSEMAPHORE boost, we go for the + * smaller (but still preempting) boost of + * NEWCLIENT. This will be enough to boost over + * a busywaiting request (as that cannot be + * NEWCLIENT) without accidentally boosting + * a busywait over real work elsewhere. + */ + i915_schedule_bump_priority(request, I915_PRIORITY_NEWCLIENT); + break; + + case FENCE_FREE: + i915_request_put(request); + break; + } + + return NOTIFY_DONE; +} + static void ring_retire_requests(struct intel_ring *ring) { struct i915_request *rq, *rn; @@ -583,11 +615,6 @@ out: return kmem_cache_alloc(global.slab_requests, GFP_KERNEL); } -static int add_timeline_barrier(struct i915_request *rq) -{ - return i915_request_await_active_request(rq, &rq->timeline->barrier); -} - /** * i915_request_alloc - allocate a request structure * @@ -706,6 +733,7 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx) /* We bump the ref for the fence chain */ i915_sw_fence_init(&i915_request_get(rq)->submit, submit_notify); + i915_sw_fence_init(&i915_request_get(rq)->semaphore, semaphore_notify); i915_sched_node_init(&rq->sched); @@ -737,10 +765,6 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx) */ rq->head = rq->ring->emit; - ret = add_timeline_barrier(rq); - if (ret) - goto err_unwind; - ret = engine->request_alloc(rq); if (ret) goto err_unwind; @@ -751,7 +775,10 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx) rq->infix = rq->ring->emit; /* end of header; start of user payload */ /* Check that we didn't interrupt ourselves with a new request */ + lockdep_assert_held(&rq->timeline->mutex); GEM_BUG_ON(rq->timeline->seqno != rq->fence.seqno); + rq->cookie = lockdep_pin_lock(&rq->timeline->mutex); + return rq; err_unwind: @@ -789,6 +816,12 @@ emit_semaphore_wait(struct i915_request *to, &from->fence, 0, I915_FENCE_GFP); + err = i915_sw_fence_await_dma_fence(&to->semaphore, + &from->fence, 0, + I915_FENCE_GFP); + if (err < 0) + return err; + /* We need to pin the signaler's HWSP until we are finished reading. */ err = i915_timeline_read_hwsp(from, to, &hwsp_offset); if (err) @@ -1070,6 +1103,8 @@ void i915_request_add(struct i915_request *request) engine->name, request->fence.context, request->fence.seqno); lockdep_assert_held(&request->timeline->mutex); + lockdep_unpin_lock(&request->timeline->mutex, request->cookie); + trace_i915_request_add(request); /* @@ -1117,6 +1152,7 @@ void i915_request_add(struct i915_request *request) * run at the earliest possible convenience. */ local_bh_disable(); + i915_sw_fence_commit(&request->semaphore); rcu_read_lock(); /* RCU serialisation for set-wedged protection */ if (engine->schedule) { struct i915_sched_attr attr = request->gem_context->sched; @@ -1323,7 +1359,9 @@ long i915_request_wait(struct i915_request *rq, if (flags & I915_WAIT_PRIORITY) { if (!i915_request_started(rq) && INTEL_GEN(rq->i915) >= 6) gen6_rps_boost(rq); + local_bh_disable(); /* suspend tasklets for reprioritisation */ i915_schedule_bump_priority(rq, I915_PRIORITY_WAIT); + local_bh_enable(); /* kick tasklets en masse */ } wait.tsk = current; diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index cd6c130964cd..a982664618c2 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/drivers/gpu/drm/i915/i915_request.h @@ -26,6 +26,7 @@ #define I915_REQUEST_H #include <linux/dma-fence.h> +#include <linux/lockdep.h> #include "i915_gem.h" #include "i915_scheduler.h" @@ -121,6 +122,15 @@ struct i915_request { unsigned long rcustate; /* + * We pin the timeline->mutex while constructing the request to + * ensure that no caller accidentally drops it during construction. + * The timeline->mutex must be held to ensure that only this caller + * can use the ring and manipulate the associated timeline during + * construction. + */ + struct pin_cookie cookie; + + /* * Fences for the various phases in the request's lifetime. * * The submit fence is used to await upon all of the request's @@ -133,6 +143,7 @@ struct i915_request { struct i915_sw_dma_fence_cb dmaq; }; struct list_head execute_cb; + struct i915_sw_fence semaphore; /* * A list of everyone we wait upon, and everyone who waits upon us. diff --git a/drivers/gpu/drm/i915/i915_reset.c b/drivers/gpu/drm/i915/i915_reset.c index ddc403ee8855..bc5f9c69895e 100644 --- a/drivers/gpu/drm/i915/i915_reset.c +++ b/drivers/gpu/drm/i915/i915_reset.c @@ -18,6 +18,26 @@ /* XXX How to handle concurrent GGTT updates using tiling registers? */ #define RESET_UNDER_STOP_MACHINE 0 +static void rmw_set(struct intel_uncore *uncore, i915_reg_t reg, u32 set) +{ + intel_uncore_rmw(uncore, reg, 0, set); +} + +static void rmw_clear(struct intel_uncore *uncore, i915_reg_t reg, u32 clr) +{ + intel_uncore_rmw(uncore, reg, clr, 0); +} + +static void rmw_set_fw(struct intel_uncore *uncore, i915_reg_t reg, u32 set) +{ + intel_uncore_rmw_fw(uncore, reg, 0, set); +} + +static void rmw_clear_fw(struct intel_uncore *uncore, i915_reg_t reg, u32 clr) +{ + intel_uncore_rmw_fw(uncore, reg, clr, 0); +} + static void engine_skip_context(struct i915_request *rq) { struct intel_engine_cs *engine = rq->engine; @@ -119,7 +139,7 @@ void i915_reset_request(struct i915_request *rq, bool guilty) static void gen3_stop_engine(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = engine->i915; + struct intel_uncore *uncore = engine->uncore; const u32 base = engine->mmio_base; GEM_TRACE("%s\n", engine->name); @@ -127,20 +147,23 @@ static void gen3_stop_engine(struct intel_engine_cs *engine) if (intel_engine_stop_cs(engine)) GEM_TRACE("%s: timed out on STOP_RING\n", engine->name); - I915_WRITE_FW(RING_HEAD(base), I915_READ_FW(RING_TAIL(base))); - POSTING_READ_FW(RING_HEAD(base)); /* paranoia */ + intel_uncore_write_fw(uncore, + RING_HEAD(base), + intel_uncore_read_fw(uncore, RING_TAIL(base))); + intel_uncore_posting_read_fw(uncore, RING_HEAD(base)); /* paranoia */ - I915_WRITE_FW(RING_HEAD(base), 0); - I915_WRITE_FW(RING_TAIL(base), 0); - POSTING_READ_FW(RING_TAIL(base)); + intel_uncore_write_fw(uncore, RING_HEAD(base), 0); + intel_uncore_write_fw(uncore, RING_TAIL(base), 0); + intel_uncore_posting_read_fw(uncore, RING_TAIL(base)); /* The ring must be empty before it is disabled */ - I915_WRITE_FW(RING_CTL(base), 0); + intel_uncore_write_fw(uncore, RING_CTL(base), 0); /* Check acts as a post */ - if (I915_READ_FW(RING_HEAD(base))) + if (intel_uncore_read_fw(uncore, RING_HEAD(base))) GEM_TRACE("%s: ring head [%x] not parked\n", - engine->name, I915_READ_FW(RING_HEAD(base))); + engine->name, + intel_uncore_read_fw(uncore, RING_HEAD(base))); } static void i915_stop_engines(struct drm_i915_private *i915, @@ -203,17 +226,17 @@ static int g33_do_reset(struct drm_i915_private *i915, return wait_for_atomic(g4x_reset_complete(pdev), 50); } -static int g4x_do_reset(struct drm_i915_private *dev_priv, +static int g4x_do_reset(struct drm_i915_private *i915, intel_engine_mask_t engine_mask, unsigned int retry) { - struct pci_dev *pdev = dev_priv->drm.pdev; + struct pci_dev *pdev = i915->drm.pdev; + struct intel_uncore *uncore = &i915->uncore; int ret; /* WaVcpClkGateDisableForMediaReset:ctg,elk */ - I915_WRITE_FW(VDECCLK_GATE_D, - I915_READ(VDECCLK_GATE_D) | VCP_UNIT_CLOCK_GATE_DISABLE); - POSTING_READ_FW(VDECCLK_GATE_D); + rmw_set_fw(uncore, VDECCLK_GATE_D, VCP_UNIT_CLOCK_GATE_DISABLE); + intel_uncore_posting_read_fw(uncore, VDECCLK_GATE_D); pci_write_config_byte(pdev, I915_GDRST, GRDOM_MEDIA | GRDOM_RESET_ENABLE); @@ -234,18 +257,17 @@ static int g4x_do_reset(struct drm_i915_private *dev_priv, out: pci_write_config_byte(pdev, I915_GDRST, 0); - I915_WRITE_FW(VDECCLK_GATE_D, - I915_READ(VDECCLK_GATE_D) & ~VCP_UNIT_CLOCK_GATE_DISABLE); - POSTING_READ_FW(VDECCLK_GATE_D); + rmw_clear_fw(uncore, VDECCLK_GATE_D, VCP_UNIT_CLOCK_GATE_DISABLE); + intel_uncore_posting_read_fw(uncore, VDECCLK_GATE_D); return ret; } -static int ironlake_do_reset(struct drm_i915_private *dev_priv, +static int ironlake_do_reset(struct drm_i915_private *i915, intel_engine_mask_t engine_mask, unsigned int retry) { - struct intel_uncore *uncore = &dev_priv->uncore; + struct intel_uncore *uncore = &i915->uncore; int ret; intel_uncore_write_fw(uncore, ILK_GDSR, @@ -277,10 +299,10 @@ out: } /* Reset the hardware domains (GENX_GRDOM_*) specified by mask */ -static int gen6_hw_domain_reset(struct drm_i915_private *dev_priv, +static int gen6_hw_domain_reset(struct drm_i915_private *i915, u32 hw_domain_mask) { - struct intel_uncore *uncore = &dev_priv->uncore; + struct intel_uncore *uncore = &i915->uncore; int err; /* @@ -331,11 +353,10 @@ static int gen6_reset_engines(struct drm_i915_private *i915, return gen6_hw_domain_reset(i915, hw_mask); } -static u32 gen11_lock_sfc(struct drm_i915_private *dev_priv, - struct intel_engine_cs *engine) +static u32 gen11_lock_sfc(struct intel_engine_cs *engine) { - struct intel_uncore *uncore = &dev_priv->uncore; - u8 vdbox_sfc_access = RUNTIME_INFO(dev_priv)->vdbox_sfc_access; + struct intel_uncore *uncore = engine->uncore; + u8 vdbox_sfc_access = RUNTIME_INFO(engine->i915)->vdbox_sfc_access; i915_reg_t sfc_forced_lock, sfc_forced_lock_ack; u32 sfc_forced_lock_bit, sfc_forced_lock_ack_bit; i915_reg_t sfc_usage; @@ -382,7 +403,7 @@ static u32 gen11_lock_sfc(struct drm_i915_private *dev_priv, * ends up being locked to the engine we want to reset, we have to reset * it as well (we will unlock it once the reset sequence is completed). */ - intel_uncore_rmw_or_fw(uncore, sfc_forced_lock, sfc_forced_lock_bit); + rmw_set_fw(uncore, sfc_forced_lock, sfc_forced_lock_bit); if (__intel_wait_for_register_fw(uncore, sfc_forced_lock_ack, @@ -399,10 +420,10 @@ static u32 gen11_lock_sfc(struct drm_i915_private *dev_priv, return 0; } -static void gen11_unlock_sfc(struct drm_i915_private *dev_priv, - struct intel_engine_cs *engine) +static void gen11_unlock_sfc(struct intel_engine_cs *engine) { - u8 vdbox_sfc_access = RUNTIME_INFO(dev_priv)->vdbox_sfc_access; + struct intel_uncore *uncore = engine->uncore; + u8 vdbox_sfc_access = RUNTIME_INFO(engine->i915)->vdbox_sfc_access; i915_reg_t sfc_forced_lock; u32 sfc_forced_lock_bit; @@ -424,8 +445,7 @@ static void gen11_unlock_sfc(struct drm_i915_private *dev_priv, return; } - I915_WRITE_FW(sfc_forced_lock, - I915_READ_FW(sfc_forced_lock) & ~sfc_forced_lock_bit); + rmw_clear_fw(uncore, sfc_forced_lock, sfc_forced_lock_bit); } static int gen11_reset_engines(struct drm_i915_private *i915, @@ -454,7 +474,7 @@ static int gen11_reset_engines(struct drm_i915_private *i915, for_each_engine_masked(engine, i915, engine_mask, tmp) { GEM_BUG_ON(engine->id >= ARRAY_SIZE(hw_engine_mask)); hw_mask |= hw_engine_mask[engine->id]; - hw_mask |= gen11_lock_sfc(i915, engine); + hw_mask |= gen11_lock_sfc(engine); } } @@ -462,37 +482,53 @@ static int gen11_reset_engines(struct drm_i915_private *i915, if (engine_mask != ALL_ENGINES) for_each_engine_masked(engine, i915, engine_mask, tmp) - gen11_unlock_sfc(i915, engine); + gen11_unlock_sfc(engine); return ret; } static int gen8_engine_reset_prepare(struct intel_engine_cs *engine) { - struct intel_uncore *uncore = &engine->i915->uncore; + struct intel_uncore *uncore = engine->uncore; + const i915_reg_t reg = RING_RESET_CTL(engine->mmio_base); + u32 request, mask, ack; int ret; - intel_uncore_write_fw(uncore, RING_RESET_CTL(engine->mmio_base), - _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET)); + ack = intel_uncore_read_fw(uncore, reg); + if (ack & RESET_CTL_CAT_ERROR) { + /* + * For catastrophic errors, ready-for-reset sequence + * needs to be bypassed: HAS#396813 + */ + request = RESET_CTL_CAT_ERROR; + mask = RESET_CTL_CAT_ERROR; + + /* Catastrophic errors need to be cleared by HW */ + ack = 0; + } else if (!(ack & RESET_CTL_READY_TO_RESET)) { + request = RESET_CTL_REQUEST_RESET; + mask = RESET_CTL_READY_TO_RESET; + ack = RESET_CTL_READY_TO_RESET; + } else { + return 0; + } - ret = __intel_wait_for_register_fw(uncore, - RING_RESET_CTL(engine->mmio_base), - RESET_CTL_READY_TO_RESET, - RESET_CTL_READY_TO_RESET, - 700, 0, - NULL); + intel_uncore_write_fw(uncore, reg, _MASKED_BIT_ENABLE(request)); + ret = __intel_wait_for_register_fw(uncore, reg, mask, ack, + 700, 0, NULL); if (ret) - DRM_ERROR("%s: reset request timeout\n", engine->name); + DRM_ERROR("%s reset request timed out: {request: %08x, RESET_CTL: %08x}\n", + engine->name, request, + intel_uncore_read_fw(uncore, reg)); return ret; } static void gen8_engine_reset_cancel(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = engine->i915; - - I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base), - _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET)); + intel_uncore_write_fw(engine->uncore, + RING_RESET_CTL(engine->mmio_base), + _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET)); } static int gen8_reset_engines(struct drm_i915_private *i915, @@ -647,7 +683,7 @@ static void reset_prepare_engine(struct intel_engine_cs *engine) * written to the powercontext is undefined and so we may lose * GPU state upon resume, i.e. fail to restart after a reset. */ - intel_uncore_forcewake_get(&engine->i915->uncore, FORCEWAKE_ALL); + intel_uncore_forcewake_get(engine->uncore, FORCEWAKE_ALL); engine->reset.prepare(engine); } @@ -719,7 +755,7 @@ static int gt_reset(struct drm_i915_private *i915, static void reset_finish_engine(struct intel_engine_cs *engine) { engine->reset.finish(engine); - intel_uncore_forcewake_put(&engine->i915->uncore, FORCEWAKE_ALL); + intel_uncore_forcewake_put(engine->uncore, FORCEWAKE_ALL); } struct i915_gpu_restart { @@ -1176,49 +1212,49 @@ static void i915_reset_device(struct drm_i915_private *i915, kobject_uevent_env(kobj, KOBJ_CHANGE, reset_done_event); } -static void clear_register(struct drm_i915_private *dev_priv, i915_reg_t reg) +static void clear_register(struct intel_uncore *uncore, i915_reg_t reg) { - I915_WRITE(reg, I915_READ(reg)); + intel_uncore_rmw(uncore, reg, 0, 0); } -void i915_clear_error_registers(struct drm_i915_private *dev_priv) +void i915_clear_error_registers(struct drm_i915_private *i915) { + struct intel_uncore *uncore = &i915->uncore; u32 eir; - if (!IS_GEN(dev_priv, 2)) - clear_register(dev_priv, PGTBL_ER); + if (!IS_GEN(i915, 2)) + clear_register(uncore, PGTBL_ER); - if (INTEL_GEN(dev_priv) < 4) - clear_register(dev_priv, IPEIR(RENDER_RING_BASE)); + if (INTEL_GEN(i915) < 4) + clear_register(uncore, IPEIR(RENDER_RING_BASE)); else - clear_register(dev_priv, IPEIR_I965); + clear_register(uncore, IPEIR_I965); - clear_register(dev_priv, EIR); - eir = I915_READ(EIR); + clear_register(uncore, EIR); + eir = intel_uncore_read(uncore, EIR); if (eir) { /* * some errors might have become stuck, * mask them. */ DRM_DEBUG_DRIVER("EIR stuck: 0x%08x, masking\n", eir); - I915_WRITE(EMR, I915_READ(EMR) | eir); - I915_WRITE(IIR, I915_MASTER_ERROR_INTERRUPT); + rmw_set(uncore, EMR, eir); + intel_uncore_write(uncore, IIR, I915_MASTER_ERROR_INTERRUPT); } - if (INTEL_GEN(dev_priv) >= 8) { - I915_WRITE(GEN8_RING_FAULT_REG, - I915_READ(GEN8_RING_FAULT_REG) & ~RING_FAULT_VALID); - POSTING_READ(GEN8_RING_FAULT_REG); - } else if (INTEL_GEN(dev_priv) >= 6) { + if (INTEL_GEN(i915) >= 8) { + rmw_clear(uncore, GEN8_RING_FAULT_REG, RING_FAULT_VALID); + intel_uncore_posting_read(uncore, GEN8_RING_FAULT_REG); + } else if (INTEL_GEN(i915) >= 6) { struct intel_engine_cs *engine; enum intel_engine_id id; - for_each_engine(engine, dev_priv, id) { - I915_WRITE(RING_FAULT_REG(engine), - I915_READ(RING_FAULT_REG(engine)) & - ~RING_FAULT_VALID); + for_each_engine(engine, i915, id) { + rmw_clear(uncore, + RING_FAULT_REG(engine), RING_FAULT_VALID); + intel_uncore_posting_read(uncore, + RING_FAULT_REG(engine)); } - POSTING_READ(RING_FAULT_REG(dev_priv->engine[RCS0])); } } diff --git a/drivers/gpu/drm/i915/i915_reset.h b/drivers/gpu/drm/i915/i915_reset.h index 86b1ac8116ce..3c0450289b8f 100644 --- a/drivers/gpu/drm/i915/i915_reset.h +++ b/drivers/gpu/drm/i915/i915_reset.h @@ -14,6 +14,7 @@ #include "intel_engine_types.h" struct drm_i915_private; +struct i915_request; struct intel_engine_cs; struct intel_guc; diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c index 77dbf7d74e12..39bc4f54e272 100644 --- a/drivers/gpu/drm/i915/i915_scheduler.c +++ b/drivers/gpu/drm/i915/i915_scheduler.c @@ -64,7 +64,7 @@ bool __i915_sched_node_add_dependency(struct i915_sched_node *node, { bool ret = false; - spin_lock(&schedule_lock); + spin_lock_irq(&schedule_lock); if (!node_signaled(signal)) { INIT_LIST_HEAD(&dep->dfs_link); @@ -81,7 +81,7 @@ bool __i915_sched_node_add_dependency(struct i915_sched_node *node, ret = true; } - spin_unlock(&schedule_lock); + spin_unlock_irq(&schedule_lock); return ret; } @@ -108,7 +108,7 @@ void i915_sched_node_fini(struct i915_sched_node *node) GEM_BUG_ON(!list_empty(&node->link)); - spin_lock(&schedule_lock); + spin_lock_irq(&schedule_lock); /* * Everyone we depended upon (the fences we wait to be signaled) @@ -135,7 +135,7 @@ void i915_sched_node_fini(struct i915_sched_node *node) i915_dependency_free(dep); } - spin_unlock(&schedule_lock); + spin_unlock_irq(&schedule_lock); } static inline struct i915_priolist *to_priolist(struct rb_node *rb) @@ -356,7 +356,7 @@ static void __i915_schedule(struct i915_request *rq, memset(&cache, 0, sizeof(cache)); engine = rq->engine; - spin_lock_irq(&engine->timeline.lock); + spin_lock(&engine->timeline.lock); /* Fifo and depth-first replacement ensure our deps execute before us */ list_for_each_entry_safe_reverse(dep, p, &dfs, dfs_link) { @@ -407,32 +407,33 @@ static void __i915_schedule(struct i915_request *rq, tasklet_hi_schedule(&engine->execlists.tasklet); } - spin_unlock_irq(&engine->timeline.lock); + spin_unlock(&engine->timeline.lock); } void i915_schedule(struct i915_request *rq, const struct i915_sched_attr *attr) { - spin_lock(&schedule_lock); + spin_lock_irq(&schedule_lock); __i915_schedule(rq, attr); - spin_unlock(&schedule_lock); + spin_unlock_irq(&schedule_lock); } void i915_schedule_bump_priority(struct i915_request *rq, unsigned int bump) { struct i915_sched_attr attr; + unsigned long flags; GEM_BUG_ON(bump & ~I915_PRIORITY_MASK); if (READ_ONCE(rq->sched.attr.priority) == I915_PRIORITY_INVALID) return; - spin_lock_bh(&schedule_lock); + spin_lock_irqsave(&schedule_lock, flags); attr = rq->sched.attr; attr.priority |= bump; __i915_schedule(rq, &attr); - spin_unlock_bh(&schedule_lock); + spin_unlock_irqrestore(&schedule_lock, flags); } void __i915_priolist_free(struct i915_priolist *p) diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index d2f2a9c2fabd..95f3dab1b229 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -25,8 +25,10 @@ */ #include <drm/i915_drm.h> -#include "intel_drv.h" + #include "i915_reg.h" +#include "intel_drv.h" +#include "intel_fbc.h" static void i915_save_display(struct drm_i915_private *dev_priv) { diff --git a/drivers/gpu/drm/i915/i915_timeline.c b/drivers/gpu/drm/i915/i915_timeline.c index 2f4907364920..5fbea0892f33 100644 --- a/drivers/gpu/drm/i915/i915_timeline.c +++ b/drivers/gpu/drm/i915/i915_timeline.c @@ -253,7 +253,6 @@ int i915_timeline_init(struct drm_i915_private *i915, spin_lock_init(&timeline->lock); mutex_init(&timeline->mutex); - INIT_ACTIVE_REQUEST(&timeline->barrier); INIT_ACTIVE_REQUEST(&timeline->last_request); INIT_LIST_HEAD(&timeline->requests); @@ -326,7 +325,6 @@ void i915_timeline_fini(struct i915_timeline *timeline) { GEM_BUG_ON(timeline->pin_count); GEM_BUG_ON(!list_empty(&timeline->requests)); - GEM_BUG_ON(i915_active_request_isset(&timeline->barrier)); i915_syncmap_free(&timeline->sync); diff --git a/drivers/gpu/drm/i915/i915_timeline.h b/drivers/gpu/drm/i915/i915_timeline.h index 4ca7f80bdf6d..27668a1a69a3 100644 --- a/drivers/gpu/drm/i915/i915_timeline.h +++ b/drivers/gpu/drm/i915/i915_timeline.h @@ -110,19 +110,4 @@ void i915_timelines_init(struct drm_i915_private *i915); void i915_timelines_park(struct drm_i915_private *i915); void i915_timelines_fini(struct drm_i915_private *i915); -/** - * i915_timeline_set_barrier - orders submission between different timelines - * @timeline: timeline to set the barrier on - * @rq: request after which new submissions can proceed - * - * Sets the passed in request as the serialization point for all subsequent - * submissions on @timeline. Subsequent requests will not be submitted to GPU - * until the barrier has been completed. - */ -static inline int -i915_timeline_set_barrier(struct i915_timeline *tl, struct i915_request *rq) -{ - return i915_active_request_set(&tl->barrier, rq); -} - #endif diff --git a/drivers/gpu/drm/i915/i915_timeline_types.h b/drivers/gpu/drm/i915/i915_timeline_types.h index 1f5b55d9ffb5..5256a0b5c5f7 100644 --- a/drivers/gpu/drm/i915/i915_timeline_types.h +++ b/drivers/gpu/drm/i915/i915_timeline_types.h @@ -61,16 +61,6 @@ struct i915_timeline { */ struct i915_syncmap *sync; - /** - * Barrier provides the ability to serialize ordering between different - * timelines. - * - * Users can call i915_timeline_set_barrier which will make all - * subsequent submissions to this timeline be executed only after the - * barrier has been completed. - */ - struct i915_active_request barrier; - struct list_head link; struct drm_i915_private *i915; diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c index b67ffaa283dc..9d962ea1e635 100644 --- a/drivers/gpu/drm/i915/icl_dsi.c +++ b/drivers/gpu/drm/i915/icl_dsi.c @@ -25,9 +25,13 @@ * Jani Nikula <[email protected]> */ -#include <drm/drm_mipi_dsi.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_mipi_dsi.h> + +#include "intel_connector.h" +#include "intel_ddi.h" #include "intel_dsi.h" +#include "intel_panel.h" static inline int header_credits_available(struct drm_i915_private *dev_priv, enum transcoder dsi_trans) @@ -323,6 +327,21 @@ static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder) } } +static void get_dsi_io_power_domains(struct drm_i915_private *dev_priv, + struct intel_dsi *intel_dsi) +{ + enum port port; + + for_each_dsi_port(port, intel_dsi->ports) { + WARN_ON(intel_dsi->io_wakeref[port]); + intel_dsi->io_wakeref[port] = + intel_display_power_get(dev_priv, + port == PORT_A ? + POWER_DOMAIN_PORT_DDI_A_IO : + POWER_DOMAIN_PORT_DDI_B_IO); + } +} + static void gen11_dsi_enable_io_power(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); @@ -336,13 +355,7 @@ static void gen11_dsi_enable_io_power(struct intel_encoder *encoder) I915_WRITE(ICL_DSI_IO_MODECTL(port), tmp); } - for_each_dsi_port(port, intel_dsi->ports) { - intel_dsi->io_wakeref[port] = - intel_display_power_get(dev_priv, - port == PORT_A ? - POWER_DOMAIN_PORT_DDI_A_IO : - POWER_DOMAIN_PORT_DDI_B_IO); - } + get_dsi_io_power_domains(dev_priv, intel_dsi); } static void gen11_dsi_power_up_lanes(struct intel_encoder *encoder) @@ -589,6 +602,12 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder, val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port); } I915_WRITE(DPCLKA_CFGCR0_ICL, val); + + for_each_dsi_port(port, intel_dsi->ports) { + val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port); + } + I915_WRITE(DPCLKA_CFGCR0_ICL, val); + POSTING_READ(DPCLKA_CFGCR0_ICL); mutex_unlock(&dev_priv->dpll_lock); @@ -1119,7 +1138,7 @@ static void gen11_dsi_disable_port(struct intel_encoder *encoder) DRM_ERROR("DDI port:%c buffer not idle\n", port_name(port)); } - gen11_dsi_ungate_clocks(encoder); + gen11_dsi_gate_clocks(encoder); } static void gen11_dsi_disable_io_power(struct intel_encoder *encoder) @@ -1133,13 +1152,11 @@ static void gen11_dsi_disable_io_power(struct intel_encoder *encoder) intel_wakeref_t wakeref; wakeref = fetch_and_zero(&intel_dsi->io_wakeref[port]); - if (wakeref) { - intel_display_power_put(dev_priv, - port == PORT_A ? - POWER_DOMAIN_PORT_DDI_A_IO : - POWER_DOMAIN_PORT_DDI_B_IO, - wakeref); - } + intel_display_power_put(dev_priv, + port == PORT_A ? + POWER_DOMAIN_PORT_DDI_A_IO : + POWER_DOMAIN_PORT_DDI_B_IO, + wakeref); } /* set mode to DDI */ @@ -1219,20 +1236,11 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder, return 0; } -static u64 gen11_dsi_get_power_domains(struct intel_encoder *encoder, - struct intel_crtc_state *crtc_state) +static void gen11_dsi_get_power_domains(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) { - struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); - u64 domains = 0; - enum port port; - - for_each_dsi_port(port, intel_dsi->ports) - if (port == PORT_A) - domains |= BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO); - else - domains |= BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO); - - return domains; + get_dsi_io_power_domains(to_i915(encoder->base.dev), + enc_to_intel_dsi(&encoder->base)); } static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index b844e8840c6f..8c8fae32ec50 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -35,6 +35,8 @@ #include <drm/drm_plane_helper.h> #include "intel_drv.h" +#include "intel_hdcp.h" +#include "intel_sprite.h" /** * intel_digital_connector_atomic_get_property - hook for connector->atomic_get_property. diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index 9d32a6fcf840..d11681d71add 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -35,7 +35,10 @@ #include <drm/drm_fourcc.h> #include <drm/drm_plane_helper.h> +#include "intel_atomic_plane.h" #include "intel_drv.h" +#include "intel_pm.h" +#include "intel_sprite.h" struct intel_plane *intel_plane_alloc(void) { diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.h b/drivers/gpu/drm/i915/intel_atomic_plane.h new file mode 100644 index 000000000000..14678620440f --- /dev/null +++ b/drivers/gpu/drm/i915/intel_atomic_plane.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_ATOMIC_PLANE_H__ +#define __INTEL_ATOMIC_PLANE_H__ + +struct drm_plane; +struct intel_atomic_state; +struct intel_crtc; +struct intel_crtc_state; +struct intel_plane; +struct intel_plane_state; + +extern const struct drm_plane_helper_funcs intel_plane_helper_funcs; + +void intel_update_plane(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state); +void intel_update_slave(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state); +void intel_disable_plane(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state); +struct intel_plane *intel_plane_alloc(void); +void intel_plane_free(struct intel_plane *plane); +struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane); +void intel_plane_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state); +void skl_update_planes_on_crtc(struct intel_atomic_state *state, + struct intel_crtc *crtc); +void i9xx_update_planes_on_crtc(struct intel_atomic_state *state, + struct intel_crtc *crtc); +int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state, + struct intel_crtc_state *crtc_state, + const struct intel_plane_state *old_plane_state, + struct intel_plane_state *intel_state); + +#endif /* __INTEL_ATOMIC_PLANE_H__ */ diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 20324b0d34c7..bca4cc025d3d 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -21,14 +21,16 @@ * DEALINGS IN THE SOFTWARE. */ -#include <linux/kernel.h> #include <linux/component.h> +#include <linux/kernel.h> + +#include <drm/drm_edid.h> #include <drm/i915_component.h> #include <drm/intel_lpe_audio.h> -#include "intel_drv.h" -#include <drm/drm_edid.h> #include "i915_drv.h" +#include "intel_audio.h" +#include "intel_drv.h" /** * DOC: High Definition Audio over HDMI and Display Port @@ -1045,7 +1047,7 @@ static const struct component_ops i915_audio_component_bind_ops = { * We ignore any error during registration and continue with reduced * functionality (i.e. without HDMI audio). */ -void i915_audio_component_init(struct drm_i915_private *dev_priv) +static void i915_audio_component_init(struct drm_i915_private *dev_priv) { int ret; @@ -1068,7 +1070,7 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv) * Deregisters the audio component, breaking any existing binding to the * corresponding snd_hda_intel driver's master component. */ -void i915_audio_component_cleanup(struct drm_i915_private *dev_priv) +static void i915_audio_component_cleanup(struct drm_i915_private *dev_priv) { if (!dev_priv->audio_component_registered) return; diff --git a/drivers/gpu/drm/i915/intel_audio.h b/drivers/gpu/drm/i915/intel_audio.h new file mode 100644 index 000000000000..a3657c7a7ba2 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_audio.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_AUDIO_H__ +#define __INTEL_AUDIO_H__ + +struct drm_connector_state; +struct drm_i915_private; +struct intel_crtc_state; +struct intel_encoder; + +void intel_init_audio_hooks(struct drm_i915_private *dev_priv); +void intel_audio_codec_enable(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state); +void intel_audio_codec_disable(struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state); +void intel_audio_init(struct drm_i915_private *dev_priv); +void intel_audio_deinit(struct drm_i915_private *dev_priv); + +#endif /* __INTEL_AUDIO_H__ */ diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index 09ed90c0ba00..3cbffd400b1b 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c @@ -27,8 +27,6 @@ #include "i915_drv.h" -#define task_asleep(tsk) ((tsk)->state & TASK_NORMAL && !(tsk)->on_rq) - static void irq_enable(struct intel_engine_cs *engine) { if (!engine->irq_enable) @@ -82,7 +80,7 @@ static inline bool __request_completed(const struct i915_request *rq) return i915_seqno_passed(__hwsp_seqno(rq), rq->fence.seqno); } -bool intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine) +void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine) { struct intel_breadcrumbs *b = &engine->breadcrumbs; struct intel_context *ce, *cn; @@ -146,19 +144,13 @@ bool intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine) dma_fence_signal(&rq->fence); i915_request_put(rq); } - - return !list_empty(&signal); } -bool intel_engine_signal_breadcrumbs(struct intel_engine_cs *engine) +void intel_engine_signal_breadcrumbs(struct intel_engine_cs *engine) { - bool result; - local_irq_disable(); - result = intel_engine_breadcrumbs_irq(engine); + intel_engine_breadcrumbs_irq(engine); local_irq_enable(); - - return result; } static void signal_irq_work(struct irq_work *work) diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c index b8cd481f5e33..7f060eaf1b17 100644 --- a/drivers/gpu/drm/i915/intel_cdclk.c +++ b/drivers/gpu/drm/i915/intel_cdclk.c @@ -21,6 +21,7 @@ * DEALINGS IN THE SOFTWARE. */ +#include "intel_cdclk.h" #include "intel_drv.h" /** @@ -1128,16 +1129,7 @@ sanitize: dev_priv->cdclk.hw.vco = -1; } -/** - * skl_init_cdclk - Initialize CDCLK on SKL - * @dev_priv: i915 device - * - * Initialize CDCLK for SKL and derivatives. This is generally - * done only during the display core initialization sequence, - * after which the DMC will take care of turning CDCLK off/on - * as needed. - */ -void skl_init_cdclk(struct drm_i915_private *dev_priv) +static void skl_init_cdclk(struct drm_i915_private *dev_priv) { struct intel_cdclk_state cdclk_state; @@ -1166,14 +1158,7 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv) skl_set_cdclk(dev_priv, &cdclk_state, INVALID_PIPE); } -/** - * skl_uninit_cdclk - Uninitialize CDCLK on SKL - * @dev_priv: i915 device - * - * Uninitialize CDCLK for SKL and derivatives. This is done only - * during the display core uninitialization sequence. - */ -void skl_uninit_cdclk(struct drm_i915_private *dev_priv) +static void skl_uninit_cdclk(struct drm_i915_private *dev_priv) { struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw; @@ -1498,16 +1483,7 @@ sanitize: dev_priv->cdclk.hw.vco = -1; } -/** - * bxt_init_cdclk - Initialize CDCLK on BXT - * @dev_priv: i915 device - * - * Initialize CDCLK for BXT and derivatives. This is generally - * done only during the display core initialization sequence, - * after which the DMC will take care of turning CDCLK off/on - * as needed. - */ -void bxt_init_cdclk(struct drm_i915_private *dev_priv) +static void bxt_init_cdclk(struct drm_i915_private *dev_priv) { struct intel_cdclk_state cdclk_state; @@ -1536,14 +1512,7 @@ void bxt_init_cdclk(struct drm_i915_private *dev_priv) bxt_set_cdclk(dev_priv, &cdclk_state, INVALID_PIPE); } -/** - * bxt_uninit_cdclk - Uninitialize CDCLK on BXT - * @dev_priv: i915 device - * - * Uninitialize CDCLK for BXT and derivatives. This is done only - * during the display core uninitialization sequence. - */ -void bxt_uninit_cdclk(struct drm_i915_private *dev_priv) +static void bxt_uninit_cdclk(struct drm_i915_private *dev_priv) { struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw; @@ -1976,16 +1945,7 @@ out: icl_calc_voltage_level(cdclk_state->cdclk); } -/** - * icl_init_cdclk - Initialize CDCLK on ICL - * @dev_priv: i915 device - * - * Initialize CDCLK for ICL. This consists mainly of initializing - * dev_priv->cdclk.hw and sanitizing the state of the hardware if needed. This - * is generally done only during the display core initialization sequence, after - * which the DMC will take care of turning CDCLK off/on as needed. - */ -void icl_init_cdclk(struct drm_i915_private *dev_priv) +static void icl_init_cdclk(struct drm_i915_private *dev_priv) { struct intel_cdclk_state sanitized_state; u32 val; @@ -2022,14 +1982,7 @@ sanitize: icl_set_cdclk(dev_priv, &sanitized_state, INVALID_PIPE); } -/** - * icl_uninit_cdclk - Uninitialize CDCLK on ICL - * @dev_priv: i915 device - * - * Uninitialize CDCLK for ICL. This is done only during the display core - * uninitialization sequence. - */ -void icl_uninit_cdclk(struct drm_i915_private *dev_priv) +static void icl_uninit_cdclk(struct drm_i915_private *dev_priv) { struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw; @@ -2040,16 +1993,7 @@ void icl_uninit_cdclk(struct drm_i915_private *dev_priv) icl_set_cdclk(dev_priv, &cdclk_state, INVALID_PIPE); } -/** - * cnl_init_cdclk - Initialize CDCLK on CNL - * @dev_priv: i915 device - * - * Initialize CDCLK for CNL. This is generally - * done only during the display core initialization sequence, - * after which the DMC will take care of turning CDCLK off/on - * as needed. - */ -void cnl_init_cdclk(struct drm_i915_private *dev_priv) +static void cnl_init_cdclk(struct drm_i915_private *dev_priv) { struct intel_cdclk_state cdclk_state; @@ -2068,14 +2012,7 @@ void cnl_init_cdclk(struct drm_i915_private *dev_priv) cnl_set_cdclk(dev_priv, &cdclk_state, INVALID_PIPE); } -/** - * cnl_uninit_cdclk - Uninitialize CDCLK on CNL - * @dev_priv: i915 device - * - * Uninitialize CDCLK for CNL. This is done only - * during the display core uninitialization sequence. - */ -void cnl_uninit_cdclk(struct drm_i915_private *dev_priv) +static void cnl_uninit_cdclk(struct drm_i915_private *dev_priv) { struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw; @@ -2087,6 +2024,46 @@ void cnl_uninit_cdclk(struct drm_i915_private *dev_priv) } /** + * intel_cdclk_init - Initialize CDCLK + * @i915: i915 device + * + * Initialize CDCLK. This consists mainly of initializing dev_priv->cdclk.hw and + * sanitizing the state of the hardware if needed. This is generally done only + * during the display core initialization sequence, after which the DMC will + * take care of turning CDCLK off/on as needed. + */ +void intel_cdclk_init(struct drm_i915_private *i915) +{ + if (IS_ICELAKE(i915)) + icl_init_cdclk(i915); + else if (IS_CANNONLAKE(i915)) + cnl_init_cdclk(i915); + else if (IS_GEN9_BC(i915)) + skl_init_cdclk(i915); + else if (IS_GEN9_LP(i915)) + bxt_init_cdclk(i915); +} + +/** + * intel_cdclk_uninit - Uninitialize CDCLK + * @i915: i915 device + * + * Uninitialize CDCLK. This is done only during the display core + * uninitialization sequence. + */ +void intel_cdclk_uninit(struct drm_i915_private *i915) +{ + if (IS_ICELAKE(i915)) + icl_uninit_cdclk(i915); + else if (IS_CANNONLAKE(i915)) + cnl_uninit_cdclk(i915); + else if (IS_GEN9_BC(i915)) + skl_uninit_cdclk(i915); + else if (IS_GEN9_LP(i915)) + bxt_uninit_cdclk(i915); +} + +/** * intel_cdclk_needs_modeset - Determine if two CDCLK states require a modeset on all pipes * @a: first CDCLK state * @b: second CDCLK state @@ -2104,6 +2081,7 @@ bool intel_cdclk_needs_modeset(const struct intel_cdclk_state *a, /** * intel_cdclk_needs_cd2x_update - Determine if two CDCLK states require a cd2x divider update + * @dev_priv: Not a CDCLK state, it's the drm_i915_private! * @a: first CDCLK state * @b: second CDCLK state * diff --git a/drivers/gpu/drm/i915/intel_cdclk.h b/drivers/gpu/drm/i915/intel_cdclk.h new file mode 100644 index 000000000000..4d6f7f5f8930 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_cdclk.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_CDCLK_H__ +#define __INTEL_CDCLK_H__ + +#include <linux/types.h> + +#include "intel_display.h" + +struct drm_i915_private; +struct intel_atomic_state; +struct intel_cdclk_state; +struct intel_crtc_state; + +int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state); +void intel_cdclk_init(struct drm_i915_private *i915); +void intel_cdclk_uninit(struct drm_i915_private *i915); +void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv); +void intel_update_max_cdclk(struct drm_i915_private *dev_priv); +void intel_update_cdclk(struct drm_i915_private *dev_priv); +void intel_update_rawclk(struct drm_i915_private *dev_priv); +bool intel_cdclk_needs_cd2x_update(struct drm_i915_private *dev_priv, + const struct intel_cdclk_state *a, + const struct intel_cdclk_state *b); +bool intel_cdclk_needs_modeset(const struct intel_cdclk_state *a, + const struct intel_cdclk_state *b); +bool intel_cdclk_changed(const struct intel_cdclk_state *a, + const struct intel_cdclk_state *b); +void intel_cdclk_swap_state(struct intel_atomic_state *state); +void +intel_set_cdclk_pre_plane_update(struct drm_i915_private *dev_priv, + const struct intel_cdclk_state *old_state, + const struct intel_cdclk_state *new_state, + enum pipe pipe); +void +intel_set_cdclk_post_plane_update(struct drm_i915_private *dev_priv, + const struct intel_cdclk_state *old_state, + const struct intel_cdclk_state *new_state, + enum pipe pipe); +void intel_dump_cdclk_state(const struct intel_cdclk_state *cdclk_state, + const char *context); + +#endif /* __INTEL_CDCLK_H__ */ diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c index 60f21a1fdbbe..ca341a9e47e6 100644 --- a/drivers/gpu/drm/i915/intel_color.c +++ b/drivers/gpu/drm/i915/intel_color.c @@ -22,6 +22,7 @@ * */ +#include "intel_color.h" #include "intel_drv.h" #define CTM_COEFF_SIGN (1ULL << 63) diff --git a/drivers/gpu/drm/i915/intel_color.h b/drivers/gpu/drm/i915/intel_color.h new file mode 100644 index 000000000000..b8a3ce609587 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_color.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_COLOR_H__ +#define __INTEL_COLOR_H__ + +struct intel_crtc_state; +struct intel_crtc; + +void intel_color_init(struct intel_crtc *crtc); +int intel_color_check(struct intel_crtc_state *crtc_state); +void intel_color_commit(const struct intel_crtc_state *crtc_state); +void intel_color_load_luts(const struct intel_crtc_state *crtc_state); + +#endif /* __INTEL_COLOR_H__ */ diff --git a/drivers/gpu/drm/i915/intel_combo_phy.c b/drivers/gpu/drm/i915/intel_combo_phy.c index 3d0271cebf99..2bf4359d7e41 100644 --- a/drivers/gpu/drm/i915/intel_combo_phy.c +++ b/drivers/gpu/drm/i915/intel_combo_phy.c @@ -239,7 +239,8 @@ void icl_combo_phys_uninit(struct drm_i915_private *dev_priv) for_each_combo_port_reverse(dev_priv, port) { u32 val; - if (!icl_combo_phy_verify_state(dev_priv, port)) + if (port == PORT_A && + !icl_combo_phy_verify_state(dev_priv, port)) DRM_WARN("Port %c combo PHY HW state changed unexpectedly\n", port_name(port)); diff --git a/drivers/gpu/drm/i915/intel_connector.c b/drivers/gpu/drm/i915/intel_connector.c index 848dd9e728d8..073b6c3ab7cc 100644 --- a/drivers/gpu/drm/i915/intel_connector.c +++ b/drivers/gpu/drm/i915/intel_connector.c @@ -23,12 +23,17 @@ * DEALINGS IN THE SOFTWARE. */ -#include <linux/slab.h> #include <linux/i2c.h> +#include <linux/slab.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_edid.h> -#include "intel_drv.h" + #include "i915_drv.h" +#include "intel_connector.h" +#include "intel_drv.h" +#include "intel_hdcp.h" +#include "intel_panel.h" int intel_connector_init(struct intel_connector *connector) { diff --git a/drivers/gpu/drm/i915/intel_connector.h b/drivers/gpu/drm/i915/intel_connector.h new file mode 100644 index 000000000000..93a7375c8196 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_connector.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_CONNECTOR_H__ +#define __INTEL_CONNECTOR_H__ + +#include "intel_display.h" + +struct drm_connector; +struct edid; +struct i2c_adapter; +struct intel_connector; +struct intel_encoder; + +int intel_connector_init(struct intel_connector *connector); +struct intel_connector *intel_connector_alloc(void); +void intel_connector_free(struct intel_connector *connector); +void intel_connector_destroy(struct drm_connector *connector); +int intel_connector_register(struct drm_connector *connector); +void intel_connector_unregister(struct drm_connector *connector); +void intel_connector_attach_encoder(struct intel_connector *connector, + struct intel_encoder *encoder); +bool intel_connector_get_hw_state(struct intel_connector *connector); +enum pipe intel_connector_get_pipe(struct intel_connector *connector); +int intel_connector_update_modes(struct drm_connector *connector, + struct edid *edid); +int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); +void intel_attach_force_audio_property(struct drm_connector *connector); +void intel_attach_broadcast_rgb_property(struct drm_connector *connector); +void intel_attach_aspect_ratio_property(struct drm_connector *connector); +void intel_attach_colorspace_property(struct drm_connector *connector); + +#endif /* __INTEL_CONNECTOR_H__ */ diff --git a/drivers/gpu/drm/i915/intel_context_types.h b/drivers/gpu/drm/i915/intel_context_types.h index 624729a35875..68b4ca1611e0 100644 --- a/drivers/gpu/drm/i915/intel_context_types.h +++ b/drivers/gpu/drm/i915/intel_context_types.h @@ -24,6 +24,7 @@ struct intel_context_ops { int (*pin)(struct intel_context *ce); void (*unpin)(struct intel_context *ce); + void (*reset)(struct intel_context *ce); void (*destroy)(struct kref *kref); }; diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 50530e49982c..b665c370111b 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -27,13 +27,18 @@ #include <linux/dmi.h> #include <linux/i2c.h> #include <linux/slab.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_edid.h> #include <drm/drm_probe_helper.h> -#include "intel_drv.h" #include <drm/i915_drm.h> + #include "i915_drv.h" +#include "intel_connector.h" +#include "intel_crt.h" +#include "intel_ddi.h" +#include "intel_drv.h" /* Here's the desired hotplug mode */ #define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_PERIOD_128 | \ diff --git a/drivers/gpu/drm/i915/intel_crt.h b/drivers/gpu/drm/i915/intel_crt.h new file mode 100644 index 000000000000..1b3fba359efc --- /dev/null +++ b/drivers/gpu/drm/i915/intel_crt.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_CRT_H__ +#define __INTEL_CRT_H__ + +#include "i915_reg.h" + +enum pipe; +struct drm_encoder; +struct drm_i915_private; +struct drm_i915_private; + +bool intel_crt_port_enabled(struct drm_i915_private *dev_priv, + i915_reg_t adpa_reg, enum pipe *pipe); +void intel_crt_init(struct drm_i915_private *dev_priv); +void intel_crt_reset(struct drm_encoder *encoder); + +#endif /* __INTEL_CRT_H__ */ diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 862a8f686ef5..f43c2a2563a5 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -21,9 +21,12 @@ * IN THE SOFTWARE. * */ + #include <linux/firmware.h> + #include "i915_drv.h" #include "i915_reg.h" +#include "intel_csr.h" /** * DOC: csr support for dmc diff --git a/drivers/gpu/drm/i915/intel_csr.h b/drivers/gpu/drm/i915/intel_csr.h new file mode 100644 index 000000000000..17a32c1e8a35 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_csr.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_CSR_H__ +#define __INTEL_CSR_H__ + +struct drm_i915_private; + +void intel_csr_ucode_init(struct drm_i915_private *i915); +void intel_csr_load_program(struct drm_i915_private *i915); +void intel_csr_ucode_fini(struct drm_i915_private *i915); +void intel_csr_ucode_suspend(struct drm_i915_private *i915); +void intel_csr_ucode_resume(struct drm_i915_private *i915); + +#endif /* __INTEL_CSR_H__ */ diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 3f1e491bd0c0..24f9106efcc6 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -26,9 +26,19 @@ */ #include <drm/drm_scdc_helper.h> + #include "i915_drv.h" +#include "intel_audio.h" +#include "intel_connector.h" +#include "intel_ddi.h" +#include "intel_dp.h" #include "intel_drv.h" #include "intel_dsi.h" +#include "intel_hdcp.h" +#include "intel_hdmi.h" +#include "intel_lspcon.h" +#include "intel_panel.h" +#include "intel_psr.h" struct ddi_buf_trans { u32 trans1; /* balance leg enable, de-emph level */ @@ -2043,12 +2053,11 @@ intel_ddi_main_link_aux_domain(struct intel_digital_port *dig_port) intel_aux_power_domain(dig_port); } -static u64 intel_ddi_get_power_domains(struct intel_encoder *encoder, - struct intel_crtc_state *crtc_state) +static void intel_ddi_get_power_domains(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_digital_port *dig_port; - u64 domains; /* * TODO: Add support for MST encoders. Atm, the following should never @@ -2056,10 +2065,10 @@ static u64 intel_ddi_get_power_domains(struct intel_encoder *encoder, * hook. */ if (WARN_ON(intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST))) - return 0; + return; dig_port = enc_to_dig_port(&encoder->base); - domains = BIT_ULL(dig_port->ddi_io_power_domain); + intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain); /* * AUX power is only needed for (e)DP mode, and for HDMI mode on TC @@ -2067,15 +2076,15 @@ static u64 intel_ddi_get_power_domains(struct intel_encoder *encoder, */ if (intel_crtc_has_dp_encoder(crtc_state) || intel_port_is_tc(dev_priv, encoder->port)) - domains |= BIT_ULL(intel_ddi_main_link_aux_domain(dig_port)); + intel_display_power_get(dev_priv, + intel_ddi_main_link_aux_domain(dig_port)); /* * VDSC power is needed when DSC is enabled */ if (crtc_state->dsc_params.compression_enable) - domains |= BIT_ULL(intel_dsc_power_domain(crtc_state)); - - return domains; + intel_display_power_get(dev_priv, + intel_dsc_power_domain(crtc_state)); } void intel_ddi_enable_pipe_clock(const struct intel_crtc_state *crtc_state) @@ -2793,10 +2802,10 @@ void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder) return; } /* - * DSI ports should have their DDI clock ungated when disabled - * and gated when enabled. + * For DSI we keep the ddi clocks gated + * except during enable/disable sequence. */ - ddi_clk_needed = !encoder->base.crtc; + ddi_clk_needed = false; } val = I915_READ(DPCLKA_CFGCR0_ICL); @@ -3848,14 +3857,16 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder, ret = intel_hdmi_compute_config(encoder, pipe_config, conn_state); else ret = intel_dp_compute_config(encoder, pipe_config, conn_state); + if (ret) + return ret; - if (IS_GEN9_LP(dev_priv) && ret) + if (IS_GEN9_LP(dev_priv)) pipe_config->lane_lat_optim_mask = bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count); intel_ddi_compute_min_voltage_level(dev_priv, pipe_config); - return ret; + return 0; } diff --git a/drivers/gpu/drm/i915/intel_ddi.h b/drivers/gpu/drm/i915/intel_ddi.h new file mode 100644 index 000000000000..9cf69175942e --- /dev/null +++ b/drivers/gpu/drm/i915/intel_ddi.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_DDI_H__ +#define __INTEL_DDI_H__ + +#include <drm/i915_drm.h> + +#include "intel_display.h" + +struct drm_connector_state; +struct drm_i915_private; +struct intel_connector; +struct intel_crtc; +struct intel_crtc_state; +struct intel_dp; +struct intel_dpll_hw_state; +struct intel_encoder; + +void intel_ddi_fdi_post_disable(struct intel_encoder *intel_encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state); +void hsw_fdi_link_train(struct intel_crtc *crtc, + const struct intel_crtc_state *crtc_state); +void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port); +bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe); +void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state); +void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state); +void intel_ddi_enable_pipe_clock(const struct intel_crtc_state *crtc_state); +void intel_ddi_disable_pipe_clock(const struct intel_crtc_state *crtc_state); +void intel_ddi_set_pipe_settings(const struct intel_crtc_state *crtc_state); +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_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config); +void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state, + bool state); +void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv, + struct intel_crtc_state *crtc_state); +u32 bxt_signal_levels(struct intel_dp *intel_dp); +u32 ddi_signal_levels(struct intel_dp *intel_dp); +u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder); +u8 intel_ddi_dp_pre_emphasis_max(struct intel_encoder *encoder, + u8 voltage_swing); +int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder, + bool enable); +void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder); +int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv, + struct intel_dpll_hw_state *state); + +#endif /* __INTEL_DDI_H__ */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7ecfb7d98839..3bd40a4a6739 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -46,19 +46,29 @@ #include "i915_drv.h" #include "i915_gem_clflush.h" +#include "i915_reset.h" #include "i915_trace.h" +#include "intel_atomic_plane.h" +#include "intel_color.h" +#include "intel_cdclk.h" +#include "intel_crt.h" +#include "intel_ddi.h" +#include "intel_dp.h" #include "intel_drv.h" #include "intel_dsi.h" +#include "intel_dvo.h" +#include "intel_fbc.h" +#include "intel_fbdev.h" #include "intel_frontbuffer.h" - -#include "intel_drv.h" -#include "intel_dsi.h" -#include "intel_frontbuffer.h" - -#include "i915_drv.h" -#include "i915_gem_clflush.h" -#include "i915_reset.h" -#include "i915_trace.h" +#include "intel_hdcp.h" +#include "intel_hdmi.h" +#include "intel_lvds.h" +#include "intel_pipe_crc.h" +#include "intel_pm.h" +#include "intel_psr.h" +#include "intel_sdvo.h" +#include "intel_sprite.h" +#include "intel_tv.h" /* Primary plane formats for gen <= 3 */ static const u32 i8xx_primary_formats[] = { @@ -115,8 +125,8 @@ static void vlv_prepare_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config); static void chv_prepare_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config); -static void intel_begin_crtc_commit(struct drm_crtc *, struct drm_crtc_state *); -static void intel_finish_crtc_commit(struct drm_crtc *, struct drm_crtc_state *); +static void intel_begin_crtc_commit(struct intel_atomic_state *, struct intel_crtc *); +static void intel_finish_crtc_commit(struct intel_atomic_state *, struct intel_crtc *); static void intel_crtc_init_scalers(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state); static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state); @@ -467,10 +477,11 @@ static const struct intel_limit intel_limits_bxt = { }; static void -skl_wa_clkgate(struct drm_i915_private *dev_priv, int pipe, bool enable) +skl_wa_827(struct drm_i915_private *dev_priv, int pipe, bool enable) { if (enable) I915_WRITE(CLKGATE_DIS_PSL(pipe), + I915_READ(CLKGATE_DIS_PSL(pipe)) | DUPS1_GATING_DIS | DUPS2_GATING_DIS); else I915_WRITE(CLKGATE_DIS_PSL(pipe), @@ -5530,7 +5541,7 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) /* Display WA 827 */ if (needs_nv12_wa(dev_priv, old_crtc_state) && !needs_nv12_wa(dev_priv, pipe_config)) { - skl_wa_clkgate(dev_priv, crtc->pipe, false); + skl_wa_827(dev_priv, crtc->pipe, false); } } @@ -5569,7 +5580,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, /* Display WA 827 */ if (!needs_nv12_wa(dev_priv, old_crtc_state) && needs_nv12_wa(dev_priv, pipe_config)) { - skl_wa_clkgate(dev_priv, crtc->pipe, true); + skl_wa_827(dev_priv, crtc->pipe, true); } /* @@ -9754,7 +9765,8 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv, static bool hsw_get_transcoder_state(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config, - u64 *power_domain_mask) + u64 *power_domain_mask, + intel_wakeref_t *wakerefs) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -9762,6 +9774,7 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc, unsigned long panel_transcoder_mask = 0; unsigned long enabled_panel_transcoders = 0; enum transcoder panel_transcoder; + intel_wakeref_t wf; u32 tmp; if (INTEL_GEN(dev_priv) >= 11) @@ -9827,10 +9840,13 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc, enabled_panel_transcoders != BIT(TRANSCODER_EDP)); power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder); - if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) + WARN_ON(*power_domain_mask & BIT_ULL(power_domain)); + + wf = intel_display_power_get_if_enabled(dev_priv, power_domain); + if (!wf) return false; - WARN_ON(*power_domain_mask & BIT_ULL(power_domain)); + wakerefs[power_domain] = wf; *power_domain_mask |= BIT_ULL(power_domain); tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder)); @@ -9840,13 +9856,15 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc, static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config, - u64 *power_domain_mask) + u64 *power_domain_mask, + intel_wakeref_t *wakerefs) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); enum intel_display_power_domain power_domain; - enum port port; enum transcoder cpu_transcoder; + intel_wakeref_t wf; + enum port port; u32 tmp; for_each_port_masked(port, BIT(PORT_A) | BIT(PORT_C)) { @@ -9856,10 +9874,13 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc, cpu_transcoder = TRANSCODER_DSI_C; power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder); - if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) + WARN_ON(*power_domain_mask & BIT_ULL(power_domain)); + + wf = intel_display_power_get_if_enabled(dev_priv, power_domain); + if (!wf) continue; - WARN_ON(*power_domain_mask & BIT_ULL(power_domain)); + wakerefs[power_domain] = wf; *power_domain_mask |= BIT_ULL(power_domain); /* @@ -9938,6 +9959,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + intel_wakeref_t wakerefs[POWER_DOMAIN_NUM], wf; enum intel_display_power_domain power_domain; u64 power_domain_mask; bool active; @@ -9945,16 +9967,21 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, intel_crtc_init_scalers(crtc, pipe_config); power_domain = POWER_DOMAIN_PIPE(crtc->pipe); - if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) + wf = intel_display_power_get_if_enabled(dev_priv, power_domain); + if (!wf) return false; + + wakerefs[power_domain] = wf; power_domain_mask = BIT_ULL(power_domain); pipe_config->shared_dpll = NULL; - active = hsw_get_transcoder_state(crtc, pipe_config, &power_domain_mask); + active = hsw_get_transcoder_state(crtc, pipe_config, + &power_domain_mask, wakerefs); if (IS_GEN9_LP(dev_priv) && - bxt_get_dsi_transcoder_state(crtc, pipe_config, &power_domain_mask)) { + bxt_get_dsi_transcoder_state(crtc, pipe_config, + &power_domain_mask, wakerefs)) { WARN_ON(active); active = true; } @@ -9988,8 +10015,11 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, } power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe); - if (intel_display_power_get_if_enabled(dev_priv, power_domain)) { - WARN_ON(power_domain_mask & BIT_ULL(power_domain)); + WARN_ON(power_domain_mask & BIT_ULL(power_domain)); + + wf = intel_display_power_get_if_enabled(dev_priv, power_domain); + if (wf) { + wakerefs[power_domain] = wf; power_domain_mask |= BIT_ULL(power_domain); if (INTEL_GEN(dev_priv) >= 9) @@ -10021,7 +10051,8 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, out: for_each_power_domain(power_domain, power_domain_mask) - intel_display_power_put_unchecked(dev_priv, power_domain); + intel_display_power_put(dev_priv, + power_domain, wakerefs[power_domain]); return active; } @@ -13243,14 +13274,14 @@ static void intel_update_crtc(struct drm_crtc *crtc, else if (new_plane_state) intel_fbc_enable(intel_crtc, pipe_config, new_plane_state); - intel_begin_crtc_commit(crtc, old_crtc_state); + intel_begin_crtc_commit(to_intel_atomic_state(state), intel_crtc); if (INTEL_GEN(dev_priv) >= 9) skl_update_planes_on_crtc(to_intel_atomic_state(state), intel_crtc); else i9xx_update_planes_on_crtc(to_intel_atomic_state(state), intel_crtc); - intel_finish_crtc_commit(crtc, old_crtc_state); + intel_finish_crtc_commit(to_intel_atomic_state(state), intel_crtc); } static void intel_update_crtcs(struct drm_atomic_state *state) @@ -14040,39 +14071,35 @@ skl_max_scale(const struct intel_crtc_state *crtc_state, return max_scale; } -static void intel_begin_crtc_commit(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state) +static void intel_begin_crtc_commit(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_crtc_state *old_intel_cstate = - to_intel_crtc_state(old_crtc_state); - struct intel_atomic_state *old_intel_state = - to_intel_atomic_state(old_crtc_state->state); - struct intel_crtc_state *intel_cstate = - intel_atomic_get_new_crtc_state(old_intel_state, intel_crtc); - bool modeset = needs_modeset(&intel_cstate->base); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + bool modeset = needs_modeset(&new_crtc_state->base); /* Perform vblank evasion around commit operation */ - intel_pipe_update_start(intel_cstate); + intel_pipe_update_start(new_crtc_state); if (modeset) goto out; - if (intel_cstate->base.color_mgmt_changed || - intel_cstate->update_pipe) - intel_color_commit(intel_cstate); + if (new_crtc_state->base.color_mgmt_changed || + new_crtc_state->update_pipe) + intel_color_commit(new_crtc_state); - if (intel_cstate->update_pipe) - intel_update_pipe_config(old_intel_cstate, intel_cstate); + if (new_crtc_state->update_pipe) + intel_update_pipe_config(old_crtc_state, new_crtc_state); else if (INTEL_GEN(dev_priv) >= 9) - skl_detach_scalers(intel_cstate); + skl_detach_scalers(new_crtc_state); out: if (dev_priv->display.atomic_update_watermarks) - dev_priv->display.atomic_update_watermarks(old_intel_state, - intel_cstate); + dev_priv->display.atomic_update_watermarks(state, + new_crtc_state); } void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc, @@ -14091,21 +14118,20 @@ void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc, } } -static void intel_finish_crtc_commit(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state) +static void intel_finish_crtc_commit(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_atomic_state *old_intel_state = - to_intel_atomic_state(old_crtc_state->state); + struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); struct intel_crtc_state *new_crtc_state = - intel_atomic_get_new_crtc_state(old_intel_state, intel_crtc); + intel_atomic_get_new_crtc_state(state, crtc); intel_pipe_update_end(new_crtc_state); if (new_crtc_state->update_pipe && !needs_modeset(&new_crtc_state->base) && - old_crtc_state->mode.private_flags & I915_MODE_FLAG_INHERITED) - intel_crtc_arm_fifo_underrun(intel_crtc, new_crtc_state); + old_crtc_state->base.mode.private_flags & I915_MODE_FLAG_INHERITED) + intel_crtc_arm_fifo_underrun(crtc, new_crtc_state); } /** @@ -16255,8 +16281,6 @@ get_encoder_power_domains(struct drm_i915_private *dev_priv) struct intel_encoder *encoder; for_each_intel_encoder(&dev_priv->drm, encoder) { - u64 get_domains; - enum intel_display_power_domain domain; struct intel_crtc_state *crtc_state; if (!encoder->get_power_domains) @@ -16270,9 +16294,7 @@ get_encoder_power_domains(struct drm_i915_private *dev_priv) continue; crtc_state = to_intel_crtc_state(encoder->base.crtc->state); - get_domains = encoder->get_power_domains(encoder, crtc_state); - for_each_power_domain(domain, get_domains) - intel_display_power_get(dev_priv, domain); + encoder->get_power_domains(encoder, crtc_state); } } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 72c49070ed14..560274d1c50b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -25,22 +25,34 @@ * */ -#include <linux/i2c.h> -#include <linux/slab.h> #include <linux/export.h> -#include <linux/types.h> +#include <linux/i2c.h> #include <linux/notifier.h> #include <linux/reboot.h> +#include <linux/slab.h> +#include <linux/types.h> #include <asm/byteorder.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_dp_helper.h> #include <drm/drm_edid.h> #include <drm/drm_hdcp.h> #include <drm/drm_probe_helper.h> -#include "intel_drv.h" #include <drm/i915_drm.h> + #include "i915_drv.h" +#include "intel_audio.h" +#include "intel_connector.h" +#include "intel_ddi.h" +#include "intel_dp.h" +#include "intel_drv.h" +#include "intel_hdcp.h" +#include "intel_hdmi.h" +#include "intel_lspcon.h" +#include "intel_lvds.h" +#include "intel_panel.h" +#include "intel_psr.h" #define DP_DPRX_ESI_LEN 14 @@ -1856,42 +1868,6 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp, return -EINVAL; } -/* Optimize link config in order: max bpp, min lanes, min clock */ -static int -intel_dp_compute_link_config_fast(struct intel_dp *intel_dp, - struct intel_crtc_state *pipe_config, - const struct link_config_limits *limits) -{ - struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; - int bpp, clock, lane_count; - int mode_rate, link_clock, link_avail; - - for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) { - mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock, - bpp); - - for (lane_count = limits->min_lane_count; - lane_count <= limits->max_lane_count; - lane_count <<= 1) { - for (clock = limits->min_clock; clock <= limits->max_clock; clock++) { - link_clock = intel_dp->common_rates[clock]; - link_avail = intel_dp_max_data_rate(link_clock, - lane_count); - - if (mode_rate <= link_avail) { - pipe_config->lane_count = lane_count; - pipe_config->pipe_bpp = bpp; - pipe_config->port_clock = link_clock; - - return 0; - } - } - } - } - - return -EINVAL; -} - static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc) { int i, num_bpc; @@ -1919,6 +1895,9 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, int pipe_bpp; int ret; + pipe_config->fec_enable = !intel_dp_is_edp(intel_dp) && + intel_dp_supports_fec(intel_dp, pipe_config); + if (!intel_dp_supports_dsc(intel_dp, pipe_config)) return -EINVAL; @@ -2002,6 +1981,14 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, return 0; } +int intel_dp_min_bpp(const struct intel_crtc_state *crtc_state) +{ + if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_RGB) + return 6 * 3; + else + return 8 * 3; +} + static int intel_dp_compute_link_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, @@ -2025,18 +2012,16 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, limits.min_lane_count = 1; limits.max_lane_count = intel_dp_max_lane_count(intel_dp); - limits.min_bpp = 6 * 3; + limits.min_bpp = intel_dp_min_bpp(pipe_config); limits.max_bpp = intel_dp_compute_bpp(intel_dp, pipe_config); - if (intel_dp_is_edp(intel_dp) && intel_dp->edp_dpcd[0] < DP_EDP_14) { + if (intel_dp_is_edp(intel_dp)) { /* * Use the maximum clock and number of lanes the eDP panel - * advertizes being capable of. The eDP 1.3 and earlier panels - * are generally designed to support only a single clock and - * lane configuration, and typically these values correspond to - * the native resolution of the panel. With eDP 1.4 rate select - * and DSC, this is decreasingly the case, and we need to be - * able to select less than maximum link config. + * advertizes being capable of. The panels are generally + * designed to support only a single clock and lane + * configuration, and typically these values correspond to the + * native resolution of the panel. */ limits.min_lane_count = limits.max_lane_count; limits.min_clock = limits.max_clock; @@ -2050,22 +2035,11 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, intel_dp->common_rates[limits.max_clock], limits.max_bpp, adjusted_mode->crtc_clock); - if (intel_dp_is_edp(intel_dp)) - /* - * Optimize for fast and narrow. eDP 1.3 section 3.3 and eDP 1.4 - * section A.1: "It is recommended that the minimum number of - * lanes be used, using the minimum link rate allowed for that - * lane configuration." - * - * Note that we use the max clock and lane count for eDP 1.3 and - * earlier, and fast vs. wide is irrelevant. - */ - ret = intel_dp_compute_link_config_fast(intel_dp, pipe_config, - &limits); - else - /* Optimize for slow and wide. */ - ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config, - &limits); + /* + * Optimize for slow and wide. This is the place to add alternative + * optimization policy. + */ + ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config, &limits); /* enable compression if the mode doesn't fit available BW */ DRM_DEBUG_KMS("Force DSC en = %d\n", intel_dp->force_dsc_en); @@ -2140,7 +2114,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, to_intel_digital_connector_state(conn_state); bool constant_n = drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_CONSTANT_N); - int ret; + int ret, output_bpp; if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && port != PORT_A) pipe_config->has_pch_encoder = true; @@ -2185,9 +2159,6 @@ intel_dp_compute_config(struct intel_encoder *encoder, if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) return -EINVAL; - pipe_config->fec_enable = !intel_dp_is_edp(intel_dp) && - intel_dp_supports_fec(intel_dp, pipe_config); - ret = intel_dp_compute_link_config(encoder, pipe_config, conn_state); if (ret < 0) return ret; @@ -2195,25 +2166,22 @@ intel_dp_compute_config(struct intel_encoder *encoder, pipe_config->limited_color_range = intel_dp_limited_color_range(pipe_config, conn_state); - if (!pipe_config->dsc_params.compression_enable) - intel_link_compute_m_n(pipe_config->pipe_bpp, - pipe_config->lane_count, - adjusted_mode->crtc_clock, - pipe_config->port_clock, - &pipe_config->dp_m_n, - constant_n); + if (pipe_config->dsc_params.compression_enable) + output_bpp = pipe_config->dsc_params.compressed_bpp; else - intel_link_compute_m_n(pipe_config->dsc_params.compressed_bpp, - pipe_config->lane_count, - adjusted_mode->crtc_clock, - pipe_config->port_clock, - &pipe_config->dp_m_n, - constant_n); + output_bpp = pipe_config->pipe_bpp; + + intel_link_compute_m_n(output_bpp, + pipe_config->lane_count, + adjusted_mode->crtc_clock, + pipe_config->port_clock, + &pipe_config->dp_m_n, + constant_n); if (intel_connector->panel.downclock_mode != NULL && dev_priv->drrs.type == SEAMLESS_DRRS_SUPPORT) { pipe_config->has_drrs = true; - intel_link_compute_m_n(pipe_config->pipe_bpp, + intel_link_compute_m_n(output_bpp, pipe_config->lane_count, intel_connector->panel.downclock_mode->clock, pipe_config->port_clock, diff --git a/drivers/gpu/drm/i915/intel_dp.h b/drivers/gpu/drm/i915/intel_dp.h new file mode 100644 index 000000000000..5e9e8d13de6e --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dp.h @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_DP_H__ +#define __INTEL_DP_H__ + +#include <linux/types.h> + +#include <drm/i915_drm.h> + +#include "i915_reg.h" + +enum pipe; +struct drm_connector_state; +struct drm_encoder; +struct drm_i915_private; +struct drm_modeset_acquire_ctx; +struct intel_connector; +struct intel_crtc_state; +struct intel_digital_port; +struct intel_dp; +struct intel_encoder; + +struct link_config_limits { + int min_clock, max_clock; + int min_lane_count, max_lane_count; + int min_bpp, max_bpp; +}; + +void intel_dp_adjust_compliance_config(struct intel_dp *intel_dp, + struct intel_crtc_state *pipe_config, + struct link_config_limits *limits); +bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state); +int intel_dp_min_bpp(const struct intel_crtc_state *crtc_state); +bool intel_dp_port_enabled(struct drm_i915_private *dev_priv, + i915_reg_t dp_reg, enum port port, + enum pipe *pipe); +bool intel_dp_init(struct drm_i915_private *dev_priv, 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, + int link_rate, u8 lane_count, + bool link_mst); +int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp, + int link_rate, u8 lane_count); +int intel_dp_retrain_link(struct intel_encoder *encoder, + struct drm_modeset_acquire_ctx *ctx); +void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); +void intel_dp_sink_set_decompression_state(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state, + bool enable); +void intel_dp_encoder_reset(struct drm_encoder *encoder); +void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder); +void intel_dp_encoder_flush_work(struct drm_encoder *encoder); +int intel_dp_compute_config(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state); +bool intel_dp_is_edp(struct intel_dp *intel_dp); +bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port); +enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, + bool long_hpd); +void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state); +void intel_edp_backlight_off(const struct drm_connector_state *conn_state); +void intel_edp_panel_vdd_on(struct intel_dp *intel_dp); +void intel_edp_panel_on(struct intel_dp *intel_dp); +void intel_edp_panel_off(struct intel_dp *intel_dp); +void intel_dp_mst_suspend(struct drm_i915_private *dev_priv); +void intel_dp_mst_resume(struct drm_i915_private *dev_priv); +int intel_dp_max_link_rate(struct intel_dp *intel_dp); +int intel_dp_max_lane_count(struct intel_dp *intel_dp); +int intel_dp_rate_select(struct intel_dp *intel_dp, int rate); +void intel_power_sequencer_reset(struct drm_i915_private *dev_priv); +u32 intel_dp_pack_aux(const u8 *src, int src_bytes); + +void intel_edp_drrs_enable(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); +void intel_edp_drrs_disable(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); +void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv, + unsigned int frontbuffer_bits); +void intel_edp_drrs_flush(struct drm_i915_private *dev_priv, + unsigned int frontbuffer_bits); + +void +intel_dp_program_link_training_pattern(struct intel_dp *intel_dp, + u8 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); +u8 +intel_dp_voltage_max(struct intel_dp *intel_dp); +u8 +intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, u8 voltage_swing); +void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, + u8 *link_bw, u8 *rate_select); +bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp); +bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp); +bool +intel_dp_get_link_status(struct intel_dp *intel_dp, u8 *link_status); +u16 intel_dp_dsc_get_output_bpp(int link_clock, u8 lane_count, + int mode_clock, int mode_hdisplay); +u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, int mode_clock, + int mode_hdisplay); + +bool intel_dp_read_dpcd(struct intel_dp *intel_dp); +int intel_dp_link_required(int pixel_clock, int bpp); +int intel_dp_max_data_rate(int max_link_clock, int max_lanes); +bool intel_digital_port_connected(struct intel_encoder *encoder); +void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv, + struct intel_digital_port *dig_port); + +static inline unsigned int intel_dp_unused_lane_mask(int lane_count) +{ + return ~((1 << lane_count) - 1) & 0xf; +} + +#endif /* __INTEL_DP_H__ */ diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c index b59c87daa4f7..54b069333e2f 100644 --- a/drivers/gpu/drm/i915/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c @@ -21,6 +21,7 @@ * IN THE SOFTWARE. */ +#include "intel_dp.h" #include "intel_drv.h" static void diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 19d81cef2ab6..8839eaea8371 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -23,12 +23,17 @@ * */ -#include "i915_drv.h" -#include "intel_drv.h" #include <drm/drm_atomic_helper.h> #include <drm/drm_edid.h> #include <drm/drm_probe_helper.h> +#include "i915_drv.h" +#include "intel_audio.h" +#include "intel_connector.h" +#include "intel_ddi.h" +#include "intel_dp.h" +#include "intel_drv.h" + static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state, @@ -119,7 +124,7 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, limits.min_lane_count = limits.max_lane_count = intel_dp_max_lane_count(intel_dp); - limits.min_bpp = 6 * 3; + limits.min_bpp = intel_dp_min_bpp(pipe_config); limits.max_bpp = pipe_config->pipe_bpp; intel_dp_adjust_compliance_config(intel_dp, pipe_config, &limits); diff --git a/drivers/gpu/drm/i915/intel_dpio_phy.c b/drivers/gpu/drm/i915/intel_dpio_phy.c index db295c77ff0d..ab4ac7158b79 100644 --- a/drivers/gpu/drm/i915/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/intel_dpio_phy.c @@ -21,6 +21,7 @@ * DEALINGS IN THE SOFTWARE. */ +#include "intel_dp.h" #include "intel_drv.h" /** diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 64544613920b..a38b9cff5cd0 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -27,23 +27,24 @@ #include <linux/async.h> #include <linux/i2c.h> -#include <linux/hdmi.h> #include <linux/sched/clock.h> #include <linux/stackdepot.h> -#include <drm/i915_drm.h> -#include "i915_drv.h" + +#include <drm/drm_atomic.h> #include <drm/drm_crtc.h> -#include <drm/drm_encoder.h> -#include <drm/drm_fb_helper.h> #include <drm/drm_dp_dual_mode_helper.h> #include <drm/drm_dp_mst_helper.h> +#include <drm/drm_encoder.h> +#include <drm/drm_fb_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_rect.h> #include <drm/drm_vblank.h> -#include <drm/drm_atomic.h> +#include <drm/i915_drm.h> #include <drm/i915_mei_hdcp_interface.h> #include <media/cec-notifier.h> +#include "i915_drv.h" + struct drm_printer; /** @@ -271,10 +272,12 @@ struct intel_encoder { * be set correctly before calling this function. */ void (*get_config)(struct intel_encoder *, struct intel_crtc_state *pipe_config); - /* Returns a mask of power domains that need to be referenced as part - * of the hardware state readout code. */ - u64 (*get_power_domains)(struct intel_encoder *encoder, - struct intel_crtc_state *crtc_state); + /* + * Acquires the power domains needed for an active encoder during + * hardware state readout. + */ + void (*get_power_domains)(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state); /* * Called during system suspend after all pending requests for the * encoder are flushed (for example for DP AUX transactions) and @@ -1600,6 +1603,7 @@ void gen11_reset_rps_interrupts(struct drm_i915_private *dev_priv); void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv); void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv); void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv); +void gen6_rps_reset_ei(struct drm_i915_private *dev_priv); static inline u32 gen6_sanitize_rps_pm_mask(const struct drm_i915_private *i915, u32 mask) @@ -1627,97 +1631,8 @@ void gen9_reset_guc_interrupts(struct drm_i915_private *dev_priv); void gen9_enable_guc_interrupts(struct drm_i915_private *dev_priv); void gen9_disable_guc_interrupts(struct drm_i915_private *dev_priv); -/* intel_crt.c */ -bool intel_crt_port_enabled(struct drm_i915_private *dev_priv, - i915_reg_t adpa_reg, enum pipe *pipe); -void intel_crt_init(struct drm_i915_private *dev_priv); -void intel_crt_reset(struct drm_encoder *encoder); - -/* intel_ddi.c */ -void intel_ddi_fdi_post_disable(struct intel_encoder *intel_encoder, - const struct intel_crtc_state *old_crtc_state, - const struct drm_connector_state *old_conn_state); -void hsw_fdi_link_train(struct intel_crtc *crtc, - const struct intel_crtc_state *crtc_state); -void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port); -bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe); -void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state); -void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state); -void intel_ddi_enable_pipe_clock(const struct intel_crtc_state *crtc_state); -void intel_ddi_disable_pipe_clock(const struct intel_crtc_state *crtc_state); -void intel_ddi_set_pipe_settings(const struct intel_crtc_state *crtc_state); -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_get_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config); - -void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state, - bool state); -void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv, - struct intel_crtc_state *crtc_state); -u32 bxt_signal_levels(struct intel_dp *intel_dp); -u32 ddi_signal_levels(struct intel_dp *intel_dp); -u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder); -u8 intel_ddi_dp_pre_emphasis_max(struct intel_encoder *encoder, - u8 voltage_swing); -int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder, - bool enable); -void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder); -int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv, - struct intel_dpll_hw_state *state); - -unsigned int intel_fb_align_height(const struct drm_framebuffer *fb, - int color_plane, unsigned int height); - -/* intel_audio.c */ -void intel_init_audio_hooks(struct drm_i915_private *dev_priv); -void intel_audio_codec_enable(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state); -void intel_audio_codec_disable(struct intel_encoder *encoder, - const struct intel_crtc_state *old_crtc_state, - const struct drm_connector_state *old_conn_state); -void i915_audio_component_init(struct drm_i915_private *dev_priv); -void i915_audio_component_cleanup(struct drm_i915_private *dev_priv); -void intel_audio_init(struct drm_i915_private *dev_priv); -void intel_audio_deinit(struct drm_i915_private *dev_priv); - -/* intel_cdclk.c */ -int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state); -void skl_init_cdclk(struct drm_i915_private *dev_priv); -void skl_uninit_cdclk(struct drm_i915_private *dev_priv); -void cnl_init_cdclk(struct drm_i915_private *dev_priv); -void cnl_uninit_cdclk(struct drm_i915_private *dev_priv); -void bxt_init_cdclk(struct drm_i915_private *dev_priv); -void bxt_uninit_cdclk(struct drm_i915_private *dev_priv); -void icl_init_cdclk(struct drm_i915_private *dev_priv); -void icl_uninit_cdclk(struct drm_i915_private *dev_priv); -void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv); -void intel_update_max_cdclk(struct drm_i915_private *dev_priv); -void intel_update_cdclk(struct drm_i915_private *dev_priv); -void intel_update_rawclk(struct drm_i915_private *dev_priv); -bool intel_cdclk_needs_cd2x_update(struct drm_i915_private *dev_priv, - const struct intel_cdclk_state *a, - const struct intel_cdclk_state *b); -bool intel_cdclk_needs_modeset(const struct intel_cdclk_state *a, - const struct intel_cdclk_state *b); -bool intel_cdclk_changed(const struct intel_cdclk_state *a, - const struct intel_cdclk_state *b); -void intel_cdclk_swap_state(struct intel_atomic_state *state); -void -intel_set_cdclk_pre_plane_update(struct drm_i915_private *dev_priv, - const struct intel_cdclk_state *old_state, - const struct intel_cdclk_state *new_state, - enum pipe pipe); -void -intel_set_cdclk_post_plane_update(struct drm_i915_private *dev_priv, - const struct intel_cdclk_state *old_state, - const struct intel_cdclk_state *new_state, - enum pipe pipe); -void intel_dump_cdclk_state(const struct intel_cdclk_state *cdclk_state, - const char *context); - /* intel_display.c */ +void intel_plane_destroy(struct drm_plane *plane); void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe); void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe); enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc); @@ -1732,6 +1647,8 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv); unsigned int intel_fb_xy_to_linear(int x, int y, const struct intel_plane_state *state, int plane); +unsigned int intel_fb_align_height(const struct drm_framebuffer *fb, + int color_plane, unsigned int height); void intel_add_fb_offsets(int *x, int *y, const struct intel_plane_state *state, int plane); unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info); @@ -1899,117 +1816,9 @@ unsigned int i9xx_plane_max_stride(struct intel_plane *plane, u32 pixel_format, u64 modifier, unsigned int rotation); -/* intel_connector.c */ -int intel_connector_init(struct intel_connector *connector); -struct intel_connector *intel_connector_alloc(void); -void intel_connector_free(struct intel_connector *connector); -void intel_connector_destroy(struct drm_connector *connector); -int intel_connector_register(struct drm_connector *connector); -void intel_connector_unregister(struct drm_connector *connector); -void intel_connector_attach_encoder(struct intel_connector *connector, - struct intel_encoder *encoder); -bool intel_connector_get_hw_state(struct intel_connector *connector); -enum pipe intel_connector_get_pipe(struct intel_connector *connector); -int intel_connector_update_modes(struct drm_connector *connector, - struct edid *edid); -int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); -void intel_attach_force_audio_property(struct drm_connector *connector); -void intel_attach_broadcast_rgb_property(struct drm_connector *connector); -void intel_attach_aspect_ratio_property(struct drm_connector *connector); -void intel_attach_colorspace_property(struct drm_connector *connector); - -/* intel_csr.c */ -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 *); -void intel_csr_ucode_suspend(struct drm_i915_private *); -void intel_csr_ucode_resume(struct drm_i915_private *); - -/* intel_dp.c */ -struct link_config_limits { - int min_clock, max_clock; - int min_lane_count, max_lane_count; - int min_bpp, max_bpp; -}; -void intel_dp_adjust_compliance_config(struct intel_dp *intel_dp, - struct intel_crtc_state *pipe_config, - struct link_config_limits *limits); -bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state); -bool intel_dp_port_enabled(struct drm_i915_private *dev_priv, - i915_reg_t dp_reg, enum port port, - enum pipe *pipe); -bool intel_dp_init(struct drm_i915_private *dev_priv, 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, - int link_rate, u8 lane_count, - bool link_mst); -int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp, - int link_rate, u8 lane_count); +/* intel_dp_link_training.c */ void intel_dp_start_link_train(struct intel_dp *intel_dp); void intel_dp_stop_link_train(struct intel_dp *intel_dp); -int intel_dp_retrain_link(struct intel_encoder *encoder, - struct drm_modeset_acquire_ctx *ctx); -void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); -void intel_dp_sink_set_decompression_state(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state, - bool enable); -void intel_dp_encoder_reset(struct drm_encoder *encoder); -void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder); -void intel_dp_encoder_flush_work(struct drm_encoder *encoder); -int intel_dp_compute_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state); -bool intel_dp_is_edp(struct intel_dp *intel_dp); -bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port); -enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, - bool long_hpd); -void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state); -void intel_edp_backlight_off(const struct drm_connector_state *conn_state); -void intel_edp_panel_vdd_on(struct intel_dp *intel_dp); -void intel_edp_panel_on(struct intel_dp *intel_dp); -void intel_edp_panel_off(struct intel_dp *intel_dp); -void intel_dp_mst_suspend(struct drm_i915_private *dev_priv); -void intel_dp_mst_resume(struct drm_i915_private *dev_priv); -int intel_dp_max_link_rate(struct intel_dp *intel_dp); -int intel_dp_max_lane_count(struct intel_dp *intel_dp); -int intel_dp_rate_select(struct intel_dp *intel_dp, int rate); -void intel_dp_hot_plug(struct intel_encoder *intel_encoder); -void intel_power_sequencer_reset(struct drm_i915_private *dev_priv); -u32 intel_dp_pack_aux(const u8 *src, int src_bytes); -void intel_plane_destroy(struct drm_plane *plane); -void intel_edp_drrs_enable(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state); -void intel_edp_drrs_disable(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state); -void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv, - unsigned int frontbuffer_bits); -void intel_edp_drrs_flush(struct drm_i915_private *dev_priv, - unsigned int frontbuffer_bits); - -void -intel_dp_program_link_training_pattern(struct intel_dp *intel_dp, - u8 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); -u8 -intel_dp_voltage_max(struct intel_dp *intel_dp); -u8 -intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, u8 voltage_swing); -void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, - u8 *link_bw, u8 *rate_select); -bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp); -bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp); -bool -intel_dp_get_link_status(struct intel_dp *intel_dp, u8 link_status[DP_LINK_STATUS_SIZE]); -u16 intel_dp_dsc_get_output_bpp(int link_clock, u8 lane_count, - int mode_clock, int mode_hdisplay); -u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, int mode_clock, - int mode_hdisplay); /* intel_vdsc.c */ int intel_dp_compute_dsc_params(struct intel_dp *intel_dp, @@ -2017,18 +1826,6 @@ int intel_dp_compute_dsc_params(struct intel_dp *intel_dp, enum intel_display_power_domain intel_dsc_power_domain(const struct intel_crtc_state *crtc_state); -static inline unsigned int intel_dp_unused_lane_mask(int lane_count) -{ - return ~((1 << lane_count) - 1) & 0xf; -} - -bool intel_dp_read_dpcd(struct intel_dp *intel_dp); -int intel_dp_link_required(int pixel_clock, int bpp); -int intel_dp_max_data_rate(int max_link_clock, int max_lanes); -bool intel_digital_port_connected(struct intel_encoder *encoder); -void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv, - struct intel_digital_port *dig_port); - /* intel_dp_aux_backlight.c */ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector); @@ -2044,109 +1841,11 @@ void icl_dsi_init(struct drm_i915_private *dev_priv); /* intel_dsi_dcs_backlight.c */ int intel_dsi_dcs_init_backlight_funcs(struct intel_connector *intel_connector); -/* intel_dvo.c */ -void intel_dvo_init(struct drm_i915_private *dev_priv); /* intel_hotplug.c */ void intel_hpd_poll_init(struct drm_i915_private *dev_priv); bool intel_encoder_hotplug(struct intel_encoder *encoder, struct intel_connector *connector); -/* 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_async(struct drm_device *dev); -extern void intel_fbdev_unregister(struct drm_i915_private *dev_priv); -extern void intel_fbdev_fini(struct drm_i915_private *dev_priv); -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); -extern void intel_fbdev_restore_mode(struct drm_device *dev); -#else -static inline int intel_fbdev_init(struct drm_device *dev) -{ - return 0; -} - -static inline void intel_fbdev_initial_config_async(struct drm_device *dev) -{ -} - -static inline void intel_fbdev_unregister(struct drm_i915_private *dev_priv) -{ -} - -static inline void intel_fbdev_fini(struct drm_i915_private *dev_priv) -{ -} - -static inline void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous) -{ -} - -static inline void intel_fbdev_output_poll_changed(struct drm_device *dev) -{ -} - -static inline void intel_fbdev_restore_mode(struct drm_device *dev) -{ -} -#endif - -/* intel_fbc.c */ -void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, - struct intel_atomic_state *state); -bool intel_fbc_is_active(struct drm_i915_private *dev_priv); -void intel_fbc_pre_update(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state, - struct intel_plane_state *plane_state); -void intel_fbc_post_update(struct intel_crtc *crtc); -void intel_fbc_init(struct drm_i915_private *dev_priv); -void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv); -void intel_fbc_enable(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state, - struct intel_plane_state *plane_state); -void intel_fbc_disable(struct intel_crtc *crtc); -void intel_fbc_global_disable(struct drm_i915_private *dev_priv); -void intel_fbc_invalidate(struct drm_i915_private *dev_priv, - unsigned int frontbuffer_bits, - enum fb_op_origin origin); -void intel_fbc_flush(struct drm_i915_private *dev_priv, - unsigned int frontbuffer_bits, enum fb_op_origin origin); -void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv); -void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv); -int intel_fbc_reset_underrun(struct drm_i915_private *dev_priv); - -/* intel_hdmi.c */ -void intel_hdmi_init(struct drm_i915_private *dev_priv, 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); -int intel_hdmi_compute_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state); -bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, - struct drm_connector *connector, - bool high_tmds_clock_ratio, - bool scrambling); -void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable); -void intel_infoframe_init(struct intel_digital_port *intel_dig_port); -u32 intel_hdmi_infoframes_enabled(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state); -u32 intel_hdmi_infoframe_enable(unsigned int type); -void intel_hdmi_read_gcp_infoframe(struct intel_encoder *encoder, - struct intel_crtc_state *crtc_state); -void intel_read_infoframe(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state, - enum hdmi_infoframe_type type, - union hdmi_infoframe *frame); - -/* intel_lvds.c */ -bool intel_lvds_port_enabled(struct drm_i915_private *dev_priv, - i915_reg_t lvds_reg, enum pipe *pipe); -void intel_lvds_init(struct drm_i915_private *dev_priv); -struct intel_encoder *intel_get_lvds_encoder(struct drm_i915_private *dev_priv); -bool intel_is_dual_link_lvds(struct drm_i915_private *dev_priv); - /* intel_overlay.c */ void intel_overlay_setup(struct drm_i915_private *dev_priv); void intel_overlay_cleanup(struct drm_i915_private *dev_priv); @@ -2157,92 +1856,6 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); void intel_overlay_reset(struct drm_i915_private *dev_priv); - -/* intel_panel.c */ -int intel_panel_init(struct intel_panel *panel, - struct drm_display_mode *fixed_mode, - struct drm_display_mode *downclock_mode); -void intel_panel_fini(struct intel_panel *panel); -void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, - struct drm_display_mode *adjusted_mode); -void intel_pch_panel_fitting(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config, - int fitting_mode); -void intel_gmch_panel_fitting(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config, - int fitting_mode); -void intel_panel_set_backlight_acpi(const struct drm_connector_state *conn_state, - u32 level, u32 max); -int intel_panel_setup_backlight(struct drm_connector *connector, - enum pipe pipe); -void intel_panel_enable_backlight(const struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state); -void intel_panel_update_backlight(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state); -void intel_panel_disable_backlight(const struct drm_connector_state *old_conn_state); -struct drm_display_mode * -intel_panel_edid_downclock_mode(struct intel_connector *connector, - const struct drm_display_mode *fixed_mode); -struct drm_display_mode * -intel_panel_edid_fixed_mode(struct intel_connector *connector); -struct drm_display_mode * -intel_panel_vbt_fixed_mode(struct intel_connector *connector); - -#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) -int intel_backlight_device_register(struct intel_connector *connector); -void intel_backlight_device_unregister(struct intel_connector *connector); -#else /* CONFIG_BACKLIGHT_CLASS_DEVICE */ -static inline int intel_backlight_device_register(struct intel_connector *connector) -{ - return 0; -} -static inline void intel_backlight_device_unregister(struct intel_connector *connector) -{ -} -#endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */ - -/* intel_hdcp.c */ -void intel_hdcp_atomic_check(struct drm_connector *connector, - struct drm_connector_state *old_state, - struct drm_connector_state *new_state); -int intel_hdcp_init(struct intel_connector *connector, - const struct intel_hdcp_shim *hdcp_shim); -int intel_hdcp_enable(struct intel_connector *connector); -int intel_hdcp_disable(struct intel_connector *connector); -bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port); -bool intel_hdcp_capable(struct intel_connector *connector); -void intel_hdcp_component_init(struct drm_i915_private *dev_priv); -void intel_hdcp_component_fini(struct drm_i915_private *dev_priv); -void intel_hdcp_cleanup(struct intel_connector *connector); -void intel_hdcp_handle_cp_irq(struct intel_connector *connector); - -/* intel_psr.c */ -#define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support) -void intel_psr_init_dpcd(struct intel_dp *intel_dp); -void intel_psr_enable(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state); -void intel_psr_disable(struct intel_dp *intel_dp, - const struct intel_crtc_state *old_crtc_state); -void intel_psr_update(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state); -int intel_psr_debug_set(struct drm_i915_private *dev_priv, u64 value); -void intel_psr_invalidate(struct drm_i915_private *dev_priv, - unsigned frontbuffer_bits, - enum fb_op_origin origin); -void intel_psr_flush(struct drm_i915_private *dev_priv, - unsigned frontbuffer_bits, - enum fb_op_origin origin); -void intel_psr_init(struct drm_i915_private *dev_priv); -void intel_psr_compute_config(struct intel_dp *intel_dp, - struct intel_crtc_state *crtc_state); -void intel_psr_irq_control(struct drm_i915_private *dev_priv, u32 debug); -void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir); -void intel_psr_short_pulse(struct intel_dp *intel_dp); -int intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state, - u32 *out_value); -bool intel_psr_enabled(struct intel_dp *intel_dp); - /* intel_quirks.c */ void intel_init_quirks(struct drm_i915_private *dev_priv); @@ -2392,102 +2005,6 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder, bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy, enum dpio_channel ch, bool override); - -/* intel_pm.c */ -void intel_init_clock_gating(struct drm_i915_private *dev_priv); -void intel_suspend_hw(struct drm_i915_private *dev_priv); -int ilk_wm_max_level(const struct drm_i915_private *dev_priv); -void intel_update_watermarks(struct intel_crtc *crtc); -void intel_init_pm(struct drm_i915_private *dev_priv); -void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv); -void intel_pm_setup(struct drm_i915_private *dev_priv); -void intel_gpu_ips_init(struct drm_i915_private *dev_priv); -void intel_gpu_ips_teardown(void); -void intel_init_gt_powersave(struct drm_i915_private *dev_priv); -void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv); -void intel_sanitize_gt_powersave(struct drm_i915_private *dev_priv); -void intel_enable_gt_powersave(struct drm_i915_private *dev_priv); -void intel_disable_gt_powersave(struct drm_i915_private *dev_priv); -void gen6_rps_busy(struct drm_i915_private *dev_priv); -void gen6_rps_reset_ei(struct drm_i915_private *dev_priv); -void gen6_rps_idle(struct drm_i915_private *dev_priv); -void gen6_rps_boost(struct i915_request *rq); -void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv); -void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv); -void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv); -void skl_wm_get_hw_state(struct drm_i915_private *dev_priv); -void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc, - struct skl_ddb_entry *ddb_y, - struct skl_ddb_entry *ddb_uv); -void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, - struct skl_ddb_allocation *ddb /* out */); -void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc, - struct skl_pipe_wm *out); -void g4x_wm_sanitize(struct drm_i915_private *dev_priv); -void vlv_wm_sanitize(struct drm_i915_private *dev_priv); -bool intel_can_enable_sagv(struct drm_atomic_state *state); -int intel_enable_sagv(struct drm_i915_private *dev_priv); -int intel_disable_sagv(struct drm_i915_private *dev_priv); -bool skl_wm_level_equals(const struct skl_wm_level *l1, - const struct skl_wm_level *l2); -bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry *ddb, - const struct skl_ddb_entry entries[], - int num_entries, int ignore_idx); -void skl_write_plane_wm(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state); -void skl_write_cursor_wm(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state); -bool ilk_disable_lp_wm(struct drm_device *dev); -int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc, - struct intel_crtc_state *cstate); -void intel_init_ipc(struct drm_i915_private *dev_priv); -void intel_enable_ipc(struct drm_i915_private *dev_priv); - -/* intel_sdvo.c */ -bool intel_sdvo_port_enabled(struct drm_i915_private *dev_priv, - i915_reg_t sdvo_reg, enum pipe *pipe); -bool intel_sdvo_init(struct drm_i915_private *dev_priv, - i915_reg_t reg, enum port port); - - -/* intel_sprite.c */ -bool is_planar_yuv_format(u32 pixelformat); -int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, - int usecs); -struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv, - enum pipe pipe, int plane); -int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state); -void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state); -int intel_plane_check_stride(const struct intel_plane_state *plane_state); -int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state); -int chv_plane_check_rotation(const struct intel_plane_state *plane_state); -struct intel_plane * -skl_universal_plane_create(struct drm_i915_private *dev_priv, - enum pipe pipe, enum plane_id plane_id); - -static inline bool icl_is_nv12_y_plane(enum plane_id id) -{ - /* Don't need to do a gen check, these planes are only available on gen11 */ - if (id == PLANE_SPRITE4 || id == PLANE_SPRITE5) - return true; - - return false; -} - -static inline bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, - enum plane_id plane_id) -{ - if (INTEL_GEN(dev_priv) < 11) - return false; - - return plane_id < PLANE_SPRITE2; -} - -/* intel_tv.c */ -void intel_tv_init(struct drm_i915_private *dev_priv); - /* intel_atomic.c */ int intel_digital_connector_atomic_get_property(struct drm_connector *connector, const struct drm_connector_state *state, @@ -2524,76 +2041,4 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state); -/* intel_atomic_plane.c */ -void intel_update_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state); -void intel_update_slave(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state); -void intel_disable_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state); -struct intel_plane *intel_plane_alloc(void); -void intel_plane_free(struct intel_plane *plane); -struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane); -void intel_plane_destroy_state(struct drm_plane *plane, - struct drm_plane_state *state); -extern const struct drm_plane_helper_funcs intel_plane_helper_funcs; -void skl_update_planes_on_crtc(struct intel_atomic_state *state, - struct intel_crtc *crtc); -void i9xx_update_planes_on_crtc(struct intel_atomic_state *state, - struct intel_crtc *crtc); -int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state, - struct intel_crtc_state *crtc_state, - const struct intel_plane_state *old_plane_state, - struct intel_plane_state *intel_state); - -/* intel_color.c */ -void intel_color_init(struct intel_crtc *crtc); -int intel_color_check(struct intel_crtc_state *crtc_state); -void intel_color_commit(const struct intel_crtc_state *crtc_state); -void intel_color_load_luts(const struct intel_crtc_state *crtc_state); - -/* intel_lspcon.c */ -bool lspcon_init(struct intel_digital_port *intel_dig_port); -void lspcon_resume(struct intel_lspcon *lspcon); -void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon); -void lspcon_write_infoframe(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state, - unsigned int type, - const void *buf, ssize_t len); -void lspcon_read_infoframe(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state, - unsigned int type, - void *frame, ssize_t len); -void lspcon_set_infoframes(struct intel_encoder *encoder, - bool enable, - const struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state); -u32 lspcon_infoframes_enabled(struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config); -void lspcon_ycbcr420_config(struct drm_connector *connector, - struct intel_crtc_state *crtc_state); - -/* intel_pipe_crc.c */ -#ifdef CONFIG_DEBUG_FS -int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name); -int intel_crtc_verify_crc_source(struct drm_crtc *crtc, - const char *source_name, size_t *values_cnt); -const char *const *intel_crtc_get_crc_sources(struct drm_crtc *crtc, - size_t *count); -void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc); -void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc); -#else -#define intel_crtc_set_crc_source NULL -#define intel_crtc_verify_crc_source NULL -#define intel_crtc_get_crc_sources NULL -static inline void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc) -{ -} - -static inline void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc) -{ -} -#endif #endif /* __INTEL_DRV_H__ */ diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index a6c82482a841..adef81c8cccb 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -24,14 +24,20 @@ * Authors: * Eric Anholt <[email protected]> */ + #include <linux/i2c.h> #include <linux/slab.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> -#include "intel_drv.h" #include <drm/i915_drm.h> -#include "i915_drv.h" + #include "dvo.h" +#include "i915_drv.h" +#include "intel_connector.h" +#include "intel_drv.h" +#include "intel_dvo.h" +#include "intel_panel.h" #define SIL164_ADDR 0x38 #define CH7xxx_ADDR 0x76 diff --git a/drivers/gpu/drm/i915/intel_dvo.h b/drivers/gpu/drm/i915/intel_dvo.h new file mode 100644 index 000000000000..3ed0fdf8efff --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dvo.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_DVO_H__ +#define __INTEL_DVO_H__ + +struct drm_i915_private; + +void intel_dvo_init(struct drm_i915_private *dev_priv); + +#endif /* __INTEL_DVO_H__ */ diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index d0427c2e3997..eea9bec04f1b 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -753,6 +753,30 @@ err_unpin: return ret; } +void intel_gt_resume(struct drm_i915_private *i915) +{ + struct intel_engine_cs *engine; + enum intel_engine_id id; + + /* + * After resume, we may need to poke into the pinned kernel + * contexts to paper over any damage caused by the sudden suspend. + * Only the kernel contexts should remain pinned over suspend, + * allowing us to fixup the user contexts on their first pin. + */ + for_each_engine(engine, i915, id) { + struct intel_context *ce; + + ce = engine->kernel_context; + if (ce) + ce->ops->reset(ce); + + ce = engine->preempt_context; + if (ce) + ce->ops->reset(ce); + } +} + /** * intel_engines_cleanup_common - cleans up the engine state created by * the common initiailizers. @@ -1381,40 +1405,33 @@ static void intel_engine_print_registers(const struct intel_engine_cs *engine, if (HAS_EXECLISTS(dev_priv)) { const u32 *hws = &engine->status_page.addr[I915_HWS_CSB_BUF0_INDEX]; + const u8 num_entries = execlists->csb_size; unsigned int idx; u8 read, write; - drm_printf(m, "\tExeclist status: 0x%08x %08x\n", + drm_printf(m, "\tExeclist status: 0x%08x %08x, entries %u\n", ENGINE_READ(engine, RING_EXECLIST_STATUS_LO), - ENGINE_READ(engine, RING_EXECLIST_STATUS_HI)); + ENGINE_READ(engine, RING_EXECLIST_STATUS_HI), + num_entries); read = execlists->csb_head; write = READ_ONCE(*execlists->csb_write); - drm_printf(m, "\tExeclist CSB read %d, write %d [mmio:%d], tasklet queued? %s (%s)\n", + drm_printf(m, "\tExeclist CSB read %d, write %d, tasklet queued? %s (%s)\n", read, write, - GEN8_CSB_WRITE_PTR(ENGINE_READ(engine, RING_CONTEXT_STATUS_PTR)), yesno(test_bit(TASKLET_STATE_SCHED, &engine->execlists.tasklet.state)), enableddisabled(!atomic_read(&engine->execlists.tasklet.count))); - if (read >= GEN8_CSB_ENTRIES) + if (read >= num_entries) read = 0; - if (write >= GEN8_CSB_ENTRIES) + if (write >= num_entries) write = 0; if (read > write) - write += GEN8_CSB_ENTRIES; + write += num_entries; while (read < write) { - idx = ++read % GEN8_CSB_ENTRIES; - drm_printf(m, "\tExeclist CSB[%d]: 0x%08x [mmio:0x%08x], context: %d [mmio:%d]\n", - idx, - hws[idx * 2], - ENGINE_READ_IDX(engine, - RING_CONTEXT_STATUS_BUF_LO, - idx), - hws[idx * 2 + 1], - ENGINE_READ_IDX(engine, - RING_CONTEXT_STATUS_BUF_HI, - idx)); + idx = ++read % num_entries; + drm_printf(m, "\tExeclist CSB[%d]: 0x%08x, context: %d\n", + idx, hws[idx * 2], hws[idx * 2 + 1]); } rcu_read_lock(); diff --git a/drivers/gpu/drm/i915/intel_engine_types.h b/drivers/gpu/drm/i915/intel_engine_types.h index 6c6d8a9aca94..1f970c76b6a6 100644 --- a/drivers/gpu/drm/i915/intel_engine_types.h +++ b/drivers/gpu/drm/i915/intel_engine_types.h @@ -247,6 +247,11 @@ struct intel_engine_execlists { u32 preempt_complete_status; /** + * @csb_size: context status buffer FIFO size + */ + u8 csb_size; + + /** * @csb_head: context status buffer head */ u8 csb_head; diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 43fe08be3b7d..c805a0966395 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -40,8 +40,10 @@ #include <drm/drm_fourcc.h> -#include "intel_drv.h" #include "i915_drv.h" +#include "intel_drv.h" +#include "intel_fbc.h" +#include "intel_frontbuffer.h" static inline bool fbc_supported(struct drm_i915_private *dev_priv) { diff --git a/drivers/gpu/drm/i915/intel_fbc.h b/drivers/gpu/drm/i915/intel_fbc.h new file mode 100644 index 000000000000..50272eda8d43 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_fbc.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_FBC_H__ +#define __INTEL_FBC_H__ + +#include <linux/types.h> + +#include "intel_frontbuffer.h" + +struct drm_i915_private; +struct intel_atomic_state; +struct intel_crtc; +struct intel_crtc_state; +struct intel_plane_state; + +void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, + struct intel_atomic_state *state); +bool intel_fbc_is_active(struct drm_i915_private *dev_priv); +void intel_fbc_pre_update(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state); +void intel_fbc_post_update(struct intel_crtc *crtc); +void intel_fbc_init(struct drm_i915_private *dev_priv); +void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv); +void intel_fbc_enable(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state); +void intel_fbc_disable(struct intel_crtc *crtc); +void intel_fbc_global_disable(struct drm_i915_private *dev_priv); +void intel_fbc_invalidate(struct drm_i915_private *dev_priv, + unsigned int frontbuffer_bits, + enum fb_op_origin origin); +void intel_fbc_flush(struct drm_i915_private *dev_priv, + unsigned int frontbuffer_bits, enum fb_op_origin origin); +void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv); +void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv); +int intel_fbc_reset_underrun(struct drm_i915_private *dev_priv); + +#endif /* __INTEL_FBC_H__ */ diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index e8f694b57b8a..285a6e20a016 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -25,26 +25,27 @@ */ #include <linux/async.h> -#include <linux/module.h> -#include <linux/kernel.h> #include <linux/console.h> +#include <linux/delay.h> #include <linux/errno.h> -#include <linux/string.h> +#include <linux/init.h> +#include <linux/kernel.h> #include <linux/mm.h> -#include <linux/tty.h> +#include <linux/module.h> +#include <linux/string.h> #include <linux/sysrq.h> -#include <linux/delay.h> -#include <linux/init.h> +#include <linux/tty.h> #include <linux/vga_switcheroo.h> #include <drm/drm_crtc.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> +#include <drm/i915_drm.h> +#include "i915_drv.h" #include "intel_drv.h" +#include "intel_fbdev.h" #include "intel_frontbuffer.h" -#include <drm/i915_drm.h> -#include "i915_drv.h" static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev) { diff --git a/drivers/gpu/drm/i915/intel_fbdev.h b/drivers/gpu/drm/i915/intel_fbdev.h new file mode 100644 index 000000000000..de7c84250eb5 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_fbdev.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_FBDEV_H__ +#define __INTEL_FBDEV_H__ + +#include <linux/types.h> + +struct drm_device; +struct drm_i915_private; + +#ifdef CONFIG_DRM_FBDEV_EMULATION +int intel_fbdev_init(struct drm_device *dev); +void intel_fbdev_initial_config_async(struct drm_device *dev); +void intel_fbdev_unregister(struct drm_i915_private *dev_priv); +void intel_fbdev_fini(struct drm_i915_private *dev_priv); +void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous); +void intel_fbdev_output_poll_changed(struct drm_device *dev); +void intel_fbdev_restore_mode(struct drm_device *dev); +#else +static inline int intel_fbdev_init(struct drm_device *dev) +{ + return 0; +} + +static inline void intel_fbdev_initial_config_async(struct drm_device *dev) +{ +} + +static inline void intel_fbdev_unregister(struct drm_i915_private *dev_priv) +{ +} + +static inline void intel_fbdev_fini(struct drm_i915_private *dev_priv) +{ +} + +static inline void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous) +{ +} + +static inline void intel_fbdev_output_poll_changed(struct drm_device *dev) +{ +} + +static inline void intel_fbdev_restore_mode(struct drm_device *dev) +{ +} +#endif + +#endif /* __INTEL_FBDEV_H__ */ diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c index f33de4be4b89..74c8b0528294 100644 --- a/drivers/gpu/drm/i915/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c @@ -27,6 +27,7 @@ #include "i915_drv.h" #include "intel_drv.h" +#include "intel_fbc.h" /** * DOC: fifo underrun handling diff --git a/drivers/gpu/drm/i915/intel_frontbuffer.c b/drivers/gpu/drm/i915/intel_frontbuffer.c index 16f253deaf8d..aa34e33b6087 100644 --- a/drivers/gpu/drm/i915/intel_frontbuffer.c +++ b/drivers/gpu/drm/i915/intel_frontbuffer.c @@ -61,9 +61,12 @@ */ +#include "i915_drv.h" +#include "intel_dp.h" #include "intel_drv.h" +#include "intel_fbc.h" #include "intel_frontbuffer.h" -#include "i915_drv.h" +#include "intel_psr.h" void __intel_fb_obj_invalidate(struct drm_i915_gem_object *obj, enum fb_op_origin origin, diff --git a/drivers/gpu/drm/i915/intel_frontbuffer.h b/drivers/gpu/drm/i915/intel_frontbuffer.h index 63cd9a753a72..d5894666f658 100644 --- a/drivers/gpu/drm/i915/intel_frontbuffer.h +++ b/drivers/gpu/drm/i915/intel_frontbuffer.h @@ -24,9 +24,19 @@ #ifndef __INTEL_FRONTBUFFER_H__ #define __INTEL_FRONTBUFFER_H__ +#include "i915_gem_object.h" + struct drm_i915_private; struct drm_i915_gem_object; +enum fb_op_origin { + ORIGIN_GTT, + ORIGIN_CPU, + ORIGIN_CS, + ORIGIN_FLIP, + ORIGIN_DIRTYFB, +}; + void intel_frontbuffer_flip_prepare(struct drm_i915_private *dev_priv, unsigned frontbuffer_bits); void intel_frontbuffer_flip_complete(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c index c58922226d47..37f60cb8e9e1 100644 --- a/drivers/gpu/drm/i915/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/intel_guc_submission.c @@ -567,7 +567,7 @@ static void inject_preempt_context(struct work_struct *work) preempt_work[engine->id]); struct intel_guc_client *client = guc->preempt_client; struct guc_stage_desc *stage_desc = __get_stage_desc(client); - struct intel_context *ce = intel_context_lookup(client->owner, engine); + struct intel_context *ce = engine->preempt_context; u32 data[7]; if (!ce->ring->emit) { /* recreate upon load/resume */ @@ -650,9 +650,10 @@ static void wait_for_guc_preempt_report(struct intel_engine_cs *engine) struct guc_ctx_report *report = &data->preempt_ctx_report[engine->guc_id]; - WARN_ON(wait_for_atomic(report->report_return_status == - INTEL_GUC_REPORT_STATUS_COMPLETE, - GUC_PREEMPT_POSTPROCESS_DELAY_MS)); + if (wait_for_atomic(report->report_return_status == + INTEL_GUC_REPORT_STATUS_COMPLETE, + GUC_PREEMPT_POSTPROCESS_DELAY_MS)) + DRM_ERROR("Timed out waiting for GuC preemption report\n"); /* * GuC is expecting that we're also going to clear the affected context * counter, let's also reset the return status to not depend on GuC @@ -871,6 +872,104 @@ static void guc_reset_prepare(struct intel_engine_cs *engine) flush_workqueue(engine->i915->guc.preempt_wq); } +static void guc_reset(struct intel_engine_cs *engine, bool stalled) +{ + struct intel_engine_execlists * const execlists = &engine->execlists; + struct i915_request *rq; + unsigned long flags; + + spin_lock_irqsave(&engine->timeline.lock, flags); + + execlists_cancel_port_requests(execlists); + + /* Push back any incomplete requests for replay after the reset. */ + rq = execlists_unwind_incomplete_requests(execlists); + if (!rq) + goto out_unlock; + + if (!i915_request_started(rq)) + stalled = false; + + i915_reset_request(rq, stalled); + intel_lr_context_reset(engine, rq->hw_context, rq->head, stalled); + +out_unlock: + spin_unlock_irqrestore(&engine->timeline.lock, flags); +} + +static void guc_cancel_requests(struct intel_engine_cs *engine) +{ + struct intel_engine_execlists * const execlists = &engine->execlists; + struct i915_request *rq, *rn; + struct rb_node *rb; + unsigned long flags; + + GEM_TRACE("%s\n", engine->name); + + /* + * Before we call engine->cancel_requests(), we should have exclusive + * access to the submission state. This is arranged for us by the + * caller disabling the interrupt generation, the tasklet and other + * threads that may then access the same state, giving us a free hand + * to reset state. However, we still need to let lockdep be aware that + * we know this state may be accessed in hardirq context, so we + * disable the irq around this manipulation and we want to keep + * the spinlock focused on its duties and not accidentally conflate + * coverage to the submission's irq state. (Similarly, although we + * shouldn't need to disable irq around the manipulation of the + * submission's irq state, we also wish to remind ourselves that + * it is irq state.) + */ + spin_lock_irqsave(&engine->timeline.lock, flags); + + /* Cancel the requests on the HW and clear the ELSP tracker. */ + execlists_cancel_port_requests(execlists); + + /* Mark all executing requests as skipped. */ + list_for_each_entry(rq, &engine->timeline.requests, link) { + if (!i915_request_signaled(rq)) + dma_fence_set_error(&rq->fence, -EIO); + + i915_request_mark_complete(rq); + } + + /* Flush the queued requests to the timeline list (for retiring). */ + while ((rb = rb_first_cached(&execlists->queue))) { + struct i915_priolist *p = to_priolist(rb); + int i; + + priolist_for_each_request_consume(rq, rn, p, i) { + list_del_init(&rq->sched.link); + __i915_request_submit(rq); + dma_fence_set_error(&rq->fence, -EIO); + i915_request_mark_complete(rq); + } + + rb_erase_cached(&p->node, &execlists->queue); + i915_priolist_free(p); + } + + /* Remaining _unready_ requests will be nop'ed when submitted */ + + execlists->queue_priority_hint = INT_MIN; + execlists->queue = RB_ROOT_CACHED; + GEM_BUG_ON(port_isset(execlists->port)); + + spin_unlock_irqrestore(&engine->timeline.lock, flags); +} + +static void guc_reset_finish(struct intel_engine_cs *engine) +{ + struct intel_engine_execlists * const execlists = &engine->execlists; + + if (__tasklet_enable(&execlists->tasklet)) + /* And kick in case we missed a new request submission. */ + tasklet_hi_schedule(&execlists->tasklet); + + GEM_TRACE("%s: depth->%d\n", engine->name, + atomic_read(&execlists->tasklet.count)); +} + /* * Everything below here is concerned with setup & teardown, and is * therefore not part of the somewhat time-critical batch-submission @@ -1292,6 +1391,10 @@ static void guc_set_default_submission(struct intel_engine_cs *engine) engine->unpark = guc_submission_unpark; engine->reset.prepare = guc_reset_prepare; + engine->reset.reset = guc_reset; + engine->reset.finish = guc_reset_finish; + + engine->cancel_requests = guc_cancel_requests; engine->flags &= ~I915_ENGINE_SUPPORTS_STATS; } diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c index 86965fa37739..99b007169c49 100644 --- a/drivers/gpu/drm/i915/intel_hdcp.c +++ b/drivers/gpu/drm/i915/intel_hdcp.c @@ -6,14 +6,16 @@ * Sean Paul <[email protected]> */ -#include <drm/drm_hdcp.h> -#include <drm/i915_component.h> +#include <linux/component.h> #include <linux/i2c.h> #include <linux/random.h> -#include <linux/component.h> -#include "intel_drv.h" +#include <drm/drm_hdcp.h> +#include <drm/i915_component.h> + #include "i915_reg.h" +#include "intel_drv.h" +#include "intel_hdcp.h" #define KEY_LOAD_TRIES 5 #define ENCRYPT_STATUS_CHANGE_TIMEOUT_MS 50 diff --git a/drivers/gpu/drm/i915/intel_hdcp.h b/drivers/gpu/drm/i915/intel_hdcp.h new file mode 100644 index 000000000000..a75f25f09d39 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_hdcp.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_HDCP_H__ +#define __INTEL_HDCP_H__ + +#include <linux/types.h> + +#include <drm/i915_drm.h> + +struct drm_connector; +struct drm_connector_state; +struct drm_i915_private; +struct intel_connector; +struct intel_hdcp_shim; + +void intel_hdcp_atomic_check(struct drm_connector *connector, + struct drm_connector_state *old_state, + struct drm_connector_state *new_state); +int intel_hdcp_init(struct intel_connector *connector, + const struct intel_hdcp_shim *hdcp_shim); +int intel_hdcp_enable(struct intel_connector *connector); +int intel_hdcp_disable(struct intel_connector *connector); +bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port); +bool intel_hdcp_capable(struct intel_connector *connector); +void intel_hdcp_component_init(struct drm_i915_private *dev_priv); +void intel_hdcp_component_fini(struct drm_i915_private *dev_priv); +void intel_hdcp_cleanup(struct intel_connector *connector); +void intel_hdcp_handle_cp_irq(struct intel_connector *connector); + +#endif /* __INTEL_HDCP_H__ */ diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 26767785f14a..e1005d7b75fd 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -26,19 +26,30 @@ * Jesse Barnes <[email protected]> */ -#include <linux/i2c.h> -#include <linux/slab.h> #include <linux/delay.h> #include <linux/hdmi.h> +#include <linux/i2c.h> +#include <linux/slab.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_edid.h> #include <drm/drm_hdcp.h> #include <drm/drm_scdc_helper.h> -#include "intel_drv.h" #include <drm/i915_drm.h> #include <drm/intel_lpe_audio.h> + #include "i915_drv.h" +#include "intel_audio.h" +#include "intel_connector.h" +#include "intel_ddi.h" +#include "intel_dp.h" +#include "intel_drv.h" +#include "intel_hdcp.h" +#include "intel_hdmi.h" +#include "intel_lspcon.h" +#include "intel_sdvo.h" +#include "intel_panel.h" static struct drm_device *intel_hdmi_to_dev(struct intel_hdmi *intel_hdmi) { diff --git a/drivers/gpu/drm/i915/intel_hdmi.h b/drivers/gpu/drm/i915/intel_hdmi.h new file mode 100644 index 000000000000..106c2e0bc3c9 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_hdmi.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_HDMI_H__ +#define __INTEL_HDMI_H__ + +#include <linux/hdmi.h> +#include <linux/types.h> + +#include <drm/i915_drm.h> + +#include "i915_reg.h" + +struct drm_connector; +struct drm_encoder; +struct drm_i915_private; +struct intel_connector; +struct intel_digital_port; +struct intel_encoder; +struct intel_crtc_state; +struct intel_hdmi; +struct drm_connector_state; +union hdmi_infoframe; + +void intel_hdmi_init(struct drm_i915_private *dev_priv, 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); +int intel_hdmi_compute_config(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state); +bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, + struct drm_connector *connector, + bool high_tmds_clock_ratio, + bool scrambling); +void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable); +void intel_infoframe_init(struct intel_digital_port *intel_dig_port); +u32 intel_hdmi_infoframes_enabled(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state); +u32 intel_hdmi_infoframe_enable(unsigned int type); +void intel_hdmi_read_gcp_infoframe(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state); +void intel_read_infoframe(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + enum hdmi_infoframe_type type, + union hdmi_infoframe *frame); + +#endif /* __INTEL_HDMI_H__ */ diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index bec232acc8d7..4e0a351bfbca 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -233,7 +233,7 @@ static inline bool need_preempt(const struct intel_engine_cs *engine, { int last_prio; - if (!intel_engine_has_preemption(engine)) + if (!engine->preempt_context) return false; if (i915_request_completed(rq)) @@ -429,13 +429,13 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine) return active; } -void +struct i915_request * execlists_unwind_incomplete_requests(struct intel_engine_execlists *execlists) { struct intel_engine_cs *engine = container_of(execlists, typeof(*engine), execlists); - __unwind_incomplete_requests(engine); + return __unwind_incomplete_requests(engine); } static inline void @@ -893,96 +893,6 @@ invalidate_csb_entries(const u32 *first, const u32 *last) clflush((void *)last); } -static void reset_csb_pointers(struct intel_engine_execlists *execlists) -{ - const unsigned int reset_value = GEN8_CSB_ENTRIES - 1; - - /* - * After a reset, the HW starts writing into CSB entry [0]. We - * therefore have to set our HEAD pointer back one entry so that - * the *first* entry we check is entry 0. To complicate this further, - * as we don't wait for the first interrupt after reset, we have to - * fake the HW write to point back to the last entry so that our - * inline comparison of our cached head position against the last HW - * write works even before the first interrupt. - */ - execlists->csb_head = reset_value; - WRITE_ONCE(*execlists->csb_write, reset_value); - - invalidate_csb_entries(&execlists->csb_status[0], - &execlists->csb_status[GEN8_CSB_ENTRIES - 1]); -} - -static void nop_submission_tasklet(unsigned long data) -{ - /* The driver is wedged; don't process any more events. */ -} - -static void execlists_cancel_requests(struct intel_engine_cs *engine) -{ - struct intel_engine_execlists * const execlists = &engine->execlists; - struct i915_request *rq, *rn; - struct rb_node *rb; - unsigned long flags; - - GEM_TRACE("%s\n", engine->name); - - /* - * Before we call engine->cancel_requests(), we should have exclusive - * access to the submission state. This is arranged for us by the - * caller disabling the interrupt generation, the tasklet and other - * threads that may then access the same state, giving us a free hand - * to reset state. However, we still need to let lockdep be aware that - * we know this state may be accessed in hardirq context, so we - * disable the irq around this manipulation and we want to keep - * the spinlock focused on its duties and not accidentally conflate - * coverage to the submission's irq state. (Similarly, although we - * shouldn't need to disable irq around the manipulation of the - * submission's irq state, we also wish to remind ourselves that - * it is irq state.) - */ - spin_lock_irqsave(&engine->timeline.lock, flags); - - /* Cancel the requests on the HW and clear the ELSP tracker. */ - execlists_cancel_port_requests(execlists); - execlists_user_end(execlists); - - /* Mark all executing requests as skipped. */ - list_for_each_entry(rq, &engine->timeline.requests, link) { - if (!i915_request_signaled(rq)) - dma_fence_set_error(&rq->fence, -EIO); - - i915_request_mark_complete(rq); - } - - /* Flush the queued requests to the timeline list (for retiring). */ - while ((rb = rb_first_cached(&execlists->queue))) { - struct i915_priolist *p = to_priolist(rb); - int i; - - priolist_for_each_request_consume(rq, rn, p, i) { - list_del_init(&rq->sched.link); - __i915_request_submit(rq); - dma_fence_set_error(&rq->fence, -EIO); - i915_request_mark_complete(rq); - } - - rb_erase_cached(&p->node, &execlists->queue); - i915_priolist_free(p); - } - - /* Remaining _unready_ requests will be nop'ed when submitted */ - - execlists->queue_priority_hint = INT_MIN; - execlists->queue = RB_ROOT_CACHED; - GEM_BUG_ON(port_isset(execlists->port)); - - GEM_BUG_ON(__tasklet_is_enabled(&execlists->tasklet)); - execlists->tasklet.func = nop_submission_tasklet; - - spin_unlock_irqrestore(&engine->timeline.lock, flags); -} - static inline bool reset_in_progress(const struct intel_engine_execlists *execlists) { @@ -994,6 +904,7 @@ static void process_csb(struct intel_engine_cs *engine) struct intel_engine_execlists * const execlists = &engine->execlists; struct execlist_port *port = execlists->port; const u32 * const buf = execlists->csb_status; + const u8 num_entries = execlists->csb_size; u8 head, tail; lockdep_assert_held(&engine->timeline.lock); @@ -1029,7 +940,7 @@ static void process_csb(struct intel_engine_cs *engine) unsigned int status; unsigned int count; - if (++head == GEN8_CSB_ENTRIES) + if (++head == num_entries) head = 0; /* @@ -1151,7 +1062,7 @@ static void process_csb(struct intel_engine_cs *engine) * the wash as hardware, working or not, will need to do the * invalidation before. */ - invalidate_csb_entries(&buf[0], &buf[GEN8_CSB_ENTRIES - 1]); + invalidate_csb_entries(&buf[0], &buf[num_entries - 1]); } static void __execlists_submission_tasklet(struct intel_engine_cs *const engine) @@ -1379,9 +1290,33 @@ static int execlists_context_pin(struct intel_context *ce) return __execlists_context_pin(ce, ce->engine); } +static void execlists_context_reset(struct intel_context *ce) +{ + /* + * Because we emit WA_TAIL_DWORDS there may be a disparity + * between our bookkeeping in ce->ring->head and ce->ring->tail and + * that stored in context. As we only write new commands from + * ce->ring->tail onwards, everything before that is junk. If the GPU + * starts reading from its RING_HEAD from the context, it may try to + * execute that junk and die. + * + * The contexts that are stilled pinned on resume belong to the + * kernel, and are local to each engine. All other contexts will + * have their head/tail sanitized upon pinning before use, so they + * will never see garbage, + * + * So to avoid that we reset the context images upon resume. For + * simplicity, we just zero everything out. + */ + intel_ring_reset(ce->ring, 0); + __execlists_update_reg_state(ce, ce->engine); +} + static const struct intel_context_ops execlists_context_ops = { .pin = execlists_context_pin, .unpin = execlists_context_unpin, + + .reset = execlists_context_reset, .destroy = execlists_context_destroy, }; @@ -1451,10 +1386,11 @@ static int emit_pdps(struct i915_request *rq) *cs++ = MI_LOAD_REGISTER_IMM(2 * GEN8_3LVL_PDPES) | MI_LRI_FORCE_POSTED; for (i = GEN8_3LVL_PDPES; i--; ) { const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i); + u32 base = engine->mmio_base; - *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_UDW(engine, i)); + *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_UDW(base, i)); *cs++ = upper_32_bits(pd_daddr); - *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_LDW(engine, i)); + *cs++ = i915_mmio_reg_offset(GEN8_RING_PDP_LDW(base, i)); *cs++ = lower_32_bits(pd_daddr); } *cs++ = MI_NOOP; @@ -1823,17 +1759,9 @@ static void enable_execlists(struct intel_engine_cs *engine) intel_engine_set_hwsp_writemask(engine, ~0u); /* HWSTAM */ - /* - * Make sure we're not enabling the new 12-deep CSB - * FIFO as that requires a slightly updated handling - * in the ctx switch irq. Since we're currently only - * using only 2 elements of the enhanced execlists the - * deeper FIFO it's not needed and it's not worth adding - * more statements to the irq handler to support it. - */ if (INTEL_GEN(dev_priv) >= 11) I915_WRITE(RING_MODE_GEN7(engine), - _MASKED_BIT_DISABLE(GEN11_GFX_DISABLE_LEGACY_MODE)); + _MASKED_BIT_ENABLE(GEN11_GFX_DISABLE_LEGACY_MODE)); else I915_WRITE(RING_MODE_GEN7(engine), _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE)); @@ -1903,7 +1831,6 @@ static void execlists_reset_prepare(struct intel_engine_cs *engine) /* And flush any current direct submission. */ spin_lock_irqsave(&engine->timeline.lock, flags); - process_csb(engine); /* drain preemption events */ spin_unlock_irqrestore(&engine->timeline.lock, flags); } @@ -1924,14 +1851,48 @@ static bool lrc_regs_ok(const struct i915_request *rq) return true; } -static void execlists_reset(struct intel_engine_cs *engine, bool stalled) +static void reset_csb_pointers(struct intel_engine_execlists *execlists) +{ + const unsigned int reset_value = execlists->csb_size - 1; + + /* + * After a reset, the HW starts writing into CSB entry [0]. We + * therefore have to set our HEAD pointer back one entry so that + * the *first* entry we check is entry 0. To complicate this further, + * as we don't wait for the first interrupt after reset, we have to + * fake the HW write to point back to the last entry so that our + * inline comparison of our cached head position against the last HW + * write works even before the first interrupt. + */ + execlists->csb_head = reset_value; + WRITE_ONCE(*execlists->csb_write, reset_value); + wmb(); /* Make sure this is visible to HW (paranoia?) */ + + invalidate_csb_entries(&execlists->csb_status[0], + &execlists->csb_status[reset_value]); +} + +static void __execlists_reset(struct intel_engine_cs *engine, bool stalled) { struct intel_engine_execlists * const execlists = &engine->execlists; + struct intel_context *ce; struct i915_request *rq; - unsigned long flags; u32 *regs; - spin_lock_irqsave(&engine->timeline.lock, flags); + process_csb(engine); /* drain preemption events */ + + /* Following the reset, we need to reload the CSB read/write pointers */ + reset_csb_pointers(&engine->execlists); + + /* + * Save the currently executing context, even if we completed + * its request, it was still running at the time of the + * reset and will have been clobbered. + */ + if (!port_isset(execlists->port)) + goto out_clear; + + ce = port_request(execlists->port)->hw_context; /* * Catch up with any missed context-switch interrupts. @@ -1946,12 +1907,13 @@ static void execlists_reset(struct intel_engine_cs *engine, bool stalled) /* Push back any incomplete requests for replay after the reset. */ rq = __unwind_incomplete_requests(engine); - - /* Following the reset, we need to reload the CSB read/write pointers */ - reset_csb_pointers(&engine->execlists); - if (!rq) - goto out_unlock; + goto out_replay; + + if (rq->hw_context != ce) { /* caught just before a CS event */ + rq = NULL; + goto out_replay; + } /* * If this request hasn't started yet, e.g. it is waiting on a @@ -1966,7 +1928,7 @@ static void execlists_reset(struct intel_engine_cs *engine, bool stalled) * perfectly and we do not need to flag the result as being erroneous. */ if (!i915_request_started(rq) && lrc_regs_ok(rq)) - goto out_unlock; + goto out_replay; /* * If the request was innocent, we leave the request in the ELSP @@ -1981,7 +1943,7 @@ static void execlists_reset(struct intel_engine_cs *engine, bool stalled) */ i915_reset_request(rq, stalled); if (!stalled && lrc_regs_ok(rq)) - goto out_unlock; + goto out_replay; /* * We want a simple context + ring to execute the breadcrumb update. @@ -1991,21 +1953,103 @@ static void execlists_reset(struct intel_engine_cs *engine, bool stalled) * future request will be after userspace has had the opportunity * to recreate its own state. */ - regs = rq->hw_context->lrc_reg_state; + regs = ce->lrc_reg_state; if (engine->pinned_default_state) { memcpy(regs, /* skip restoring the vanilla PPHWSP */ engine->pinned_default_state + LRC_STATE_PN * PAGE_SIZE, engine->context_size - PAGE_SIZE); } + execlists_init_reg_state(regs, ce, engine, ce->ring); /* Rerun the request; its payload has been neutered (if guilty). */ - rq->ring->head = intel_ring_wrap(rq->ring, rq->head); - intel_ring_update_space(rq->ring); +out_replay: + ce->ring->head = + rq ? intel_ring_wrap(ce->ring, rq->head) : ce->ring->tail; + intel_ring_update_space(ce->ring); + __execlists_update_reg_state(ce, engine); - execlists_init_reg_state(regs, rq->hw_context, engine, rq->ring); - __execlists_update_reg_state(rq->hw_context, engine); +out_clear: + execlists_clear_all_active(execlists); +} + +static void execlists_reset(struct intel_engine_cs *engine, bool stalled) +{ + unsigned long flags; + + GEM_TRACE("%s\n", engine->name); + + spin_lock_irqsave(&engine->timeline.lock, flags); + + __execlists_reset(engine, stalled); + + spin_unlock_irqrestore(&engine->timeline.lock, flags); +} + +static void nop_submission_tasklet(unsigned long data) +{ + /* The driver is wedged; don't process any more events. */ +} + +static void execlists_cancel_requests(struct intel_engine_cs *engine) +{ + struct intel_engine_execlists * const execlists = &engine->execlists; + struct i915_request *rq, *rn; + struct rb_node *rb; + unsigned long flags; + + GEM_TRACE("%s\n", engine->name); + + /* + * Before we call engine->cancel_requests(), we should have exclusive + * access to the submission state. This is arranged for us by the + * caller disabling the interrupt generation, the tasklet and other + * threads that may then access the same state, giving us a free hand + * to reset state. However, we still need to let lockdep be aware that + * we know this state may be accessed in hardirq context, so we + * disable the irq around this manipulation and we want to keep + * the spinlock focused on its duties and not accidentally conflate + * coverage to the submission's irq state. (Similarly, although we + * shouldn't need to disable irq around the manipulation of the + * submission's irq state, we also wish to remind ourselves that + * it is irq state.) + */ + spin_lock_irqsave(&engine->timeline.lock, flags); + + __execlists_reset(engine, true); + + /* Mark all executing requests as skipped. */ + list_for_each_entry(rq, &engine->timeline.requests, link) { + if (!i915_request_signaled(rq)) + dma_fence_set_error(&rq->fence, -EIO); + + i915_request_mark_complete(rq); + } + + /* Flush the queued requests to the timeline list (for retiring). */ + while ((rb = rb_first_cached(&execlists->queue))) { + struct i915_priolist *p = to_priolist(rb); + int i; + + priolist_for_each_request_consume(rq, rn, p, i) { + list_del_init(&rq->sched.link); + __i915_request_submit(rq); + dma_fence_set_error(&rq->fence, -EIO); + i915_request_mark_complete(rq); + } + + rb_erase_cached(&p->node, &execlists->queue); + i915_priolist_free(p); + } + + /* Remaining _unready_ requests will be nop'ed when submitted */ + + execlists->queue_priority_hint = INT_MIN; + execlists->queue = RB_ROOT_CACHED; + GEM_BUG_ON(port_isset(execlists->port)); + + GEM_BUG_ON(__tasklet_is_enabled(&execlists->tasklet)); + execlists->tasklet.func = nop_submission_tasklet; -out_unlock: spin_unlock_irqrestore(&engine->timeline.lock, flags); } @@ -2035,7 +2079,7 @@ static int gen8_emit_bb_start(struct i915_request *rq, { u32 *cs; - cs = intel_ring_begin(rq, 6); + cs = intel_ring_begin(rq, 4); if (IS_ERR(cs)) return PTR_ERR(cs); @@ -2046,19 +2090,37 @@ static int gen8_emit_bb_start(struct i915_request *rq, * particular all the gen that do not need the w/a at all!), if we * took care to make sure that on every switch into this context * (both ordinary and for preemption) that arbitrartion was enabled - * we would be fine. However, there doesn't seem to be a downside to - * being paranoid and making sure it is set before each batch and - * every context-switch. - * - * Note that if we fail to enable arbitration before the request - * is complete, then we do not see the context-switch interrupt and - * the engine hangs (with RING_HEAD == RING_TAIL). - * - * That satisfies both the GPGPU w/a and our heavy-handed paranoia. + * we would be fine. However, for gen8 there is another w/a that + * requires us to not preempt inside GPGPU execution, so we keep + * arbitration disabled for gen8 batches. Arbitration will be + * re-enabled before we close the request + * (engine->emit_fini_breadcrumb). */ + *cs++ = MI_ARB_ON_OFF | MI_ARB_DISABLE; + + /* FIXME(BDW+): Address space and security selectors. */ + *cs++ = MI_BATCH_BUFFER_START_GEN8 | + (flags & I915_DISPATCH_SECURE ? 0 : BIT(8)); + *cs++ = lower_32_bits(offset); + *cs++ = upper_32_bits(offset); + + intel_ring_advance(rq, cs); + + return 0; +} + +static int gen9_emit_bb_start(struct i915_request *rq, + u64 offset, u32 len, + const unsigned int flags) +{ + u32 *cs; + + cs = intel_ring_begin(rq, 6); + if (IS_ERR(cs)) + return PTR_ERR(cs); + *cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE; - /* FIXME(BDW): Address space and security selectors. */ *cs++ = MI_BATCH_BUFFER_START_GEN8 | (flags & I915_DISPATCH_SECURE ? 0 : BIT(8)); *cs++ = lower_32_bits(offset); @@ -2309,6 +2371,8 @@ void intel_execlists_set_default_submission(struct intel_engine_cs *engine) engine->execlists.tasklet.func = execlists_submission_tasklet; engine->reset.prepare = execlists_reset_prepare; + engine->reset.reset = execlists_reset; + engine->reset.finish = execlists_reset_finish; engine->park = NULL; engine->unpark = NULL; @@ -2316,7 +2380,8 @@ void intel_execlists_set_default_submission(struct intel_engine_cs *engine) engine->flags |= I915_ENGINE_SUPPORTS_STATS; if (!intel_vgpu_active(engine->i915)) engine->flags |= I915_ENGINE_HAS_SEMAPHORES; - if (engine->preempt_context) + if (engine->preempt_context && + HAS_LOGICAL_RING_PREEMPTION(engine->i915)) engine->flags |= I915_ENGINE_HAS_PREEMPTION; } @@ -2350,7 +2415,10 @@ logical_ring_default_vfuncs(struct intel_engine_cs *engine) * until a more refined solution exists. */ } - engine->emit_bb_start = gen8_emit_bb_start; + if (IS_GEN(engine->i915, 8)) + engine->emit_bb_start = gen8_emit_bb_start; + else + engine->emit_bb_start = gen9_emit_bb_start; } static inline void @@ -2429,6 +2497,11 @@ static int logical_ring_init(struct intel_engine_cs *engine) execlists->csb_write = &engine->status_page.addr[intel_hws_csb_write_index(i915)]; + if (INTEL_GEN(engine->i915) < 11) + execlists->csb_size = GEN8_CSB_ENTRIES; + else + execlists->csb_size = GEN11_CSB_ENTRIES; + reset_csb_pointers(execlists); return 0; @@ -2707,14 +2780,14 @@ static void execlists_init_reg_state(u32 *regs, CTX_REG(regs, CTX_CTX_TIMESTAMP, RING_CTX_TIMESTAMP(base), 0); /* PDP values well be assigned later if needed */ - CTX_REG(regs, CTX_PDP3_UDW, GEN8_RING_PDP_UDW(engine, 3), 0); - CTX_REG(regs, CTX_PDP3_LDW, GEN8_RING_PDP_LDW(engine, 3), 0); - CTX_REG(regs, CTX_PDP2_UDW, GEN8_RING_PDP_UDW(engine, 2), 0); - CTX_REG(regs, CTX_PDP2_LDW, GEN8_RING_PDP_LDW(engine, 2), 0); - CTX_REG(regs, CTX_PDP1_UDW, GEN8_RING_PDP_UDW(engine, 1), 0); - CTX_REG(regs, CTX_PDP1_LDW, GEN8_RING_PDP_LDW(engine, 1), 0); - CTX_REG(regs, CTX_PDP0_UDW, GEN8_RING_PDP_UDW(engine, 0), 0); - CTX_REG(regs, CTX_PDP0_LDW, GEN8_RING_PDP_LDW(engine, 0), 0); + CTX_REG(regs, CTX_PDP3_UDW, GEN8_RING_PDP_UDW(base, 3), 0); + CTX_REG(regs, CTX_PDP3_LDW, GEN8_RING_PDP_LDW(base, 3), 0); + CTX_REG(regs, CTX_PDP2_UDW, GEN8_RING_PDP_UDW(base, 2), 0); + CTX_REG(regs, CTX_PDP2_LDW, GEN8_RING_PDP_LDW(base, 2), 0); + CTX_REG(regs, CTX_PDP1_UDW, GEN8_RING_PDP_UDW(base, 1), 0); + CTX_REG(regs, CTX_PDP1_LDW, GEN8_RING_PDP_LDW(base, 1), 0); + CTX_REG(regs, CTX_PDP0_UDW, GEN8_RING_PDP_UDW(base, 0), 0); + CTX_REG(regs, CTX_PDP0_LDW, GEN8_RING_PDP_LDW(base, 0), 0); if (i915_vm_is_4lvl(&ppgtt->vm)) { /* 64b PPGTT (48bit canonical) @@ -2872,31 +2945,6 @@ error_deref_obj: return ret; } -void intel_lr_context_resume(struct drm_i915_private *i915) -{ - struct i915_gem_context *ctx; - struct intel_context *ce; - - /* - * Because we emit WA_TAIL_DWORDS there may be a disparity - * between our bookkeeping in ce->ring->head and ce->ring->tail and - * that stored in context. As we only write new commands from - * ce->ring->tail onwards, everything before that is junk. If the GPU - * starts reading from its RING_HEAD from the context, it may try to - * execute that junk and die. - * - * So to avoid that we reset the context images upon resume. For - * simplicity, we just zero everything out. - */ - list_for_each_entry(ctx, &i915->contexts.list, link) { - list_for_each_entry(ce, &ctx->active_engines, active_link) { - GEM_BUG_ON(!ce->ring); - intel_ring_reset(ce->ring, 0); - __execlists_update_reg_state(ce, ce->engine); - } - } -} - void intel_execlists_show_requests(struct intel_engine_cs *engine, struct drm_printer *m, void (*show_request)(struct drm_printer *m, @@ -2957,6 +3005,37 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine, spin_unlock_irqrestore(&engine->timeline.lock, flags); } +void intel_lr_context_reset(struct intel_engine_cs *engine, + struct intel_context *ce, + u32 head, + bool scrub) +{ + /* + * We want a simple context + ring to execute the breadcrumb update. + * We cannot rely on the context being intact across the GPU hang, + * so clear it and rebuild just what we need for the breadcrumb. + * All pending requests for this context will be zapped, and any + * future request will be after userspace has had the opportunity + * to recreate its own state. + */ + if (scrub) { + u32 *regs = ce->lrc_reg_state; + + if (engine->pinned_default_state) { + memcpy(regs, /* skip restoring the vanilla PPHWSP */ + engine->pinned_default_state + LRC_STATE_PN * PAGE_SIZE, + engine->context_size - PAGE_SIZE); + } + execlists_init_reg_state(regs, ce, engine, ce->ring); + } + + /* Rerun the request; its payload has been neutered (if guilty). */ + ce->ring->head = head; + intel_ring_update_space(ce->ring); + + __execlists_update_reg_state(ce, engine); +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/intel_lrc.c" #endif diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 92642ab91472..84aa230ea27b 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -36,12 +36,10 @@ #define CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT (1 << 0) #define CTX_CTRL_RS_CTX_ENABLE (1 << 1) #define CTX_CTRL_ENGINE_CTX_SAVE_INHIBIT (1 << 2) -#define RING_CONTEXT_STATUS_BUF_BASE(base) _MMIO((base) + 0x370) -#define RING_CONTEXT_STATUS_BUF_LO(base, i) _MMIO((base) + 0x370 + (i) * 8) -#define RING_CONTEXT_STATUS_BUF_HI(base, i) _MMIO((base) + 0x370 + (i) * 8 + 4) #define RING_CONTEXT_STATUS_PTR(base) _MMIO((base) + 0x3a0) #define RING_EXECLIST_SQ_CONTENTS(base) _MMIO((base) + 0x510) #define RING_EXECLIST_CONTROL(base) _MMIO((base) + 0x550) + #define EL_CTRL_LOAD (1 << 0) /* The docs specify that the write pointer wraps around after 5h, "After status @@ -55,10 +53,11 @@ #define GEN8_CSB_PTR_MASK 0x7 #define GEN8_CSB_READ_PTR_MASK (GEN8_CSB_PTR_MASK << 8) #define GEN8_CSB_WRITE_PTR_MASK (GEN8_CSB_PTR_MASK << 0) -#define GEN8_CSB_WRITE_PTR(csb_status) \ - (((csb_status) & GEN8_CSB_WRITE_PTR_MASK) >> 0) -#define GEN8_CSB_READ_PTR(csb_status) \ - (((csb_status) & GEN8_CSB_READ_PTR_MASK) >> 8) + +#define GEN11_CSB_ENTRIES 12 +#define GEN11_CSB_PTR_MASK 0xf +#define GEN11_CSB_READ_PTR_MASK (GEN11_CSB_PTR_MASK << 8) +#define GEN11_CSB_WRITE_PTR_MASK (GEN11_CSB_PTR_MASK << 0) enum { INTEL_CONTEXT_SCHEDULE_IN = 0, @@ -102,9 +101,13 @@ struct drm_printer; struct drm_i915_private; struct i915_gem_context; -void intel_lr_context_resume(struct drm_i915_private *dev_priv); void intel_execlists_set_default_submission(struct intel_engine_cs *engine); +void intel_lr_context_reset(struct intel_engine_cs *engine, + struct intel_context *ce, + u32 head, + bool scrub); + void intel_execlists_show_requests(struct intel_engine_cs *engine, struct drm_printer *m, void (*show_request)(struct drm_printer *m, diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c index 8d202b13e24f..7028d0cf3bb1 100644 --- a/drivers/gpu/drm/i915/intel_lspcon.c +++ b/drivers/gpu/drm/i915/intel_lspcon.c @@ -22,10 +22,14 @@ * * */ -#include <drm/drm_edid.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_dp_dual_mode_helper.h> +#include <drm/drm_edid.h> + +#include "intel_dp.h" #include "intel_drv.h" +#include "intel_lspcon.h" /* LSPCON OUI Vendor ID(signatures) */ #define LSPCON_VENDOR_PARADE_OUI 0x001CF8 diff --git a/drivers/gpu/drm/i915/intel_lspcon.h b/drivers/gpu/drm/i915/intel_lspcon.h new file mode 100644 index 000000000000..37cfddf8a9c5 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_lspcon.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_LSPCON_H__ +#define __INTEL_LSPCON_H__ + +#include <linux/types.h> + +struct drm_connector; +struct drm_connector_state; +struct intel_crtc_state; +struct intel_digital_port; +struct intel_encoder; +struct intel_lspcon; + +bool lspcon_init(struct intel_digital_port *intel_dig_port); +void lspcon_resume(struct intel_lspcon *lspcon); +void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon); +void lspcon_write_infoframe(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + unsigned int type, + const void *buf, ssize_t len); +void lspcon_read_infoframe(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + unsigned int type, + void *frame, ssize_t len); +void lspcon_set_infoframes(struct intel_encoder *encoder, + bool enable, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state); +u32 lspcon_infoframes_enabled(struct intel_encoder *encoder, + const struct intel_crtc_state *pipe_config); +void lspcon_ycbcr420_config(struct drm_connector *connector, + struct intel_crtc_state *crtc_state); + +#endif /* __INTEL_LSPCON_H__ */ diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 34dd2d71814b..51d1d59c1619 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -28,17 +28,22 @@ */ #include <acpi/button.h> +#include <linux/acpi.h> #include <linux/dmi.h> #include <linux/i2c.h> #include <linux/slab.h> #include <linux/vga_switcheroo.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_edid.h> -#include "intel_drv.h" #include <drm/i915_drm.h> + #include "i915_drv.h" -#include <linux/acpi.h> +#include "intel_connector.h" +#include "intel_drv.h" +#include "intel_lvds.h" +#include "intel_panel.h" /* Private structure for the integrated LVDS support */ struct intel_lvds_pps { diff --git a/drivers/gpu/drm/i915/intel_lvds.h b/drivers/gpu/drm/i915/intel_lvds.h new file mode 100644 index 000000000000..bc9c8b84ba2f --- /dev/null +++ b/drivers/gpu/drm/i915/intel_lvds.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_LVDS_H__ +#define __INTEL_LVDS_H__ + +#include <linux/types.h> + +#include "i915_reg.h" + +enum pipe; +struct drm_i915_private; + +bool intel_lvds_port_enabled(struct drm_i915_private *dev_priv, + i915_reg_t lvds_reg, enum pipe *pipe); +void intel_lvds_init(struct drm_i915_private *dev_priv); +struct intel_encoder *intel_get_lvds_encoder(struct drm_i915_private *dev_priv); +bool intel_is_dual_link_lvds(struct drm_i915_private *dev_priv); + +#endif /* __INTEL_LVDS_H__ */ diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 5e00ee9270b5..8fa1159d097f 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -32,9 +32,10 @@ #include <drm/i915_drm.h> -#include "intel_opregion.h" #include "i915_drv.h" #include "intel_drv.h" +#include "intel_opregion.h" +#include "intel_panel.h" #define OPREGION_HEADER_OFFSET 0 #define OPREGION_ACPI_OFFSET 0x100 diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 47cd4a338db6..4ab4ce6569e7 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -33,7 +33,10 @@ #include <linux/kernel.h> #include <linux/moduleparam.h> #include <linux/pwm.h> + +#include "intel_connector.h" #include "intel_drv.h" +#include "intel_panel.h" #define CRC_PMIC_PWM_PERIOD_NS 21333 diff --git a/drivers/gpu/drm/i915/intel_panel.h b/drivers/gpu/drm/i915/intel_panel.h new file mode 100644 index 000000000000..cedeea443336 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_panel.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_PANEL_H__ +#define __INTEL_PANEL_H__ + +#include <linux/types.h> + +#include "intel_display.h" + +struct drm_connector; +struct drm_connector_state; +struct drm_display_mode; +struct intel_connector; +struct intel_crtc; +struct intel_crtc_state; +struct intel_encoder; +struct intel_panel; + +int intel_panel_init(struct intel_panel *panel, + struct drm_display_mode *fixed_mode, + struct drm_display_mode *downclock_mode); +void intel_panel_fini(struct intel_panel *panel); +void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, + struct drm_display_mode *adjusted_mode); +void intel_pch_panel_fitting(struct intel_crtc *crtc, + struct intel_crtc_state *pipe_config, + int fitting_mode); +void intel_gmch_panel_fitting(struct intel_crtc *crtc, + struct intel_crtc_state *pipe_config, + int fitting_mode); +void intel_panel_set_backlight_acpi(const struct drm_connector_state *conn_state, + u32 level, u32 max); +int intel_panel_setup_backlight(struct drm_connector *connector, + enum pipe pipe); +void intel_panel_enable_backlight(const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state); +void intel_panel_update_backlight(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state); +void intel_panel_disable_backlight(const struct drm_connector_state *old_conn_state); +struct drm_display_mode * +intel_panel_edid_downclock_mode(struct intel_connector *connector, + const struct drm_display_mode *fixed_mode); +struct drm_display_mode * +intel_panel_edid_fixed_mode(struct intel_connector *connector); +struct drm_display_mode * +intel_panel_vbt_fixed_mode(struct intel_connector *connector); + +#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) +int intel_backlight_device_register(struct intel_connector *connector); +void intel_backlight_device_unregister(struct intel_connector *connector); +#else /* CONFIG_BACKLIGHT_CLASS_DEVICE */ +static inline int intel_backlight_device_register(struct intel_connector *connector) +{ + return 0; +} +static inline void intel_backlight_device_unregister(struct intel_connector *connector) +{ +} +#endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */ + +#endif /* __INTEL_PANEL_H__ */ diff --git a/drivers/gpu/drm/i915/intel_pipe_crc.c b/drivers/gpu/drm/i915/intel_pipe_crc.c index 0b1378f0bff7..e94b5b1bc1b7 100644 --- a/drivers/gpu/drm/i915/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/intel_pipe_crc.c @@ -24,11 +24,13 @@ * */ -#include <linux/seq_file.h> #include <linux/circ_buf.h> #include <linux/ctype.h> #include <linux/debugfs.h> +#include <linux/seq_file.h> + #include "intel_drv.h" +#include "intel_pipe_crc.h" static const char * const pipe_crc_sources[] = { [INTEL_PIPE_CRC_SOURCE_NONE] = "none", diff --git a/drivers/gpu/drm/i915/intel_pipe_crc.h b/drivers/gpu/drm/i915/intel_pipe_crc.h new file mode 100644 index 000000000000..81eaf1854788 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_pipe_crc.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_PIPE_CRC_H__ +#define __INTEL_PIPE_CRC_H__ + +#include <linux/types.h> + +struct drm_crtc; +struct intel_crtc; + +#ifdef CONFIG_DEBUG_FS +int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name); +int intel_crtc_verify_crc_source(struct drm_crtc *crtc, + const char *source_name, size_t *values_cnt); +const char *const *intel_crtc_get_crc_sources(struct drm_crtc *crtc, + size_t *count); +void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc); +void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc); +#else +#define intel_crtc_set_crc_source NULL +#define intel_crtc_verify_crc_source NULL +#define intel_crtc_get_crc_sources NULL +static inline void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc) +{ +} + +static inline void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc) +{ +} +#endif + +#endif /* __INTEL_PIPE_CRC_H__ */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0e05ee1f3ea0..44be676fabd6 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -35,6 +35,9 @@ #include "i915_drv.h" #include "intel_drv.h" +#include "intel_fbc.h" +#include "intel_pm.h" +#include "intel_sprite.h" #include "../../../platform/x86/intel_ips.h" /** @@ -4527,10 +4530,10 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, memset(&wm->wm[level], 0, sizeof(wm->wm[level])); /* - * Wa_1408961008:icl + * Wa_1408961008:icl, ehl * Underruns with WM1+ disabled */ - if (IS_ICELAKE(dev_priv) && + if (IS_GEN(dev_priv, 11) && level == 1 && wm->wm[0].plane_en) { wm->wm[level].plane_res_b = wm->wm[0].plane_res_b; wm->wm[level].plane_res_l = wm->wm[0].plane_res_l; @@ -5251,7 +5254,7 @@ static inline bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a, } bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry *ddb, - const struct skl_ddb_entry entries[], + const struct skl_ddb_entry *entries, int num_entries, int ignore_idx) { int i; @@ -6603,7 +6606,7 @@ static void rps_set_power(struct drm_i915_private *dev_priv, int new_power) ei_down * threshold_down / 100)); I915_WRITE(GEN6_RP_CONTROL, - GEN6_RP_MEDIA_TURBO | + (INTEL_GEN(dev_priv) > 9 ? 0 : GEN6_RP_MEDIA_TURBO) | GEN6_RP_MEDIA_HW_NORMAL_MODE | GEN6_RP_MEDIA_IS_GFX | GEN6_RP_ENABLE | @@ -7117,6 +7120,78 @@ static void gen9_enable_rps(struct drm_i915_private *dev_priv) intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL); } +static void gen11_enable_rc6(struct drm_i915_private *dev_priv) +{ + struct intel_engine_cs *engine; + enum intel_engine_id id; + + /* 1a: Software RC state - RC0 */ + I915_WRITE(GEN6_RC_STATE, 0); + + /* + * 1b: Get forcewake during program sequence. Although the driver + * hasn't enabled a state yet where we need forcewake, BIOS may have. + */ + intel_uncore_forcewake_get(&dev_priv->uncore, FORCEWAKE_ALL); + + /* 2a: Disable RC states. */ + I915_WRITE(GEN6_RC_CONTROL, 0); + + /* 2b: Program RC6 thresholds.*/ + I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16 | 85); + I915_WRITE(GEN10_MEDIA_WAKE_RATE_LIMIT, 150); + + I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ + I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ + for_each_engine(engine, dev_priv, id) + I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); + + if (HAS_GUC(dev_priv)) + I915_WRITE(GUC_MAX_IDLE_COUNT, 0xA); + + I915_WRITE(GEN6_RC_SLEEP, 0); + + I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */ + + /* + * 2c: Program Coarse Power Gating Policies. + * + * Bspec's guidance is to use 25us (really 25 * 1280ns) here. What we + * use instead is a more conservative estimate for the maximum time + * it takes us to service a CS interrupt and submit a new ELSP - that + * is the time which the GPU is idle waiting for the CPU to select the + * next request to execute. If the idle hysteresis is less than that + * interrupt service latency, the hardware will automatically gate + * the power well and we will then incur the wake up cost on top of + * the service latency. A similar guide from intel_pstate is that we + * do not want the enable hysteresis to less than the wakeup latency. + * + * igt/gem_exec_nop/sequential provides a rough estimate for the + * service latency, and puts it around 10us for Broadwell (and other + * big core) and around 40us for Broxton (and other low power cores). + * [Note that for legacy ringbuffer submission, this is less than 1us!] + * However, the wakeup latency on Broxton is closer to 100us. To be + * conservative, we have to factor in a context switch on top (due + * to ksoftirqd). + */ + I915_WRITE(GEN9_MEDIA_PG_IDLE_HYSTERESIS, 250); + I915_WRITE(GEN9_RENDER_PG_IDLE_HYSTERESIS, 250); + + /* 3a: Enable RC6 */ + I915_WRITE(GEN6_RC_CONTROL, + GEN6_RC_CTL_HW_ENABLE | + GEN6_RC_CTL_RC6_ENABLE | + GEN6_RC_CTL_EI_MODE(1)); + + /* 3b: Enable Coarse Power Gating only when RC6 is enabled. */ + I915_WRITE(GEN9_PG_ENABLE, + GEN9_RENDER_PG_ENABLE | + GEN9_MEDIA_PG_ENABLE | + GEN11_MEDIA_SAMPLER_PG_ENABLE); + + intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL); +} + static void gen9_enable_rc6(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; @@ -8188,14 +8263,14 @@ unsigned long i915_gfx_val(struct drm_i915_private *dev_priv) return val; } -static struct drm_i915_private *i915_mch_dev; +static struct drm_i915_private __rcu *i915_mch_dev; static struct drm_i915_private *mchdev_get(void) { struct drm_i915_private *i915; rcu_read_lock(); - i915 = i915_mch_dev; + i915 = rcu_dereference(i915_mch_dev); if (!kref_get_unless_zero(&i915->drm.ref)) i915 = NULL; rcu_read_unlock(); @@ -8593,6 +8668,8 @@ static void intel_enable_rc6(struct drm_i915_private *dev_priv) cherryview_enable_rc6(dev_priv); else if (IS_VALLEYVIEW(dev_priv)) valleyview_enable_rc6(dev_priv); + else if (INTEL_GEN(dev_priv) >= 11) + gen11_enable_rc6(dev_priv); else if (INTEL_GEN(dev_priv) >= 9) gen9_enable_rc6(dev_priv); else if (IS_BROADWELL(dev_priv)) @@ -9496,7 +9573,7 @@ static void nop_init_clock_gating(struct drm_i915_private *dev_priv) */ void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv) { - if (IS_ICELAKE(dev_priv)) + if (IS_GEN(dev_priv, 11)) dev_priv->display.init_clock_gating = icl_init_clock_gating; else if (IS_CANNONLAKE(dev_priv)) dev_priv->display.init_clock_gating = cnl_init_clock_gating; diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h new file mode 100644 index 000000000000..674a3f0f16a7 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_pm.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_PM_H__ +#define __INTEL_PM_H__ + +#include <linux/types.h> + +struct drm_atomic_state; +struct drm_device; +struct drm_i915_private; +struct i915_request; +struct intel_crtc; +struct intel_crtc_state; +struct intel_plane; +struct skl_ddb_allocation; +struct skl_ddb_entry; +struct skl_pipe_wm; +struct skl_wm_level; + +void intel_init_clock_gating(struct drm_i915_private *dev_priv); +void intel_suspend_hw(struct drm_i915_private *dev_priv); +int ilk_wm_max_level(const struct drm_i915_private *dev_priv); +void intel_update_watermarks(struct intel_crtc *crtc); +void intel_init_pm(struct drm_i915_private *dev_priv); +void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv); +void intel_pm_setup(struct drm_i915_private *dev_priv); +void intel_gpu_ips_init(struct drm_i915_private *dev_priv); +void intel_gpu_ips_teardown(void); +void intel_init_gt_powersave(struct drm_i915_private *dev_priv); +void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv); +void intel_sanitize_gt_powersave(struct drm_i915_private *dev_priv); +void intel_enable_gt_powersave(struct drm_i915_private *dev_priv); +void intel_disable_gt_powersave(struct drm_i915_private *dev_priv); +void gen6_rps_busy(struct drm_i915_private *dev_priv); +void gen6_rps_idle(struct drm_i915_private *dev_priv); +void gen6_rps_boost(struct i915_request *rq); +void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv); +void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv); +void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv); +void skl_wm_get_hw_state(struct drm_i915_private *dev_priv); +void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc, + struct skl_ddb_entry *ddb_y, + struct skl_ddb_entry *ddb_uv); +void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, + struct skl_ddb_allocation *ddb /* out */); +void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc, + struct skl_pipe_wm *out); +void g4x_wm_sanitize(struct drm_i915_private *dev_priv); +void vlv_wm_sanitize(struct drm_i915_private *dev_priv); +bool intel_can_enable_sagv(struct drm_atomic_state *state); +int intel_enable_sagv(struct drm_i915_private *dev_priv); +int intel_disable_sagv(struct drm_i915_private *dev_priv); +bool skl_wm_level_equals(const struct skl_wm_level *l1, + const struct skl_wm_level *l2); +bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry *ddb, + const struct skl_ddb_entry *entries, + int num_entries, int ignore_idx); +void skl_write_plane_wm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state); +void skl_write_cursor_wm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state); +bool ilk_disable_lp_wm(struct drm_device *dev); +int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc, + struct intel_crtc_state *cstate); +void intel_init_ipc(struct drm_i915_private *dev_priv); +void intel_enable_ipc(struct drm_i915_private *dev_priv); + +#endif /* __INTEL_PM_H__ */ diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index ec874d802d48..963663ba0edf 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -21,6 +21,14 @@ * DEALINGS IN THE SOFTWARE. */ +#include <drm/drm_atomic_helper.h> + +#include "i915_drv.h" +#include "intel_dp.h" +#include "intel_drv.h" +#include "intel_psr.h" +#include "intel_sprite.h" + /** * DOC: Panel Self Refresh (PSR/SRD) * @@ -51,11 +59,6 @@ * must be correctly synchronized/cancelled when shutting down the pipe." */ -#include <drm/drm_atomic_helper.h> - -#include "intel_drv.h" -#include "i915_drv.h" - static bool psr_global_enabled(u32 debug) { switch (debug & I915_PSR_DEBUG_MODE_MASK) { @@ -531,10 +534,8 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) val |= EDP_PSR2_TP2_TIME_2500us; /* - * FIXME: There is probably a issue in DMC firmwares(icl_dmc_ver1_07.bin - * and kbl_dmc_ver1_04.bin at least) that causes PSR2 SU to fail after - * exiting DC6 if EDP_PSR_TP1_TP3_SEL is kept in PSR_CTL, so for now - * lets workaround the issue by cleaning PSR_CTL before enable PSR2. + * PSR2 HW is incorrectly using EDP_PSR_TP1_TP3_SEL and BSpec is + * recommending keep this bit unset while PSR2 is enabled. */ I915_WRITE(EDP_PSR_CTL, 0); @@ -629,9 +630,8 @@ void intel_psr_compute_config(struct intel_dp *intel_dp, return; } - if (IS_HASWELL(dev_priv) && - adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { - DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n"); + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { + DRM_DEBUG_KMS("PSR condition failed: Interlaced mode enabled\n"); return; } @@ -1229,7 +1229,6 @@ void intel_psr_init(struct drm_i915_private *dev_priv) if (val) { DRM_DEBUG_KMS("PSR interruption error set\n"); dev_priv->psr.sink_not_reliable = true; - return; } /* Set link_standby x link_off defaults */ diff --git a/drivers/gpu/drm/i915/intel_psr.h b/drivers/gpu/drm/i915/intel_psr.h new file mode 100644 index 000000000000..dc818826f36d --- /dev/null +++ b/drivers/gpu/drm/i915/intel_psr.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_PSR_H__ +#define __INTEL_PSR_H__ + +#include "intel_frontbuffer.h" + +struct drm_i915_private; +struct intel_crtc_state; +struct intel_dp; + +#define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support) +void intel_psr_init_dpcd(struct intel_dp *intel_dp); +void intel_psr_enable(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); +void intel_psr_disable(struct intel_dp *intel_dp, + const struct intel_crtc_state *old_crtc_state); +void intel_psr_update(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); +int intel_psr_debug_set(struct drm_i915_private *dev_priv, u64 value); +void intel_psr_invalidate(struct drm_i915_private *dev_priv, + unsigned frontbuffer_bits, + enum fb_op_origin origin); +void intel_psr_flush(struct drm_i915_private *dev_priv, + unsigned frontbuffer_bits, + enum fb_op_origin origin); +void intel_psr_init(struct drm_i915_private *dev_priv); +void intel_psr_compute_config(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state); +void intel_psr_irq_control(struct drm_i915_private *dev_priv, u32 debug); +void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir); +void intel_psr_short_pulse(struct intel_dp *intel_dp); +int intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state, + u32 *out_value); +bool intel_psr_enabled(struct intel_dp *intel_dp); + +#endif /* __INTEL_PSR_H__ */ diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 8a19eee9c5d4..af35f99c5940 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1508,9 +1508,16 @@ err_unpin: return err; } +static void ring_context_reset(struct intel_context *ce) +{ + intel_ring_reset(ce->ring, 0); +} + static const struct intel_context_ops ring_context_ops = { .pin = ring_context_pin, .unpin = ring_context_unpin, + + .reset = ring_context_reset, .destroy = ring_context_destroy, }; @@ -1581,16 +1588,6 @@ void intel_engine_cleanup(struct intel_engine_cs *engine) kfree(engine); } -void intel_legacy_submission_resume(struct drm_i915_private *dev_priv) -{ - struct intel_engine_cs *engine; - enum intel_engine_id id; - - /* Restart from the beginning of the rings for convenience */ - for_each_engine(engine, dev_priv, id) - intel_ring_reset(engine->buffer, 0); -} - static int load_pd_dir(struct i915_request *rq, const struct i915_hw_ppgtt *ppgtt) { diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index e58d6f04177b..72c7c337ace9 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -165,7 +165,7 @@ void execlists_user_end(struct intel_engine_execlists *execlists); void execlists_cancel_port_requests(struct intel_engine_execlists * const execlists); -void +struct i915_request * execlists_unwind_incomplete_requests(struct intel_engine_execlists *execlists); static inline unsigned int @@ -268,8 +268,6 @@ static inline void intel_ring_put(struct intel_ring *ring) void intel_engine_stop(struct intel_engine_cs *engine); void intel_engine_cleanup(struct intel_engine_cs *engine); -void intel_legacy_submission_resume(struct drm_i915_private *dev_priv); - int __must_check intel_ring_cacheline_align(struct i915_request *rq); u32 __must_check *intel_ring_begin(struct i915_request *rq, unsigned int n); @@ -390,7 +388,7 @@ void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); void intel_engine_pin_breadcrumbs_irq(struct intel_engine_cs *engine); void intel_engine_unpin_breadcrumbs_irq(struct intel_engine_cs *engine); -bool intel_engine_signal_breadcrumbs(struct intel_engine_cs *engine); +void intel_engine_signal_breadcrumbs(struct intel_engine_cs *engine); void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine); static inline void @@ -399,7 +397,7 @@ intel_engine_queue_breadcrumbs(struct intel_engine_cs *engine) irq_work_queue(&engine->breadcrumbs.irq_work); } -bool intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine); +void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine); void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine); void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); @@ -463,6 +461,7 @@ static inline void intel_engine_reset(struct intel_engine_cs *engine, } void intel_engines_sanitize(struct drm_i915_private *i915, bool force); +void intel_gt_resume(struct drm_i915_private *i915); bool intel_engine_is_idle(struct intel_engine_cs *engine); bool intel_engines_are_idle(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 40ddfbb97acb..d4f4262d0fee 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -32,6 +32,10 @@ #include <drm/drm_print.h> #include "i915_drv.h" +#include "intel_cdclk.h" +#include "intel_crt.h" +#include "intel_csr.h" +#include "intel_dp.h" #include "intel_drv.h" /** @@ -158,7 +162,7 @@ static void cancel_intel_runtime_pm_wakeref(struct drm_i915_private *i915, rpm->debug.count, atomic_read(&rpm->wakeref_count))) { char *buf; - buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + buf = kmalloc(PAGE_SIZE, GFP_NOWAIT | __GFP_NOWARN); if (!buf) return; @@ -194,7 +198,7 @@ __print_intel_runtime_pm_wakeref(struct drm_printer *p, unsigned long i; char *buf; - buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + buf = kmalloc(PAGE_SIZE, GFP_NOWAIT | __GFP_NOWARN); if (!buf) return; @@ -278,7 +282,9 @@ void print_intel_runtime_pm_wakeref(struct drm_i915_private *i915, if (dbg.count <= alloc) break; - s = krealloc(dbg.owners, dbg.count * sizeof(*s), GFP_KERNEL); + s = krealloc(dbg.owners, + dbg.count * sizeof(*s), + GFP_NOWAIT | __GFP_NOWARN); if (!s) goto out; @@ -3442,7 +3448,7 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv) * The enabling order will be from lower to higher indexed wells, * the disabling order is reversed. */ - if (IS_ICELAKE(dev_priv)) { + if (IS_GEN(dev_priv, 11)) { err = set_power_wells(power_domains, icl_power_wells); } else if (IS_CANNONLAKE(dev_priv)) { err = set_power_wells(power_domains, cnl_power_wells); @@ -3660,7 +3666,7 @@ static void skl_display_core_init(struct drm_i915_private *dev_priv, mutex_unlock(&power_domains->lock); - skl_init_cdclk(dev_priv); + intel_cdclk_init(dev_priv); gen9_dbuf_enable(dev_priv); @@ -3677,7 +3683,7 @@ static void skl_display_core_uninit(struct drm_i915_private *dev_priv) gen9_dbuf_disable(dev_priv); - skl_uninit_cdclk(dev_priv); + intel_cdclk_uninit(dev_priv); /* The spec doesn't call for removing the reset handshake flag */ /* disable PG1 and Misc I/O */ @@ -3722,7 +3728,7 @@ void bxt_display_core_init(struct drm_i915_private *dev_priv, mutex_unlock(&power_domains->lock); - bxt_init_cdclk(dev_priv); + intel_cdclk_init(dev_priv); gen9_dbuf_enable(dev_priv); @@ -3739,7 +3745,7 @@ void bxt_display_core_uninit(struct drm_i915_private *dev_priv) gen9_dbuf_disable(dev_priv); - bxt_uninit_cdclk(dev_priv); + intel_cdclk_uninit(dev_priv); /* The spec doesn't call for removing the reset handshake flag */ @@ -3781,7 +3787,7 @@ static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume mutex_unlock(&power_domains->lock); /* 5. Enable CD clock */ - cnl_init_cdclk(dev_priv); + intel_cdclk_init(dev_priv); /* 6. Enable DBUF */ gen9_dbuf_enable(dev_priv); @@ -3803,7 +3809,7 @@ static void cnl_display_core_uninit(struct drm_i915_private *dev_priv) gen9_dbuf_disable(dev_priv); /* 3. Disable CD clock */ - cnl_uninit_cdclk(dev_priv); + intel_cdclk_uninit(dev_priv); /* * 4. Disable Power Well 1 (PG1). @@ -3845,7 +3851,7 @@ void icl_display_core_init(struct drm_i915_private *dev_priv, mutex_unlock(&power_domains->lock); /* 5. Enable CDCLK. */ - icl_init_cdclk(dev_priv); + intel_cdclk_init(dev_priv); /* 6. Enable DBUF. */ icl_dbuf_enable(dev_priv); @@ -3870,7 +3876,7 @@ void icl_display_core_uninit(struct drm_i915_private *dev_priv) icl_dbuf_disable(dev_priv); /* 3. Disable CD clock */ - icl_uninit_cdclk(dev_priv); + intel_cdclk_uninit(dev_priv); /* * 4. Disable Power Well 1 (PG1). @@ -4055,7 +4061,7 @@ void intel_power_domains_init_hw(struct drm_i915_private *i915, bool resume) power_domains->initializing = true; - if (IS_ICELAKE(i915)) { + if (INTEL_GEN(i915) >= 11) { icl_display_core_init(i915, resume); } else if (IS_CANNONLAKE(i915)) { cnl_display_core_init(i915, resume); @@ -4203,7 +4209,7 @@ void intel_power_domains_suspend(struct drm_i915_private *i915, intel_power_domains_verify_state(i915); } - if (IS_ICELAKE(i915)) + if (INTEL_GEN(i915) >= 11) icl_display_core_uninit(i915); else if (IS_CANNONLAKE(i915)) cnl_display_core_uninit(i915); diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 68f497493d43..0e3d91d9ef13 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -25,16 +25,23 @@ * Authors: * Eric Anholt <[email protected]> */ -#include <linux/i2c.h> -#include <linux/slab.h> + #include <linux/delay.h> #include <linux/export.h> +#include <linux/i2c.h> +#include <linux/slab.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_edid.h> -#include "intel_drv.h" #include <drm/i915_drm.h> + #include "i915_drv.h" +#include "intel_connector.h" +#include "intel_drv.h" +#include "intel_hdmi.h" +#include "intel_panel.h" +#include "intel_sdvo.h" #include "intel_sdvo_regs.h" #define SDVO_TMDS_MASK (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1) diff --git a/drivers/gpu/drm/i915/intel_sdvo.h b/drivers/gpu/drm/i915/intel_sdvo.h new file mode 100644 index 000000000000..c9e05bcdd141 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_sdvo.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_SDVO_H__ +#define __INTEL_SDVO_H__ + +#include <linux/types.h> + +#include <drm/i915_drm.h> + +#include "i915_reg.h" + +struct drm_i915_private; +enum pipe; + +bool intel_sdvo_port_enabled(struct drm_i915_private *dev_priv, + i915_reg_t sdvo_reg, enum pipe *pipe); +bool intel_sdvo_init(struct drm_i915_private *dev_priv, + i915_reg_t reg, enum port port); + +#endif /* __INTEL_SDVO_H__ */ diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 65de7387bf1b..2913e89280d7 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -29,17 +29,23 @@ * registers; newer ones are much simpler and we can use the new DRM plane * support. */ + +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_color_mgmt.h> #include <drm/drm_crtc.h> #include <drm/drm_fourcc.h> -#include <drm/drm_rect.h> -#include <drm/drm_atomic.h> #include <drm/drm_plane_helper.h> -#include "intel_drv.h" -#include "intel_frontbuffer.h" +#include <drm/drm_rect.h> #include <drm/i915_drm.h> + #include "i915_drv.h" -#include <drm/drm_color_mgmt.h> +#include "intel_atomic_plane.h" +#include "intel_drv.h" +#include "intel_frontbuffer.h" +#include "intel_pm.h" +#include "intel_psr.h" +#include "intel_sprite.h" bool is_planar_yuv_format(u32 pixelformat) { diff --git a/drivers/gpu/drm/i915/intel_sprite.h b/drivers/gpu/drm/i915/intel_sprite.h new file mode 100644 index 000000000000..84be8686be16 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_sprite.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_SPRITE_H__ +#define __INTEL_SPRITE_H__ + +#include <linux/types.h> + +#include "i915_drv.h" +#include "intel_display.h" + +struct drm_device; +struct drm_display_mode; +struct drm_file; +struct drm_i915_private; +struct intel_crtc_state; +struct intel_plane_state; + +bool is_planar_yuv_format(u32 pixelformat); +int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, + int usecs); +struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv, + enum pipe pipe, int plane); +int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state); +void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state); +int intel_plane_check_stride(const struct intel_plane_state *plane_state); +int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state); +int chv_plane_check_rotation(const struct intel_plane_state *plane_state); +struct intel_plane * +skl_universal_plane_create(struct drm_i915_private *dev_priv, + enum pipe pipe, enum plane_id plane_id); + +static inline bool icl_is_nv12_y_plane(enum plane_id id) +{ + /* Don't need to do a gen check, these planes are only available on gen11 */ + if (id == PLANE_SPRITE4 || id == PLANE_SPRITE5) + return true; + + return false; +} + +static inline bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, + enum plane_id plane_id) +{ + if (INTEL_GEN(dev_priv) < 11) + return false; + + return plane_id < PLANE_SPRITE2; +} + +#endif /* __INTEL_SPRITE_H__ */ diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 3924c4944e1f..5dbba33f4202 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -33,9 +33,12 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_edid.h> -#include "intel_drv.h" #include <drm/i915_drm.h> + #include "i915_drv.h" +#include "intel_connector.h" +#include "intel_drv.h" +#include "intel_tv.h" enum tv_margin { TV_MARGIN_LEFT, TV_MARGIN_TOP, diff --git a/drivers/gpu/drm/i915/intel_tv.h b/drivers/gpu/drm/i915/intel_tv.h new file mode 100644 index 000000000000..44518575ec5c --- /dev/null +++ b/drivers/gpu/drm/i915/intel_tv.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_TV_H__ +#define __INTEL_TV_H__ + +struct drm_i915_private; + +void intel_tv_init(struct drm_i915_private *dev_priv); + +#endif /* __INTEL_TV_H__ */ diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index a01d1b352a7c..d1d51e1121e2 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -21,12 +21,13 @@ * IN THE SOFTWARE. */ +#include <linux/pm_runtime.h> +#include <asm/iosf_mbi.h> + #include "i915_drv.h" -#include "intel_drv.h" #include "i915_vgpu.h" - -#include <asm/iosf_mbi.h> -#include <linux/pm_runtime.h> +#include "intel_drv.h" +#include "intel_pm.h" #define FORCEWAKE_ACK_TIMEOUT_MS 50 #define GT_FIFO_TIMEOUT_MS 10 diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h index a64d3dc0db4d..d6af3de70121 100644 --- a/drivers/gpu/drm/i915/intel_uncore.h +++ b/drivers/gpu/drm/i915/intel_uncore.h @@ -369,11 +369,26 @@ intel_uncore_read64_2x32(struct intel_uncore *uncore, #define intel_uncore_write64_fw(...) __raw_uncore_write64(__VA_ARGS__) #define intel_uncore_posting_read_fw(...) ((void)intel_uncore_read_fw(__VA_ARGS__)) -static inline void intel_uncore_rmw_or_fw(struct intel_uncore *uncore, - i915_reg_t reg, u32 or_val) +static inline void intel_uncore_rmw(struct intel_uncore *uncore, + i915_reg_t reg, u32 clear, u32 set) { - intel_uncore_write_fw(uncore, reg, - intel_uncore_read_fw(uncore, reg) | or_val); + u32 val; + + val = intel_uncore_read(uncore, reg); + val &= ~clear; + val |= set; + intel_uncore_write(uncore, reg, val); +} + +static inline void intel_uncore_rmw_fw(struct intel_uncore *uncore, + i915_reg_t reg, u32 clear, u32 set) +{ + u32 val; + + val = intel_uncore_read_fw(uncore, reg); + val &= ~clear; + val |= set; + intel_uncore_write_fw(uncore, reg, val); } #define raw_reg_read(base, reg) \ diff --git a/drivers/gpu/drm/i915/intel_workarounds.c b/drivers/gpu/drm/i915/intel_workarounds.c index a04dbc58ec1c..ccaf63679435 100644 --- a/drivers/gpu/drm/i915/intel_workarounds.c +++ b/drivers/gpu/drm/i915/intel_workarounds.c @@ -569,7 +569,7 @@ void intel_engine_init_ctx_wa(struct intel_engine_cs *engine) wa_init_start(wal, "context"); - if (IS_ICELAKE(i915)) + if (IS_GEN(i915, 11)) icl_ctx_workarounds_init(engine); else if (IS_CANNONLAKE(i915)) cnl_ctx_workarounds_init(engine); @@ -729,9 +729,9 @@ cfl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal) } static void -wa_init_mcr(struct drm_i915_private *dev_priv, struct i915_wa_list *wal) +wa_init_mcr(struct drm_i915_private *i915, struct i915_wa_list *wal) { - const struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu; + const struct sseu_dev_info *sseu = &RUNTIME_INFO(i915)->sseu; u32 mcr_slice_subslice_mask; /* @@ -747,14 +747,15 @@ wa_init_mcr(struct drm_i915_private *dev_priv, struct i915_wa_list *wal) * something more complex that requires checking the range of every * MMIO read). */ - if (INTEL_GEN(dev_priv) >= 10 && + if (INTEL_GEN(i915) >= 10 && is_power_of_2(sseu->slice_mask)) { /* * read FUSE3 for enabled L3 Bank IDs, if L3 Bank matches * enabled subslice, no need to redirect MCR packet */ u32 slice = fls(sseu->slice_mask); - u32 fuse3 = I915_READ(GEN10_MIRROR_FUSE3); + u32 fuse3 = + intel_uncore_read(&i915->uncore, GEN10_MIRROR_FUSE3); u8 ss_mask = sseu->subslice_mask[slice]; u8 enabled_mask = (ss_mask | ss_mask >> @@ -768,7 +769,7 @@ wa_init_mcr(struct drm_i915_private *dev_priv, struct i915_wa_list *wal) WARN_ON((enabled_mask & disabled_mask) != enabled_mask); } - if (INTEL_GEN(dev_priv) >= 11) + if (INTEL_GEN(i915) >= 11) mcr_slice_subslice_mask = GEN11_MCR_SLICE_MASK | GEN11_MCR_SUBSLICE_MASK; else @@ -788,7 +789,7 @@ wa_init_mcr(struct drm_i915_private *dev_priv, struct i915_wa_list *wal) wa_write_masked_or(wal, GEN8_MCR_SELECTOR, mcr_slice_subslice_mask, - intel_calculate_mcr_s_ss_select(dev_priv)); + intel_calculate_mcr_s_ss_select(i915)); } static void @@ -867,7 +868,7 @@ icl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal) static void gt_init_workarounds(struct drm_i915_private *i915, struct i915_wa_list *wal) { - if (IS_ICELAKE(i915)) + if (IS_GEN(i915, 11)) icl_gt_workarounds_init(i915, wal); else if (IS_CANNONLAKE(i915)) cnl_gt_workarounds_init(i915, wal); @@ -897,15 +898,14 @@ void intel_gt_init_workarounds(struct drm_i915_private *i915) } static enum forcewake_domains -wal_get_fw_for_rmw(struct drm_i915_private *dev_priv, - const struct i915_wa_list *wal) +wal_get_fw_for_rmw(struct intel_uncore *uncore, const struct i915_wa_list *wal) { enum forcewake_domains fw = 0; struct i915_wa *wa; unsigned int i; for (i = 0, wa = wal->list; i < wal->count; i++, wa++) - fw |= intel_uncore_forcewake_for_reg(&dev_priv->uncore, + fw |= intel_uncore_forcewake_for_reg(uncore, wa->reg, FW_REG_READ | FW_REG_WRITE); @@ -914,7 +914,7 @@ wal_get_fw_for_rmw(struct drm_i915_private *dev_priv, } static void -wa_list_apply(struct drm_i915_private *dev_priv, const struct i915_wa_list *wal) +wa_list_apply(struct intel_uncore *uncore, const struct i915_wa_list *wal) { enum forcewake_domains fw; unsigned long flags; @@ -924,27 +924,22 @@ wa_list_apply(struct drm_i915_private *dev_priv, const struct i915_wa_list *wal) if (!wal->count) return; - fw = wal_get_fw_for_rmw(dev_priv, wal); + fw = wal_get_fw_for_rmw(uncore, wal); - spin_lock_irqsave(&dev_priv->uncore.lock, flags); - intel_uncore_forcewake_get__locked(&dev_priv->uncore, fw); + spin_lock_irqsave(&uncore->lock, flags); + intel_uncore_forcewake_get__locked(uncore, fw); for (i = 0, wa = wal->list; i < wal->count; i++, wa++) { - u32 val = I915_READ_FW(wa->reg); - - val &= ~wa->mask; - val |= wa->val; - - I915_WRITE_FW(wa->reg, val); + intel_uncore_rmw_fw(uncore, wa->reg, wa->mask, wa->val); } - intel_uncore_forcewake_put__locked(&dev_priv->uncore, fw); - spin_unlock_irqrestore(&dev_priv->uncore.lock, flags); + intel_uncore_forcewake_put__locked(uncore, fw); + spin_unlock_irqrestore(&uncore->lock, flags); } -void intel_gt_apply_workarounds(struct drm_i915_private *dev_priv) +void intel_gt_apply_workarounds(struct drm_i915_private *i915) { - wa_list_apply(dev_priv, &dev_priv->gt_wa_list); + wa_list_apply(&i915->uncore, &i915->gt_wa_list); } static bool @@ -961,7 +956,7 @@ wa_verify(const struct i915_wa *wa, u32 cur, const char *name, const char *from) return true; } -static bool wa_list_verify(struct drm_i915_private *dev_priv, +static bool wa_list_verify(struct intel_uncore *uncore, const struct i915_wa_list *wal, const char *from) { @@ -970,15 +965,17 @@ static bool wa_list_verify(struct drm_i915_private *dev_priv, bool ok = true; for (i = 0, wa = wal->list; i < wal->count; i++, wa++) - ok &= wa_verify(wa, I915_READ(wa->reg), wal->name, from); + ok &= wa_verify(wa, + intel_uncore_read(uncore, wa->reg), + wal->name, from); return ok; } -bool intel_gt_verify_workarounds(struct drm_i915_private *dev_priv, +bool intel_gt_verify_workarounds(struct drm_i915_private *i915, const char *from) { - return wa_list_verify(dev_priv, &dev_priv->gt_wa_list, from); + return wa_list_verify(&i915->uncore, &i915->gt_wa_list, from); } static void @@ -1064,7 +1061,7 @@ void intel_engine_init_whitelist(struct intel_engine_cs *engine) wa_init_start(w, "whitelist"); - if (IS_ICELAKE(i915)) + if (IS_GEN(i915, 11)) icl_whitelist_build(w); else if (IS_CANNONLAKE(i915)) cnl_whitelist_build(w); @@ -1088,8 +1085,8 @@ void intel_engine_init_whitelist(struct intel_engine_cs *engine) void intel_engine_apply_whitelist(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = engine->i915; const struct i915_wa_list *wal = &engine->whitelist; + struct intel_uncore *uncore = engine->uncore; const u32 base = engine->mmio_base; struct i915_wa *wa; unsigned int i; @@ -1098,13 +1095,15 @@ void intel_engine_apply_whitelist(struct intel_engine_cs *engine) return; for (i = 0, wa = wal->list; i < wal->count; i++, wa++) - I915_WRITE(RING_FORCE_TO_NONPRIV(base, i), - i915_mmio_reg_offset(wa->reg)); + intel_uncore_write(uncore, + RING_FORCE_TO_NONPRIV(base, i), + i915_mmio_reg_offset(wa->reg)); /* And clear the rest just in case of garbage */ for (; i < RING_MAX_NONPRIV_SLOTS; i++) - I915_WRITE(RING_FORCE_TO_NONPRIV(base, i), - i915_mmio_reg_offset(RING_NOPID(base))); + intel_uncore_write(uncore, + RING_FORCE_TO_NONPRIV(base, i), + i915_mmio_reg_offset(RING_NOPID(base))); } static void @@ -1112,7 +1111,7 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) { struct drm_i915_private *i915 = engine->i915; - if (IS_ICELAKE(i915)) { + if (IS_GEN(i915, 11)) { /* This is not an Wa. Enable for better image quality */ wa_masked_en(wal, _3D_CHICKEN3, @@ -1253,7 +1252,7 @@ void intel_engine_init_workarounds(struct intel_engine_cs *engine) void intel_engine_apply_workarounds(struct intel_engine_cs *engine) { - wa_list_apply(engine->i915, &engine->wa_list); + wa_list_apply(engine->uncore, &engine->wa_list); } #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) diff --git a/drivers/gpu/drm/i915/intel_workarounds.h b/drivers/gpu/drm/i915/intel_workarounds.h index a1bf51c611a9..34eee5ec511e 100644 --- a/drivers/gpu/drm/i915/intel_workarounds.h +++ b/drivers/gpu/drm/i915/intel_workarounds.h @@ -20,9 +20,9 @@ static inline void intel_wa_list_free(struct i915_wa_list *wal) void intel_engine_init_ctx_wa(struct intel_engine_cs *engine); int intel_engine_emit_ctx_wa(struct i915_request *rq); -void intel_gt_init_workarounds(struct drm_i915_private *dev_priv); -void intel_gt_apply_workarounds(struct drm_i915_private *dev_priv); -bool intel_gt_verify_workarounds(struct drm_i915_private *dev_priv, +void intel_gt_init_workarounds(struct drm_i915_private *i915); +void intel_gt_apply_workarounds(struct drm_i915_private *i915); +bool intel_gt_verify_workarounds(struct drm_i915_private *i915, const char *from); void intel_engine_init_whitelist(struct intel_engine_cs *engine); diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c index 50bb7bbd26d3..6fd70d326468 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem.c @@ -215,5 +215,8 @@ int i915_gem_live_selftests(struct drm_i915_private *i915) SUBTEST(igt_gem_hibernate), }; + if (i915_terminally_wedged(i915)) + return 0; + return i915_subtests(tests, i915); } diff --git a/drivers/gpu/drm/i915/selftests/i915_timeline.c b/drivers/gpu/drm/i915/selftests/i915_timeline.c index 8e7bcaa1eb66..bd96afcadfe7 100644 --- a/drivers/gpu/drm/i915/selftests/i915_timeline.c +++ b/drivers/gpu/drm/i915/selftests/i915_timeline.c @@ -838,5 +838,8 @@ int i915_timeline_live_selftests(struct drm_i915_private *i915) SUBTEST(live_hwsp_wrap), }; + if (i915_terminally_wedged(i915)) + return 0; + return i915_subtests(tests, i915); } diff --git a/drivers/gpu/drm/i915/selftests/intel_lrc.c b/drivers/gpu/drm/i915/selftests/intel_lrc.c index 0d3cae564db8..fbee030db940 100644 --- a/drivers/gpu/drm/i915/selftests/intel_lrc.c +++ b/drivers/gpu/drm/i915/selftests/intel_lrc.c @@ -76,6 +76,185 @@ err_unlock: return err; } +static int live_busywait_preempt(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct i915_gem_context *ctx_hi, *ctx_lo; + struct intel_engine_cs *engine; + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + enum intel_engine_id id; + intel_wakeref_t wakeref; + int err = -ENOMEM; + u32 *map; + + /* + * Verify that even without HAS_LOGICAL_RING_PREEMPTION, we can + * preempt the busywaits used to synchronise between rings. + */ + + mutex_lock(&i915->drm.struct_mutex); + wakeref = intel_runtime_pm_get(i915); + + ctx_hi = kernel_context(i915); + if (!ctx_hi) + goto err_unlock; + ctx_hi->sched.priority = INT_MAX; + + ctx_lo = kernel_context(i915); + if (!ctx_lo) + goto err_ctx_hi; + ctx_lo->sched.priority = INT_MIN; + + obj = i915_gem_object_create_internal(i915, PAGE_SIZE); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + goto err_ctx_lo; + } + + map = i915_gem_object_pin_map(obj, I915_MAP_WC); + if (IS_ERR(map)) { + err = PTR_ERR(map); + goto err_obj; + } + + vma = i915_vma_instance(obj, &i915->ggtt.vm, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto err_map; + } + + err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL); + if (err) + goto err_map; + + for_each_engine(engine, i915, id) { + struct i915_request *lo, *hi; + struct igt_live_test t; + u32 *cs; + + if (!intel_engine_can_store_dword(engine)) + continue; + + if (igt_live_test_begin(&t, i915, __func__, engine->name)) { + err = -EIO; + goto err_vma; + } + + /* + * We create two requests. The low priority request + * busywaits on a semaphore (inside the ringbuffer where + * is should be preemptible) and the high priority requests + * uses a MI_STORE_DWORD_IMM to update the semaphore value + * allowing the first request to complete. If preemption + * fails, we hang instead. + */ + + lo = i915_request_alloc(engine, ctx_lo); + if (IS_ERR(lo)) { + err = PTR_ERR(lo); + goto err_vma; + } + + cs = intel_ring_begin(lo, 8); + if (IS_ERR(cs)) { + err = PTR_ERR(cs); + i915_request_add(lo); + goto err_vma; + } + + *cs++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT; + *cs++ = i915_ggtt_offset(vma); + *cs++ = 0; + *cs++ = 1; + + /* XXX Do we need a flush + invalidate here? */ + + *cs++ = MI_SEMAPHORE_WAIT | + MI_SEMAPHORE_GLOBAL_GTT | + MI_SEMAPHORE_POLL | + MI_SEMAPHORE_SAD_EQ_SDD; + *cs++ = 0; + *cs++ = i915_ggtt_offset(vma); + *cs++ = 0; + + intel_ring_advance(lo, cs); + i915_request_add(lo); + + if (wait_for(READ_ONCE(*map), 10)) { + err = -ETIMEDOUT; + goto err_vma; + } + + /* Low priority request should be busywaiting now */ + if (i915_request_wait(lo, I915_WAIT_LOCKED, 1) != -ETIME) { + pr_err("%s: Busywaiting request did not!\n", + engine->name); + err = -EIO; + goto err_vma; + } + + hi = i915_request_alloc(engine, ctx_hi); + if (IS_ERR(hi)) { + err = PTR_ERR(hi); + goto err_vma; + } + + cs = intel_ring_begin(hi, 4); + if (IS_ERR(cs)) { + err = PTR_ERR(cs); + i915_request_add(hi); + goto err_vma; + } + + *cs++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT; + *cs++ = i915_ggtt_offset(vma); + *cs++ = 0; + *cs++ = 0; + + intel_ring_advance(hi, cs); + i915_request_add(hi); + + if (i915_request_wait(lo, I915_WAIT_LOCKED, HZ / 5) < 0) { + struct drm_printer p = drm_info_printer(i915->drm.dev); + + pr_err("%s: Failed to preempt semaphore busywait!\n", + engine->name); + + intel_engine_dump(engine, &p, "%s\n", engine->name); + GEM_TRACE_DUMP(); + + i915_gem_set_wedged(i915); + err = -EIO; + goto err_vma; + } + GEM_BUG_ON(READ_ONCE(*map)); + + if (igt_live_test_end(&t)) { + err = -EIO; + goto err_vma; + } + } + + err = 0; +err_vma: + i915_vma_unpin(vma); +err_map: + i915_gem_object_unpin_map(obj); +err_obj: + i915_gem_object_put(obj); +err_ctx_lo: + kernel_context_close(ctx_lo); +err_ctx_hi: + kernel_context_close(ctx_hi); +err_unlock: + if (igt_flush_test(i915, I915_WAIT_LOCKED)) + err = -EIO; + intel_runtime_pm_put(i915, wakeref); + mutex_unlock(&i915->drm.struct_mutex); + return err; +} + static int live_preempt(void *arg) { struct drm_i915_private *i915 = arg; @@ -1127,6 +1306,7 @@ int intel_execlists_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { SUBTEST(live_sanitycheck), + SUBTEST(live_busywait_preempt), SUBTEST(live_preempt), SUBTEST(live_late_preempt), SUBTEST(live_suppress_self_preempt), diff --git a/drivers/gpu/drm/i915/selftests/intel_uncore.c b/drivers/gpu/drm/i915/selftests/intel_uncore.c index ee0bc91f7664..e0d7ebecb215 100644 --- a/drivers/gpu/drm/i915/selftests/intel_uncore.c +++ b/drivers/gpu/drm/i915/selftests/intel_uncore.c @@ -155,6 +155,17 @@ static int live_forcewake_ops(void *arg) return 0; } + /* + * Not quite as reliable across the gen as one would hope. + * + * Either our theory of operation is incorrect, or there remain + * external parties interfering with the powerwells. + * + * https://bugs.freedesktop.org/show_bug.cgi?id=110210 + */ + if (!IS_ENABLED(CONFIG_DRM_I915_SELFTEST_BROKEN)) + return 0; + /* We have to pick carefully to get the exact behaviour we need */ for (r = registers; r->name; r++) if (r->platforms & INTEL_INFO(i915)->gen_mask) diff --git a/drivers/gpu/drm/i915/selftests/intel_workarounds.c b/drivers/gpu/drm/i915/selftests/intel_workarounds.c index 3baed59008d7..567b6f8dae86 100644 --- a/drivers/gpu/drm/i915/selftests/intel_workarounds.c +++ b/drivers/gpu/drm/i915/selftests/intel_workarounds.c @@ -750,10 +750,11 @@ static bool verify_gt_engine_wa(struct drm_i915_private *i915, enum intel_engine_id id; bool ok = true; - ok &= wa_list_verify(i915, &lists->gt_wa_list, str); + ok &= wa_list_verify(&i915->uncore, &lists->gt_wa_list, str); for_each_engine(engine, i915, id) - ok &= wa_list_verify(i915, &lists->engine[id].wa_list, str); + ok &= wa_list_verify(engine->uncore, + &lists->engine[id].wa_list, str); return ok; } diff --git a/drivers/gpu/drm/i915/selftests/mock_timeline.c b/drivers/gpu/drm/i915/selftests/mock_timeline.c index 416d85233263..e084476469ef 100644 --- a/drivers/gpu/drm/i915/selftests/mock_timeline.c +++ b/drivers/gpu/drm/i915/selftests/mock_timeline.c @@ -16,7 +16,6 @@ void mock_timeline_init(struct i915_timeline *timeline, u64 context) spin_lock_init(&timeline->lock); mutex_init(&timeline->mutex); - INIT_ACTIVE_REQUEST(&timeline->barrier); INIT_ACTIVE_REQUEST(&timeline->last_request); INIT_LIST_HEAD(&timeline->requests); diff --git a/drivers/gpu/drm/i915/test_i915_active_types_standalone.c b/drivers/gpu/drm/i915/test_i915_active_types_standalone.c deleted file mode 100644 index 144ebd153e57..000000000000 --- a/drivers/gpu/drm/i915/test_i915_active_types_standalone.c +++ /dev/null @@ -1,7 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright © 2019 Intel Corporation - */ - -#include "i915_active_types.h" diff --git a/drivers/gpu/drm/i915/test_i915_gem_context_types_standalone.c b/drivers/gpu/drm/i915/test_i915_gem_context_types_standalone.c deleted file mode 100644 index 4e4da4860bc2..000000000000 --- a/drivers/gpu/drm/i915/test_i915_gem_context_types_standalone.c +++ /dev/null @@ -1,7 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright © 2019 Intel Corporation - */ - -#include "i915_gem_context_types.h" diff --git a/drivers/gpu/drm/i915/test_i915_priolist_types_standalone.c b/drivers/gpu/drm/i915/test_i915_priolist_types_standalone.c deleted file mode 100644 index f465eb99bb47..000000000000 --- a/drivers/gpu/drm/i915/test_i915_priolist_types_standalone.c +++ /dev/null @@ -1,7 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright © 2019 Intel Corporation - */ - -#include "i915_priolist_types.h" diff --git a/drivers/gpu/drm/i915/test_i915_scheduler_types_standalone.c b/drivers/gpu/drm/i915/test_i915_scheduler_types_standalone.c deleted file mode 100644 index 8afa2c3719fb..000000000000 --- a/drivers/gpu/drm/i915/test_i915_scheduler_types_standalone.c +++ /dev/null @@ -1,7 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright © 2019 Intel Corporation - */ - -#include "i915_scheduler_types.h" diff --git a/drivers/gpu/drm/i915/test_i915_timeline_types_standalone.c b/drivers/gpu/drm/i915/test_i915_timeline_types_standalone.c deleted file mode 100644 index f58e148e8946..000000000000 --- a/drivers/gpu/drm/i915/test_i915_timeline_types_standalone.c +++ /dev/null @@ -1,7 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright © 2019 Intel Corporation - */ - -#include "i915_timeline_types.h" diff --git a/drivers/gpu/drm/i915/test_intel_context_types_standalone.c b/drivers/gpu/drm/i915/test_intel_context_types_standalone.c deleted file mode 100644 index b39e3c4e6551..000000000000 --- a/drivers/gpu/drm/i915/test_intel_context_types_standalone.c +++ /dev/null @@ -1,7 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright © 2019 Intel Corporation - */ - -#include "intel_context_types.h" diff --git a/drivers/gpu/drm/i915/test_intel_engine_types_standalone.c b/drivers/gpu/drm/i915/test_intel_engine_types_standalone.c deleted file mode 100644 index d05e4cdcbcf9..000000000000 --- a/drivers/gpu/drm/i915/test_intel_engine_types_standalone.c +++ /dev/null @@ -1,7 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright © 2019 Intel Corporation - */ - -#include "intel_engine_types.h" diff --git a/drivers/gpu/drm/i915/test_intel_workarounds_types_standalone.c b/drivers/gpu/drm/i915/test_intel_workarounds_types_standalone.c deleted file mode 100644 index 4f658bb00825..000000000000 --- a/drivers/gpu/drm/i915/test_intel_workarounds_types_standalone.c +++ /dev/null @@ -1,7 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * - * Copyright © 2019 Intel Corporation - */ - -#include "intel_workarounds_types.h" diff --git a/drivers/gpu/drm/i915/vlv_dsi.c b/drivers/gpu/drm/i915/vlv_dsi.c index 0a950c976bbb..e0b1ec821960 100644 --- a/drivers/gpu/drm/i915/vlv_dsi.c +++ b/drivers/gpu/drm/i915/vlv_dsi.c @@ -23,16 +23,20 @@ * Author: Jani Nikula <[email protected]> */ +#include <linux/gpio/consumer.h> +#include <linux/slab.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_edid.h> -#include <drm/i915_drm.h> #include <drm/drm_mipi_dsi.h> -#include <linux/slab.h> -#include <linux/gpio/consumer.h> +#include <drm/i915_drm.h> + #include "i915_drv.h" +#include "intel_connector.h" #include "intel_drv.h" #include "intel_dsi.h" +#include "intel_panel.h" /* return pixels in terms of txbyteclkhs */ static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count, @@ -256,6 +260,28 @@ static void band_gap_reset(struct drm_i915_private *dev_priv) mutex_unlock(&dev_priv->sb_lock); } +static int bdw_get_pipemisc_bpp(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + u32 tmp; + + tmp = I915_READ(PIPEMISC(crtc->pipe)); + + switch (tmp & PIPEMISC_DITHER_BPC_MASK) { + case PIPEMISC_DITHER_6_BPC: + return 18; + case PIPEMISC_DITHER_8_BPC: + return 24; + case PIPEMISC_DITHER_10_BPC: + return 30; + case PIPEMISC_DITHER_12_BPC: + return 36; + default: + MISSING_CASE(tmp); + return 0; + } +} + static int intel_dsi_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) @@ -1082,6 +1108,8 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, bpp = mipi_dsi_pixel_format_to_bpp( pixel_format_from_register_bits(fmt)); + pipe_config->pipe_bpp = bdw_get_pipemisc_bpp(crtc); + /* Enable Frame time stamo based scanline reporting */ adjusted_mode->private_flags |= I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP; diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 9c37d9af3023..ec7715c6b0c0 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c @@ -107,7 +107,6 @@ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, INIT_LIST_HEAD(&bus->hlink_list); bus->idx = idx++; - mutex_init(&bus->lock); bus->cmd_dma_state = true; return 0; diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c index 012305177f68..ad8eee08013f 100644 --- a/sound/hda/hdac_bus.c +++ b/sound/hda/hdac_bus.c @@ -38,6 +38,7 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events); spin_lock_init(&bus->reg_lock); mutex_init(&bus->cmd_mutex); + mutex_init(&bus->lock); bus->irq = -1; return 0; } diff --git a/sound/hda/hdac_component.c b/sound/hda/hdac_component.c index 13915fdc6a54..dfe7e755f594 100644 --- a/sound/hda/hdac_component.c +++ b/sound/hda/hdac_component.c @@ -69,13 +69,15 @@ void snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable) dev_dbg(bus->dev, "display power %s\n", enable ? "enable" : "disable"); + + mutex_lock(&bus->lock); if (enable) set_bit(idx, &bus->display_power_status); else clear_bit(idx, &bus->display_power_status); if (!acomp || !acomp->ops) - return; + goto unlock; if (bus->display_power_status) { if (!bus->display_power_active) { @@ -98,6 +100,8 @@ void snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable) bus->display_power_active = 0; } } + unlock: + mutex_unlock(&bus->lock); } EXPORT_SYMBOL_GPL(snd_hdac_display_power); |