From 03e1b3df217a94c75e644bf50d3b3b2203acba00 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 12 Dec 2024 18:08:48 +0100 Subject: [PATCH 01/16] drm/i915/display: Remove preferred_bpp from struct intel_fbdev The value preferred_bpp in struct intel_fbdev duplicates preferred_bpp in struct drm_fb_helper. Remove the former. Instead let intel_fbdev_init_bios() read the framebuffer from the hardware. Then derive preferred_bpp from its format and initialize struct drm_fb_helper with the value. The default is 32 (i.e., XRGB8888). Also removes one of those deprecated references to the cpp field of struct drm_format_info. Signed-off-by: Thomas Zimmermann Reviewed-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20241212170913.185939-8-tzimmermann@suse.de Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_fbdev.c | 29 +++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index a99793723695..db396e1856de 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -60,7 +60,6 @@ struct intel_fbdev { struct intel_framebuffer *fb; struct i915_vma *vma; unsigned long vma_flags; - int preferred_bpp; }; static struct intel_fbdev *to_intel_fbdev(struct drm_fb_helper *fb_helper) @@ -430,7 +429,6 @@ static bool intel_fbdev_init_bios(struct drm_device *dev, goto out; } - ifbdev->preferred_bpp = fb->base.format->cpp[0] * 8; ifbdev->fb = fb; drm_framebuffer_get(&ifbdev->fb->base); @@ -461,6 +459,23 @@ out: return false; } +static unsigned int intel_fbdev_color_mode(const struct drm_format_info *info) +{ + unsigned int bpp; + + if (!info->depth || info->num_planes != 1 || info->has_alpha || info->is_yuv) + return 0; + + bpp = drm_format_info_bpp(info, 0); + + switch (bpp) { + case 16: + return info->depth; // 15 or 16 + default: + return bpp; + } +} + static void intel_fbdev_suspend_worker(struct work_struct *work) { intel_fbdev_set_suspend(&container_of(work, @@ -625,6 +640,7 @@ void intel_fbdev_setup(struct drm_i915_private *i915) { struct drm_device *dev = &i915->drm; struct intel_fbdev *ifbdev; + unsigned int preferred_bpp = 0; int ret; if (!HAS_DISPLAY(i915)) @@ -633,14 +649,15 @@ void intel_fbdev_setup(struct drm_i915_private *i915) ifbdev = kzalloc(sizeof(*ifbdev), GFP_KERNEL); if (!ifbdev) return; - drm_fb_helper_prepare(dev, &ifbdev->helper, 32, &intel_fb_helper_funcs); i915->display.fbdev.fbdev = ifbdev; INIT_WORK(&i915->display.fbdev.suspend_work, intel_fbdev_suspend_worker); if (intel_fbdev_init_bios(dev, ifbdev)) - ifbdev->helper.preferred_bpp = ifbdev->preferred_bpp; - else - ifbdev->preferred_bpp = ifbdev->helper.preferred_bpp; + preferred_bpp = intel_fbdev_color_mode(ifbdev->fb->base.format); + if (!preferred_bpp) + preferred_bpp = 32; + + drm_fb_helper_prepare(dev, &ifbdev->helper, preferred_bpp, &intel_fb_helper_funcs); ret = drm_client_init(dev, &ifbdev->helper.client, "intel-fbdev", &intel_fbdev_client_funcs); -- 2.51.0 From 04a1c47798f773cc6b071790c56eaa460a1e5caf Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 12 Dec 2024 18:08:49 +0100 Subject: [PATCH 02/16] drm/i915/display: Remove struct drm_fb_helper from struct intel_fbdev Store instances of drm_fb_helper and struct intel_fbdev separately. This will allow i915 to use the common fbdev client, which allocates its own instance of struct drm_fb_helper. There is at most one instance of type each per DRM device, so both can be referenced directly from the i915 and DRM device structures. A later patchset might rework the common fbdev client to allow for storing both, drm_fb_helper and intel_fbdev, together in the same place. Signed-off-by: Thomas Zimmermann Reviewed-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20241212170913.185939-9-tzimmermann@suse.de Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_fbdev.c | 49 ++++++++++++---------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index db396e1856de..7f9de9f49087 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include "i915_drv.h" @@ -56,7 +57,6 @@ #include "intel_frontbuffer.h" struct intel_fbdev { - struct drm_fb_helper helper; struct intel_framebuffer *fb; struct i915_vma *vma; unsigned long vma_flags; @@ -64,7 +64,9 @@ struct intel_fbdev { static struct intel_fbdev *to_intel_fbdev(struct drm_fb_helper *fb_helper) { - return container_of(fb_helper, struct intel_fbdev, helper); + struct drm_i915_private *i915 = to_i915(fb_helper->client.dev); + + return i915->display.fbdev.fbdev; } static struct intel_frontbuffer *to_frontbuffer(struct intel_fbdev *ifbdev) @@ -120,8 +122,8 @@ static int intel_fbdev_pan_display(struct fb_var_screeninfo *var, static int intel_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma) { - struct intel_fbdev *fbdev = to_intel_fbdev(info->par); - struct drm_gem_object *obj = drm_gem_fb_get_obj(&fbdev->fb->base, 0); + struct drm_fb_helper *fb_helper = info->par; + struct drm_gem_object *obj = drm_gem_fb_get_obj(fb_helper->fb, 0); return intel_bo_fb_mmap(obj, vma); } @@ -129,9 +131,9 @@ static int intel_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma) static void intel_fbdev_fb_destroy(struct fb_info *info) { struct drm_fb_helper *fb_helper = info->par; - struct intel_fbdev *ifbdev = container_of(fb_helper, struct intel_fbdev, helper); + struct intel_fbdev *ifbdev = to_intel_fbdev(fb_helper); - drm_fb_helper_fini(&ifbdev->helper); + drm_fb_helper_fini(fb_helper); /* * We rely on the object-free to release the VMA pinning for @@ -139,11 +141,11 @@ static void intel_fbdev_fb_destroy(struct fb_info *info) * trying to rectify all the possible error paths leading here. */ intel_fb_unpin_vma(ifbdev->vma, ifbdev->vma_flags); - drm_framebuffer_remove(&ifbdev->fb->base); + drm_framebuffer_remove(fb_helper->fb); drm_client_release(&fb_helper->client); - drm_fb_helper_unprepare(&ifbdev->helper); - kfree(ifbdev); + drm_fb_helper_unprepare(fb_helper); + kfree(fb_helper); } __diag_push(); @@ -227,7 +229,7 @@ static int intelfb_create(struct drm_fb_helper *helper, goto out_unpin; } - ifbdev->helper.fb = &fb->base; + helper->fb = &fb->base; info->fbops = &intelfb_ops; @@ -237,7 +239,7 @@ static int intelfb_create(struct drm_fb_helper *helper, if (ret) goto out_unpin; - drm_fb_helper_fill_info(info, &ifbdev->helper, sizes); + drm_fb_helper_fill_info(info, dev->fb_helper, sizes); /* If the object is shmemfs backed, it will have given us zeroed pages. * If the object is stolen however, it will be full of whatever @@ -528,13 +530,14 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous } } - drm_fb_helper_set_suspend(&ifbdev->helper, state); + drm_fb_helper_set_suspend(dev->fb_helper, state); console_unlock(); } static int intel_fbdev_restore_mode(struct drm_i915_private *dev_priv) { struct intel_fbdev *ifbdev = dev_priv->display.fbdev.fbdev; + struct drm_device *dev = &dev_priv->drm; int ret; if (!ifbdev) @@ -543,7 +546,7 @@ static int intel_fbdev_restore_mode(struct drm_i915_private *dev_priv) if (!ifbdev->vma) return -ENOMEM; - ret = drm_fb_helper_restore_fbdev_mode_unlocked(&ifbdev->helper); + ret = drm_fb_helper_restore_fbdev_mode_unlocked(dev->fb_helper); if (ret) return ret; @@ -640,13 +643,14 @@ void intel_fbdev_setup(struct drm_i915_private *i915) { struct drm_device *dev = &i915->drm; struct intel_fbdev *ifbdev; + struct drm_fb_helper *fb_helper; unsigned int preferred_bpp = 0; int ret; if (!HAS_DISPLAY(i915)) return; - ifbdev = kzalloc(sizeof(*ifbdev), GFP_KERNEL); + ifbdev = drmm_kzalloc(dev, sizeof(*ifbdev), GFP_KERNEL); if (!ifbdev) return; @@ -657,30 +661,33 @@ void intel_fbdev_setup(struct drm_i915_private *i915) if (!preferred_bpp) preferred_bpp = 32; - drm_fb_helper_prepare(dev, &ifbdev->helper, preferred_bpp, &intel_fb_helper_funcs); + fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL); + if (!fb_helper) + return; + drm_fb_helper_prepare(dev, fb_helper, preferred_bpp, &intel_fb_helper_funcs); - ret = drm_client_init(dev, &ifbdev->helper.client, "intel-fbdev", + ret = drm_client_init(dev, &fb_helper->client, "intel-fbdev", &intel_fbdev_client_funcs); if (ret) { drm_err(dev, "Failed to register client: %d\n", ret); goto err_drm_fb_helper_unprepare; } - drm_client_register(&ifbdev->helper.client); + drm_client_register(&fb_helper->client); return; err_drm_fb_helper_unprepare: - drm_fb_helper_unprepare(&ifbdev->helper); - kfree(ifbdev); + drm_fb_helper_unprepare(dev->fb_helper); + kfree(fb_helper); } struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev *fbdev) { - if (!fbdev || !fbdev->helper.fb) + if (!fbdev) return NULL; - return to_intel_framebuffer(fbdev->helper.fb); + return fbdev->fb; } struct i915_vma *intel_fbdev_vma_pointer(struct intel_fbdev *fbdev) -- 2.51.0 From ef9e0e2ef958cd50a50b63f4444ebd946e24d99a Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 12 Dec 2024 18:08:50 +0100 Subject: [PATCH 03/16] drm/i915/display: Move fbdev code around Move fbdev code around in the source file before switching to DRM's generic fbdev client. This will make the conversion less intrusive. No functional changes. Signed-off-by: Thomas Zimmermann Reviewed-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20241212170913.185939-10-tzimmermann@suse.de Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_fbdev.c | 85 +++++++++++----------- 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 7f9de9f49087..4578634cc4ab 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -56,6 +56,9 @@ #include "intel_fbdev_fb.h" #include "intel_frontbuffer.h" +static int intelfb_create(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes); + struct intel_fbdev { struct intel_framebuffer *fb; struct i915_vma *vma; @@ -165,6 +168,47 @@ static const struct fb_ops intelfb_ops = { __diag_pop(); +static int intelfb_dirty(struct drm_fb_helper *helper, struct drm_clip_rect *clip) +{ + if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2)) + return 0; + + if (helper->fb->funcs->dirty) + return helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, clip, 1); + + return 0; +} + +static void intelfb_restore(struct drm_fb_helper *fb_helper) +{ + struct intel_fbdev *ifbdev = to_intel_fbdev(fb_helper); + + intel_fbdev_invalidate(ifbdev); +} + +static void intelfb_set_suspend(struct drm_fb_helper *fb_helper, bool suspend) +{ + struct fb_info *info = fb_helper->info; + + /* + * When resuming from hibernation, Linux restores the object's + * content from swap if the buffer is backed by shmemfs. If the + * object is stolen however, it will be full of whatever garbage + * was left in there. Clear it to zero in this case. + */ + if (!suspend && !intel_bo_is_shmem(intel_fb_bo(fb_helper->fb))) + memset_io(info->screen_base, 0, info->screen_size); + + fb_set_suspend(info, suspend); +} + +static const struct drm_fb_helper_funcs intel_fb_helper_funcs = { + .fb_probe = intelfb_create, + .fb_dirty = intelfb_dirty, + .fb_restore = intelfb_restore, + .fb_set_suspend = intelfb_set_suspend, +}; + static int intelfb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { @@ -268,47 +312,6 @@ out_unlock: return ret; } -static int intelfb_dirty(struct drm_fb_helper *helper, struct drm_clip_rect *clip) -{ - if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2)) - return 0; - - if (helper->fb->funcs->dirty) - return helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, clip, 1); - - return 0; -} - -static void intelfb_restore(struct drm_fb_helper *fb_helper) -{ - struct intel_fbdev *ifbdev = to_intel_fbdev(fb_helper); - - intel_fbdev_invalidate(ifbdev); -} - -static void intelfb_set_suspend(struct drm_fb_helper *fb_helper, bool suspend) -{ - struct fb_info *info = fb_helper->info; - - /* - * When resuming from hibernation, Linux restores the object's - * content from swap if the buffer is backed by shmemfs. If the - * object is stolen however, it will be full of whatever garbage - * was left in there. Clear it to zero in this case. - */ - if (!suspend && !intel_bo_is_shmem(intel_fb_bo(fb_helper->fb))) - memset_io(info->screen_base, 0, info->screen_size); - - fb_set_suspend(info, suspend); -} - -static const struct drm_fb_helper_funcs intel_fb_helper_funcs = { - .fb_probe = intelfb_create, - .fb_dirty = intelfb_dirty, - .fb_restore = intelfb_restore, - .fb_set_suspend = intelfb_set_suspend, -}; - /* * Build an intel_fbdev struct using a BIOS allocated framebuffer, if possible. * The core display code will have read out the current plane configuration, -- 2.51.0 From 9fa154f40eb6b4bc17fefaf94e91f6f4d5b4fda2 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 12 Dec 2024 18:08:51 +0100 Subject: [PATCH 04/16] drm/{i915,xe}: Run DRM default client setup Rework fbdev probing to support fbdev_probe in struct drm_driver and remove the old fb_probe callback. Provide an initializer macro that sets the callback in struct drm_driver according to the kernel configuration. Call drm_client_setup_with_color_mode() to run the kernel's default client setup for DRM. This commit also prepares support for the kernel's drm_log client (or any future client) in i915. Using drm_log will also require vmap support in GEM objects. Signed-off-by: Thomas Zimmermann Reviewed-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20241212170913.185939-11-tzimmermann@suse.de Signed-off-by: Maarten Lankhorst --- .../gpu/drm/i915/display/intel_display_core.h | 1 - drivers/gpu/drm/i915/display/intel_fbdev.c | 194 +----------------- drivers/gpu/drm/i915/display/intel_fbdev.h | 17 +- drivers/gpu/drm/i915/i915_driver.c | 3 + drivers/gpu/drm/xe/display/xe_display.c | 5 + 5 files changed, 21 insertions(+), 199 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 1970d4c15090..7360ad39b1cc 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -386,7 +386,6 @@ struct intel_display { struct { /* list of fbdev register on this device */ struct intel_fbdev *fbdev; - struct work_struct suspend_work; } fbdev; struct { diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 4578634cc4ab..adc19d5607de 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -56,9 +57,6 @@ #include "intel_fbdev_fb.h" #include "intel_frontbuffer.h" -static int intelfb_create(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes); - struct intel_fbdev { struct intel_framebuffer *fb; struct i915_vma *vma; @@ -203,14 +201,13 @@ static void intelfb_set_suspend(struct drm_fb_helper *fb_helper, bool suspend) } static const struct drm_fb_helper_funcs intel_fb_helper_funcs = { - .fb_probe = intelfb_create, .fb_dirty = intelfb_dirty, .fb_restore = intelfb_restore, .fb_set_suspend = intelfb_set_suspend, }; -static int intelfb_create(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) +int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) { struct intel_fbdev *ifbdev = to_intel_fbdev(helper); struct intel_framebuffer *fb = ifbdev->fb; @@ -273,6 +270,7 @@ static int intelfb_create(struct drm_fb_helper *helper, goto out_unpin; } + helper->funcs = &intel_fb_helper_funcs; helper->fb = &fb->base; info->fbops = &intelfb_ops; @@ -481,174 +479,11 @@ static unsigned int intel_fbdev_color_mode(const struct drm_format_info *info) } } -static void intel_fbdev_suspend_worker(struct work_struct *work) -{ - intel_fbdev_set_suspend(&container_of(work, - struct drm_i915_private, - display.fbdev.suspend_work)->drm, - FBINFO_STATE_RUNNING, - true); -} - -void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_fbdev *ifbdev = dev_priv->display.fbdev.fbdev; - - if (!ifbdev) - return; - - if (drm_WARN_ON(&dev_priv->drm, !HAS_DISPLAY(dev_priv))) - return; - - if (!ifbdev->vma) - return; - - if (synchronous) { - /* Flush any pending work to turn the console on, and then - * wait to turn it off. It must be synchronous as we are - * about to suspend or unload the driver. - * - * Note that from within the work-handler, we cannot flush - * ourselves, so only flush outstanding work upon suspend! - */ - if (state != FBINFO_STATE_RUNNING) - flush_work(&dev_priv->display.fbdev.suspend_work); - - console_lock(); - } else { - /* - * The console lock can be pretty contented on resume due - * to all the printk activity. Try to keep it out of the hot - * path of resume if possible. - */ - drm_WARN_ON(dev, state != FBINFO_STATE_RUNNING); - if (!console_trylock()) { - /* Don't block our own workqueue as this can - * be run in parallel with other i915.ko tasks. - */ - queue_work(dev_priv->unordered_wq, - &dev_priv->display.fbdev.suspend_work); - return; - } - } - - drm_fb_helper_set_suspend(dev->fb_helper, state); - console_unlock(); -} - -static int intel_fbdev_restore_mode(struct drm_i915_private *dev_priv) -{ - struct intel_fbdev *ifbdev = dev_priv->display.fbdev.fbdev; - struct drm_device *dev = &dev_priv->drm; - int ret; - - if (!ifbdev) - return -EINVAL; - - if (!ifbdev->vma) - return -ENOMEM; - - ret = drm_fb_helper_restore_fbdev_mode_unlocked(dev->fb_helper); - if (ret) - return ret; - - return 0; -} - -/* - * Fbdev client and struct drm_client_funcs - */ - -static void intel_fbdev_client_unregister(struct drm_client_dev *client) -{ - struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); - struct drm_device *dev = fb_helper->dev; - struct pci_dev *pdev = to_pci_dev(dev->dev); - - if (fb_helper->info) { - vga_switcheroo_client_fb_set(pdev, NULL); - drm_fb_helper_unregister_info(fb_helper); - } else { - drm_fb_helper_unprepare(fb_helper); - drm_client_release(&fb_helper->client); - kfree(fb_helper); - } -} - -static int intel_fbdev_client_restore(struct drm_client_dev *client) -{ - struct drm_i915_private *dev_priv = to_i915(client->dev); - int ret; - - ret = intel_fbdev_restore_mode(dev_priv); - if (ret) - return ret; - - vga_switcheroo_process_delayed_switch(); - - return 0; -} - -static int intel_fbdev_client_hotplug(struct drm_client_dev *client) -{ - struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); - struct drm_device *dev = client->dev; - struct pci_dev *pdev = to_pci_dev(dev->dev); - int ret; - - if (dev->fb_helper) - return drm_fb_helper_hotplug_event(dev->fb_helper); - - ret = drm_fb_helper_init(dev, fb_helper); - if (ret) - goto err_drm_err; - - ret = drm_fb_helper_initial_config(fb_helper); - if (ret) - goto err_drm_fb_helper_fini; - - vga_switcheroo_client_fb_set(pdev, fb_helper->info); - - return 0; - -err_drm_fb_helper_fini: - drm_fb_helper_fini(fb_helper); -err_drm_err: - drm_err(dev, "Failed to setup i915 fbdev emulation (ret=%d)\n", ret); - return ret; -} - -static int intel_fbdev_client_suspend(struct drm_client_dev *client, bool holds_console_lock) -{ - intel_fbdev_set_suspend(client->dev, FBINFO_STATE_SUSPENDED, true); - - return 0; -} - -static int intel_fbdev_client_resume(struct drm_client_dev *client, bool holds_console_lock) -{ - intel_fbdev_set_suspend(client->dev, FBINFO_STATE_RUNNING, false); - - return 0; -} - -static const struct drm_client_funcs intel_fbdev_client_funcs = { - .owner = THIS_MODULE, - .unregister = intel_fbdev_client_unregister, - .restore = intel_fbdev_client_restore, - .hotplug = intel_fbdev_client_hotplug, - .suspend = intel_fbdev_client_suspend, - .resume = intel_fbdev_client_resume, -}; - void intel_fbdev_setup(struct drm_i915_private *i915) { struct drm_device *dev = &i915->drm; struct intel_fbdev *ifbdev; - struct drm_fb_helper *fb_helper; unsigned int preferred_bpp = 0; - int ret; if (!HAS_DISPLAY(i915)) return; @@ -658,31 +493,12 @@ void intel_fbdev_setup(struct drm_i915_private *i915) return; i915->display.fbdev.fbdev = ifbdev; - INIT_WORK(&i915->display.fbdev.suspend_work, intel_fbdev_suspend_worker); if (intel_fbdev_init_bios(dev, ifbdev)) preferred_bpp = intel_fbdev_color_mode(ifbdev->fb->base.format); if (!preferred_bpp) preferred_bpp = 32; - fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL); - if (!fb_helper) - return; - drm_fb_helper_prepare(dev, fb_helper, preferred_bpp, &intel_fb_helper_funcs); - - ret = drm_client_init(dev, &fb_helper->client, "intel-fbdev", - &intel_fbdev_client_funcs); - if (ret) { - drm_err(dev, "Failed to register client: %d\n", ret); - goto err_drm_fb_helper_unprepare; - } - - drm_client_register(&fb_helper->client); - - return; - -err_drm_fb_helper_unprepare: - drm_fb_helper_unprepare(dev->fb_helper); - kfree(fb_helper); + drm_client_setup_with_color_mode(dev, preferred_bpp); } struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev *fbdev) diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.h b/drivers/gpu/drm/i915/display/intel_fbdev.h index 24a3434558cb..ca2c8c438f02 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.h +++ b/drivers/gpu/drm/i915/display/intel_fbdev.h @@ -6,28 +6,27 @@ #ifndef __INTEL_FBDEV_H__ #define __INTEL_FBDEV_H__ -#include - -struct drm_device; +struct drm_fb_helper; +struct drm_fb_helper_surface_size; struct drm_i915_private; struct intel_fbdev; struct intel_framebuffer; #ifdef CONFIG_DRM_FBDEV_EMULATION +int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes); +#define INTEL_FBDEV_DRIVER_OPS \ + .fbdev_probe = intel_fbdev_driver_fbdev_probe void intel_fbdev_setup(struct drm_i915_private *dev_priv); -void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous); struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev *fbdev); struct i915_vma *intel_fbdev_vma_pointer(struct intel_fbdev *fbdev); #else +#define INTEL_FBDEV_DRIVER_OPS \ + .fbdev_probe = NULL static inline void intel_fbdev_setup(struct drm_i915_private *dev_priv) { } - -static inline void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous) -{ -} - static inline struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev *fbdev) { return NULL; diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 2cabfd611671..ce3cc93ea211 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -56,6 +56,7 @@ #include "display/intel_dp.h" #include "display/intel_dpt.h" #include "display/intel_encoder.h" +#include "display/intel_fbdev.h" #include "display/intel_hotplug.h" #include "display/intel_overlay.h" #include "display/intel_pch_refclk.h" @@ -1808,6 +1809,8 @@ static const struct drm_driver i915_drm_driver = { .dumb_create = i915_gem_dumb_create, .dumb_map_offset = i915_gem_dumb_mmap_offset, + INTEL_FBDEV_DRIVER_OPS, + .ioctls = i915_ioctls, .num_ioctls = ARRAY_SIZE(i915_ioctls), .fops = &i915_driver_fops, diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 0c1b45b855de..4f434f84b2cc 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -27,6 +27,7 @@ #include "intel_dmc_wl.h" #include "intel_dp.h" #include "intel_encoder.h" +#include "intel_fbdev.h" #include "intel_hdcp.h" #include "intel_hotplug.h" #include "intel_opregion.h" @@ -68,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; } -- 2.51.0 From 69acb6bd5e9bf6587883a3528a9cae3e63c9e9c5 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 12 Dec 2024 18:08:52 +0100 Subject: [PATCH 05/16] drm/i915/display: Remove compile guard around fbdev debugfs output If fbdev support has been disabled, no output will be shown. Remove the fbdev-related compile guard from the driver's debugfs code. Signed-off-by: Thomas Zimmermann Reviewed-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20241212170913.185939-12-tzimmermann@suse.de Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 510c15a6271f..fdedf65bee53 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -114,7 +114,6 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) struct intel_framebuffer *fbdev_fb = NULL; struct drm_framebuffer *drm_fb; -#ifdef CONFIG_DRM_FBDEV_EMULATION fbdev_fb = intel_fbdev_framebuffer(display->fbdev.fbdev); if (fbdev_fb) { seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ", @@ -127,7 +126,6 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) intel_bo_describe(m, intel_fb_bo(&fbdev_fb->base)); seq_putc(m, '\n'); } -#endif mutex_lock(&display->drm->mode_config.fb_lock); drm_for_each_fb(drm_fb, display->drm) { -- 2.51.0 From 41ff0b424d81b7936bc4d96e8957aa7f454c3527 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 12 Dec 2024 18:08:53 +0100 Subject: [PATCH 06/16] drm/fb-helper: Remove struct drm_fb_helper.fb_probe The callback fb_probe in struct drm_fb_helper is unused. Remove it. New drivers should set struct drm_driver.fbdev_probe instead and call drm_client_setup() to instantiate in-kernel DRM clients. Signed-off-by: Thomas Zimmermann Reviewed-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20241212170913.185939-13-tzimmermann@suse.de Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/drm_fb_helper.c | 8 ++++---- include/drm/drm_fb_helper.h | 17 ----------------- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 0703fddd750f..937c3939e502 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1634,6 +1634,9 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper) struct fb_info *info; int ret; + if (drm_WARN_ON(dev, !dev->driver->fbdev_probe)) + return -EINVAL; + ret = drm_fb_helper_find_sizes(fb_helper, &sizes); if (ret) { /* First time: disable all crtc's.. */ @@ -1643,10 +1646,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper) } /* push down into drivers */ - if (dev->driver->fbdev_probe) - ret = dev->driver->fbdev_probe(fb_helper, &sizes); - else if (fb_helper->funcs) - ret = fb_helper->funcs->fb_probe(fb_helper, &sizes); + ret = dev->driver->fbdev_probe(fb_helper, &sizes); if (ret < 0) return ret; diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index ddce2408ca2b..c1d38d54a112 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -69,23 +69,6 @@ struct drm_fb_helper_surface_size { * Driver callbacks used by the fbdev emulation helper library. */ struct drm_fb_helper_funcs { - /** - * @fb_probe: - * - * Driver callback to allocate and initialize the fbdev info structure. - * Furthermore it also needs to allocate the DRM framebuffer used to - * back the fbdev. - * - * This callback is mandatory. - * - * RETURNS: - * - * The driver should return 0 on success and a negative error code on - * failure. - */ - int (*fb_probe)(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes); - /** * @fb_dirty: * -- 2.51.0 From fb64f5568c0e0b5730733d70a012ae26b1a55815 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 18 Feb 2025 23:18:55 +0200 Subject: [PATCH 07/16] drm/i915/cdclk: Do cdclk post plane programming later MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit We currently call intel_set_cdclk_post_plane_update() far too early. When pipes are active during the reprogramming the current spot only works for the cd2x divider update case, as that is synchronize to the pipe's vblank. Squashing and crawling are not synchronized in any way, so doing the programming while the pipes/planes are potentially still using the old hardware state could lead to underruns. Move the post plane reprgramming to a spot where we know that the pipes/planes have switched over the new hardware state. Cc: stable@vger.kernel.org Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250218211913.27867-2-ville.syrjala@linux.intel.com Reviewed-by: Vinod Govindapillai --- drivers/gpu/drm/i915/display/intel_display.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index f7cb38145e9d..51c011de4a16 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7354,9 +7354,6 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_program_dpkgc_latency(state); - if (state->modeset) - intel_set_cdclk_post_plane_update(state); - intel_wait_for_vblank_workers(state); /* FIXME: We should call drm_atomic_helper_commit_hw_done() here @@ -7433,6 +7430,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_verify_planes(state); intel_sagv_post_plane_update(state); + if (state->modeset) + intel_set_cdclk_post_plane_update(state); intel_pmdemand_post_plane_update(state); drm_atomic_helper_commit_hw_done(&state->base); -- 2.51.0 From 2fff55d499eea7c61a2671c5d7394e9c62995d9f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 5 Mar 2025 18:38:22 +0200 Subject: [PATCH 08/16] drm/xe/compat: refactor compat i915_drv.h The compat i915_drv.h contains things that aren't there in the original i915_drv.h. Split out gem/i915_gem_object.h and i915_scheduler_types.h, moving the corresponding pieces out, including FORCEWAKE_ALL to intel_uncore.h. Technically I915_PRIORITY_DISPLAY should be in i915_priolist_types.h, but it's a bit overkill to split out another file just for that. i915_scheduler_types.h shall do. With this, the compat i915_drv.h becomes a strict subset of the original. Reviewed-by: Nemesa Garg Link: https://patchwork.freedesktop.org/patch/msgid/d6bd95bf52aa37f48ddec3e675b7a3cc66829eef.1741192597.git.jani.nikula@intel.com [Jani: fix i915_gem_object.h header guard while applying] Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 2 ++ .../xe/compat-i915-headers/gem/i915_gem_object.h | 15 +++++++++++++++ drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h | 8 -------- .../xe/compat-i915-headers/i915_scheduler_types.h | 13 +++++++++++++ .../gpu/drm/xe/compat-i915-headers/intel_uncore.h | 2 ++ 5 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h create mode 100644 drivers/gpu/drm/xe/compat-i915-headers/i915_scheduler_types.h diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index a26b54185d5b..d899c37d80c6 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -41,8 +41,10 @@ #include #include +#include "gem/i915_gem_object.h" #include "i915_config.h" #include "i915_drv.h" +#include "i915_scheduler_types.h" #include "i915_vma.h" #include "i9xx_plane_regs.h" #include "intel_atomic_plane.h" diff --git a/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h b/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h new file mode 100644 index 000000000000..8a048980ea38 --- /dev/null +++ b/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2025 Intel Corporation */ + +#ifndef __I915_GEM_OBJECT_H__ +#define __I915_GEM_OBJECT_H__ + +struct dma_fence; +struct i915_sched_attr; + +static inline void i915_gem_fence_wait_priority(struct dma_fence *fence, + const struct i915_sched_attr *attr) +{ +} + +#endif diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h index 84b0991b35b3..dfec5108d2c3 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h @@ -95,14 +95,6 @@ static inline struct drm_i915_private *to_i915(const struct drm_device *dev) #define HAS_128_BYTE_Y_TILING(xe) (xe || 1) -#define I915_PRIORITY_DISPLAY 0 -struct i915_sched_attr { - int priority; -}; -#define i915_gem_fence_wait_priority(fence, attr) do { (void) attr; } while (0) - -#define FORCEWAKE_ALL XE_FORCEWAKE_ALL - #ifdef CONFIG_ARM64 /* * arm64 indirectly includes linux/rtc.h, diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_scheduler_types.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_scheduler_types.h new file mode 100644 index 000000000000..c11130440d31 --- /dev/null +++ b/drivers/gpu/drm/xe/compat-i915-headers/i915_scheduler_types.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2025 Intel Corporation */ + +#ifndef __I915_SCHEDULER_TYPES_H__ +#define __I915_SCHEDULER_TYPES_H__ + +#define I915_PRIORITY_DISPLAY 0 + +struct i915_sched_attr { + int priority; +}; + +#endif diff --git a/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h b/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h index 4fc3e535de91..0c1e88e36a1e 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/intel_uncore.h @@ -10,6 +10,8 @@ #include "xe_device_types.h" #include "xe_mmio.h" +#define FORCEWAKE_ALL XE_FORCEWAKE_ALL + static inline struct intel_uncore *to_intel_uncore(struct drm_device *drm) { return &to_xe_device(drm)->uncore; -- 2.51.0 From 30a6be2c200fdbdaad8adcdd68eae9d90a23c291 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 5 Mar 2025 18:38:23 +0200 Subject: [PATCH 09/16] drm/i915/plane: convert intel_atomic_plane.[ch] to struct intel_display Going forward, struct intel_display is the main display device data pointer. Convert intel_atomic_plane.[ch] to struct intel_display. Reviewed-by: Nemesa Garg Link: https://patchwork.freedesktop.org/patch/msgid/d7e28ad43f67d92e54fb7e14373872b5e561038c.1741192597.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../gpu/drm/i915/display/intel_atomic_plane.c | 78 +++++++++---------- 1 file changed, 38 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index d899c37d80c6..7276179df878 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -43,7 +43,6 @@ #include "gem/i915_gem_object.h" #include "i915_config.h" -#include "i915_drv.h" #include "i915_scheduler_types.h" #include "i915_vma.h" #include "i9xx_plane_regs.h" @@ -169,10 +168,10 @@ intel_plane_destroy_state(struct drm_plane *plane, bool intel_plane_needs_physical(struct intel_plane *plane) { - struct drm_i915_private *i915 = to_i915(plane->base.dev); + struct intel_display *display = to_intel_display(plane); return plane->id == PLANE_CURSOR && - DISPLAY_INFO(i915)->cursor_needs_physical; + DISPLAY_INFO(display)->cursor_needs_physical; } bool intel_plane_can_async_flip(struct intel_plane *plane, u64 modifier) @@ -277,7 +276,7 @@ int intel_plane_calc_min_cdclk(struct intel_atomic_state *state, struct intel_plane *plane, bool *need_cdclk_calc) { - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + struct intel_display *display = to_intel_display(plane); const struct intel_plane_state *plane_state = intel_atomic_get_new_plane_state(state, plane); struct intel_crtc *crtc = to_intel_crtc(plane_state->hw.crtc); @@ -322,7 +321,7 @@ int intel_plane_calc_min_cdclk(struct intel_atomic_state *state, cdclk_state->min_cdclk[crtc->pipe]) return 0; - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(display->drm, "[PLANE:%d:%s] min cdclk (%d kHz) > [CRTC:%d:%s] min cdclk (%d kHz)\n", plane->base.base.id, plane->base.name, new_crtc_state->min_cdclk[plane->id], @@ -435,7 +434,7 @@ static bool intel_plane_do_async_flip(struct intel_plane *plane, const struct intel_crtc_state *old_crtc_state, const struct intel_crtc_state *new_crtc_state) { - struct drm_i915_private *i915 = to_i915(plane->base.dev); + struct intel_display *display = to_intel_display(plane); if (!plane->async_flip) return false; @@ -456,7 +455,7 @@ static bool intel_plane_do_async_flip(struct intel_plane *plane, * extend this so other scanout parameters (stride/etc) could * be changed as well... */ - return DISPLAY_VER(i915) < 9 || old_crtc_state->uapi.async_flip; + return DISPLAY_VER(display) < 9 || old_crtc_state->uapi.async_flip; } static bool i9xx_must_disable_cxsr(const struct intel_crtc_state *new_crtc_state, @@ -560,16 +559,16 @@ static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_cr const struct intel_plane_state *old_plane_state, struct intel_plane_state *new_plane_state) { + struct intel_display *display = to_intel_display(new_crtc_state); struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); bool mode_changed = intel_crtc_needs_modeset(new_crtc_state); bool was_crtc_enabled = old_crtc_state->hw.active; bool is_crtc_enabled = new_crtc_state->hw.active; bool turn_off, turn_on, visible, was_visible; int ret; - if (DISPLAY_VER(dev_priv) >= 9 && plane->id != PLANE_CURSOR) { + if (DISPLAY_VER(display) >= 9 && plane->id != PLANE_CURSOR) { ret = skl_update_scaler_plane(new_crtc_state, new_plane_state); if (ret) return ret; @@ -578,7 +577,7 @@ static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_cr was_visible = old_plane_state->uapi.visible; visible = new_plane_state->uapi.visible; - if (!was_crtc_enabled && drm_WARN_ON(&dev_priv->drm, was_visible)) + if (!was_crtc_enabled && drm_WARN_ON(display->drm, was_visible)) was_visible = false; /* @@ -602,7 +601,7 @@ static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_cr turn_off = was_visible && (!visible || mode_changed); turn_on = visible && (!was_visible || mode_changed); - drm_dbg_atomic(&dev_priv->drm, + drm_dbg_atomic(display->drm, "[CRTC:%d:%s] with [PLANE:%d:%s] visible %i -> %i, off %i, on %i, ms %i\n", crtc->base.base.id, crtc->base.name, plane->base.base.id, plane->base.name, @@ -612,11 +611,11 @@ static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_cr if (visible || was_visible) new_crtc_state->fb_bits |= plane->frontbuffer_bit; - if (HAS_GMCH(dev_priv) && + if (HAS_GMCH(display) && i9xx_must_disable_cxsr(new_crtc_state, old_plane_state, new_plane_state)) new_crtc_state->disable_cxsr = true; - if ((IS_IRONLAKE(dev_priv) || IS_SANDYBRIDGE(dev_priv) || IS_IVYBRIDGE(dev_priv)) && + if ((display->platform.ironlake || display->platform.sandybridge || display->platform.ivybridge) && ilk_must_disable_cxsr(new_crtc_state, old_plane_state, new_plane_state)) new_crtc_state->disable_cxsr = true; @@ -709,10 +708,10 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ struct intel_plane * intel_crtc_get_plane(struct intel_crtc *crtc, enum plane_id plane_id) { - struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_display *display = to_intel_display(crtc); struct intel_plane *plane; - for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { + for_each_intel_plane_on_crtc(display->drm, crtc, plane) { if (plane->id == plane_id) return plane; } @@ -961,9 +960,9 @@ void intel_crtc_planes_update_arm(struct intel_dsb *dsb, struct intel_atomic_state *state, struct intel_crtc *crtc) { - struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state); - if (DISPLAY_VER(i915) >= 9) + if (DISPLAY_VER(display) >= 9) skl_crtc_planes_update_arm(dsb, state, crtc); else i9xx_crtc_planes_update_arm(dsb, state, crtc); @@ -974,7 +973,7 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state, int min_scale, int max_scale, bool can_position) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_display *display = to_intel_display(plane_state); struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_framebuffer *fb = plane_state->hw.fb; struct drm_rect *src = &plane_state->uapi.src; @@ -994,7 +993,7 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state, hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale); vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale); if (hscale < 0 || vscale < 0) { - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[PLANE:%d:%s] invalid scaling "DRM_RECT_FP_FMT " -> " DRM_RECT_FMT "\n", plane->base.base.id, plane->base.name, DRM_RECT_FP_ARG(src), DRM_RECT_ARG(dst)); @@ -1011,7 +1010,7 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state, if (!can_position && plane_state->uapi.visible && !drm_rect_equals(dst, clip)) { - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[PLANE:%d:%s] plane (" DRM_RECT_FMT ") must cover entire CRTC (" DRM_RECT_FMT ")\n", plane->base.base.id, plane->base.name, DRM_RECT_ARG(dst), DRM_RECT_ARG(clip)); @@ -1026,7 +1025,7 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state, int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_display *display = to_intel_display(plane_state); struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); const struct drm_framebuffer *fb = plane_state->hw.fb; struct drm_rect *src = &plane_state->uapi.src; @@ -1060,18 +1059,18 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state) if (fb->format->format == DRM_FORMAT_RGB565 && rotated) { hsub = 2; vsub = 2; - } else if (DISPLAY_VER(i915) >= 20 && + } else if (DISPLAY_VER(display) >= 20 && intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) { /* * This allows NV12 and P0xx formats to have odd size and/or odd - * source coordinates on DISPLAY_VER(i915) >= 20 + * source coordinates on DISPLAY_VER(display) >= 20 */ hsub = 1; vsub = 1; /* Wa_16023981245 */ - if ((DISPLAY_VERx100(i915) == 2000 || - DISPLAY_VERx100(i915) == 3000) && + if ((DISPLAY_VERx100(display) == 2000 || + DISPLAY_VERx100(display) == 3000) && src_x % 2 != 0) hsub = 2; } else { @@ -1083,7 +1082,7 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state) hsub = vsub = max(hsub, vsub); if (src_x % hsub || src_w % hsub) { - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[PLANE:%d:%s] src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n", plane->base.base.id, plane->base.name, src_x, src_w, hsub, str_yes_no(rotated)); @@ -1091,7 +1090,7 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state) } if (src_y % vsub || src_h % vsub) { - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[PLANE:%d:%s] src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n", plane->base.base.id, plane->base.name, src_y, src_h, vsub, str_yes_no(rotated)); @@ -1336,14 +1335,13 @@ static int icl_check_nv12_planes(struct intel_atomic_state *state, struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(state); - struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); struct intel_plane_state *plane_state; struct intel_plane *plane; int i; - if (DISPLAY_VER(dev_priv) < 11) + if (DISPLAY_VER(display) < 11) return 0; /* @@ -1371,7 +1369,7 @@ static int icl_check_nv12_planes(struct intel_atomic_state *state, if ((crtc_state->nv12_planes & BIT(plane->id)) == 0) continue; - for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, y_plane) { + for_each_intel_plane_on_crtc(display->drm, crtc, y_plane) { if (!icl_is_nv12_y_plane(display, y_plane->id)) continue; @@ -1386,7 +1384,7 @@ static int icl_check_nv12_planes(struct intel_atomic_state *state, } if (!y_plane_state) { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(display->drm, "[CRTC:%d:%s] need %d free Y planes for planar YUV\n", crtc->base.base.id, crtc->base.name, hweight8(crtc_state->nv12_planes)); @@ -1403,10 +1401,10 @@ static int intel_crtc_add_planes_to_state(struct intel_atomic_state *state, struct intel_crtc *crtc, u8 plane_ids_mask) { - struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state); struct intel_plane *plane; - for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) { + for_each_intel_plane_on_crtc(display->drm, crtc, plane) { struct intel_plane_state *plane_state; if ((plane_ids_mask & BIT(plane->id)) == 0) @@ -1433,12 +1431,12 @@ int intel_atomic_add_affected_planes(struct intel_atomic_state *state, new_crtc_state->enabled_planes); } -static bool active_planes_affects_min_cdclk(struct drm_i915_private *dev_priv) +static bool active_planes_affects_min_cdclk(struct intel_display *display) { /* See {hsw,vlv,ivb}_plane_ratio() */ - return IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv) || - IS_CHERRYVIEW(dev_priv) || IS_VALLEYVIEW(dev_priv) || - IS_IVYBRIDGE(dev_priv); + return display->platform.broadwell || display->platform.haswell || + display->platform.cherryview || display->platform.valleyview || + display->platform.ivybridge; } static u8 intel_joiner_affected_planes(struct intel_atomic_state *state, @@ -1517,7 +1515,7 @@ static int intel_add_affected_planes(struct intel_atomic_state *state) int intel_atomic_check_planes(struct intel_atomic_state *state) { - struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state); struct intel_crtc_state *old_crtc_state, *new_crtc_state; struct intel_plane_state __maybe_unused *plane_state; struct intel_plane *plane; @@ -1531,7 +1529,7 @@ int intel_atomic_check_planes(struct intel_atomic_state *state) for_each_new_intel_plane_in_state(state, plane, plane_state, i) { ret = intel_plane_atomic_check(state, plane); if (ret) { - drm_dbg_atomic(&dev_priv->drm, + drm_dbg_atomic(display->drm, "[PLANE:%d:%s] atomic driver check failed\n", plane->base.base.id, plane->base.name); return ret; @@ -1551,7 +1549,7 @@ int intel_atomic_check_planes(struct intel_atomic_state *state) * the planes' minimum cdclk calculation. Add such planes * to the state before we compute the minimum cdclk. */ - if (!active_planes_affects_min_cdclk(dev_priv)) + if (!active_planes_affects_min_cdclk(display)) continue; old_active_planes = old_crtc_state->active_planes & ~BIT(PLANE_CURSOR); -- 2.51.0 From 68b97b12c46105b0859dd7636f3247e9f6fceab2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 3 Mar 2025 14:39:52 +0200 Subject: [PATCH 10/16] drm/i915: Program CURSOR_PROGRAM and COEFF_POLARITY for icl+ combo PHYs MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Bspec asks us to clear the CURSOR_PROGRAM and COEFF_POLARITY bits in PORT_TX_DW5 on icl+ combo PHYs. Make it so. Bspec: 21257, 49291 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250303123952.5669-2-ville.syrjala@linux.intel.com Reviewed-by: Chaitanya Kumar Borah --- drivers/gpu/drm/i915/display/intel_combo_phy_regs.h | 2 ++ drivers/gpu/drm/i915/display/intel_ddi.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy_regs.h b/drivers/gpu/drm/i915/display/intel_combo_phy_regs.h index 0964e392d02c..ee41acdccf4e 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy_regs.h +++ b/drivers/gpu/drm/i915/display/intel_combo_phy_regs.h @@ -133,6 +133,8 @@ #define TX_TRAINING_EN REG_BIT(31) #define TAP2_DISABLE REG_BIT(30) #define TAP3_DISABLE REG_BIT(29) +#define CURSOR_PROGRAM REG_BIT(26) +#define COEFF_POLARITY REG_BIT(25) #define SCALING_MODE_SEL_MASK REG_GENMASK(20, 18) #define SCALING_MODE_SEL(x) REG_FIELD_PREP(SCALING_MODE_SEL_MASK, (x)) #define RTERM_SELECT_MASK REG_GENMASK(5, 3) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 676c1826f15c..f38c998935b9 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1193,7 +1193,8 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder, /* Set PORT_TX_DW5 */ val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy)); val &= ~(SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK | - TAP2_DISABLE | TAP3_DISABLE); + COEFF_POLARITY | CURSOR_PROGRAM | + TAP2_DISABLE | TAP3_DISABLE); val |= SCALING_MODE_SEL(0x2); val |= RTERM_SELECT(0x6); val |= TAP3_DISABLE; -- 2.51.0 From 72eea9175e4d30097ca4a8834de03a7227be5c03 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 6 Mar 2025 18:34:03 +0200 Subject: [PATCH 11/16] drm/i915: Drop redundant shared_dpll=NULL assignments MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The crtc state is expected to be fully cleared before readout, so there is no need to clear the shared_dpll pointers by hand. Reviewed-by: Vinod Govindapillai Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250306163420.3961-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 51c011de4a16..5c1c2cb83d51 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2997,7 +2997,6 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; pipe_config->sink_format = pipe_config->output_format; pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; - pipe_config->shared_dpll = NULL; ret = false; @@ -3339,7 +3338,6 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc, return false; pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; - pipe_config->shared_dpll = NULL; ret = false; tmp = intel_de_read(display, @@ -3906,8 +3904,6 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc, POWER_DOMAIN_PIPE(crtc->pipe))) return false; - pipe_config->shared_dpll = NULL; - active = hsw_get_transcoder_state(crtc, pipe_config, &crtc->hw_readout_power_domains); if ((display->platform.geminilake || display->platform.broxton) && -- 2.51.0 From 0851227d62bb3b7c3e819bb7de3d0918a3c6889c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 6 Mar 2025 18:34:04 +0200 Subject: [PATCH 12/16] drm/i915: Don't clobber crtc_state->cpu_transcoder for inactive crtcs MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Inactive crtcs are supposed to have their crtc_state completely cleared. Currently we are clobbering crtc_state->cpu_transcoder before determining whether it's actually enabled or not. Don't do that. I want to rework the inherited flag handling for inactive crtcs a bit, and having a bogus cpu_transcoder in the crtc state can then cause confusing fastset mismatches even when the crtc never changes state during the commit. Reviewed-by: Vinod Govindapillai Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250306163420.3961-3-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 28 +++++++++----------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 5c1c2cb83d51..8d94ab7de669 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2985,26 +2985,25 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, { struct intel_display *display = to_intel_display(crtc); enum intel_display_power_domain power_domain; + enum transcoder cpu_transcoder = (enum transcoder)crtc->pipe; intel_wakeref_t wakeref; + bool ret = false; u32 tmp; - bool ret; power_domain = POWER_DOMAIN_PIPE(crtc->pipe); wakeref = intel_display_power_get_if_enabled(display, power_domain); if (!wakeref) return false; - pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; - pipe_config->sink_format = pipe_config->output_format; - pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; - - ret = false; - - tmp = intel_de_read(display, - TRANSCONF(display, pipe_config->cpu_transcoder)); + tmp = intel_de_read(display, TRANSCONF(display, cpu_transcoder)); if (!(tmp & TRANSCONF_ENABLE)) goto out; + pipe_config->cpu_transcoder = cpu_transcoder; + + pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; + pipe_config->sink_format = pipe_config->output_format; + if (display->platform.g4x || display->platform.valleyview || display->platform.cherryview) { switch (tmp & TRANSCONF_BPC_MASK) { @@ -3328,23 +3327,22 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc, { struct intel_display *display = to_intel_display(crtc); enum intel_display_power_domain power_domain; + enum transcoder cpu_transcoder = (enum transcoder)crtc->pipe; intel_wakeref_t wakeref; + bool ret = false; u32 tmp; - bool ret; power_domain = POWER_DOMAIN_PIPE(crtc->pipe); wakeref = intel_display_power_get_if_enabled(display, power_domain); if (!wakeref) return false; - pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; - - ret = false; - tmp = intel_de_read(display, - TRANSCONF(display, pipe_config->cpu_transcoder)); + tmp = intel_de_read(display, TRANSCONF(display, cpu_transcoder)); if (!(tmp & TRANSCONF_ENABLE)) goto out; + pipe_config->cpu_transcoder = cpu_transcoder; + switch (tmp & TRANSCONF_BPC_MASK) { case TRANSCONF_BPC_6: pipe_config->pipe_bpp = 18; -- 2.51.0 From cd5693cf5ec4f45dface7db611e8f30526048b40 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 6 Mar 2025 18:34:05 +0200 Subject: [PATCH 13/16] drm/i915: Use intel_plane_set_invisible() in intel_plane_disable_noatomic() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Reuse intel_plane_set_invisible() in intel_plane_disable_noatomic() instead of hand rolling the same stuff. Reviewed-by: Vinod Govindapillai Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250306163420.3961-4-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 8d94ab7de669..5d7b28f6009f 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -674,13 +674,9 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc, plane->base.base.id, plane->base.name, crtc->base.base.id, crtc->base.name); + intel_plane_set_invisible(crtc_state, plane_state); intel_set_plane_visible(crtc_state, plane_state, false); intel_plane_fixup_bitmasks(crtc_state); - crtc_state->data_rate[plane->id] = 0; - crtc_state->data_rate_y[plane->id] = 0; - crtc_state->rel_data_rate[plane->id] = 0; - crtc_state->rel_data_rate_y[plane->id] = 0; - crtc_state->min_cdclk[plane->id] = 0; if ((crtc_state->active_planes & ~BIT(PLANE_CURSOR)) == 0 && hsw_ips_disable(crtc_state)) { -- 2.51.0 From 082ed1ffc24ab25be1d21f2edc83b2657142749d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 6 Mar 2025 18:34:06 +0200 Subject: [PATCH 14/16] drm/i915: Extract intel_cdclk_crtc_disable_noatomic() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Hoist the cdclk stuff into a separate function from intel_crtc_disable_noatomic_complete() so that the details are better hidden inside intel_cdclk.c. Reviewed-by: Vinod Govindapillai Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250306163420.3961-5-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_cdclk.c | 12 ++++++++++++ drivers/gpu/drm/i915/display/intel_cdclk.h | 2 ++ drivers/gpu/drm/i915/display/intel_modeset_setup.c | 6 +----- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index c6cfc57a0346..4b7058e65588 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -3340,6 +3340,18 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state) return 0; } +void intel_cdclk_crtc_disable_noatomic(struct intel_crtc *crtc) +{ + struct intel_display *display = to_intel_display(crtc); + struct intel_cdclk_state *cdclk_state = + to_intel_cdclk_state(display->cdclk.obj.state); + enum pipe pipe = crtc->pipe; + + cdclk_state->min_cdclk[pipe] = 0; + cdclk_state->min_voltage_level[pipe] = 0; + cdclk_state->active_pipes &= ~BIT(pipe); +} + static int intel_compute_max_dotclk(struct intel_display *display) { int ppc = intel_cdclk_ppc(display, HAS_DOUBLE_WIDE(display)); diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.h b/drivers/gpu/drm/i915/display/intel_cdclk.h index 6b0e7a41eba3..689e12e2196b 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.h +++ b/drivers/gpu/drm/i915/display/intel_cdclk.h @@ -12,6 +12,7 @@ #include "intel_global_state.h" struct intel_atomic_state; +struct intel_crtc; struct intel_crtc_state; struct intel_display; @@ -83,6 +84,7 @@ int intel_cdclk_atomic_check(struct intel_atomic_state *state, int intel_cdclk_state_set_joined_mbus(struct intel_atomic_state *state, bool joined_mbus); struct intel_cdclk_state * intel_atomic_get_cdclk_state(struct intel_atomic_state *state); +void intel_cdclk_crtc_disable_noatomic(struct intel_crtc *crtc); #define to_intel_cdclk_state(global_state) \ container_of_const((global_state), struct intel_cdclk_state, base) diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index a5a00b3ce98f..826998909045 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -158,8 +158,6 @@ static void intel_crtc_disable_noatomic_complete(struct intel_crtc *crtc) struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct intel_bw_state *bw_state = to_intel_bw_state(i915->display.bw.obj.state); - struct intel_cdclk_state *cdclk_state = - to_intel_cdclk_state(i915->display.cdclk.obj.state); struct intel_dbuf_state *dbuf_state = to_intel_dbuf_state(i915->display.dbuf.obj.state); struct intel_pmdemand_state *pmdemand_state = @@ -179,9 +177,7 @@ static void intel_crtc_disable_noatomic_complete(struct intel_crtc *crtc) intel_display_power_put_all_in_set(display, &crtc->enabled_power_domains); - cdclk_state->min_cdclk[pipe] = 0; - cdclk_state->min_voltage_level[pipe] = 0; - cdclk_state->active_pipes &= ~BIT(pipe); + intel_cdclk_crtc_disable_noatomic(crtc); dbuf_state->active_pipes &= ~BIT(pipe); -- 2.51.0 From d66fbd662ddae1ab133e3269a4c2d68971075afc Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 6 Mar 2025 18:34:07 +0200 Subject: [PATCH 15/16] drm/i915: Extract skl_wm_crtc_disable_noatomic() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Hoist the dbuf stuff into a separate function from intel_crtc_disable_noatomic_complete() so that the details are better hidden inside skl_watermark.c. We can also skip the whole thing on pre-skl since the dbuf state isn't actually used on those platforms. The readout path does still fill dbuf_state->active_pipes but we'll remedy that later. Reviewed-by: Vinod Govindapillai Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250306163420.3961-6-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_modeset_setup.c | 5 +---- drivers/gpu/drm/i915/display/skl_watermark.c | 13 +++++++++++++ drivers/gpu/drm/i915/display/skl_watermark.h | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index 826998909045..10a2421f7c50 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -158,8 +158,6 @@ static void intel_crtc_disable_noatomic_complete(struct intel_crtc *crtc) struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct intel_bw_state *bw_state = to_intel_bw_state(i915->display.bw.obj.state); - struct intel_dbuf_state *dbuf_state = - to_intel_dbuf_state(i915->display.dbuf.obj.state); struct intel_pmdemand_state *pmdemand_state = to_intel_pmdemand_state(i915->display.pmdemand.obj.state); struct intel_crtc_state *crtc_state = @@ -178,8 +176,7 @@ static void intel_crtc_disable_noatomic_complete(struct intel_crtc *crtc) intel_display_power_put_all_in_set(display, &crtc->enabled_power_domains); intel_cdclk_crtc_disable_noatomic(crtc); - - dbuf_state->active_pipes &= ~BIT(pipe); + skl_wm_crtc_disable_noatomic(crtc); bw_state->data_rate[pipe] = 0; bw_state->num_active_planes[pipe] = 0; diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 10a1daad28eb..4930e52322d3 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -3845,6 +3845,19 @@ static void skl_wm_get_hw_state_and_sanitize(struct drm_i915_private *i915) skl_dbuf_sanitize(i915); } +void skl_wm_crtc_disable_noatomic(struct intel_crtc *crtc) +{ + struct intel_display *display = to_intel_display(crtc); + struct intel_dbuf_state *dbuf_state = + to_intel_dbuf_state(display->dbuf.obj.state); + enum pipe pipe = crtc->pipe; + + if (DISPLAY_VER(display) < 9) + return; + + dbuf_state->active_pipes &= ~BIT(pipe); +} + void intel_wm_state_verify(struct intel_atomic_state *state, struct intel_crtc *crtc) { diff --git a/drivers/gpu/drm/i915/display/skl_watermark.h b/drivers/gpu/drm/i915/display/skl_watermark.h index c5547485225a..8c07c11135c7 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.h +++ b/drivers/gpu/drm/i915/display/skl_watermark.h @@ -41,6 +41,8 @@ bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry *ddb, void intel_wm_state_verify(struct intel_atomic_state *state, struct intel_crtc *crtc); +void skl_wm_crtc_disable_noatomic(struct intel_crtc *crtc); + void skl_watermark_ipc_init(struct drm_i915_private *i915); void skl_watermark_ipc_update(struct drm_i915_private *i915); bool skl_watermark_ipc_enabled(struct drm_i915_private *i915); -- 2.51.0 From 1dc6076c67a0341acc168858e833c9cebd734a4d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 6 Mar 2025 18:34:08 +0200 Subject: [PATCH 16/16] drm/i915: clean up pipe's ddb usage in intel_crtc_disable_noatomic() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Update the ddb tracking information when we disable a pipe during sanitization. Avoids leaving stale junk in the states. Currently this doesn't do anything as we haven't read out this state yet when we do the sanitization, but that will change soon. Reviewed-by: Vinod Govindapillai Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250306163420.3961-7-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/skl_watermark.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 4930e52322d3..9584d4da13d0 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -3848,6 +3848,8 @@ static void skl_wm_get_hw_state_and_sanitize(struct drm_i915_private *i915) void skl_wm_crtc_disable_noatomic(struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(crtc); + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); struct intel_dbuf_state *dbuf_state = to_intel_dbuf_state(display->dbuf.obj.state); enum pipe pipe = crtc->pipe; @@ -3856,6 +3858,13 @@ void skl_wm_crtc_disable_noatomic(struct intel_crtc *crtc) return; dbuf_state->active_pipes &= ~BIT(pipe); + + dbuf_state->weight[pipe] = 0; + dbuf_state->slices[pipe] = 0; + + memset(&dbuf_state->ddb[pipe], 0, sizeof(dbuf_state->ddb[pipe])); + + memset(&crtc_state->wm.skl.ddb, 0, sizeof(crtc_state->wm.skl.ddb)); } void intel_wm_state_verify(struct intel_atomic_state *state, -- 2.51.0