diff options
Diffstat (limited to 'drivers/gpu/drm/xe/display')
-rw-r--r-- | drivers/gpu/drm/xe/display/ext/i915_irq.c | 23 | ||||
-rw-r--r-- | drivers/gpu/drm/xe/display/intel_bo.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/xe/display/intel_fb_bo.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/xe/display/intel_fbdev_fb.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/xe/display/xe_display.c | 199 | ||||
-rw-r--r-- | drivers/gpu/drm/xe/display/xe_display.h | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/xe/display/xe_display_rps.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/xe/display/xe_fb_pin.c | 68 | ||||
-rw-r--r-- | drivers/gpu/drm/xe/display/xe_plane_initial.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/xe/display/xe_tdf.c | 6 |
10 files changed, 210 insertions, 137 deletions
diff --git a/drivers/gpu/drm/xe/display/ext/i915_irq.c b/drivers/gpu/drm/xe/display/ext/i915_irq.c index ac4cda2d81c7..3c6bca66ddab 100644 --- a/drivers/gpu/drm/xe/display/ext/i915_irq.c +++ b/drivers/gpu/drm/xe/display/ext/i915_irq.c @@ -51,6 +51,29 @@ void gen2_irq_init(struct intel_uncore *uncore, struct i915_irq_regs regs, intel_uncore_posting_read(uncore, regs.imr); } +void gen2_error_reset(struct intel_uncore *uncore, struct i915_error_regs regs) +{ + intel_uncore_write(uncore, regs.emr, 0xffffffff); + intel_uncore_posting_read(uncore, regs.emr); + + intel_uncore_write(uncore, regs.eir, 0xffffffff); + intel_uncore_posting_read(uncore, regs.eir); + intel_uncore_write(uncore, regs.eir, 0xffffffff); + intel_uncore_posting_read(uncore, regs.eir); +} + +void gen2_error_init(struct intel_uncore *uncore, struct i915_error_regs regs, + u32 emr_val) +{ + intel_uncore_write(uncore, regs.eir, 0xffffffff); + intel_uncore_posting_read(uncore, regs.eir); + intel_uncore_write(uncore, regs.eir, 0xffffffff); + intel_uncore_posting_read(uncore, regs.eir); + + intel_uncore_write(uncore, regs.emr, emr_val); + intel_uncore_posting_read(uncore, regs.emr); +} + bool intel_irqs_enabled(struct xe_device *xe) { return atomic_read(&xe->irq.enabled); diff --git a/drivers/gpu/drm/xe/display/intel_bo.c b/drivers/gpu/drm/xe/display/intel_bo.c index b463f5bd4eed..27437c22bd70 100644 --- a/drivers/gpu/drm/xe/display/intel_bo.c +++ b/drivers/gpu/drm/xe/display/intel_bo.c @@ -25,7 +25,7 @@ bool intel_bo_is_shmem(struct drm_gem_object *obj) bool intel_bo_is_protected(struct drm_gem_object *obj) { - return false; + return xe_bo_is_protected(gem_to_xe_bo(obj)); } void intel_bo_flush_if_display(struct drm_gem_object *obj) diff --git a/drivers/gpu/drm/xe/display/intel_fb_bo.c b/drivers/gpu/drm/xe/display/intel_fb_bo.c index 4d209ebc26c2..ebdb22c9499d 100644 --- a/drivers/gpu/drm/xe/display/intel_fb_bo.c +++ b/drivers/gpu/drm/xe/display/intel_fb_bo.c @@ -24,7 +24,7 @@ void intel_fb_bo_framebuffer_fini(struct drm_gem_object *obj) xe_bo_put(bo); } -int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb, +int intel_fb_bo_framebuffer_init(struct drm_framebuffer *fb, struct drm_gem_object *obj, struct drm_mode_fb_cmd2 *mode_cmd) { @@ -50,10 +50,10 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb, /* * XE_BO_FLAG_SCANOUT should ideally be set at creation, or is * automatically set when creating FB. We cannot change caching - * mode when the boect is VM_BINDed, so we can only set + * mode when the bo is VM_BINDed, so we can only set * coherency with display when unbound. */ - if (XE_IOCTL_DBG(xe, !list_empty(&bo->ttm.base.gpuva.list))) { + if (XE_IOCTL_DBG(xe, xe_bo_is_vm_bound(bo))) { ttm_bo_unreserve(&bo->ttm); ret = -EINVAL; goto err; @@ -68,10 +68,11 @@ err: return ret; } -struct drm_gem_object *intel_fb_bo_lookup_valid_bo(struct drm_i915_private *i915, +struct drm_gem_object *intel_fb_bo_lookup_valid_bo(struct drm_device *drm, struct drm_file *filp, const struct drm_mode_fb_cmd2 *mode_cmd) { + struct xe_device *xe = to_xe_device(drm); struct xe_bo *bo; struct drm_gem_object *gem = drm_gem_object_lookup(filp, mode_cmd->handles[0]); @@ -80,7 +81,7 @@ struct drm_gem_object *intel_fb_bo_lookup_valid_bo(struct drm_i915_private *i915 bo = gem_to_xe_bo(gem); /* Require vram placement or dma-buf import */ - if (IS_DGFX(i915) && + if (IS_DGFX(xe) && !xe_bo_can_migrate(bo, XE_PL_VRAM0) && bo->ttm.type != ttm_bo_type_sg) { drm_gem_object_put(gem); diff --git a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c index ca95fcd098ec..3a1e505ff182 100644 --- a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c +++ b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c @@ -45,7 +45,7 @@ struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper, NULL, size, ttm_bo_type_kernel, XE_BO_FLAG_SCANOUT | XE_BO_FLAG_STOLEN | - XE_BO_FLAG_PINNED); + XE_BO_FLAG_GGTT | XE_BO_FLAG_PINNED); if (!IS_ERR(obj)) drm_info(&xe->drm, "Allocated fbdev into stolen\n"); else @@ -56,7 +56,7 @@ struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper, obj = xe_bo_create_pin_map(xe, xe_device_get_root_tile(xe), NULL, size, ttm_bo_type_kernel, XE_BO_FLAG_SCANOUT | XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(xe)) | - XE_BO_FLAG_PINNED); + XE_BO_FLAG_GGTT | XE_BO_FLAG_PINNED); } if (IS_ERR(obj)) { diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index b3921dbc52ff..0b0aca7a25af 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -8,6 +8,8 @@ #include <linux/fb.h> +#include <drm/drm_client.h> +#include <drm/drm_client_event.h> #include <drm/drm_drv.h> #include <drm/drm_managed.h> #include <drm/drm_probe_helper.h> @@ -29,6 +31,7 @@ #include "intel_hdcp.h" #include "intel_hotplug.h" #include "intel_opregion.h" +#include "skl_watermark.h" #include "xe_module.h" /* Xe device functions */ @@ -66,6 +69,10 @@ void xe_display_driver_set_hooks(struct drm_driver *driver) if (!xe_modparam.probe_display) return; +#ifdef CONFIG_DRM_FBDEV_EMULATION + driver->fbdev_probe = intel_fbdev_driver_fbdev_probe; +#endif + driver->driver_features |= DRIVER_MODESET | DRIVER_ATOMIC; } @@ -101,19 +108,25 @@ int xe_display_create(struct xe_device *xe) return drmm_add_action_or_reset(&xe->drm, display_destroy, NULL); } -static void xe_display_fini_nommio(struct drm_device *dev, void *dummy) +static void xe_display_fini_early(void *arg) { - struct xe_device *xe = to_xe_device(dev); + struct xe_device *xe = arg; struct intel_display *display = &xe->display; if (!xe->info.probe_display) return; + intel_display_driver_remove_nogem(display); + intel_display_driver_remove_noirq(display); + intel_opregion_cleanup(display); intel_power_domains_cleanup(display); } -int xe_display_init_nommio(struct xe_device *xe) +int xe_display_init_early(struct xe_device *xe) { + struct intel_display *display = &xe->display; + int err; + if (!xe->info.probe_display) return 0; @@ -123,29 +136,6 @@ int xe_display_init_nommio(struct xe_device *xe) /* This must be called before any calls to HAS_PCH_* */ intel_detect_pch(xe); - return drmm_add_action_or_reset(&xe->drm, xe_display_fini_nommio, xe); -} - -static void xe_display_fini_noirq(void *arg) -{ - struct xe_device *xe = arg; - struct intel_display *display = &xe->display; - - if (!xe->info.probe_display) - return; - - intel_display_driver_remove_noirq(display); - intel_opregion_cleanup(display); -} - -int xe_display_init_noirq(struct xe_device *xe) -{ - struct intel_display *display = &xe->display; - int err; - - if (!xe->info.probe_display) - return 0; - intel_display_driver_early_probe(display); /* Early display init.. */ @@ -162,26 +152,34 @@ int xe_display_init_noirq(struct xe_device *xe) intel_display_device_info_runtime_init(display); err = intel_display_driver_probe_noirq(display); - if (err) { - intel_opregion_cleanup(display); - return err; - } + if (err) + goto err_opregion; + + err = intel_display_driver_probe_nogem(display); + if (err) + goto err_noirq; - return devm_add_action_or_reset(xe->drm.dev, xe_display_fini_noirq, xe); + return devm_add_action_or_reset(xe->drm.dev, xe_display_fini_early, xe); +err_noirq: + intel_display_driver_remove_noirq(display); + intel_power_domains_cleanup(display); +err_opregion: + intel_opregion_cleanup(display); + return err; } -static void xe_display_fini_noaccel(void *arg) +static void xe_display_fini(void *arg) { struct xe_device *xe = arg; struct intel_display *display = &xe->display; - if (!xe->info.probe_display) - return; - - intel_display_driver_remove_nogem(display); + intel_hpd_poll_fini(xe); + intel_hdcp_component_fini(display); + intel_audio_deinit(display); + intel_display_driver_remove(display); } -int xe_display_init_noaccel(struct xe_device *xe) +int xe_display_init(struct xe_device *xe) { struct intel_display *display = &xe->display; int err; @@ -189,34 +187,11 @@ int xe_display_init_noaccel(struct xe_device *xe) if (!xe->info.probe_display) return 0; - err = intel_display_driver_probe_nogem(display); + err = intel_display_driver_probe(display); if (err) return err; - return devm_add_action_or_reset(xe->drm.dev, xe_display_fini_noaccel, xe); -} - -int xe_display_init(struct xe_device *xe) -{ - struct intel_display *display = &xe->display; - - if (!xe->info.probe_display) - return 0; - - return intel_display_driver_probe(display); -} - -void xe_display_fini(struct xe_device *xe) -{ - struct intel_display *display = &xe->display; - - if (!xe->info.probe_display) - return; - - intel_hpd_poll_fini(xe); - - intel_hdcp_component_fini(display); - intel_audio_deinit(xe); + return devm_add_action_or_reset(xe->drm.dev, xe_display_fini, xe); } void xe_display_register(struct xe_device *xe) @@ -228,7 +203,6 @@ void xe_display_register(struct xe_device *xe) intel_display_driver_register(display); intel_power_domains_enable(display); - intel_register_dsm_handler(); } void xe_display_unregister(struct xe_device *xe) @@ -238,21 +212,10 @@ void xe_display_unregister(struct xe_device *xe) if (!xe->info.probe_display) return; - intel_unregister_dsm_handler(); intel_power_domains_disable(display); intel_display_driver_unregister(display); } -void xe_display_driver_remove(struct xe_device *xe) -{ - struct intel_display *display = &xe->display; - - if (!xe->info.probe_display) - return; - - intel_display_driver_remove(display); -} - /* IRQ-related functions */ void xe_display_irq_handler(struct xe_device *xe, u32 master_ctl) @@ -322,11 +285,58 @@ static void xe_display_flush_cleanup_work(struct xe_device *xe) } } -/* TODO: System and runtime suspend/resume sequences will be sanitized as a follow-up. */ -static void __xe_display_pm_suspend(struct xe_device *xe, bool runtime) +static void xe_display_enable_d3cold(struct xe_device *xe) +{ + struct intel_display *display = &xe->display; + + if (!xe->info.probe_display) + return; + + /* + * We do a lot of poking in a lot of registers, make sure they work + * properly. + */ + intel_power_domains_disable(display); + + xe_display_flush_cleanup_work(xe); + + intel_opregion_suspend(display, PCI_D3cold); + + intel_dmc_suspend(display); + + if (has_display(xe)) + intel_hpd_poll_enable(xe); +} + +static void xe_display_disable_d3cold(struct xe_device *xe) +{ + struct intel_display *display = &xe->display; + + if (!xe->info.probe_display) + return; + + intel_dmc_resume(display); + + if (has_display(xe)) + drm_mode_config_reset(&xe->drm); + + intel_display_driver_init_hw(display); + + intel_hpd_init(xe); + + if (has_display(xe)) + intel_hpd_poll_disable(xe); + + intel_opregion_resume(display); + + intel_power_domains_enable(display); +} + +void xe_display_pm_suspend(struct xe_device *xe) { struct intel_display *display = &xe->display; bool s2idle = suspend_to_idle(); + if (!xe->info.probe_display) return; @@ -335,10 +345,9 @@ static void __xe_display_pm_suspend(struct xe_device *xe, bool runtime) * properly. */ intel_power_domains_disable(display); - if (!runtime) - intel_fbdev_set_suspend(&xe->drm, FBINFO_STATE_SUSPENDED, true); + drm_client_dev_suspend(&xe->drm, false); - if (!runtime && has_display(xe)) { + if (has_display(xe)) { drm_kms_helper_poll_disable(&xe->drm); intel_display_driver_disable_user_access(display); intel_display_driver_suspend(display); @@ -348,7 +357,7 @@ static void __xe_display_pm_suspend(struct xe_device *xe, bool runtime) intel_hpd_cancel_work(xe); - if (!runtime && has_display(xe)) { + if (has_display(xe)) { intel_display_driver_suspend_access(display); intel_encoder_suspend_all(&xe->display); } @@ -356,14 +365,6 @@ static void __xe_display_pm_suspend(struct xe_device *xe, bool runtime) intel_opregion_suspend(display, s2idle ? PCI_D1 : PCI_D3cold); intel_dmc_suspend(display); - - if (runtime && has_display(xe)) - intel_hpd_poll_enable(xe); -} - -void xe_display_pm_suspend(struct xe_device *xe) -{ - __xe_display_pm_suspend(xe, false); } void xe_display_pm_shutdown(struct xe_device *xe) @@ -374,7 +375,8 @@ void xe_display_pm_shutdown(struct xe_device *xe) return; intel_power_domains_disable(display); - intel_fbdev_set_suspend(&xe->drm, FBINFO_STATE_SUSPENDED, true); + drm_client_dev_suspend(&xe->drm, false); + if (has_display(xe)) { drm_kms_helper_poll_disable(&xe->drm); intel_display_driver_disable_user_access(display); @@ -402,7 +404,7 @@ void xe_display_pm_runtime_suspend(struct xe_device *xe) return; if (xe->d3cold.allowed) { - __xe_display_pm_suspend(xe, true); + xe_display_enable_d3cold(xe); return; } @@ -463,7 +465,7 @@ void xe_display_pm_resume_early(struct xe_device *xe) intel_display_power_resume_early(display); } -static void __xe_display_pm_resume(struct xe_device *xe, bool runtime) +void xe_display_pm_resume(struct xe_device *xe) { struct intel_display *display = &xe->display; @@ -477,12 +479,12 @@ static void __xe_display_pm_resume(struct xe_device *xe, bool runtime) intel_display_driver_init_hw(display); - if (!runtime && has_display(xe)) + if (has_display(xe)) intel_display_driver_resume_access(display); intel_hpd_init(xe); - if (!runtime && has_display(xe)) { + if (has_display(xe)) { intel_display_driver_resume(display); drm_kms_helper_poll_enable(&xe->drm); intel_display_driver_enable_user_access(display); @@ -493,29 +495,24 @@ static void __xe_display_pm_resume(struct xe_device *xe, bool runtime) intel_opregion_resume(display); - if (!runtime) - intel_fbdev_set_suspend(&xe->drm, FBINFO_STATE_RUNNING, false); + drm_client_dev_resume(&xe->drm, false); intel_power_domains_enable(display); } -void xe_display_pm_resume(struct xe_device *xe) -{ - __xe_display_pm_resume(xe, false); -} - void xe_display_pm_runtime_resume(struct xe_device *xe) { if (!xe->info.probe_display) return; if (xe->d3cold.allowed) { - __xe_display_pm_resume(xe, true); + xe_display_disable_d3cold(xe); return; } intel_hpd_init(xe); intel_hpd_poll_disable(xe); + skl_watermark_ipc_update(xe); } diff --git a/drivers/gpu/drm/xe/display/xe_display.h b/drivers/gpu/drm/xe/display/xe_display.h index 233f81a26c25..46e14f8dee28 100644 --- a/drivers/gpu/drm/xe/display/xe_display.h +++ b/drivers/gpu/drm/xe/display/xe_display.h @@ -14,17 +14,13 @@ struct drm_driver; bool xe_display_driver_probe_defer(struct pci_dev *pdev); void xe_display_driver_set_hooks(struct drm_driver *driver); -void xe_display_driver_remove(struct xe_device *xe); int xe_display_create(struct xe_device *xe); int xe_display_probe(struct xe_device *xe); -int xe_display_init_nommio(struct xe_device *xe); -int xe_display_init_noirq(struct xe_device *xe); -int xe_display_init_noaccel(struct xe_device *xe); +int xe_display_init_early(struct xe_device *xe); int xe_display_init(struct xe_device *xe); -void xe_display_fini(struct xe_device *xe); void xe_display_register(struct xe_device *xe); void xe_display_unregister(struct xe_device *xe); @@ -54,11 +50,8 @@ static inline int xe_display_create(struct xe_device *xe) { return 0; } static inline int xe_display_probe(struct xe_device *xe) { return 0; } -static inline int xe_display_init_nommio(struct xe_device *xe) { return 0; } -static inline int xe_display_init_noirq(struct xe_device *xe) { return 0; } -static inline int xe_display_init_noaccel(struct xe_device *xe) { return 0; } +static inline int xe_display_init_early(struct xe_device *xe) { return 0; } static inline int xe_display_init(struct xe_device *xe) { return 0; } -static inline void xe_display_fini(struct xe_device *xe) {} static inline void xe_display_register(struct xe_device *xe) {} static inline void xe_display_unregister(struct xe_device *xe) {} diff --git a/drivers/gpu/drm/xe/display/xe_display_rps.c b/drivers/gpu/drm/xe/display/xe_display_rps.c index ab21c581c192..fa616f9688a5 100644 --- a/drivers/gpu/drm/xe/display/xe_display_rps.c +++ b/drivers/gpu/drm/xe/display/xe_display_rps.c @@ -10,7 +10,7 @@ void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc, { } -void intel_display_rps_mark_interactive(struct drm_i915_private *i915, +void intel_display_rps_mark_interactive(struct intel_display *display, struct intel_atomic_state *state, bool interactive) { diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index 9fa51b84737c..d918ae1c8061 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -5,10 +5,12 @@ #include <drm/ttm/ttm_bo.h> +#include "i915_vma.h" #include "intel_display_types.h" #include "intel_dpt.h" #include "intel_fb.h" #include "intel_fb_pin.h" +#include "intel_fbdev.h" #include "xe_bo.h" #include "xe_device.h" #include "xe_ggtt.h" @@ -80,7 +82,7 @@ write_dpt_remapped(struct xe_bo *bo, struct iosys_map *map, u32 *dpt_ofs, static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb, const struct i915_gtt_view *view, struct i915_vma *vma, - u64 physical_alignment) + unsigned int alignment) { struct xe_device *xe = to_xe_device(fb->base.dev); struct xe_tile *tile0 = xe_device_get_root_tile(xe); @@ -106,7 +108,7 @@ static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb, XE_BO_FLAG_VRAM0 | XE_BO_FLAG_GGTT | XE_BO_FLAG_PAGETABLE, - physical_alignment); + alignment); else dpt = xe_bo_create_pin_map_at_aligned(xe, tile0, NULL, dpt_size, ~0ull, @@ -114,7 +116,7 @@ static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb, XE_BO_FLAG_STOLEN | XE_BO_FLAG_GGTT | XE_BO_FLAG_PAGETABLE, - physical_alignment); + alignment); if (IS_ERR(dpt)) dpt = xe_bo_create_pin_map_at_aligned(xe, tile0, NULL, dpt_size, ~0ull, @@ -122,7 +124,7 @@ static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb, XE_BO_FLAG_SYSTEM | XE_BO_FLAG_GGTT | XE_BO_FLAG_PAGETABLE, - physical_alignment); + alignment); if (IS_ERR(dpt)) return PTR_ERR(dpt); @@ -192,7 +194,7 @@ write_ggtt_rotated(struct xe_bo *bo, struct xe_ggtt *ggtt, u32 *ggtt_ofs, u32 bo static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, const struct i915_gtt_view *view, struct i915_vma *vma, - u64 physical_alignment) + unsigned int alignment) { struct drm_gem_object *obj = intel_fb_bo(&fb->base); struct xe_bo *bo = gem_to_xe_bo(obj); @@ -275,7 +277,7 @@ out: static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb, const struct i915_gtt_view *view, - u64 physical_alignment) + unsigned int alignment) { struct drm_device *dev = fb->base.dev; struct xe_device *xe = to_xe_device(dev); @@ -287,6 +289,7 @@ static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb, if (!vma) return ERR_PTR(-ENODEV); + refcount_set(&vma->ref, 1); if (IS_DGFX(to_xe_device(bo->ttm.base.dev)) && intel_fb_rc_ccs_cc_plane(&fb->base) >= 0 && !(bo->flags & XE_BO_FLAG_NEEDS_CPU_ACCESS)) { @@ -324,9 +327,9 @@ static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb, vma->bo = bo; if (intel_fb_uses_dpt(&fb->base)) - ret = __xe_pin_fb_vma_dpt(fb, view, vma, physical_alignment); + ret = __xe_pin_fb_vma_dpt(fb, view, vma, alignment); else - ret = __xe_pin_fb_vma_ggtt(fb, view, vma, physical_alignment); + ret = __xe_pin_fb_vma_ggtt(fb, view, vma, alignment); if (ret) goto err_unpin; @@ -347,6 +350,9 @@ static void __xe_unpin_fb_vma(struct i915_vma *vma) { u8 tile_id = vma->node->ggtt->tile->id; + if (!refcount_dec_and_test(&vma->ref)) + return; + if (vma->dpt) xe_bo_unpin_map_no_vm(vma->dpt); else if (!xe_ggtt_node_allocated(vma->bo->ggtt_node[tile_id]) || @@ -364,6 +370,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, const struct i915_gtt_view *view, unsigned int alignment, unsigned int phys_alignment, + unsigned int vtd_guard, bool uses_fence, unsigned long *out_flags) { @@ -377,25 +384,58 @@ void intel_fb_unpin_vma(struct i915_vma *vma, unsigned long flags) __xe_unpin_fb_vma(vma); } -int intel_plane_pin_fb(struct intel_plane_state *plane_state) +static bool reuse_vma(struct intel_plane_state *new_plane_state, + const struct intel_plane_state *old_plane_state) { - struct drm_framebuffer *fb = plane_state->hw.fb; + struct intel_framebuffer *fb = to_intel_framebuffer(new_plane_state->hw.fb); + struct xe_device *xe = to_xe_device(fb->base.dev); + struct i915_vma *vma; + + if (old_plane_state->hw.fb == new_plane_state->hw.fb && + !memcmp(&old_plane_state->view.gtt, + &new_plane_state->view.gtt, + sizeof(new_plane_state->view.gtt))) { + vma = old_plane_state->ggtt_vma; + goto found; + } + + if (fb == intel_fbdev_framebuffer(xe->display.fbdev.fbdev)) { + vma = intel_fbdev_vma_pointer(xe->display.fbdev.fbdev); + if (vma) + goto found; + } + + return false; + +found: + refcount_inc(&vma->ref); + new_plane_state->ggtt_vma = vma; + return true; +} + +int intel_plane_pin_fb(struct intel_plane_state *new_plane_state, + const struct intel_plane_state *old_plane_state) +{ + struct drm_framebuffer *fb = new_plane_state->hw.fb; struct drm_gem_object *obj = intel_fb_bo(fb); struct xe_bo *bo = gem_to_xe_bo(obj); struct i915_vma *vma; struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); - u64 phys_alignment = plane->min_alignment(plane, fb, 0); + struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane); + unsigned int alignment = plane->min_alignment(plane, fb, 0); + + if (reuse_vma(new_plane_state, old_plane_state)) + return 0; /* We reject creating !SCANOUT fb's, so this is weird.. */ drm_WARN_ON(bo->ttm.base.dev, !(bo->flags & XE_BO_FLAG_SCANOUT)); - vma = __xe_pin_fb_vma(intel_fb, &plane_state->view.gtt, phys_alignment); + vma = __xe_pin_fb_vma(intel_fb, &new_plane_state->view.gtt, alignment); if (IS_ERR(vma)) return PTR_ERR(vma); - plane_state->ggtt_vma = vma; + new_plane_state->ggtt_vma = vma; return 0; } diff --git a/drivers/gpu/drm/xe/display/xe_plane_initial.c b/drivers/gpu/drm/xe/display/xe_plane_initial.c index 2a2f250fa495..4ca0cb571194 100644 --- a/drivers/gpu/drm/xe/display/xe_plane_initial.c +++ b/drivers/gpu/drm/xe/display/xe_plane_initial.c @@ -8,7 +8,9 @@ #include "regs/xe_gtt_defs.h" #include "xe_ggtt.h" +#include "xe_mmio.h" +#include "i915_reg.h" #include "intel_atomic_plane.h" #include "intel_crtc.h" #include "intel_display.h" @@ -22,6 +24,21 @@ #include <generated/xe_wa_oob.h> +void intel_plane_initial_vblank_wait(struct intel_crtc *crtc) +{ + /* Early xe has no irq */ + struct xe_device *xe = to_xe_device(crtc->base.dev); + struct xe_reg pipe_frmtmstmp = XE_REG(i915_mmio_reg_offset(PIPE_FRMTMSTMP(crtc->pipe))); + u32 timestamp; + int ret; + + timestamp = xe_mmio_read32(xe_root_tile_mmio(xe), pipe_frmtmstmp); + + ret = xe_mmio_wait32_not(xe_root_tile_mmio(xe), pipe_frmtmstmp, ~0U, timestamp, 40000U, ×tamp, false); + if (ret < 0) + drm_warn(&xe->drm, "waiting for early vblank failed with %i\n", ret); +} + static bool intel_reuse_initial_plane_obj(struct intel_crtc *this, const struct intel_initial_plane_config plane_configs[], @@ -215,7 +232,7 @@ intel_find_initial_plane_obj(struct intel_crtc *crtc, plane_state->uapi.rotation, &plane_state->view); vma = intel_fb_pin_to_ggtt(fb, &plane_state->view.gtt, - 0, 0, false, &plane_state->flags); + 0, 0, 0, false, &plane_state->flags); if (IS_ERR(vma)) goto nofb; @@ -293,7 +310,7 @@ void intel_initial_plane_config(struct intel_display *display) intel_find_initial_plane_obj(crtc, plane_configs); if (display->funcs.display->fixup_initial_plane_config(crtc, plane_config)) - intel_crtc_wait_for_next_vblank(crtc); + intel_plane_initial_vblank_wait(crtc); plane_config_fini(plane_config); } diff --git a/drivers/gpu/drm/xe/display/xe_tdf.c b/drivers/gpu/drm/xe/display/xe_tdf.c index 2c0d4e144e09..2a7fccbeb1d5 100644 --- a/drivers/gpu/drm/xe/display/xe_tdf.c +++ b/drivers/gpu/drm/xe/display/xe_tdf.c @@ -7,7 +7,9 @@ #include "intel_display_types.h" #include "intel_tdf.h" -void intel_td_flush(struct drm_i915_private *i915) +void intel_td_flush(struct intel_display *display) { - xe_device_td_flush(i915); + struct xe_device *xe = to_xe_device(display->drm); + + xe_device_td_flush(xe); } |