summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/xe/display
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/xe/display')
-rw-r--r--drivers/gpu/drm/xe/display/ext/i915_irq.c23
-rw-r--r--drivers/gpu/drm/xe/display/intel_bo.c2
-rw-r--r--drivers/gpu/drm/xe/display/intel_fb_bo.c11
-rw-r--r--drivers/gpu/drm/xe/display/intel_fbdev_fb.c4
-rw-r--r--drivers/gpu/drm/xe/display/xe_display.c199
-rw-r--r--drivers/gpu/drm/xe/display/xe_display.h11
-rw-r--r--drivers/gpu/drm/xe/display/xe_display_rps.c2
-rw-r--r--drivers/gpu/drm/xe/display/xe_fb_pin.c68
-rw-r--r--drivers/gpu/drm/xe/display/xe_plane_initial.c21
-rw-r--r--drivers/gpu/drm/xe/display/xe_tdf.c6
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, &timestamp, 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);
}