From 0f45696ddb2b901fbf15cb8d2e89767be481d59f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 7 May 2025 18:19:53 +0300 Subject: [PATCH 0001/1479] drm/i915/dp: Fix determining SST/MST mode during MTP TU state computation Determining the SST/MST mode during state computation must be done based on the output type stored in the CRTC state, which in turn is set once based on the modeset connector's SST vs. MST type and will not change as long as the connector is using the CRTC. OTOH the MST mode indicated by the given connector's intel_dp::is_mst flag can change independently of the above output type, based on what sink is at any moment plugged to the connector. Fix the state computation accordingly. Cc: Jani Nikula Fixes: f6971d7427c2 ("drm/i915/mst: adapt intel_dp_mtp_tu_compute_config() for 128b/132b SST") Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/4607 Reviewed-by: Jani Nikula Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250507151953.251846-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index aeda59f5fa7a4..30f5636d18b7d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -253,7 +253,7 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, to_intel_connector(conn_state->connector); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - bool is_mst = intel_dp->is_mst; + bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST); int bpp_x16, slots = -EINVAL; int dsc_slice_count = 0; int max_dpt_bpp_x16; -- GitLab From ff868667a4f9c6e349f4a4f0dcc3ff60d6ea8a73 Mon Sep 17 00:00:00 2001 From: Julia Filipchuk Date: Fri, 2 May 2025 15:39:24 -0700 Subject: [PATCH 0002/1479] drm/i915/guc: Enable DUAL_QUEUE_WA for newer platforms For newer platforms (post DG2) hardware intentionally stalls on submisstion of concurrent submissions on RCS and CCS of different address spaces. With this workaround GuC will never schedule such conlicting contexts; preventing detection of a stall as a hang. GuC specs recommend to enable this for all platforms starting from MTL supporting CCS. v2: Use existing macros for version check. (Jani) v3: Reword explanation for clarity. Remove unneeded parens. Remove accidental comment change. (Daniele) Signed-off-by: Julia Filipchuk Cc: Daniele Ceraolo Spurio Reviewed-by: Daniele Ceraolo Spurio Signed-off-by: Daniele Ceraolo Spurio Link: https://lore.kernel.org/r/20250502223924.94628-1-julia.filipchuk@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 5949ff0b0161f..553daf32c0b54 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -313,8 +313,13 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) * * The same WA bit is used for both and 22011391025 is applicable to * all DG2. + * + * Platforms post DG2 prevent this issue in hardware by stalling + * submissions. With this flag GuC will schedule as to avoid such + * stalls. */ - if (IS_DG2(gt->i915)) + if (IS_DG2(gt->i915) || + (CCS_MASK(gt) && GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 70))) flags |= GUC_WA_DUAL_QUEUE; /* Wa_22011802037: graphics version 11/12 */ -- GitLab From 243bf99e2fe75edf8df1711c1377b6fc020b806c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Thu, 8 May 2025 13:29:31 +0200 Subject: [PATCH 0003/1479] drm/xe: Fix the gem shrinker name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The xe buffer object shrinker name is visible in the /shrinker directory and most if not all other shinkers follow a naming convention that looks like -_: Follow the same convention for xe, changing the name to drm-xe_gem:. Other shrinkers typically use the device node for but since drm drivers typically don't have a single unique device- node, instead use the unique name in the drm device. Fixes: 00c8efc3180f ("drm/xe: Add a shrinker for xe bos") Cc: Matthew Brost Signed-off-by: Thomas Hellström Reviewed-by: Francois Dugast Link: https://lore.kernel.org/r/20250508112931.3347-1-thomas.hellstrom@linux.intel.com --- drivers/gpu/drm/xe/xe_shrinker.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c index 8184390f9c7b9..86d47aaf03589 100644 --- a/drivers/gpu/drm/xe/xe_shrinker.c +++ b/drivers/gpu/drm/xe/xe_shrinker.c @@ -227,7 +227,7 @@ struct xe_shrinker *xe_shrinker_create(struct xe_device *xe) if (!shrinker) return ERR_PTR(-ENOMEM); - shrinker->shrink = shrinker_alloc(0, "xe system shrinker"); + shrinker->shrink = shrinker_alloc(0, "drm-xe_gem:%s", xe->drm.unique); if (!shrinker->shrink) { kfree(shrinker); return ERR_PTR(-ENOMEM); -- GitLab From 5dd933e33b9a2a379bcdefa140b4ee94ea184444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Thu, 8 May 2025 13:30:15 +0200 Subject: [PATCH 0004/1479] drm/xe: Make the gem shrinker drm managed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the xe drm shrinker drm managed like many other resources created at device creation time. Signed-off-by: Thomas Hellström Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/20250508113015.3374-1-thomas.hellstrom@linux.intel.com --- drivers/gpu/drm/xe/xe_device.c | 9 +++----- drivers/gpu/drm/xe/xe_shrinker.c | 37 ++++++++++++++++---------------- drivers/gpu/drm/xe/xe_shrinker.h | 4 +--- 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index c02c4c4e94128..399ae5f40321a 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -402,9 +402,6 @@ static void xe_device_destroy(struct drm_device *dev, void *dummy) if (xe->unordered_wq) destroy_workqueue(xe->unordered_wq); - if (!IS_ERR_OR_NULL(xe->mem.shrinker)) - xe_shrinker_destroy(xe->mem.shrinker); - if (xe->destroy_wq) destroy_workqueue(xe->destroy_wq); @@ -438,9 +435,9 @@ struct xe_device *xe_device_create(struct pci_dev *pdev, if (err) goto err; - xe->mem.shrinker = xe_shrinker_create(xe); - if (IS_ERR(xe->mem.shrinker)) - return ERR_CAST(xe->mem.shrinker); + err = xe_shrinker_create(xe); + if (err) + goto err; xe->info.devid = pdev->device; xe->info.revid = pdev->revision; diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c index 86d47aaf03589..125c836e0ee42 100644 --- a/drivers/gpu/drm/xe/xe_shrinker.c +++ b/drivers/gpu/drm/xe/xe_shrinker.c @@ -5,6 +5,7 @@ #include +#include #include #include #include @@ -213,24 +214,34 @@ static void xe_shrinker_pm(struct work_struct *work) xe_pm_runtime_put(shrinker->xe); } +static void xe_shrinker_fini(struct drm_device *drm, void *arg) +{ + struct xe_shrinker *shrinker = arg; + + xe_assert(shrinker->xe, !shrinker->shrinkable_pages); + xe_assert(shrinker->xe, !shrinker->purgeable_pages); + shrinker_free(shrinker->shrink); + flush_work(&shrinker->pm_worker); + kfree(shrinker); +} + /** * xe_shrinker_create() - Create an xe per-device shrinker * @xe: Pointer to the xe device. * - * Returns: A pointer to the created shrinker on success, - * Negative error code on failure. + * Return: %0 on success. Negative error code on failure. */ -struct xe_shrinker *xe_shrinker_create(struct xe_device *xe) +int xe_shrinker_create(struct xe_device *xe) { struct xe_shrinker *shrinker = kzalloc(sizeof(*shrinker), GFP_KERNEL); if (!shrinker) - return ERR_PTR(-ENOMEM); + return -ENOMEM; shrinker->shrink = shrinker_alloc(0, "drm-xe_gem:%s", xe->drm.unique); if (!shrinker->shrink) { kfree(shrinker); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } INIT_WORK(&shrinker->pm_worker, xe_shrinker_pm); @@ -240,19 +251,7 @@ struct xe_shrinker *xe_shrinker_create(struct xe_device *xe) shrinker->shrink->scan_objects = xe_shrinker_scan; shrinker->shrink->private_data = shrinker; shrinker_register(shrinker->shrink); + xe->mem.shrinker = shrinker; - return shrinker; -} - -/** - * xe_shrinker_destroy() - Destroy an xe per-device shrinker - * @shrinker: Pointer to the shrinker to destroy. - */ -void xe_shrinker_destroy(struct xe_shrinker *shrinker) -{ - xe_assert(shrinker->xe, !shrinker->shrinkable_pages); - xe_assert(shrinker->xe, !shrinker->purgeable_pages); - shrinker_free(shrinker->shrink); - flush_work(&shrinker->pm_worker); - kfree(shrinker); + return drmm_add_action_or_reset(&xe->drm, xe_shrinker_fini, shrinker); } diff --git a/drivers/gpu/drm/xe/xe_shrinker.h b/drivers/gpu/drm/xe/xe_shrinker.h index 28a038f4fcbff..5132ae5192e1c 100644 --- a/drivers/gpu/drm/xe/xe_shrinker.h +++ b/drivers/gpu/drm/xe/xe_shrinker.h @@ -11,8 +11,6 @@ struct xe_device; void xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgeable); -struct xe_shrinker *xe_shrinker_create(struct xe_device *xe); - -void xe_shrinker_destroy(struct xe_shrinker *shrinker); +int xe_shrinker_create(struct xe_device *xe); #endif -- GitLab From c58af5cd9c6529e92d559b66470ae1bca6360015 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 2 May 2025 15:07:25 +0300 Subject: [PATCH 0005/1479] drm/i915/irq: stop using HAS_GMCH() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Right or wrong, HAS_GMCH() has become a display only thing. The last three users outside of display are in irq code. Reorder the if ladders to stop using HAS_GMCH(). Reviewed-by: Michał Grzelak Link: https://lore.kernel.org/r/20250502120725.439800-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_irq.c | 105 +++++++++++++++----------------- 1 file changed, 48 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 95042879bec4a..cc05f347555ad 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1152,71 +1152,62 @@ void intel_irq_fini(struct drm_i915_private *i915) static irq_handler_t intel_irq_handler(struct drm_i915_private *dev_priv) { - if (HAS_GMCH(dev_priv)) { - if (IS_CHERRYVIEW(dev_priv)) - return cherryview_irq_handler; - else if (IS_VALLEYVIEW(dev_priv)) - return valleyview_irq_handler; - else if (GRAPHICS_VER(dev_priv) == 4) - return i965_irq_handler; - else - return i915_irq_handler; - } else { - if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) - return dg1_irq_handler; - else if (GRAPHICS_VER(dev_priv) >= 11) - return gen11_irq_handler; - else if (GRAPHICS_VER(dev_priv) >= 8) - return gen8_irq_handler; - else - return ilk_irq_handler; - } + if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) + return dg1_irq_handler; + else if (GRAPHICS_VER(dev_priv) >= 11) + return gen11_irq_handler; + else if (IS_CHERRYVIEW(dev_priv)) + return cherryview_irq_handler; + else if (GRAPHICS_VER(dev_priv) >= 8) + return gen8_irq_handler; + else if (IS_VALLEYVIEW(dev_priv)) + return valleyview_irq_handler; + else if (GRAPHICS_VER(dev_priv) >= 5) + return ilk_irq_handler; + else if (GRAPHICS_VER(dev_priv) == 4) + return i965_irq_handler; + else + return i915_irq_handler; } static void intel_irq_reset(struct drm_i915_private *dev_priv) { - if (HAS_GMCH(dev_priv)) { - if (IS_CHERRYVIEW(dev_priv)) - cherryview_irq_reset(dev_priv); - else if (IS_VALLEYVIEW(dev_priv)) - valleyview_irq_reset(dev_priv); - else if (GRAPHICS_VER(dev_priv) == 4) - i965_irq_reset(dev_priv); - else - i915_irq_reset(dev_priv); - } else { - if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) - dg1_irq_reset(dev_priv); - else if (GRAPHICS_VER(dev_priv) >= 11) - gen11_irq_reset(dev_priv); - else if (GRAPHICS_VER(dev_priv) >= 8) - gen8_irq_reset(dev_priv); - else - ilk_irq_reset(dev_priv); - } + if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) + dg1_irq_reset(dev_priv); + else if (GRAPHICS_VER(dev_priv) >= 11) + gen11_irq_reset(dev_priv); + else if (IS_CHERRYVIEW(dev_priv)) + cherryview_irq_reset(dev_priv); + else if (GRAPHICS_VER(dev_priv) >= 8) + gen8_irq_reset(dev_priv); + else if (IS_VALLEYVIEW(dev_priv)) + valleyview_irq_reset(dev_priv); + else if (GRAPHICS_VER(dev_priv) >= 5) + ilk_irq_reset(dev_priv); + else if (GRAPHICS_VER(dev_priv) == 4) + i965_irq_reset(dev_priv); + else + i915_irq_reset(dev_priv); } static void intel_irq_postinstall(struct drm_i915_private *dev_priv) { - if (HAS_GMCH(dev_priv)) { - if (IS_CHERRYVIEW(dev_priv)) - cherryview_irq_postinstall(dev_priv); - else if (IS_VALLEYVIEW(dev_priv)) - valleyview_irq_postinstall(dev_priv); - else if (GRAPHICS_VER(dev_priv) == 4) - i965_irq_postinstall(dev_priv); - else - i915_irq_postinstall(dev_priv); - } else { - if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) - dg1_irq_postinstall(dev_priv); - else if (GRAPHICS_VER(dev_priv) >= 11) - gen11_irq_postinstall(dev_priv); - else if (GRAPHICS_VER(dev_priv) >= 8) - gen8_irq_postinstall(dev_priv); - else - ilk_irq_postinstall(dev_priv); - } + if (GRAPHICS_VER_FULL(dev_priv) >= IP_VER(12, 10)) + dg1_irq_postinstall(dev_priv); + else if (GRAPHICS_VER(dev_priv) >= 11) + gen11_irq_postinstall(dev_priv); + else if (IS_CHERRYVIEW(dev_priv)) + cherryview_irq_postinstall(dev_priv); + else if (GRAPHICS_VER(dev_priv) >= 8) + gen8_irq_postinstall(dev_priv); + else if (IS_VALLEYVIEW(dev_priv)) + valleyview_irq_postinstall(dev_priv); + else if (GRAPHICS_VER(dev_priv) >= 5) + ilk_irq_postinstall(dev_priv); + else if (GRAPHICS_VER(dev_priv) == 4) + i965_irq_postinstall(dev_priv); + else + i915_irq_postinstall(dev_priv); } /** -- GitLab From 5dff17241483d934d8a72633fb2c2b7eaf2d91a3 Mon Sep 17 00:00:00 2001 From: Mikolaj Wasiak Date: Fri, 9 May 2025 09:57:18 +0200 Subject: [PATCH 0006/1479] drm/i915/selftest: allow larger memory allocation Due to changes in allocator, the size of the allocation for contiguous region is not rounded up to a power-of-two and instead allocated as is. Thus, change the part of test that expected the allocation to fail. Signed-off-by: Mikolaj Wasiak Reviewed-by: Krzysztof Karas Reviewed-by: Andi Shyti Reviewed-by: Krzysztof Niemiec Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/fptevdfbclvg2lbfuys5ibffbl2baouywkutnr7vdsy5tzcqfk@mpflwlh6jxfd --- .../gpu/drm/i915/selftests/intel_memory_region.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c index f08f6674911ee..7b856b5090f9a 100644 --- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c +++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c @@ -413,15 +413,8 @@ static int igt_mock_splintered_region(void *arg) close_objects(mem, &objects); - /* - * While we should be able allocate everything without any flag - * restrictions, if we consider I915_BO_ALLOC_CONTIGUOUS then we are - * actually limited to the largest power-of-two for the region size i.e - * max_order, due to the inner workings of the buddy allocator. So make - * sure that does indeed hold true. - */ - - obj = igt_object_create(mem, &objects, size, I915_BO_ALLOC_CONTIGUOUS); + obj = igt_object_create(mem, &objects, roundup_pow_of_two(size), + I915_BO_ALLOC_CONTIGUOUS); if (!IS_ERR(obj)) { pr_err("%s too large contiguous allocation was not rejected\n", __func__); @@ -429,8 +422,7 @@ static int igt_mock_splintered_region(void *arg) goto out_close; } - obj = igt_object_create(mem, &objects, rounddown_pow_of_two(size), - I915_BO_ALLOC_CONTIGUOUS); + obj = igt_object_create(mem, &objects, size, I915_BO_ALLOC_CONTIGUOUS); if (IS_ERR(obj)) { pr_err("%s largest possible contiguous allocation failed\n", __func__); -- GitLab From 44b6535d8acebbbdb8b8e79b22118bb3d7fa93df Mon Sep 17 00:00:00 2001 From: Vivek Kasireddy Date: Thu, 1 May 2025 16:24:19 -0700 Subject: [PATCH 0007/1479] drm/virtio: Fix NULL pointer deref in virtgpu_dma_buf_free_obj() There is a chance that obj->dma_buf would be NULL by the time virtgpu_dma_buf_free_obj() is called. This can happen for imported prime objects, when drm_gem_object_exported_dma_buf_free() gets called on them before drm_gem_object_free(). This is because drm_gem_object_exported_dma_buf_free() explicitly sets obj->dma_buf to NULL. Therefore, fix this issue by storing the dma_buf pointer in the virtio_gpu_object instance and using it in virtgpu_dma_buf_free_obj. This stored pointer is guaranteed to be valid until the object is freed as we took a reference on it in virtgpu_gem_prime_import(). Fixes: 415cb45895f4 ("drm/virtio: Use dma_buf from GEM object instance") Cc: Dmitry Osipenko Cc: Thomas Zimmermann Signed-off-by: Vivek Kasireddy Reviewed-by: Dmitry Osipenko Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20250501232419.180337-1-vivek.kasireddy@intel.com --- drivers/gpu/drm/virtio/virtgpu_drv.h | 1 + drivers/gpu/drm/virtio/virtgpu_prime.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index f17660a71a3e7..f7def8b42068f 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -88,6 +88,7 @@ struct virtio_gpu_object_params { struct virtio_gpu_object { struct drm_gem_shmem_object base; + struct dma_buf *dma_buf; struct sg_table *sgt; uint32_t hw_res_handle; bool dumb; diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c index 1118a0250279b..722cde5e2d864 100644 --- a/drivers/gpu/drm/virtio/virtgpu_prime.c +++ b/drivers/gpu/drm/virtio/virtgpu_prime.c @@ -206,7 +206,7 @@ static void virtgpu_dma_buf_free_obj(struct drm_gem_object *obj) struct virtio_gpu_device *vgdev = obj->dev->dev_private; if (drm_gem_is_imported(obj)) { - struct dma_buf *dmabuf = obj->dma_buf; + struct dma_buf *dmabuf = bo->dma_buf; dma_resv_lock(dmabuf->resv, NULL); virtgpu_dma_buf_unmap(bo); @@ -332,6 +332,7 @@ struct drm_gem_object *virtgpu_gem_prime_import(struct drm_device *dev, obj->import_attach = attach; get_dma_buf(buf); + bo->dma_buf = buf; ret = virtgpu_dma_buf_init_obj(dev, bo, attach); if (ret < 0) -- GitLab From 266e2fcfe2ea0d062ea392cd22f6250ae0d11c04 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:28 +0300 Subject: [PATCH 0008/1479] drm/i915/dp_mst: Use the correct connector while computing the link BPP limit on MST Atm, on an MST link in DSC mode intel_dp_compute_config_link_bpp_limits() calculates the maximum link bpp limit using the MST root connector's DSC capabilities. That's not correct in general: the decompression could be performed by a branch device downstream of the root branch device or the sink itself. Fix the above by passing to intel_dp_compute_config_link_bpp_limits() the actual connector being modeset, containing the correct DSC capabilities. Cc: Ankit Nautiyal Fixes: 1c5b72daff46 ("drm/i915/dp: Set the DSC link limits in intel_dp_compute_config_link_bpp_limits") Reviewed-by: Ankit Nautiyal Reviewed-by: Luca Coelho Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-2-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 7 ++++--- drivers/gpu/drm/i915/display/intel_dp.h | 1 + drivers/gpu/drm/i915/display/intel_dp_mst.c | 5 +++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 593b29b56714a..ad1e4fc9c7fe3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2524,6 +2524,7 @@ intel_dp_dsc_compute_pipe_bpp_limits(struct intel_dp *intel_dp, bool intel_dp_compute_config_limits(struct intel_dp *intel_dp, + struct intel_connector *connector, struct intel_crtc_state *crtc_state, bool respect_downstream_limits, bool dsc, @@ -2577,7 +2578,7 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp, intel_dp_test_compute_config(intel_dp, crtc_state, limits); return intel_dp_compute_config_link_bpp_limits(intel_dp, - intel_dp->attached_connector, + connector, crtc_state, dsc, limits); @@ -2638,7 +2639,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, joiner_needs_dsc = intel_dp_joiner_needs_dsc(display, num_joined_pipes); dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en || - !intel_dp_compute_config_limits(intel_dp, pipe_config, + !intel_dp_compute_config_limits(intel_dp, connector, pipe_config, respect_downstream_limits, false, &limits); @@ -2672,7 +2673,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, str_yes_no(ret), str_yes_no(joiner_needs_dsc), str_yes_no(intel_dp->force_dsc_en)); - if (!intel_dp_compute_config_limits(intel_dp, pipe_config, + if (!intel_dp_compute_config_limits(intel_dp, connector, pipe_config, respect_downstream_limits, true, &limits)) diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index a7cc10800e0b4..742ae26ac4a9a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -194,6 +194,7 @@ void intel_dp_wait_source_oui(struct intel_dp *intel_dp); int intel_dp_output_bpp(enum intel_output_format output_format, int bpp); bool intel_dp_compute_config_limits(struct intel_dp *intel_dp, + struct intel_connector *connector, struct intel_crtc_state *crtc_state, bool respect_downstream_limits, bool dsc, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 30f5636d18b7d..06f4ad8de591e 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -599,12 +599,13 @@ adjust_limits_for_dsc_hblank_expansion_quirk(struct intel_dp *intel_dp, static bool mst_stream_compute_config_limits(struct intel_dp *intel_dp, - const struct intel_connector *connector, + struct intel_connector *connector, struct intel_crtc_state *crtc_state, bool dsc, struct link_config_limits *limits) { - if (!intel_dp_compute_config_limits(intel_dp, crtc_state, false, dsc, + if (!intel_dp_compute_config_limits(intel_dp, connector, + crtc_state, false, dsc, limits)) return false; -- GitLab From 49a50054b784989ad56f8df911611f823d628044 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:29 +0300 Subject: [PATCH 0009/1479] drm/i915/dp_mst: Simplify handling the single-bpp case during state computation A follow-up change wants to skip invalid bpps in the bpp select loop of a stream state computation. To allow for that, using the usual 'continue' statement in the loop, change the way the single-bpp range is handled. v2: Fix typo in commit message. (Ankit) Cc: Jani Nikula Reviewed-by: Luca Coelho Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-3-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 06f4ad8de591e..fa969b46245cd 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -263,6 +263,12 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, fxp_q4_to_frac(max_bpp_x16) || fxp_q4_to_frac(bpp_step_x16))); + if (!bpp_step_x16) { + /* Allow using zero step only to indicate single try for a given bpp. */ + drm_WARN_ON(display->drm, min_bpp_x16 != max_bpp_x16); + bpp_step_x16 = 1; + } + if (is_mst) { mst_state = drm_atomic_get_mst_topology_state(state, &intel_dp->mst.mgr); if (IS_ERR(mst_state)) @@ -386,10 +392,6 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, break; } - - /* Allow using zero step to indicate one try */ - if (!bpp_step_x16) - break; } if (slots < 0) { -- GitLab From 97ae79d3ad91122991d1ad0032be02fa3e9d918f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:30 +0300 Subject: [PATCH 0010/1479] drm/i915/dp_mst: Validate compressed bpp vs. platform restrictions Atm TGL supports only a fixed set of valid DSC compressed bpps (6,8,10,12,15), but this is not taken into account while looking for a bpp in the minimum..maximum compressed bpp range. This happened to work only by chance since atm from the above min..max range it's always the maximum bpp that is selected, which is one of the above valid bpps (see mst_stream_dsc_compute_link_config() -> intel_dp_dsc_nearest_valid_bpp()). Before selecting a bpp however, the bpp's BW requirement should be checked wrt. to the MST total link BW; after doing that - in a follow-up change - the validity of any bpp in the min..max range must be ensured before the bpp is selected, do that here. Cc: Jani Nikula Reviewed-by: Ankit Nautiyal Reviewed-by: Luca Coelho Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-4-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 9 ++++++--- drivers/gpu/drm/i915/display/intel_dp.h | 1 + drivers/gpu/drm/i915/display/intel_dp_mst.c | 6 ++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index ad1e4fc9c7fe3..c67c3b5b2dafa 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2111,8 +2111,11 @@ static int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector) return fxp_q4_from_int(1) / incr; } -/* Note: This is not universally usable! */ -static bool intel_dp_dsc_valid_bpp(struct intel_dp *intel_dp, int bpp_x16) +/* + * Note: for bpp_x16 to be valid it must be also within the source/sink's + * min..max bpp capability range. + */ +bool intel_dp_dsc_valid_compressed_bpp(struct intel_dp *intel_dp, int bpp_x16) { struct intel_display *display = to_intel_display(intel_dp); int i; @@ -2176,7 +2179,7 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, max_bpp_x16 = min(max_bpp_x16, fxp_q4_from_int(output_bpp) - bpp_step_x16); for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) { - if (!intel_dp_dsc_valid_bpp(intel_dp, bpp_x16)) + if (!intel_dp_dsc_valid_compressed_bpp(intel_dp, bpp_x16)) continue; ret = dsc_compute_link_config(intel_dp, diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 742ae26ac4a9a..4d8c3f2b90dff 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -147,6 +147,7 @@ int intel_dp_dsc_sink_min_compressed_bpp(const struct intel_crtc_state *pipe_con int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector, const struct intel_crtc_state *pipe_config, int bpc); +bool intel_dp_dsc_valid_compressed_bpp(struct intel_dp *intel_dp, int bpp_x16); u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector, int mode_clock, int mode_hdisplay, int num_joined_pipes); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index fa969b46245cd..196182c3fd988 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -310,6 +310,12 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, drm_dbg_kms(display->drm, "Trying bpp " FXP_Q4_FMT "\n", FXP_Q4_ARGS(bpp_x16)); + if (dsc && !intel_dp_dsc_valid_compressed_bpp(intel_dp, bpp_x16)) { + /* SST must have validated the single bpp tried here already earlier. */ + drm_WARN_ON(display->drm, !is_mst); + continue; + } + link_bpp_x16 = dsc ? bpp_x16 : fxp_q4_from_int(intel_dp_output_bpp(crtc_state->output_format, fxp_q4_to_int(bpp_x16))); -- GitLab From dd697c720fea53d415c4d86f6e128b8bfceb35ce Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:31 +0300 Subject: [PATCH 0011/1479] drm/i915/dp_mst: Update the total link slot count early A follow up change will check a selected bpp's BW requirement in intel_dp_mtp_tu_compute_config(), however that requires the total link slot count to be up-to-date. The latter in turn depends on the channel encoding and hence the link rate used, so it can be set after the link rate used is selected. This also allows simplifying mst_stream_update_slots(), do that as well, moving the function definition before its use. Cc: Jani Nikula Reviewed-by: Ankit Nautiyal Reviewed-by: Luca Coelho Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-5-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 36 +++++++-------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 196182c3fd988..4345107aa3e81 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -241,6 +241,15 @@ static int intel_dp_mst_dsc_get_slice_count(const struct intel_connector *connec num_joined_pipes); } +static void mst_stream_update_slots(const struct intel_crtc_state *crtc_state, + struct drm_dp_mst_topology_state *topology_state) +{ + u8 link_coding_cap = intel_dp_is_uhbr(crtc_state) ? + DP_CAP_ANSI_128B132B : DP_CAP_ANSI_8B10B; + + drm_dp_mst_update_slots(topology_state, link_coding_cap); +} + int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state, @@ -276,6 +285,8 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, mst_state->pbn_div = drm_dp_get_vc_payload_bw(crtc_state->port_clock, crtc_state->lane_count); + + mst_stream_update_slots(crtc_state, mst_state); } if (dsc) { @@ -491,27 +502,6 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, fxp_q4_from_int(1), true); } -static int mst_stream_update_slots(struct intel_dp *intel_dp, - struct intel_crtc_state *crtc_state, - struct drm_connector_state *conn_state) -{ - struct intel_display *display = to_intel_display(intel_dp); - struct drm_dp_mst_topology_mgr *mgr = &intel_dp->mst.mgr; - struct drm_dp_mst_topology_state *topology_state; - u8 link_coding_cap = intel_dp_is_uhbr(crtc_state) ? - DP_CAP_ANSI_128B132B : DP_CAP_ANSI_8B10B; - - topology_state = drm_atomic_get_mst_topology_state(conn_state->state, mgr); - if (IS_ERR(topology_state)) { - drm_dbg_kms(display->drm, "slot update failed\n"); - return PTR_ERR(topology_state); - } - - drm_dp_mst_update_slots(topology_state, link_coding_cap); - - return 0; -} - static int mode_hblank_period_ns(const struct drm_display_mode *mode) { return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(mode->htotal - mode->hdisplay, @@ -714,10 +704,6 @@ static int mst_stream_compute_config(struct intel_encoder *encoder, pipe_config->dp_m_n.tu); } - if (ret) - return ret; - - ret = mst_stream_update_slots(intel_dp, pipe_config, conn_state); if (ret) return ret; -- GitLab From c2a38dc3006a2f8eff7044a3d1f0510fd7b749bd Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:32 +0300 Subject: [PATCH 0012/1479] drm/i915/dp_mst: Check BW limit on the local MST link early Check the BW requirement of a selected compressed bpp against the total MST link BW early. This didn't cause a problem, since all the BW limits within the MST topology are checked during the later MST topology BW check. However it doesn't make sense to defer the total link BW check, since for resolving a BW limit issue due to this later also (a) requires selecting a pipe to reduce its bpp, ending up reducing the bpp for another pipe, which is not ideal (b) requires recomputing the state for all CRTC/stream's in the topology which may slow down the commit considerably (especially when using fractional bpps). Based on the above, check a stream bpp's BW requirement against the MST link's total BW early. Ideally drm_dp_atomic_find_time_slots() should check internally the corresponding PBN/TU slot BW against the total link BW, returning an error if the check fails, however that change would also affect other drivers, so leaving this for a follow-up. v2: Rephrase description of pipe selection/bpp reduction in commit message. (Ankit) Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-6-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 4345107aa3e81..ff88888e4b293 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -390,6 +390,10 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst.mgr, connector->mst.port, dfixed_trunc(pbn)); + + /* TODO: Check this already in drm_dp_atomic_find_time_slots(). */ + if (slots > mst_state->total_avail_slots) + slots = -EINVAL; } else { /* Same as above for remote_tu */ crtc_state->dp_m_n.tu = ALIGN(crtc_state->dp_m_n.tu, -- GitLab From 1f581f38bc0d23c6ac6714c84a72e098f1f645fe Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:33 +0300 Subject: [PATCH 0013/1479] drm/i915/dp_mst: Simplify computing the min/max compressed bpp limits Adjusting the compressed bpp range min/max limits in intel_dp_dsc_nearest_valid_bpp() is unnecessary: - The source/sink min/max values are enforced already by the link_config_limits::min_bpp_x16/max_bpp_x16 values computed early in intel_dp_compute_config_link_bpp_limits(). - The fixed set of valid bpps are enforced already - for all bpps in the min .. max range by intel_dp_dsc_valid_compressed_bpp() called from intel_dp_mtp_tu_compute_config(). The only thing needed is limiting max compressed bpp below the uncompressed pipe bpp, do that one thing only instead of calling intel_dp_dsc_nearest_valid_bpp(). Reviewed-by: Luca Coelho Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-7-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_dp.h | 2 -- drivers/gpu/drm/i915/display/intel_dp_mst.c | 6 +----- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index c67c3b5b2dafa..f8de29d8a4da4 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -847,7 +847,7 @@ small_joiner_ram_size_bits(struct intel_display *display) return 6144 * 8; } -u32 intel_dp_dsc_nearest_valid_bpp(struct intel_display *display, u32 bpp, u32 pipe_bpp) +static u32 intel_dp_dsc_nearest_valid_bpp(struct intel_display *display, u32 bpp, u32 pipe_bpp) { u32 bits_per_pixel = bpp; int i; diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 4d8c3f2b90dff..2fe6720a88fc1 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -174,8 +174,6 @@ bool intel_dp_supports_dsc(struct intel_dp *intel_dp, const struct intel_connector *connector, const struct intel_crtc_state *crtc_state); -u32 intel_dp_dsc_nearest_valid_bpp(struct intel_display *display, u32 bpp, u32 pipe_bpp); - void intel_ddi_update_pipe(struct intel_atomic_state *state, struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index ff88888e4b293..42351229177d8 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -491,11 +491,7 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, drm_dbg_kms(display->drm, "DSC Sink supported compressed min bpp %d compressed max bpp %d\n", min_compressed_bpp, max_compressed_bpp); - /* Align compressed bpps according to our own constraints */ - max_compressed_bpp = intel_dp_dsc_nearest_valid_bpp(display, max_compressed_bpp, - crtc_state->pipe_bpp); - min_compressed_bpp = intel_dp_dsc_nearest_valid_bpp(display, min_compressed_bpp, - crtc_state->pipe_bpp); + max_compressed_bpp = min(max_compressed_bpp, crtc_state->pipe_bpp - 1); crtc_state->lane_count = limits->max_lane_count; crtc_state->port_clock = limits->max_rate; -- GitLab From 7acc7a6fc77413ab061819cee2ab7771c4132cf0 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:34 +0300 Subject: [PATCH 0014/1479] drm/i915/dp: Limit max link bpp properly to a fractional value on SST The maximum link bpp - determined by the link BW for instance - can be fractional, handle this properly during computing the link bpp on SST. This keeps the pipe joiner specific maximum link bpp as a rounded-down integer value still, changing that to a fractional value is left for later. v2: Align the min/max bpp value to the bpp step. Reviewed-by: Luca Coelho Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-8-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f8de29d8a4da4..b91c1e43051a1 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -27,6 +27,8 @@ #include #include +#include +#include #include #include #include @@ -939,6 +941,7 @@ static u32 ultrajoiner_ram_max_bpp(u32 mode_hdisplay) return ultrajoiner_ram_bits() / mode_hdisplay; } +/* TODO: return a bpp_x16 value */ static u32 get_max_compressed_bpp_with_joiner(struct intel_display *display, u32 mode_clock, u32 mode_hdisplay, @@ -2153,24 +2156,16 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, const struct intel_connector *connector = to_intel_connector(conn_state->connector); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; int output_bpp; - int dsc_min_bpp; - int dsc_max_bpp; int min_bpp_x16, max_bpp_x16, bpp_step_x16; int dsc_joiner_max_bpp; int num_joined_pipes = intel_crtc_num_joined_pipes(pipe_config); int bpp_x16; int ret; - dsc_min_bpp = fxp_q4_to_int_roundup(limits->link.min_bpp_x16); - dsc_joiner_max_bpp = get_max_compressed_bpp_with_joiner(display, adjusted_mode->clock, adjusted_mode->hdisplay, num_joined_pipes); - dsc_max_bpp = min(dsc_joiner_max_bpp, fxp_q4_to_int(limits->link.max_bpp_x16)); - - /* FIXME: remove the round trip via integers */ - min_bpp_x16 = fxp_q4_from_int(dsc_min_bpp); - max_bpp_x16 = fxp_q4_from_int(dsc_max_bpp); + max_bpp_x16 = min(fxp_q4_from_int(dsc_joiner_max_bpp), limits->link.max_bpp_x16); bpp_step_x16 = intel_dp_dsc_bpp_step_x16(connector); @@ -2178,6 +2173,10 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_bpp); max_bpp_x16 = min(max_bpp_x16, fxp_q4_from_int(output_bpp) - bpp_step_x16); + drm_WARN_ON(display->drm, !is_power_of_2(bpp_step_x16)); + min_bpp_x16 = round_up(limits->link.min_bpp_x16, bpp_step_x16); + max_bpp_x16 = round_down(max_bpp_x16, bpp_step_x16); + for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) { if (!intel_dp_dsc_valid_compressed_bpp(intel_dp, bpp_x16)) continue; -- GitLab From 00f00859820e021e0f228ff3244401da6efc9d51 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:35 +0300 Subject: [PATCH 0015/1479] drm/i915/dp_mst: Add support for fractional compressed link bpps on MST Add support for a fractional compressed link bpp on an MST link. Leave the actual enabling of fractional bpps to a follow-up change. While at it add an assert before the bpp loop, that the min and max bpps are aligned to the bpp step. This should hold regardless of the non-DSC/DSC or MST/UHBR-SST modes. This keeps the mode validation and DSC->DPT BW specific maximum link bpps as rounded-down integer values still, changing those to a fractional value is left for later, add here TODO comments for them. v2: - Align the min/max bpp value to the bpp step. - Assert that the min/max bpp values are aligned to the bpp step. Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-9-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 1 + drivers/gpu/drm/i915/display/intel_dp_mst.c | 32 +++++++++++++++------ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index b91c1e43051a1..cdbdf20a46b7d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -958,6 +958,7 @@ u32 get_max_compressed_bpp_with_joiner(struct intel_display *display, return max_bpp; } +/* TODO: return a bpp_x16 value */ u16 intel_dp_dsc_get_max_compressed_bpp(struct intel_display *display, u32 link_clock, u32 lane_count, u32 mode_clock, u32 mode_hdisplay, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 42351229177d8..13b2bd3ec8607 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -23,6 +23,9 @@ * */ +#include +#include + #include #include #include @@ -135,6 +138,7 @@ static bool intel_dp_mst_inc_active_streams(struct intel_dp *intel_dp) return intel_dp->mst.active_streams++ == 0; } +/* TODO: return a bpp_x16 value */ static int intel_dp_mst_max_dpt_bpp(const struct intel_crtc_state *crtc_state, bool dsc) { @@ -315,6 +319,8 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, } } + drm_WARN_ON(display->drm, min_bpp_x16 % bpp_step_x16 || max_bpp_x16 % bpp_step_x16); + for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) { int local_bw_overhead; int link_bpp_x16; @@ -460,7 +466,8 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, int num_bpc; u8 dsc_bpc[3] = {}; int min_bpp, max_bpp, sink_min_bpp, sink_max_bpp; - int min_compressed_bpp, max_compressed_bpp; + int min_compressed_bpp_x16, max_compressed_bpp_x16; + int bpp_step_x16; max_bpp = limits->pipe.max_bpp; min_bpp = limits->pipe.min_bpp; @@ -485,21 +492,28 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, crtc_state->pipe_bpp = max_bpp; - max_compressed_bpp = fxp_q4_to_int(limits->link.max_bpp_x16); - min_compressed_bpp = fxp_q4_to_int_roundup(limits->link.min_bpp_x16); + min_compressed_bpp_x16 = limits->link.min_bpp_x16; + max_compressed_bpp_x16 = limits->link.max_bpp_x16; + + drm_dbg_kms(display->drm, + "DSC Sink supported compressed min bpp " FXP_Q4_FMT " compressed max bpp " FXP_Q4_FMT "\n", + FXP_Q4_ARGS(min_compressed_bpp_x16), FXP_Q4_ARGS(max_compressed_bpp_x16)); + + bpp_step_x16 = fxp_q4_from_int(1); - drm_dbg_kms(display->drm, "DSC Sink supported compressed min bpp %d compressed max bpp %d\n", - min_compressed_bpp, max_compressed_bpp); + max_compressed_bpp_x16 = min(max_compressed_bpp_x16, fxp_q4_from_int(crtc_state->pipe_bpp) - bpp_step_x16); - max_compressed_bpp = min(max_compressed_bpp, crtc_state->pipe_bpp - 1); + drm_WARN_ON(display->drm, !is_power_of_2(bpp_step_x16)); + min_compressed_bpp_x16 = round_up(min_compressed_bpp_x16, bpp_step_x16); + max_compressed_bpp_x16 = round_down(max_compressed_bpp_x16, bpp_step_x16); crtc_state->lane_count = limits->max_lane_count; crtc_state->port_clock = limits->max_rate; return intel_dp_mtp_tu_compute_config(intel_dp, crtc_state, conn_state, - fxp_q4_from_int(min_compressed_bpp), - fxp_q4_from_int(max_compressed_bpp), - fxp_q4_from_int(1), true); + min_compressed_bpp_x16, + max_compressed_bpp_x16, + bpp_step_x16, true); } static int mode_hblank_period_ns(const struct drm_display_mode *mode) -- GitLab From a43a02d8f5f4360f7e2473c54cddc4a9bfcd0b62 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:36 +0300 Subject: [PATCH 0016/1479] drm/i915/display: Factor out intel_display_{min, max}_pipe_bpp() Factor out helpers that can be used in a follow-up change to query the minimum and maximum pipe bpp supported by the HW. Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-10-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 28 +++++++++++++------- drivers/gpu/drm/i915/display/intel_display.h | 3 +++ drivers/gpu/drm/i915/display/intel_dp.c | 2 +- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 287110e4e4351..704ca079980c2 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4318,6 +4318,22 @@ compute_sink_pipe_bpp(const struct drm_connector_state *conn_state, return 0; } +int intel_display_min_pipe_bpp(void) +{ + return 6 * 3; +} + +int intel_display_max_pipe_bpp(struct intel_display *display) +{ + if (display->platform.g4x || display->platform.valleyview || + display->platform.cherryview) + return 10*3; + else if (DISPLAY_VER(display) >= 5) + return 12*3; + else + return 8*3; +} + static int compute_baseline_pipe_bpp(struct intel_atomic_state *state, struct intel_crtc *crtc) @@ -4327,17 +4343,9 @@ compute_baseline_pipe_bpp(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); struct drm_connector *connector; struct drm_connector_state *connector_state; - int bpp, i; - - if (display->platform.g4x || display->platform.valleyview || - display->platform.cherryview) - bpp = 10*3; - else if (DISPLAY_VER(display) >= 5) - bpp = 12*3; - else - bpp = 8*3; + int i; - crtc_state->pipe_bpp = bpp; + crtc_state->pipe_bpp = intel_display_max_pipe_bpp(display); /* Clamp display bpp to connector max bpp */ for_each_new_connector_in_state(&state->base, connector, connector_state, i) { diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 3b54a62c290af..b6610e9175a7a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -524,6 +524,9 @@ void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state); bool intel_crtc_vrr_disabling(struct intel_atomic_state *state, struct intel_crtc *crtc); +int intel_display_min_pipe_bpp(void); +int intel_display_max_pipe_bpp(struct intel_display *display); + /* modesetting */ int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state, const char *reason, u8 pipe_mask); diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index cdbdf20a46b7d..eb3898a49d1ca 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1199,7 +1199,7 @@ intel_dp_output_format(struct intel_connector *connector, int intel_dp_min_bpp(enum intel_output_format output_format) { if (output_format == INTEL_OUTPUT_FORMAT_RGB) - return 6 * 3; + return intel_display_min_pipe_bpp(); else return 8 * 3; } -- GitLab From 67e12c64b49f5a2b5a2db50d84f69b16f6d6d42e Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:37 +0300 Subject: [PATCH 0017/1479] drm/i915/dp: Export intel_dp_dsc_min_src_compressed_bpp() Export the function that can be used by a follow-up change to query the minimum compressed link bpp supported by the HW. Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-11-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 4 ++-- drivers/gpu/drm/i915/display/intel_dp.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index eb3898a49d1ca..3021395dead2d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2071,7 +2071,7 @@ int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector pipe_config, bpc) >> 4; } -static int dsc_src_min_compressed_bpp(void) +int intel_dp_dsc_min_src_compressed_bpp(void) { /* Min Compressed bpp supported by source is 8 */ return 8; @@ -2482,7 +2482,7 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp, int dsc_src_min_bpp, dsc_sink_min_bpp, dsc_min_bpp; int dsc_src_max_bpp, dsc_sink_max_bpp, dsc_max_bpp; - dsc_src_min_bpp = dsc_src_min_compressed_bpp(); + dsc_src_min_bpp = intel_dp_dsc_min_src_compressed_bpp(); dsc_sink_min_bpp = intel_dp_dsc_sink_min_compressed_bpp(crtc_state); dsc_min_bpp = max(dsc_src_min_bpp, dsc_sink_min_bpp); limits->link.min_bpp_x16 = fxp_q4_from_int(dsc_min_bpp); diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 2fe6720a88fc1..0b8a9b939070f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -208,6 +208,7 @@ bool intel_dp_has_connector(struct intel_dp *intel_dp, const struct drm_connector_state *conn_state); int intel_dp_dsc_max_src_input_bpc(struct intel_display *display); int intel_dp_dsc_min_src_input_bpc(void); +int intel_dp_dsc_min_src_compressed_bpp(void); int intel_dp_compute_min_hblank(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); -- GitLab From f7f46a80fa68c19260aa6c88881cee4a18682562 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:38 +0300 Subject: [PATCH 0018/1479] drm/i915: Add support for forcing the link bpp on a connector Add support for forcing the link bpp on a connector via a connector debugfs entry. During reducing link bpps due to a link BW limit, keep bpps close to their forced value. Add the debugfs entry to all relevant connectors: all DP connectors and on an FDI link CRT/SDVO/LVDS/HDMI connectors. v2: - Move adding the debugfs entries to this patch. - Rename i915_force_link_bpp to intel_force_link_bpp. (Jani) - Select the relevant connectors via platform checks. (Jani) - Use for_each_new_intel_connector_in_state(). (Jani) - Fix 64 bit division vs. 32 bit build when converting str to q4. (lkp) - Avoid division and addition overflow when converting str to q4. v3: - Add TODO: to make the non-DSC min bpp value connector specific. (Ankit) Cc: Jani Nikula Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-12-imre.deak@intel.com --- .../drm/i915/display/intel_display_debugfs.c | 2 + .../drm/i915/display/intel_display_device.h | 1 + .../drm/i915/display/intel_display_types.h | 4 + drivers/gpu/drm/i915/display/intel_link_bw.c | 239 +++++++++++++++++- drivers/gpu/drm/i915/display/intel_link_bw.h | 2 + 5 files changed, 241 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 8d0a1779dd193..a9b1ec4cf0f75 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -39,6 +39,7 @@ #include "intel_hdcp.h" #include "intel_hdmi.h" #include "intel_hotplug.h" +#include "intel_link_bw.h" #include "intel_panel.h" #include "intel_pps.h" #include "intel_psr.h" @@ -1325,6 +1326,7 @@ void intel_connector_debugfs_add(struct intel_connector *connector) intel_psr_connector_debugfs_add(connector); intel_alpm_lobf_debugfs_add(connector); intel_dp_link_training_debugfs_add(connector); + intel_link_bw_connector_debugfs_add(connector); if (DISPLAY_VER(display) >= 11 && ((connector_type == DRM_MODE_CONNECTOR_DisplayPort && !connector->mst.dp) || diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h index 87c666792c0da..fe14a92ae8c65 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.h +++ b/drivers/gpu/drm/i915/display/intel_display_device.h @@ -172,6 +172,7 @@ struct intel_display_platforms { #define HAS_GMBUS_BURST_READ(__display) (DISPLAY_VER(__display) >= 10 || (__display)->platform.kabylake) #define HAS_GMBUS_IRQ(__display) (DISPLAY_VER(__display) >= 4) #define HAS_GMCH(__display) (DISPLAY_INFO(__display)->has_gmch) +#define HAS_FDI(__display) (IS_DISPLAY_VER((__display), 5, 8) && !HAS_GMCH(__display)) #define HAS_HOTPLUG(__display) (DISPLAY_INFO(__display)->has_hotplug) #define HAS_HW_SAGV_WM(__display) (DISPLAY_VER(__display) >= 13 && !(__display)->platform.dgfx) #define HAS_IPC(__display) (DISPLAY_INFO(__display)->has_ipc) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index d6d0440dcee9b..056219272c36e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -550,6 +550,10 @@ struct intel_connector { struct intel_dp *dp; } mst; + struct { + int force_bpp_x16; + } link; + /* Work struct to schedule a uevent on link train failure */ struct work_struct modeset_retry_work; diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c index a10cd39926075..3caef7f9c7c47 100644 --- a/drivers/gpu/drm/i915/display/intel_link_bw.c +++ b/drivers/gpu/drm/i915/display/intel_link_bw.c @@ -3,6 +3,11 @@ * Copyright © 2023 Intel Corporation */ +#include +#include +#include +#include + #include #include @@ -10,11 +15,33 @@ #include "intel_crtc.h" #include "intel_display_core.h" #include "intel_display_types.h" +#include "intel_dp.h" #include "intel_dp_mst.h" #include "intel_dp_tunnel.h" #include "intel_fdi.h" #include "intel_link_bw.h" +static int get_forced_link_bpp_x16(struct intel_atomic_state *state, + const struct intel_crtc *crtc) +{ + struct intel_digital_connector_state *conn_state; + struct intel_connector *connector; + int force_bpp_x16 = INT_MAX; + int i; + + for_each_new_intel_connector_in_state(state, connector, conn_state, i) { + if (conn_state->base.crtc != &crtc->base) + continue; + + if (!connector->link.force_bpp_x16) + continue; + + force_bpp_x16 = min(force_bpp_x16, connector->link.force_bpp_x16); + } + + return force_bpp_x16 < INT_MAX ? force_bpp_x16 : 0; +} + /** * intel_link_bw_init_limits - initialize BW limits * @state: Atomic state @@ -31,9 +58,10 @@ void intel_link_bw_init_limits(struct intel_atomic_state *state, limits->force_fec_pipes = 0; limits->bpp_limit_reached_pipes = 0; for_each_pipe(display, pipe) { + struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe); const struct intel_crtc_state *crtc_state = - intel_atomic_get_new_crtc_state(state, - intel_crtc_for_pipe(display, pipe)); + intel_atomic_get_new_crtc_state(state, crtc); + int forced_bpp_x16 = get_forced_link_bpp_x16(state, crtc); if (state->base.duplicated && crtc_state) { limits->max_bpp_x16[pipe] = crtc_state->max_link_bpp_x16; @@ -42,15 +70,19 @@ void intel_link_bw_init_limits(struct intel_atomic_state *state, } else { limits->max_bpp_x16[pipe] = INT_MAX; } + + if (forced_bpp_x16) + limits->max_bpp_x16[pipe] = min(limits->max_bpp_x16[pipe], forced_bpp_x16); } } /** - * intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe + * __intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe * @state: atomic state * @limits: link BW limits * @pipe_mask: mask of pipes to select from * @reason: explanation of why bpp reduction is needed + * @reduce_forced_bpp: allow reducing bpps below their forced link bpp * * Select the pipe from @pipe_mask with the biggest link bpp value and set the * maximum of link bpp in @limits below this value. Modeset the selected pipe, @@ -64,10 +96,11 @@ void intel_link_bw_init_limits(struct intel_atomic_state *state, * - %-ENOSPC if no pipe can further reduce its link bpp * - Other negative error, if modesetting the selected pipe failed */ -int intel_link_bw_reduce_bpp(struct intel_atomic_state *state, - struct intel_link_bw_limits *limits, - u8 pipe_mask, - const char *reason) +static int __intel_link_bw_reduce_bpp(struct intel_atomic_state *state, + struct intel_link_bw_limits *limits, + u8 pipe_mask, + const char *reason, + bool reduce_forced_bpp) { struct intel_display *display = to_intel_display(state); enum pipe max_bpp_pipe = INVALID_PIPE; @@ -97,6 +130,10 @@ int intel_link_bw_reduce_bpp(struct intel_atomic_state *state, */ link_bpp_x16 = fxp_q4_from_int(crtc_state->pipe_bpp); + if (!reduce_forced_bpp && + link_bpp_x16 <= get_forced_link_bpp_x16(state, crtc)) + continue; + if (link_bpp_x16 > max_bpp_x16) { max_bpp_x16 = link_bpp_x16; max_bpp_pipe = crtc->pipe; @@ -112,6 +149,21 @@ int intel_link_bw_reduce_bpp(struct intel_atomic_state *state, BIT(max_bpp_pipe)); } +int intel_link_bw_reduce_bpp(struct intel_atomic_state *state, + struct intel_link_bw_limits *limits, + u8 pipe_mask, + const char *reason) +{ + int ret; + + /* Try to keep any forced link BPP. */ + ret = __intel_link_bw_reduce_bpp(state, limits, pipe_mask, reason, false); + if (ret == -ENOSPC) + ret = __intel_link_bw_reduce_bpp(state, limits, pipe_mask, reason, true); + + return ret; +} + /** * intel_link_bw_set_bpp_limit_for_pipe - set link bpp limit for a pipe to its minimum * @state: atomic state @@ -245,3 +297,176 @@ int intel_link_bw_atomic_check(struct intel_atomic_state *state, return -EAGAIN; } + +static int force_link_bpp_show(struct seq_file *m, void *data) +{ + struct intel_connector *connector = m->private; + + seq_printf(m, FXP_Q4_FMT "\n", FXP_Q4_ARGS(connector->link.force_bpp_x16)); + + return 0; +} + +static int str_to_fxp_q4_nonneg_int(const char *str, int *val_x16) +{ + unsigned int val; + int err; + + err = kstrtouint(str, 10, &val); + if (err) + return err; + + if (val > INT_MAX >> 4) + return -ERANGE; + + *val_x16 = fxp_q4_from_int(val); + + return 0; +} + +/* modifies str */ +static int str_to_fxp_q4_nonneg(char *str, int *val_x16) +{ + const char *int_str; + char *frac_str; + int frac_digits; + int frac_val; + int err; + + int_str = strim(str); + frac_str = strchr(int_str, '.'); + + if (frac_str) + *frac_str++ = '\0'; + + err = str_to_fxp_q4_nonneg_int(int_str, val_x16); + if (err) + return err; + + if (!frac_str) + return 0; + + /* prevent negative number/leading +- sign mark */ + if (!isdigit(*frac_str)) + return -EINVAL; + + err = str_to_fxp_q4_nonneg_int(frac_str, &frac_val); + if (err) + return err; + + frac_digits = strlen(frac_str); + if (frac_digits > intlog10(INT_MAX) >> 24 || + frac_val > INT_MAX - int_pow(10, frac_digits) / 2) + return -ERANGE; + + frac_val = DIV_ROUND_CLOSEST(frac_val, (int)int_pow(10, frac_digits)); + + if (*val_x16 > INT_MAX - frac_val) + return -ERANGE; + + *val_x16 += frac_val; + + return 0; +} + +static int user_str_to_fxp_q4_nonneg(const char __user *ubuf, size_t len, int *val_x16) +{ + char *kbuf; + int err; + + kbuf = memdup_user_nul(ubuf, len); + if (IS_ERR(kbuf)) + return PTR_ERR(kbuf); + + err = str_to_fxp_q4_nonneg(kbuf, val_x16); + + kfree(kbuf); + + return err; +} + +static bool connector_supports_dsc(struct intel_connector *connector) +{ + struct intel_display *display = to_intel_display(connector); + + switch (connector->base.connector_type) { + case DRM_MODE_CONNECTOR_eDP: + return intel_dp_has_dsc(connector); + case DRM_MODE_CONNECTOR_DisplayPort: + if (connector->mst.dp) + return HAS_DSC_MST(display); + + return HAS_DSC(display); + default: + return false; + } +} + +static ssize_t +force_link_bpp_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) +{ + struct seq_file *m = file->private_data; + struct intel_connector *connector = m->private; + struct intel_display *display = to_intel_display(connector); + int min_bpp; + int bpp_x16; + int err; + + err = user_str_to_fxp_q4_nonneg(ubuf, len, &bpp_x16); + if (err) + return err; + + /* TODO: Make the non-DSC min_bpp value connector specific. */ + if (connector_supports_dsc(connector)) + min_bpp = intel_dp_dsc_min_src_compressed_bpp(); + else + min_bpp = intel_display_min_pipe_bpp(); + + if (bpp_x16 && + (bpp_x16 < fxp_q4_from_int(min_bpp) || + bpp_x16 > fxp_q4_from_int(intel_display_max_pipe_bpp(display)))) + return -EINVAL; + + err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex); + if (err) + return err; + + connector->link.force_bpp_x16 = bpp_x16; + + drm_modeset_unlock(&display->drm->mode_config.connection_mutex); + + *offp += len; + + return len; +} +DEFINE_SHOW_STORE_ATTRIBUTE(force_link_bpp); + +void intel_link_bw_connector_debugfs_add(struct intel_connector *connector) +{ + struct intel_display *display = to_intel_display(connector); + struct dentry *root = connector->base.debugfs_entry; + + switch (connector->base.connector_type) { + case DRM_MODE_CONNECTOR_DisplayPort: + case DRM_MODE_CONNECTOR_eDP: + break; + case DRM_MODE_CONNECTOR_VGA: + case DRM_MODE_CONNECTOR_SVIDEO: + case DRM_MODE_CONNECTOR_LVDS: + case DRM_MODE_CONNECTOR_DVID: + if (HAS_FDI(display)) + break; + + return; + case DRM_MODE_CONNECTOR_HDMIA: + if (HAS_FDI(display) && !HAS_DDI(display)) + break; + + return; + default: + return; + } + + debugfs_create_file("intel_force_link_bpp", 0644, root, + connector, &force_link_bpp_fops); +} diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.h b/drivers/gpu/drm/i915/display/intel_link_bw.h index e69049cf178f6..b499042e62b13 100644 --- a/drivers/gpu/drm/i915/display/intel_link_bw.h +++ b/drivers/gpu/drm/i915/display/intel_link_bw.h @@ -11,6 +11,7 @@ #include "intel_display_limits.h" struct intel_atomic_state; +struct intel_connector; struct intel_crtc_state; struct intel_link_bw_limits { @@ -32,5 +33,6 @@ bool intel_link_bw_set_bpp_limit_for_pipe(struct intel_atomic_state *state, enum pipe pipe); int intel_link_bw_atomic_check(struct intel_atomic_state *state, struct intel_link_bw_limits *new_limits); +void intel_link_bw_connector_debugfs_add(struct intel_connector *connector); #endif -- GitLab From f77d8675c1adfb7bad559c1183161db5e39e4a4d Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 9 May 2025 21:03:39 +0300 Subject: [PATCH 0019/1479] drm/i915/dp_mst: Enable fractional link bpps on MST if the bpp is forced Enable using a fractional (compressed) link bpp on MST links, if this is supported and the link bpp is forced. Fractional link bpps will be enabled by default as a follow-up change after testing this functionality within a set of commonly used MST monitors and docks/hubs which support it. Reviewed-by: Ankit Nautiyal Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250509180340.554867-13-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 6 +++++- drivers/gpu/drm/i915/display/intel_dp.h | 2 ++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 3021395dead2d..91a34d474463a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2103,7 +2103,7 @@ static int dsc_src_max_compressed_bpp(struct intel_dp *intel_dp) /* * Note: for pre-13 display you still need to check the validity of each step. */ -static int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector) +int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector) { struct intel_display *display = to_intel_display(connector); u8 incr = drm_dp_dsc_sink_bpp_incr(connector->dp.dsc_dpcd); @@ -2111,6 +2111,10 @@ static int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector) if (DISPLAY_VER(display) < 14 || !incr) return fxp_q4_from_int(1); + if (connector->mst.dp && + !connector->link.force_bpp_x16 && !connector->mst.dp->force_dsc_fractional_bpp_en) + return fxp_q4_from_int(1); + /* fxp q4 */ return fxp_q4_from_int(1) / incr; } diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 0b8a9b939070f..eff3414c05dbf 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -212,4 +212,6 @@ int intel_dp_dsc_min_src_compressed_bpp(void); int intel_dp_compute_min_hblank(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); +int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector); + #endif /* __INTEL_DP_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 13b2bd3ec8607..57602606acd5a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -499,7 +499,7 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp, "DSC Sink supported compressed min bpp " FXP_Q4_FMT " compressed max bpp " FXP_Q4_FMT "\n", FXP_Q4_ARGS(min_compressed_bpp_x16), FXP_Q4_ARGS(max_compressed_bpp_x16)); - bpp_step_x16 = fxp_q4_from_int(1); + bpp_step_x16 = intel_dp_dsc_bpp_step_x16(connector); max_compressed_bpp_x16 = min(max_compressed_bpp_x16, fxp_q4_from_int(crtc_state->pipe_bpp) - bpp_step_x16); -- GitLab From dd39212b5f43577bcd0c4493c0ae4c7828bb55e1 Mon Sep 17 00:00:00 2001 From: Tomasz Lis Date: Mon, 12 May 2025 13:40:15 +0200 Subject: [PATCH 0020/1479] drm/xe/vf: Divide GGTT ballooning into allocation and insertion The balloon nodes, which are used to fill areas of GGTT inaccessible for a specific VF, were allocated and inserted into GGTT within one function. To be able to re-use that insertion code during VF migration recovery, we need to split it. This patch separates allocation (init/fini functs) from the insertion of balloons (balloon/deballoon functs). Locks are also moved to ensure calls from post-migration recovery worker will not cause a deadlock. v2: Moved declarations to proper header v3: Rephrased description, introduced "_locked" versions of some functs, more lockdep checks, some functions renamed, altered error handling, added missing kerneldocs. v4: Suffixed more functs with `_locked`, moved lockdep asserts, fixed finalization in error path, added asserts v5: Renamed another few functs, used xe_ggtt_node_allocated(), moved lockdep back again to avoid null dereference, added asserts, improved comments v6: Changed params of cleanup_ggtt() Signed-off-by: Tomasz Lis Cc: Michal Wajdeczko Reviewed-by: Michal Wajdeczko Signed-off-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250512114018.361843-2-tomasz.lis@intel.com --- drivers/gpu/drm/xe/xe_ggtt.c | 35 ++++----- drivers/gpu/drm/xe/xe_ggtt.h | 6 +- drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 114 +++++++++++++++++++++------- drivers/gpu/drm/xe/xe_gt_sriov_vf.h | 2 + 4 files changed, 107 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index 7062115909f2d..5a37233f24205 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -429,16 +429,17 @@ static void xe_ggtt_dump_node(struct xe_ggtt *ggtt, } /** - * xe_ggtt_node_insert_balloon - prevent allocation of specified GGTT addresses + * xe_ggtt_node_insert_balloon_locked - prevent allocation of specified GGTT addresses * @node: the &xe_ggtt_node to hold reserved GGTT node * @start: the starting GGTT address of the reserved region * @end: then end GGTT address of the reserved region * - * Use xe_ggtt_node_remove_balloon() to release a reserved GGTT node. + * To be used in cases where ggtt->lock is already taken. + * Use xe_ggtt_node_remove_balloon_locked() to release a reserved GGTT node. * * Return: 0 on success or a negative error code on failure. */ -int xe_ggtt_node_insert_balloon(struct xe_ggtt_node *node, u64 start, u64 end) +int xe_ggtt_node_insert_balloon_locked(struct xe_ggtt_node *node, u64 start, u64 end) { struct xe_ggtt *ggtt = node->ggtt; int err; @@ -447,14 +448,13 @@ int xe_ggtt_node_insert_balloon(struct xe_ggtt_node *node, u64 start, u64 end) xe_tile_assert(ggtt->tile, IS_ALIGNED(start, XE_PAGE_SIZE)); xe_tile_assert(ggtt->tile, IS_ALIGNED(end, XE_PAGE_SIZE)); xe_tile_assert(ggtt->tile, !drm_mm_node_allocated(&node->base)); + lockdep_assert_held(&ggtt->lock); node->base.color = 0; node->base.start = start; node->base.size = end - start; - mutex_lock(&ggtt->lock); err = drm_mm_reserve_node(&ggtt->mm, &node->base); - mutex_unlock(&ggtt->lock); if (xe_gt_WARN(ggtt->tile->primary_gt, err, "Failed to balloon GGTT %#llx-%#llx (%pe)\n", @@ -466,27 +466,22 @@ int xe_ggtt_node_insert_balloon(struct xe_ggtt_node *node, u64 start, u64 end) } /** - * xe_ggtt_node_remove_balloon - release a reserved GGTT region + * xe_ggtt_node_remove_balloon_locked - release a reserved GGTT region * @node: the &xe_ggtt_node with reserved GGTT region * - * See xe_ggtt_node_insert_balloon() for details. + * To be used in cases where ggtt->lock is already taken. + * See xe_ggtt_node_insert_balloon_locked() for details. */ -void xe_ggtt_node_remove_balloon(struct xe_ggtt_node *node) +void xe_ggtt_node_remove_balloon_locked(struct xe_ggtt_node *node) { - if (!node || !node->ggtt) + if (!xe_ggtt_node_allocated(node)) return; - if (!drm_mm_node_allocated(&node->base)) - goto free_node; + lockdep_assert_held(&node->ggtt->lock); xe_ggtt_dump_node(node->ggtt, &node->base, "remove-balloon"); - mutex_lock(&node->ggtt->lock); drm_mm_remove_node(&node->base); - mutex_unlock(&node->ggtt->lock); - -free_node: - xe_ggtt_node_fini(node); } /** @@ -537,12 +532,12 @@ int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align) * xe_ggtt_node_init - Initialize %xe_ggtt_node struct * @ggtt: the &xe_ggtt where the new node will later be inserted/reserved. * - * This function will allocated the struct %xe_ggtt_node and return it's pointer. + * This function will allocate the struct %xe_ggtt_node and return its pointer. * This struct will then be freed after the node removal upon xe_ggtt_node_remove() - * or xe_ggtt_node_remove_balloon(). + * or xe_ggtt_node_remove_balloon_locked(). * Having %xe_ggtt_node struct allocated doesn't mean that the node is already allocated * in GGTT. Only the xe_ggtt_node_insert(), xe_ggtt_node_insert_locked(), - * xe_ggtt_node_insert_balloon() will ensure the node is inserted or reserved in GGTT. + * xe_ggtt_node_insert_balloon_locked() will ensure the node is inserted or reserved in GGTT. * * Return: A pointer to %xe_ggtt_node struct on success. An ERR_PTR otherwise. **/ @@ -564,7 +559,7 @@ struct xe_ggtt_node *xe_ggtt_node_init(struct xe_ggtt *ggtt) * @node: the &xe_ggtt_node to be freed * * If anything went wrong with either xe_ggtt_node_insert(), xe_ggtt_node_insert_locked(), - * or xe_ggtt_node_insert_balloon(); and this @node is not going to be reused, then, + * or xe_ggtt_node_insert_balloon_locked(); and this @node is not going to be reused, then, * this function needs to be called to free the %xe_ggtt_node struct **/ void xe_ggtt_node_fini(struct xe_ggtt_node *node) diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h index 27e7d67de0047..d468af96b465e 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.h +++ b/drivers/gpu/drm/xe/xe_ggtt.h @@ -15,9 +15,9 @@ int xe_ggtt_init(struct xe_ggtt *ggtt); struct xe_ggtt_node *xe_ggtt_node_init(struct xe_ggtt *ggtt); void xe_ggtt_node_fini(struct xe_ggtt_node *node); -int xe_ggtt_node_insert_balloon(struct xe_ggtt_node *node, - u64 start, u64 size); -void xe_ggtt_node_remove_balloon(struct xe_ggtt_node *node); +int xe_ggtt_node_insert_balloon_locked(struct xe_ggtt_node *node, + u64 start, u64 size); +void xe_ggtt_node_remove_balloon_locked(struct xe_ggtt_node *node); int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align); int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node, diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c index a439261bf4d72..f82ddff79b3b9 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c @@ -560,35 +560,43 @@ u64 xe_gt_sriov_vf_lmem(struct xe_gt *gt) return gt->sriov.vf.self_config.lmem_size; } -static struct xe_ggtt_node * -vf_balloon_ggtt_node(struct xe_ggtt *ggtt, u64 start, u64 end) +static int vf_init_ggtt_balloons(struct xe_gt *gt) { - struct xe_ggtt_node *node; - int err; + struct xe_tile *tile = gt_to_tile(gt); + struct xe_ggtt *ggtt = tile->mem.ggtt; - node = xe_ggtt_node_init(ggtt); - if (IS_ERR(node)) - return node; + xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); + xe_gt_assert(gt, !xe_gt_is_media_type(gt)); - err = xe_ggtt_node_insert_balloon(node, start, end); - if (err) { - xe_ggtt_node_fini(node); - return ERR_PTR(err); + tile->sriov.vf.ggtt_balloon[0] = xe_ggtt_node_init(ggtt); + if (IS_ERR(tile->sriov.vf.ggtt_balloon[0])) + return PTR_ERR(tile->sriov.vf.ggtt_balloon[0]); + + tile->sriov.vf.ggtt_balloon[1] = xe_ggtt_node_init(ggtt); + if (IS_ERR(tile->sriov.vf.ggtt_balloon[1])) { + xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]); + return PTR_ERR(tile->sriov.vf.ggtt_balloon[1]); } - return node; + return 0; } -static int vf_balloon_ggtt(struct xe_gt *gt) +/** + * xe_gt_sriov_vf_balloon_ggtt_locked - Insert balloon nodes to limit used GGTT address range. + * @gt: the &xe_gt struct instance + * Return: 0 on success or a negative error code on failure. + */ +int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt) { struct xe_gt_sriov_vf_selfconfig *config = >->sriov.vf.self_config; struct xe_tile *tile = gt_to_tile(gt); - struct xe_ggtt *ggtt = tile->mem.ggtt; struct xe_device *xe = gt_to_xe(gt); u64 start, end; + int err; xe_gt_assert(gt, IS_SRIOV_VF(xe)); xe_gt_assert(gt, !xe_gt_is_media_type(gt)); + lockdep_assert_held(&tile->mem.ggtt->lock); if (!config->ggtt_size) return -ENODATA; @@ -611,31 +619,77 @@ static int vf_balloon_ggtt(struct xe_gt *gt) start = xe_wopcm_size(xe); end = config->ggtt_base; if (end != start) { - tile->sriov.vf.ggtt_balloon[0] = vf_balloon_ggtt_node(ggtt, start, end); - if (IS_ERR(tile->sriov.vf.ggtt_balloon[0])) - return PTR_ERR(tile->sriov.vf.ggtt_balloon[0]); + err = xe_ggtt_node_insert_balloon_locked(tile->sriov.vf.ggtt_balloon[0], + start, end); + if (err) + return err; } start = config->ggtt_base + config->ggtt_size; end = GUC_GGTT_TOP; if (end != start) { - tile->sriov.vf.ggtt_balloon[1] = vf_balloon_ggtt_node(ggtt, start, end); - if (IS_ERR(tile->sriov.vf.ggtt_balloon[1])) { - xe_ggtt_node_remove_balloon(tile->sriov.vf.ggtt_balloon[0]); - return PTR_ERR(tile->sriov.vf.ggtt_balloon[1]); + err = xe_ggtt_node_insert_balloon_locked(tile->sriov.vf.ggtt_balloon[1], + start, end); + if (err) { + xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[0]); + return err; } } return 0; } -static void deballoon_ggtt(struct drm_device *drm, void *arg) +static int vf_balloon_ggtt(struct xe_gt *gt) +{ + struct xe_ggtt *ggtt = gt_to_tile(gt)->mem.ggtt; + int err; + + mutex_lock(&ggtt->lock); + err = xe_gt_sriov_vf_balloon_ggtt_locked(gt); + mutex_unlock(&ggtt->lock); + + return err; +} + +/** + * xe_gt_sriov_vf_deballoon_ggtt_locked - Remove balloon nodes. + * @gt: the &xe_gt struct instance + */ +void xe_gt_sriov_vf_deballoon_ggtt_locked(struct xe_gt *gt) { - struct xe_tile *tile = arg; + struct xe_tile *tile = gt_to_tile(gt); xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile))); - xe_ggtt_node_remove_balloon(tile->sriov.vf.ggtt_balloon[1]); - xe_ggtt_node_remove_balloon(tile->sriov.vf.ggtt_balloon[0]); + xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[1]); + xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[0]); +} + +static void vf_deballoon_ggtt(struct xe_gt *gt) +{ + struct xe_tile *tile = gt_to_tile(gt); + + mutex_lock(&tile->mem.ggtt->lock); + xe_gt_sriov_vf_deballoon_ggtt_locked(gt); + mutex_unlock(&tile->mem.ggtt->lock); +} + +static void vf_fini_ggtt_balloons(struct xe_gt *gt) +{ + struct xe_tile *tile = gt_to_tile(gt); + + xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); + xe_gt_assert(gt, !xe_gt_is_media_type(gt)); + + xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[1]); + xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]); +} + +static void cleanup_ggtt(struct drm_device *drm, void *arg) +{ + struct xe_gt *gt = arg; + + vf_deballoon_ggtt(gt); + vf_fini_ggtt_balloons(gt); } /** @@ -655,11 +709,17 @@ int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt) if (xe_gt_is_media_type(gt)) return 0; - err = vf_balloon_ggtt(gt); + err = vf_init_ggtt_balloons(gt); if (err) return err; - return drmm_add_action_or_reset(&xe->drm, deballoon_ggtt, tile); + err = vf_balloon_ggtt(gt); + if (err) { + vf_fini_ggtt_balloons(gt); + return err; + } + + return drmm_add_action_or_reset(&xe->drm, cleanup_ggtt, gt); } static int relay_action_handshake(struct xe_gt *gt, u32 *major, u32 *minor) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h index ba6c5d74e326f..d717deb8af914 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h @@ -18,6 +18,8 @@ int xe_gt_sriov_vf_query_config(struct xe_gt *gt); int xe_gt_sriov_vf_connect(struct xe_gt *gt); int xe_gt_sriov_vf_query_runtime(struct xe_gt *gt); int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt); +int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt); +void xe_gt_sriov_vf_deballoon_ggtt_locked(struct xe_gt *gt); int xe_gt_sriov_vf_notify_resfix_done(struct xe_gt *gt); void xe_gt_sriov_vf_migrated_event_handler(struct xe_gt *gt); -- GitLab From 3e693945b125da0f8459e84cee385cec77910c2f Mon Sep 17 00:00:00 2001 From: Tomasz Lis Date: Mon, 12 May 2025 13:40:16 +0200 Subject: [PATCH 0021/1479] drm/xe/vf: Shifting GGTT area post migration We have only one GGTT for all IOV functions, with each VF having assigned a range of addresses for its use. After migration, a VF can receive a different range of addresses than it had initially. This implements shifting GGTT addresses within drm_mm nodes, so that VMAs stay valid after migration. This will make the driver use new addresses when accessing GGTT from the moment the shifting ends. By taking the ggtt->lock for the period of VMA fixups, this change also adds constraint on that mutex. Any locks used during the recovery cannot ever wait for hardware response - because after migration, the hardware will not do anything until fixups are finished. v2: Moved some functs to xe_ggtt.c; moved shift computation to just after querying; improved documentation; switched some warns to asserts; skipping fixups when GGTT shift eq 0; iterating through tiles (Michal) v3: Updated kerneldocs, removed unused funct, properly allocate balloning nodes if non existent v4: Re-used ballooning functions from VF init, used bool in place of standard error codes v5: Renamed one function v6: Subject tag change, several kerneldocs updated, some functions renamed, some moved, added several asserts, shuffled declarations of variables, revealed more detail in high level functions v7: Fixed typos, added `_locked` suffix to some functs, improved readability of asserts, removed unneeded conditional v8: Moved one function, removed implementation detail from kerneldoc, added asserts v9: Code shuffling without much change, and one param rename v10: Minor error path change, added printing the shift via debugfs Signed-off-by: Tomasz Lis Cc: Michal Wajdeczko Reviewed-by: Michal Wajdeczko Signed-off-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250512114018.361843-3-tomasz.lis@intel.com --- drivers/gpu/drm/xe/xe_ggtt.c | 50 +++++++++++ drivers/gpu/drm/xe/xe_ggtt.h | 1 + drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 104 ++++++++++++++++++++++ drivers/gpu/drm/xe/xe_gt_sriov_vf.h | 2 + drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h | 2 + drivers/gpu/drm/xe/xe_sriov_vf.c | 21 +++++ 6 files changed, 180 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index 5a37233f24205..af8e53014b874 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -484,6 +484,56 @@ void xe_ggtt_node_remove_balloon_locked(struct xe_ggtt_node *node) drm_mm_remove_node(&node->base); } +static void xe_ggtt_assert_fit(struct xe_ggtt *ggtt, u64 start, u64 size) +{ + struct xe_tile *tile = ggtt->tile; + struct xe_device *xe = tile_to_xe(tile); + u64 __maybe_unused wopcm = xe_wopcm_size(xe); + + xe_tile_assert(tile, start >= wopcm); + xe_tile_assert(tile, start + size < ggtt->size - wopcm); +} + +/** + * xe_ggtt_shift_nodes_locked - Shift GGTT nodes to adjust for a change in usable address range. + * @ggtt: the &xe_ggtt struct instance + * @shift: change to the location of area provisioned for current VF + * + * This function moves all nodes from the GGTT VM, to a temp list. These nodes are expected + * to represent allocations in range formerly assigned to current VF, before the range changed. + * When the GGTT VM is completely clear of any nodes, they are re-added with shifted offsets. + * + * The function has no ability of failing - because it shifts existing nodes, without + * any additional processing. If the nodes were successfully existing at the old address, + * they will do the same at the new one. A fail inside this function would indicate that + * the list of nodes was either already damaged, or that the shift brings the address range + * outside of valid bounds. Both cases justify an assert rather than error code. + */ +void xe_ggtt_shift_nodes_locked(struct xe_ggtt *ggtt, s64 shift) +{ + struct xe_tile *tile __maybe_unused = ggtt->tile; + struct drm_mm_node *node, *tmpn; + LIST_HEAD(temp_list_head); + + lockdep_assert_held(&ggtt->lock); + + if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) + drm_mm_for_each_node_safe(node, tmpn, &ggtt->mm) + xe_ggtt_assert_fit(ggtt, node->start + shift, node->size); + + drm_mm_for_each_node_safe(node, tmpn, &ggtt->mm) { + drm_mm_remove_node(node); + list_add(&node->node_list, &temp_list_head); + } + + list_for_each_entry_safe(node, tmpn, &temp_list_head, node_list) { + list_del(&node->node_list); + node->start += shift; + drm_mm_reserve_node(&ggtt->mm, node); + xe_tile_assert(tile, drm_mm_node_allocated(node)); + } +} + /** * xe_ggtt_node_insert_locked - Locked version to insert a &xe_ggtt_node into the GGTT * @node: the &xe_ggtt_node to be inserted diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h index d468af96b465e..4337a279ff3b0 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.h +++ b/drivers/gpu/drm/xe/xe_ggtt.h @@ -18,6 +18,7 @@ void xe_ggtt_node_fini(struct xe_ggtt_node *node); int xe_ggtt_node_insert_balloon_locked(struct xe_ggtt_node *node, u64 start, u64 size); void xe_ggtt_node_remove_balloon_locked(struct xe_ggtt_node *node); +void xe_ggtt_shift_nodes_locked(struct xe_ggtt *ggtt, s64 shift); int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align); int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node, diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c index f82ddff79b3b9..4ff7ae1a5f16c 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c @@ -415,6 +415,7 @@ static int vf_get_ggtt_info(struct xe_gt *gt) xe_gt_sriov_dbg_verbose(gt, "GGTT %#llx-%#llx = %lluK\n", start, start + size - 1, size / SZ_1K); + config->ggtt_shift = start - (s64)config->ggtt_base; config->ggtt_base = start; config->ggtt_size = size; @@ -560,6 +561,24 @@ u64 xe_gt_sriov_vf_lmem(struct xe_gt *gt) return gt->sriov.vf.self_config.lmem_size; } +/** + * xe_gt_sriov_vf_ggtt_shift - Return shift in GGTT range due to VF migration + * @gt: the &xe_gt struct instance + * + * This function is for VF use only. + * + * Return: The shift value; could be negative + */ +s64 xe_gt_sriov_vf_ggtt_shift(struct xe_gt *gt) +{ + struct xe_gt_sriov_vf_selfconfig *config = >->sriov.vf.self_config; + + xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); + xe_gt_assert(gt, !xe_gt_is_media_type(gt)); + + return config->ggtt_shift; +} + static int vf_init_ggtt_balloons(struct xe_gt *gt) { struct xe_tile *tile = gt_to_tile(gt); @@ -817,6 +836,89 @@ int xe_gt_sriov_vf_connect(struct xe_gt *gt) return err; } +/** + * DOC: GGTT nodes shifting during VF post-migration recovery + * + * The first fixup applied to the VF KMD structures as part of post-migration + * recovery is shifting nodes within &xe_ggtt instance. The nodes are moved + * from range previously assigned to this VF, into newly provisioned area. + * The changes include balloons, which are resized accordingly. + * + * The balloon nodes are there to eliminate unavailable ranges from use: one + * reserves the GGTT area below the range for current VF, and another one + * reserves area above. + * + * Below is a GGTT layout of example VF, with a certain address range assigned to + * said VF, and inaccessible areas above and below: + * + * 0 4GiB + * |<--------------------------- Total GGTT size ----------------------------->| + * WOPCM GUC_TOP + * |<-------------- Area mappable by xe_ggtt instance ---------------->| + * + * +---+---------------------------------+----------+----------------------+---+ + * |\\\|/////////////////////////////////| VF mem |//////////////////////|\\\| + * +---+---------------------------------+----------+----------------------+---+ + * + * Hardware enforced access rules before migration: + * + * |<------- inaccessible for VF ------->||<-- inaccessible for VF ->| + * + * GGTT nodes used for tracking allocations: + * + * |<---------- balloon ------------>|<- nodes->|<----- balloon ------>| + * + * After the migration, GGTT area assigned to the VF might have shifted, either + * to lower or to higher address. But we expect the total size and extra areas to + * be identical, as migration can only happen between matching platforms. + * Below is an example of GGTT layout of the VF after migration. Content of the + * GGTT for VF has been moved to a new area, and we receive its address from GuC: + * + * +---+----------------------+----------+---------------------------------+---+ + * |\\\|//////////////////////| VF mem |/////////////////////////////////|\\\| + * +---+----------------------+----------+---------------------------------+---+ + * + * Hardware enforced access rules after migration: + * + * |<- inaccessible for VF -->||<------- inaccessible for VF ------->| + * + * So the VF has a new slice of GGTT assigned, and during migration process, the + * memory content was copied to that new area. But the &xe_ggtt nodes are still + * tracking allocations using the old addresses. The nodes within VF owned area + * have to be shifted, and balloon nodes need to be resized to properly mask out + * areas not owned by the VF. + * + * Fixed &xe_ggtt nodes used for tracking allocations: + * + * |<------ balloon ------>|<- nodes->|<----------- balloon ----------->| + * + * Due to use of GPU profiles, we do not expect the old and new GGTT ares to + * overlap; but our node shifting will fix addresses properly regardless. + */ + +/** + * xe_gt_sriov_vf_fixup_ggtt_nodes - Shift GGTT allocations to match assigned range. + * @gt: the &xe_gt struct instance + * @shift: the shift value + * + * Since Global GTT is not virtualized, each VF has an assigned range + * within the global space. This range might have changed during migration, + * which requires all memory addresses pointing to GGTT to be shifted. + */ +void xe_gt_sriov_vf_fixup_ggtt_nodes(struct xe_gt *gt, s64 shift) +{ + struct xe_tile *tile = gt_to_tile(gt); + struct xe_ggtt *ggtt = tile->mem.ggtt; + + xe_gt_assert(gt, !xe_gt_is_media_type(gt)); + + mutex_lock(&ggtt->lock); + xe_gt_sriov_vf_deballoon_ggtt_locked(gt); + xe_ggtt_shift_nodes_locked(ggtt, shift); + xe_gt_sriov_vf_balloon_ggtt_locked(gt); + mutex_unlock(&ggtt->lock); +} + /** * xe_gt_sriov_vf_migrated_event_handler - Start a VF migration recovery, * or just mark that a GuC is ready for it. @@ -1103,6 +1205,8 @@ void xe_gt_sriov_vf_print_config(struct xe_gt *gt, struct drm_printer *p) string_get_size(config->ggtt_size, 1, STRING_UNITS_2, buf, sizeof(buf)); drm_printf(p, "GGTT size:\t%llu (%s)\n", config->ggtt_size, buf); + drm_printf(p, "GGTT shift on last restore:\t%lld\n", config->ggtt_shift); + if (IS_DGFX(xe) && !xe_gt_is_media_type(gt)) { string_get_size(config->lmem_size, 1, STRING_UNITS_2, buf, sizeof(buf)); drm_printf(p, "LMEM size:\t%llu (%s)\n", config->lmem_size, buf); diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h index d717deb8af914..9db41afddd5a8 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h @@ -20,6 +20,8 @@ int xe_gt_sriov_vf_query_runtime(struct xe_gt *gt); int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt); int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt); void xe_gt_sriov_vf_deballoon_ggtt_locked(struct xe_gt *gt); +s64 xe_gt_sriov_vf_ggtt_shift(struct xe_gt *gt); +void xe_gt_sriov_vf_fixup_ggtt_nodes(struct xe_gt *gt, s64 shift); int xe_gt_sriov_vf_notify_resfix_done(struct xe_gt *gt); void xe_gt_sriov_vf_migrated_event_handler(struct xe_gt *gt); diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h index a57f13b5afcd0..5ccbdf8d08b64 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf_types.h @@ -40,6 +40,8 @@ struct xe_gt_sriov_vf_selfconfig { u64 ggtt_base; /** @ggtt_size: assigned size of the GGTT region. */ u64 ggtt_size; + /** @ggtt_shift: difference in ggtt_base on last migration */ + s64 ggtt_shift; /** @lmem_size: assigned size of the LMEM. */ u64 lmem_size; /** @num_ctxs: assigned number of GuC submission context IDs. */ diff --git a/drivers/gpu/drm/xe/xe_sriov_vf.c b/drivers/gpu/drm/xe/xe_sriov_vf.c index c1275e64aa9c6..d48ea70d0f624 100644 --- a/drivers/gpu/drm/xe/xe_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_sriov_vf.c @@ -7,6 +7,7 @@ #include "xe_assert.h" #include "xe_device.h" +#include "xe_gt.h" #include "xe_gt_sriov_printk.h" #include "xe_gt_sriov_vf.h" #include "xe_pm.h" @@ -170,6 +171,25 @@ static bool vf_post_migration_imminent(struct xe_device *xe) work_pending(&xe->sriov.vf.migration.worker); } +static bool vf_post_migration_fixup_ggtt_nodes(struct xe_device *xe) +{ + bool need_fixups = false; + struct xe_tile *tile; + unsigned int id; + + for_each_tile(tile, xe, id) { + struct xe_gt *gt = tile->primary_gt; + s64 shift; + + shift = xe_gt_sriov_vf_ggtt_shift(gt); + if (shift) { + need_fixups = true; + xe_gt_sriov_vf_fixup_ggtt_nodes(gt, shift); + } + } + return need_fixups; +} + /* * Notify all GuCs about resource fixups apply finished. */ @@ -201,6 +221,7 @@ static void vf_post_migration_recovery(struct xe_device *xe) if (unlikely(err)) goto fail; + vf_post_migration_fixup_ggtt_nodes(xe); /* FIXME: add the recovery steps */ vf_post_migration_notify_resfix_done(xe); xe_pm_runtime_put(xe); -- GitLab From e327592cc901a3e415e28e1b6aa26381a2a93582 Mon Sep 17 00:00:00 2001 From: Tomasz Lis Date: Mon, 12 May 2025 13:40:17 +0200 Subject: [PATCH 0022/1479] drm/xe/guc: Introduce enum with offsets for context register H2Gs Some GuC messages are constructed with incrementing dword counter rather than referencing specific DWORDs, as described in GuC interface specification. This change introduces the definitions of DWORD numbers for parameters which will need to be referenced in a CTB parser to be added in a following patch. To ensure correctness of these DWORDs, verification in form of asserts was added to the message construction code. v2: Renamed enum members, added ones for single context registration, modified asserts to check values rather than indexes. v3: Reordered assert args to take less lines v4: Added lengths v5: Renamed MULTI_LRC_MSG_LEN to MULTI_LRC_MSG_MIN_LEN Suggested-by: Michal Wajdeczko Signed-off-by: Tomasz Lis Reviewed-by: Michal Wajdeczko Signed-off-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250512114018.361843-4-tomasz.lis@intel.com --- drivers/gpu/drm/xe/abi/guc_actions_abi.h | 31 ++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_guc_submit.c | 17 +++++++++++++ 2 files changed, 48 insertions(+) diff --git a/drivers/gpu/drm/xe/abi/guc_actions_abi.h b/drivers/gpu/drm/xe/abi/guc_actions_abi.h index 448afb86e05c7..ff4f412c28d8c 100644 --- a/drivers/gpu/drm/xe/abi/guc_actions_abi.h +++ b/drivers/gpu/drm/xe/abi/guc_actions_abi.h @@ -161,6 +161,37 @@ enum xe_guc_preempt_options { XE_GUC_PREEMPT_OPTION_DROP_SUBMIT_Q = 0x8, }; +enum xe_guc_register_context_param_offsets { + XE_GUC_REGISTER_CONTEXT_DATA_0_MBZ = 0, + XE_GUC_REGISTER_CONTEXT_DATA_1_FLAGS, + XE_GUC_REGISTER_CONTEXT_DATA_2_CONTEXT_INDEX, + XE_GUC_REGISTER_CONTEXT_DATA_3_ENGINE_CLASS, + XE_GUC_REGISTER_CONTEXT_DATA_4_ENGINE_SUBMIT_MASK, + XE_GUC_REGISTER_CONTEXT_DATA_5_WQ_DESC_ADDR_LOWER, + XE_GUC_REGISTER_CONTEXT_DATA_6_WQ_DESC_ADDR_UPPER, + XE_GUC_REGISTER_CONTEXT_DATA_7_WQ_BUF_BASE_LOWER, + XE_GUC_REGISTER_CONTEXT_DATA_8_WQ_BUF_BASE_UPPER, + XE_GUC_REGISTER_CONTEXT_DATA_9_WQ_BUF_SIZE, + XE_GUC_REGISTER_CONTEXT_DATA_10_HW_LRC_ADDR, + XE_GUC_REGISTER_CONTEXT_MSG_LEN, +}; + +enum xe_guc_register_context_multi_lrc_param_offsets { + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_0_MBZ = 0, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_1_FLAGS, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_2_PARENT_CONTEXT, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_3_ENGINE_CLASS, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_4_ENGINE_SUBMIT_MASK, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_5_WQ_DESC_ADDR_LOWER, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_6_WQ_DESC_ADDR_UPPER, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_7_WQ_BUF_BASE_LOWER, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_8_WQ_BUF_BASE_UPPER, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_9_WQ_BUF_SIZE, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_10_NUM_CTXS, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_11_HW_LRC_ADDR, + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_MSG_MIN_LEN = 11, +}; + enum xe_guc_report_status { XE_GUC_REPORT_STATUS_UNKNOWN = 0x0, XE_GUC_REPORT_STATUS_ACKED = 0x1, diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 369be36f7dc5a..06e2998b0e214 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -487,6 +487,15 @@ static void __register_mlrc_exec_queue(struct xe_guc *guc, action[len++] = upper_32_bits(xe_lrc_descriptor(lrc)); } + /* explicitly checks some fields that we might fixup later */ + xe_gt_assert(guc_to_gt(guc), info->wq_desc_lo == + action[XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_5_WQ_DESC_ADDR_LOWER]); + xe_gt_assert(guc_to_gt(guc), info->wq_base_lo == + action[XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_7_WQ_BUF_BASE_LOWER]); + xe_gt_assert(guc_to_gt(guc), q->width == + action[XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_10_NUM_CTXS]); + xe_gt_assert(guc_to_gt(guc), info->hwlrca_lo == + action[XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_11_HW_LRC_ADDR]); xe_gt_assert(guc_to_gt(guc), len <= MAX_MLRC_REG_SIZE); #undef MAX_MLRC_REG_SIZE @@ -511,6 +520,14 @@ static void __register_exec_queue(struct xe_guc *guc, info->hwlrca_hi, }; + /* explicitly checks some fields that we might fixup later */ + xe_gt_assert(guc_to_gt(guc), info->wq_desc_lo == + action[XE_GUC_REGISTER_CONTEXT_DATA_5_WQ_DESC_ADDR_LOWER]); + xe_gt_assert(guc_to_gt(guc), info->wq_base_lo == + action[XE_GUC_REGISTER_CONTEXT_DATA_7_WQ_BUF_BASE_LOWER]); + xe_gt_assert(guc_to_gt(guc), info->hwlrca_lo == + action[XE_GUC_REGISTER_CONTEXT_DATA_10_HW_LRC_ADDR]); + xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), 0, 0); } -- GitLab From cef88d1265cac7d415606af73ba58926fd3cd8b7 Mon Sep 17 00:00:00 2001 From: Tomasz Lis Date: Mon, 12 May 2025 13:40:18 +0200 Subject: [PATCH 0023/1479] drm/xe/vf: Fixup CTB send buffer messages after migration During post-migration recovery of a VF, it is necessary to update GGTT references included in messages which are going to be sent to GuC. GuC will start consuming messages after VF KMD will inform it about fixups being done; before that, the VF KMD is expected to update any H2G messages which are already in send buffer but were not consumed by GuC. Only a small subset of messages allowed for VFs have GGTT references in them. This patch adds the functionality to parse the CTB send ring buffer and shift addresses contained within. While fixing the CTB content, ct->lock is not taken. This means the only barrier taken remains GGTT address lock - which is ok, because only requests with GGTT addresses matter, but it also means tail changes can happen during the CTB fixups execution (which may be ignored as any new messages will not have anything to fix). The GGTT address locking will be introduced in a future series. v2: removed storing shift as that's now done in VMA nodes patch; macros to inlines; warns to asserts; log messages fixes (Michal) v3: removed inline keywords, enums for offsets in CTB messages, less error messages, if return unused then made functs void (Michal) v4: update the cached head before starting fixups v5: removed/updated comments, wrapped lines, converted assert into error, enums for offsets to separate patch, reused xe_map_rd v6: define xe_map_*_array() macros, support CTB wrap which divides a message, updated comments, moved one function to an earlier patch v7: renamed few functions, wider use on previously introduced helper, separate cases in parsing messges, documented a static funct v8: Introduced more helpers, fixed coding style mistakes v9: Move xe_map*() functs to macros, add asserts, add debug print v10: Errors in place of some asserts, style fixes v11: Fixed invalid conditionals, added debug-only local pointer v12: Removed redundant __maybe_unused Signed-off-by: Tomasz Lis Cc: Michal Wajdeczko Reviewed-by: Michal Wajdeczko Signed-off-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250512114018.361843-5-tomasz.lis@intel.com --- drivers/gpu/drm/xe/xe_guc_ct.c | 183 +++++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_guc_ct.h | 2 + drivers/gpu/drm/xe/xe_map.h | 18 +++ drivers/gpu/drm/xe/xe_sriov_vf.c | 21 +++- 4 files changed, 223 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c index 2447de0ebedf4..ff6edf1b14f49 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.c +++ b/drivers/gpu/drm/xe/xe_guc_ct.c @@ -25,6 +25,7 @@ #include "xe_gt_printk.h" #include "xe_gt_sriov_pf_control.h" #include "xe_gt_sriov_pf_monitor.h" +#include "xe_gt_sriov_printk.h" #include "xe_gt_tlb_invalidation.h" #include "xe_guc.h" #include "xe_guc_log.h" @@ -84,6 +85,8 @@ struct g2h_fence { bool done; }; +#define make_u64(hi, lo) ((u64)((u64)(u32)(hi) << 32 | (u32)(lo))) + static void g2h_fence_init(struct g2h_fence *g2h_fence, u32 *response_buffer) { g2h_fence->response_buffer = response_buffer; @@ -1624,6 +1627,186 @@ static void g2h_worker_func(struct work_struct *w) receive_g2h(ct); } +static void xe_fixup_u64_in_cmds(struct xe_device *xe, struct iosys_map *cmds, + u32 size, u32 idx, s64 shift) +{ + u32 hi, lo; + u64 offset; + + lo = xe_map_rd_ring_u32(xe, cmds, idx, size); + hi = xe_map_rd_ring_u32(xe, cmds, idx + 1, size); + offset = make_u64(hi, lo); + offset += shift; + lo = lower_32_bits(offset); + hi = upper_32_bits(offset); + xe_map_wr_ring_u32(xe, cmds, idx, size, lo); + xe_map_wr_ring_u32(xe, cmds, idx + 1, size, hi); +} + +/* + * Shift any GGTT addresses within a single message left within CTB from + * before post-migration recovery. + * @ct: pointer to CT struct of the target GuC + * @cmds: iomap buffer containing CT messages + * @head: start of the target message within the buffer + * @len: length of the target message + * @size: size of the commands buffer + * @shift: the address shift to be added to each GGTT reference + * Return: true if the message was fixed or needed no fixups, false on failure + */ +static bool ct_fixup_ggtt_in_message(struct xe_guc_ct *ct, + struct iosys_map *cmds, u32 head, + u32 len, u32 size, s64 shift) +{ + struct xe_gt *gt = ct_to_gt(ct); + struct xe_device *xe = ct_to_xe(ct); + u32 msg[GUC_HXG_MSG_MIN_LEN]; + u32 action, i, n; + + xe_gt_assert(gt, len >= GUC_HXG_MSG_MIN_LEN); + + msg[0] = xe_map_rd_ring_u32(xe, cmds, head, size); + action = FIELD_GET(GUC_HXG_REQUEST_MSG_0_ACTION, msg[0]); + + xe_gt_sriov_dbg_verbose(gt, "fixing H2G %#x\n", action); + + switch (action) { + case XE_GUC_ACTION_REGISTER_CONTEXT: + if (len != XE_GUC_REGISTER_CONTEXT_MSG_LEN) + goto err_len; + xe_fixup_u64_in_cmds(xe, cmds, size, head + + XE_GUC_REGISTER_CONTEXT_DATA_5_WQ_DESC_ADDR_LOWER, + shift); + xe_fixup_u64_in_cmds(xe, cmds, size, head + + XE_GUC_REGISTER_CONTEXT_DATA_7_WQ_BUF_BASE_LOWER, + shift); + xe_fixup_u64_in_cmds(xe, cmds, size, head + + XE_GUC_REGISTER_CONTEXT_DATA_10_HW_LRC_ADDR, shift); + break; + case XE_GUC_ACTION_REGISTER_CONTEXT_MULTI_LRC: + if (len < XE_GUC_REGISTER_CONTEXT_MULTI_LRC_MSG_MIN_LEN) + goto err_len; + n = xe_map_rd_ring_u32(xe, cmds, head + + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_10_NUM_CTXS, size); + if (len != XE_GUC_REGISTER_CONTEXT_MULTI_LRC_MSG_MIN_LEN + 2 * n) + goto err_len; + xe_fixup_u64_in_cmds(xe, cmds, size, head + + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_5_WQ_DESC_ADDR_LOWER, + shift); + xe_fixup_u64_in_cmds(xe, cmds, size, head + + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_7_WQ_BUF_BASE_LOWER, + shift); + for (i = 0; i < n; i++) + xe_fixup_u64_in_cmds(xe, cmds, size, head + + XE_GUC_REGISTER_CONTEXT_MULTI_LRC_DATA_11_HW_LRC_ADDR + + 2 * i, shift); + break; + default: + break; + } + return true; + +err_len: + xe_gt_err(gt, "Skipped G2G %#x message fixups, unexpected length (%u)\n", action, len); + return false; +} + +/* + * Apply fixups to the next outgoing CT message within given CTB + * @ct: the &xe_guc_ct struct instance representing the target GuC + * @h2g: the &guc_ctb struct instance of the target buffer + * @shift: shift to be added to all GGTT addresses within the CTB + * @mhead: pointer to an integer storing message start position; the + * position is changed to next message before this function return + * @avail: size of the area available for parsing, that is length + * of all remaining messages stored within the CTB + * Return: size of the area available for parsing after one message + * has been parsed, that is length remaining from the updated mhead + */ +static int ct_fixup_ggtt_in_buffer(struct xe_guc_ct *ct, struct guc_ctb *h2g, + s64 shift, u32 *mhead, s32 avail) +{ + struct xe_gt *gt = ct_to_gt(ct); + struct xe_device *xe = ct_to_xe(ct); + u32 msg[GUC_HXG_MSG_MIN_LEN]; + u32 size = h2g->info.size; + u32 head = *mhead; + u32 len; + + xe_gt_assert(gt, avail >= (s32)GUC_CTB_MSG_MIN_LEN); + + /* Read header */ + msg[0] = xe_map_rd_ring_u32(xe, &h2g->cmds, head, size); + len = FIELD_GET(GUC_CTB_MSG_0_NUM_DWORDS, msg[0]) + GUC_CTB_MSG_MIN_LEN; + + if (unlikely(len > (u32)avail)) { + xe_gt_err(gt, "H2G channel broken on read, avail=%d, len=%d, fixups skipped\n", + avail, len); + return 0; + } + + head = (head + GUC_CTB_MSG_MIN_LEN) % size; + if (!ct_fixup_ggtt_in_message(ct, &h2g->cmds, head, msg_len_to_hxg_len(len), size, shift)) + return 0; + *mhead = (head + msg_len_to_hxg_len(len)) % size; + + return avail - len; +} + +/** + * xe_guc_ct_fixup_messages_with_ggtt - Fixup any pending H2G CTB messages + * @ct: pointer to CT struct of the target GuC + * @ggtt_shift: shift to be added to all GGTT addresses within the CTB + * + * Messages in GuC to Host CTB are owned by GuC and any fixups in them + * are made by GuC. But content of the Host to GuC CTB is owned by the + * KMD, so fixups to GGTT references in any pending messages need to be + * applied here. + * This function updates GGTT offsets in payloads of pending H2G CTB + * messages (messages which were not consumed by GuC before the VF got + * paused). + */ +void xe_guc_ct_fixup_messages_with_ggtt(struct xe_guc_ct *ct, s64 ggtt_shift) +{ + struct guc_ctb *h2g = &ct->ctbs.h2g; + struct xe_guc *guc = ct_to_guc(ct); + struct xe_gt *gt = guc_to_gt(guc); + u32 head, tail, size; + s32 avail; + + if (unlikely(h2g->info.broken)) + return; + + h2g->info.head = desc_read(ct_to_xe(ct), h2g, head); + head = h2g->info.head; + tail = READ_ONCE(h2g->info.tail); + size = h2g->info.size; + + if (unlikely(head > size)) + goto corrupted; + + if (unlikely(tail >= size)) + goto corrupted; + + avail = tail - head; + + /* beware of buffer wrap case */ + if (unlikely(avail < 0)) + avail += size; + xe_gt_dbg(gt, "available %d (%u:%u:%u)\n", avail, head, tail, size); + xe_gt_assert(gt, avail >= 0); + + while (avail > 0) + avail = ct_fixup_ggtt_in_buffer(ct, h2g, ggtt_shift, &head, avail); + + return; + +corrupted: + xe_gt_err(gt, "Corrupted H2G descriptor head=%u tail=%u size=%u, fixups not applied\n", + head, tail, size); + h2g->info.broken = true; +} + static struct xe_guc_ct_snapshot *guc_ct_snapshot_alloc(struct xe_guc_ct *ct, bool atomic, bool want_ctb) { diff --git a/drivers/gpu/drm/xe/xe_guc_ct.h b/drivers/gpu/drm/xe/xe_guc_ct.h index 82c4ae458dda3..5649bda828239 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.h +++ b/drivers/gpu/drm/xe/xe_guc_ct.h @@ -22,6 +22,8 @@ void xe_guc_ct_snapshot_print(struct xe_guc_ct_snapshot *snapshot, struct drm_pr void xe_guc_ct_snapshot_free(struct xe_guc_ct_snapshot *snapshot); void xe_guc_ct_print(struct xe_guc_ct *ct, struct drm_printer *p, bool want_ctb); +void xe_guc_ct_fixup_messages_with_ggtt(struct xe_guc_ct *ct, s64 ggtt_shift); + static inline bool xe_guc_ct_enabled(struct xe_guc_ct *ct) { return ct->state == XE_GUC_CT_STATE_ENABLED; diff --git a/drivers/gpu/drm/xe/xe_map.h b/drivers/gpu/drm/xe/xe_map.h index f62e0c8b67aba..8d67f6ba2d95b 100644 --- a/drivers/gpu/drm/xe/xe_map.h +++ b/drivers/gpu/drm/xe/xe_map.h @@ -78,6 +78,24 @@ static inline void xe_map_write32(struct xe_device *xe, struct iosys_map *map, iosys_map_wr(map__, offset__, type__, val__); \ }) +#define xe_map_rd_array(xe__, map__, index__, type__) \ + xe_map_rd(xe__, map__, (index__) * sizeof(type__), type__) + +#define xe_map_wr_array(xe__, map__, index__, type__, val__) \ + xe_map_wr(xe__, map__, (index__) * sizeof(type__), type__, val__) + +#define xe_map_rd_array_u32(xe__, map__, index__) \ + xe_map_rd_array(xe__, map__, index__, u32) + +#define xe_map_wr_array_u32(xe__, map__, index__, val__) \ + xe_map_wr_array(xe__, map__, index__, u32, val__) + +#define xe_map_rd_ring_u32(xe__, map__, index__, size__) \ + xe_map_rd_array_u32(xe__, map__, (index__) % (size__)) + +#define xe_map_wr_ring_u32(xe__, map__, index__, size__, val__) \ + xe_map_wr_array_u32(xe__, map__, (index__) % (size__), val__) + #define xe_map_rd_field(xe__, map__, struct_offset__, struct_type__, field__) ({ \ struct xe_device *__xe = xe__; \ xe_device_assert_mem_access(__xe); \ diff --git a/drivers/gpu/drm/xe/xe_sriov_vf.c b/drivers/gpu/drm/xe/xe_sriov_vf.c index d48ea70d0f624..2674fa948fda3 100644 --- a/drivers/gpu/drm/xe/xe_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_sriov_vf.c @@ -10,6 +10,7 @@ #include "xe_gt.h" #include "xe_gt_sriov_printk.h" #include "xe_gt_sriov_vf.h" +#include "xe_guc_ct.h" #include "xe_pm.h" #include "xe_sriov.h" #include "xe_sriov_printk.h" @@ -158,6 +159,20 @@ static int vf_post_migration_requery_guc(struct xe_device *xe) return ret; } +static void vf_post_migration_fixup_ctb(struct xe_device *xe) +{ + struct xe_gt *gt; + unsigned int id; + + xe_assert(xe, IS_SRIOV_VF(xe)); + + for_each_gt(gt, xe, id) { + s32 shift = xe_gt_sriov_vf_ggtt_shift(gt); + + xe_guc_ct_fixup_messages_with_ggtt(>->uc.guc.ct, shift); + } +} + /* * vf_post_migration_imminent - Check if post-restore recovery is coming. * @xe: the &xe_device struct instance @@ -211,6 +226,7 @@ static void vf_post_migration_notify_resfix_done(struct xe_device *xe) static void vf_post_migration_recovery(struct xe_device *xe) { + bool need_fixups; int err; drm_dbg(&xe->drm, "migration recovery in progress\n"); @@ -221,8 +237,11 @@ static void vf_post_migration_recovery(struct xe_device *xe) if (unlikely(err)) goto fail; - vf_post_migration_fixup_ggtt_nodes(xe); + need_fixups = vf_post_migration_fixup_ggtt_nodes(xe); /* FIXME: add the recovery steps */ + if (need_fixups) + vf_post_migration_fixup_ctb(xe); + vf_post_migration_notify_resfix_done(xe); xe_pm_runtime_put(xe); drm_notice(&xe->drm, "migration recovery ended\n"); -- GitLab From e5c13e2c505b73a8667ef9a0fd5cbd4227e483e6 Mon Sep 17 00:00:00 2001 From: Aradhya Bhatia Date: Mon, 12 May 2025 06:50:04 +0000 Subject: [PATCH 0024/1479] drm/xe/xe2hpg: Add Wa_22021007897 Add Wa_22021007897 for the Xe2_HPG (graphics version: 20.01) IP. It is a permanent workaround, and applicable on all the steppings. Reviewed-by: Gustavo Sousa Reviewed-by: Tejas Upadhyay Signed-off-by: Aradhya Bhatia Link: https://lore.kernel.org/r/20250512065004.2576-1-aradhya.bhatia@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/regs/xe_gt_regs.h | 1 + drivers/gpu/drm/xe/xe_wa.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h index cbb9f7cbcfc0e..5cd5ab8529c5c 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -156,6 +156,7 @@ #define XEHPG_SC_INSTDONE_EXTRA2 XE_REG_MCR(0x7108) #define COMMON_SLICE_CHICKEN4 XE_REG(0x7300, XE_REG_OPTION_MASKED) +#define SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE REG_BIT(12) #define DISABLE_TDC_LOAD_BALANCING_CALC REG_BIT(6) #define COMMON_SLICE_CHICKEN3 XE_REG(0x7304, XE_REG_OPTION_MASKED) diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c index 6f6563cc74306..67196baa42492 100644 --- a/drivers/gpu/drm/xe/xe_wa.c +++ b/drivers/gpu/drm/xe/xe_wa.c @@ -827,6 +827,10 @@ static const struct xe_rtp_entry_sr lrc_was[] = { XE_RTP_RULES(GRAPHICS_VERSION(2001), ENGINE_CLASS(RENDER)), XE_RTP_ACTIONS(SET(CHICKEN_RASTER_1, DIS_CLIP_NEGATIVE_BOUNDING_BOX)) }, + { XE_RTP_NAME("22021007897"), + XE_RTP_RULES(GRAPHICS_VERSION(2001), ENGINE_CLASS(RENDER)), + XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN4, SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE)) + }, /* Xe3_LPG */ { XE_RTP_NAME("14021490052"), -- GitLab From 8a9b978ebd47df9e0694c34748c2d6fa0c31eb4d Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Mon, 12 May 2025 06:54:55 -0700 Subject: [PATCH 0025/1479] drm/gpusvm: Introduce devmem_only flag for allocation This commit adds a new flag, devmem_only, to the drm_gpusvm structure. The purpose of this flag is to ensure that the get_pages function allocates memory exclusively from the device's memory. If the allocation from device memory fails, the function will return an -EFAULT error. Required for shared CPU and GPU atomics on certain devices. v3: - s/vram_only/devmem_only/ Fixes: 99624bdff867 ("drm/gpusvm: Add support for GPU Shared Virtual Memory") Cc: stable@vger.kernel.org Signed-off-by: Matthew Brost Signed-off-by: Himal Prasad Ghimiray Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250512135500.1405019-2-matthew.brost@intel.com --- drivers/gpu/drm/drm_gpusvm.c | 5 +++++ include/drm/drm_gpusvm.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index de424e670995c..a58d03e6cac27 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -1454,6 +1454,11 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm, goto err_unmap; } + if (ctx->devmem_only) { + err = -EFAULT; + goto err_unmap; + } + addr = dma_map_page(gpusvm->drm->dev, page, 0, PAGE_SIZE << order, diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h index df120b4d1f836..9fd25fc880a49 100644 --- a/include/drm/drm_gpusvm.h +++ b/include/drm/drm_gpusvm.h @@ -286,6 +286,7 @@ struct drm_gpusvm { * @in_notifier: entering from a MMU notifier * @read_only: operating on read-only memory * @devmem_possible: possible to use device memory + * @devmem_only: use only device memory * * Context that is DRM GPUSVM is operating in (i.e. user arguments). */ @@ -294,6 +295,7 @@ struct drm_gpusvm_ctx { unsigned int in_notifier :1; unsigned int read_only :1; unsigned int devmem_possible :1; + unsigned int devmem_only :1; }; int drm_gpusvm_init(struct drm_gpusvm *gpusvm, -- GitLab From a9ac0fa455b050d03e3032501368048fb284d318 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Mon, 12 May 2025 06:54:56 -0700 Subject: [PATCH 0026/1479] drm/xe: Strict migration policy for atomic SVM faults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mixing GPU and CPU atomics does not work unless a strict migration policy of GPU atomics must be device memory. Enforce a policy of must be in VRAM with a retry loop of 3 attempts, if retry loop fails abort fault. Removing always_migrate_to_vram modparam as we now have real migration policy. v2: - Only retry migration on atomics - Drop alway migrate modparam v3: - Only set vram_only on DGFX (Himal) - Bail on get_pages failure if vram_only and retry count exceeded (Himal) - s/vram_only/devmem_only - Update xe_svm_range_is_valid to accept devmem_only argument v4: - Fix logic bug get_pages failure v5: - Fix commit message (Himal) - Mention removing always_migrate_to_vram in commit message (Lucas) - Fix xe_svm_range_is_valid to check for devmem pages - Bail on devmem_only && !migrate_devmem (Thomas) v6: - Add READ_ONCE barriers for opportunistic checks (Thomas) - Pair READ_ONCE with WRITE_ONCE (Thomas) v7: - Adjust comments (Thomas) Fixes: 2f118c949160 ("drm/xe: Add SVM VRAM migration") Cc: stable@vger.kernel.org Signed-off-by: Himal Prasad Ghimiray Signed-off-by: Matthew Brost Acked-by: Himal Prasad Ghimiray Reviewed-by: Thomas Hellström Link: https://lore.kernel.org/r/20250512135500.1405019-3-matthew.brost@intel.com --- drivers/gpu/drm/drm_gpusvm.c | 23 +++++-- drivers/gpu/drm/xe/xe_module.c | 3 - drivers/gpu/drm/xe/xe_module.h | 1 - drivers/gpu/drm/xe/xe_pt.c | 14 ++++- drivers/gpu/drm/xe/xe_svm.c | 111 +++++++++++++++++++++++++-------- drivers/gpu/drm/xe/xe_svm.h | 5 -- include/drm/drm_gpusvm.h | 40 +++++++----- 7 files changed, 140 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index a58d03e6cac27..41f6616bcf76f 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -1118,6 +1118,10 @@ static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm, lockdep_assert_held(&gpusvm->notifier_lock); if (range->flags.has_dma_mapping) { + struct drm_gpusvm_range_flags flags = { + .__flags = range->flags.__flags, + }; + for (i = 0, j = 0; i < npages; j++) { struct drm_pagemap_device_addr *addr = &range->dma_addr[j]; @@ -1131,8 +1135,12 @@ static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm, dev, *addr); i += 1 << addr->order; } - range->flags.has_devmem_pages = false; - range->flags.has_dma_mapping = false; + + /* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */ + flags.has_devmem_pages = false; + flags.has_dma_mapping = false; + WRITE_ONCE(range->flags.__flags, flags.__flags); + range->dpagemap = NULL; } } @@ -1334,6 +1342,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm, int err = 0; struct dev_pagemap *pagemap; struct drm_pagemap *dpagemap; + struct drm_gpusvm_range_flags flags; retry: hmm_range.notifier_seq = mmu_interval_read_begin(notifier); @@ -1378,7 +1387,8 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm, */ drm_gpusvm_notifier_lock(gpusvm); - if (range->flags.unmapped) { + flags.__flags = range->flags.__flags; + if (flags.unmapped) { drm_gpusvm_notifier_unlock(gpusvm); err = -EFAULT; goto err_free; @@ -1474,14 +1484,17 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm, } i += 1 << order; num_dma_mapped = i; - range->flags.has_dma_mapping = true; + flags.has_dma_mapping = true; } if (zdd) { - range->flags.has_devmem_pages = true; + flags.has_devmem_pages = true; range->dpagemap = dpagemap; } + /* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */ + WRITE_ONCE(range->flags.__flags, flags.__flags); + drm_gpusvm_notifier_unlock(gpusvm); kvfree(pfns); set_seqno: diff --git a/drivers/gpu/drm/xe/xe_module.c b/drivers/gpu/drm/xe/xe_module.c index 64bf466465449..e4742e27e2cd3 100644 --- a/drivers/gpu/drm/xe/xe_module.c +++ b/drivers/gpu/drm/xe/xe_module.c @@ -30,9 +30,6 @@ struct xe_modparam xe_modparam = { module_param_named(svm_notifier_size, xe_modparam.svm_notifier_size, uint, 0600); MODULE_PARM_DESC(svm_notifier_size, "Set the svm notifier size(in MiB), must be power of 2"); -module_param_named(always_migrate_to_vram, xe_modparam.always_migrate_to_vram, bool, 0444); -MODULE_PARM_DESC(always_migrate_to_vram, "Always migrate to VRAM on GPU fault"); - module_param_named_unsafe(force_execlist, xe_modparam.force_execlist, bool, 0444); MODULE_PARM_DESC(force_execlist, "Force Execlist submission"); diff --git a/drivers/gpu/drm/xe/xe_module.h b/drivers/gpu/drm/xe/xe_module.h index 84339e509c80d..5a3bfea8b7b4c 100644 --- a/drivers/gpu/drm/xe/xe_module.h +++ b/drivers/gpu/drm/xe/xe_module.h @@ -12,7 +12,6 @@ struct xe_modparam { bool force_execlist; bool probe_display; - bool always_migrate_to_vram; u32 force_vram_bar_size; int guc_log_level; char *guc_firmware_path; diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index b42cf5d1b20c3..b04756a97cdcf 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -2270,11 +2270,19 @@ static void op_commit(struct xe_vm *vm, } case DRM_GPUVA_OP_DRIVER: { + /* WRITE_ONCE pairs with READ_ONCE in xe_svm.c */ + if (op->subop == XE_VMA_SUBOP_MAP_RANGE) { - op->map_range.range->tile_present |= BIT(tile->id); - op->map_range.range->tile_invalidated &= ~BIT(tile->id); + WRITE_ONCE(op->map_range.range->tile_present, + op->map_range.range->tile_present | + BIT(tile->id)); + WRITE_ONCE(op->map_range.range->tile_invalidated, + op->map_range.range->tile_invalidated & + ~BIT(tile->id)); } else if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE) { - op->unmap_range.range->tile_present &= ~BIT(tile->id); + WRITE_ONCE(op->unmap_range.range->tile_present, + op->unmap_range.range->tile_present & + ~BIT(tile->id)); } break; } diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index d25f02c8d7fc7..d8e15259a8dfc 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -16,8 +16,17 @@ static bool xe_svm_range_in_vram(struct xe_svm_range *range) { - /* Not reliable without notifier lock */ - return range->base.flags.has_devmem_pages; + /* + * Advisory only check whether the range is currently backed by VRAM + * memory. + */ + + struct drm_gpusvm_range_flags flags = { + /* Pairs with WRITE_ONCE in drm_gpusvm.c */ + .__flags = READ_ONCE(range->base.flags.__flags), + }; + + return flags.has_devmem_pages; } static bool xe_svm_range_has_vram_binding(struct xe_svm_range *range) @@ -650,9 +659,16 @@ void xe_svm_fini(struct xe_vm *vm) } static bool xe_svm_range_is_valid(struct xe_svm_range *range, - struct xe_tile *tile) + struct xe_tile *tile, + bool devmem_only) { - return (range->tile_present & ~range->tile_invalidated) & BIT(tile->id); + /* + * Advisory only check whether the range currently has a valid mapping, + * READ_ONCE pairs with WRITE_ONCE in xe_pt.c + */ + return ((READ_ONCE(range->tile_present) & + ~READ_ONCE(range->tile_invalidated)) & BIT(tile->id)) && + (!devmem_only || xe_svm_range_in_vram(range)); } #if IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) @@ -726,6 +742,36 @@ static int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, } #endif +static bool supports_4K_migration(struct xe_device *xe) +{ + if (xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K) + return false; + + return true; +} + +static bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, + struct xe_vma *vma) +{ + struct xe_vm *vm = range_to_vm(&range->base); + u64 range_size = xe_svm_range_size(range); + + if (!range->base.flags.migrate_devmem) + return false; + + if (xe_svm_range_in_vram(range)) { + drm_dbg(&vm->xe->drm, "Range is already in VRAM\n"); + return false; + } + + if (range_size <= SZ_64K && !supports_4K_migration(vm->xe)) { + drm_dbg(&vm->xe->drm, "Platform doesn't support SZ_4K range migration\n"); + return false; + } + + return true; +} + /** * xe_svm_handle_pagefault() - SVM handle page fault * @vm: The VM. @@ -749,12 +795,15 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR), .check_pages_threshold = IS_DGFX(vm->xe) && IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ? SZ_64K : 0, + .devmem_only = atomic && IS_DGFX(vm->xe) && + IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR), }; struct xe_svm_range *range; struct drm_gpusvm_range *r; struct drm_exec exec; struct dma_fence *fence; struct xe_tile *tile = gt_to_tile(gt); + int migrate_try_count = ctx.devmem_only ? 3 : 1; ktime_t end = 0; int err; @@ -775,24 +824,30 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, if (IS_ERR(r)) return PTR_ERR(r); + if (ctx.devmem_only && !r->flags.migrate_devmem) + return -EACCES; + range = to_xe_range(r); - if (xe_svm_range_is_valid(range, tile)) + if (xe_svm_range_is_valid(range, tile, ctx.devmem_only)) return 0; range_debug(range, "PAGE FAULT"); - /* XXX: Add migration policy, for now migrate range once */ - if (!range->skip_migrate && range->base.flags.migrate_devmem && - xe_svm_range_size(range) >= SZ_64K) { - range->skip_migrate = true; - + if (--migrate_try_count >= 0 && + xe_svm_range_needs_migrate_to_vram(range, vma)) { err = xe_svm_alloc_vram(vm, tile, range, &ctx); if (err) { - drm_dbg(&vm->xe->drm, - "VRAM allocation failed, falling back to " - "retrying fault, asid=%u, errno=%pe\n", - vm->usm.asid, ERR_PTR(err)); - goto retry; + if (migrate_try_count || !ctx.devmem_only) { + drm_dbg(&vm->xe->drm, + "VRAM allocation failed, falling back to retrying fault, asid=%u, errno=%pe\n", + vm->usm.asid, ERR_PTR(err)); + goto retry; + } else { + drm_err(&vm->xe->drm, + "VRAM allocation failed, retry count exceeded, asid=%u, errno=%pe\n", + vm->usm.asid, ERR_PTR(err)); + return err; + } } } @@ -800,15 +855,22 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, err = drm_gpusvm_range_get_pages(&vm->svm.gpusvm, r, &ctx); /* Corner where CPU mappings have changed */ if (err == -EOPNOTSUPP || err == -EFAULT || err == -EPERM) { - if (err == -EOPNOTSUPP) { - range_debug(range, "PAGE FAULT - EVICT PAGES"); - drm_gpusvm_range_evict(&vm->svm.gpusvm, &range->base); + if (migrate_try_count > 0 || !ctx.devmem_only) { + if (err == -EOPNOTSUPP) { + range_debug(range, "PAGE FAULT - EVICT PAGES"); + drm_gpusvm_range_evict(&vm->svm.gpusvm, + &range->base); + } + drm_dbg(&vm->xe->drm, + "Get pages failed, falling back to retrying, asid=%u, gpusvm=%p, errno=%pe\n", + vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); + range_debug(range, "PAGE FAULT - RETRY PAGES"); + goto retry; + } else { + drm_err(&vm->xe->drm, + "Get pages failed, retry count exceeded, asid=%u, gpusvm=%p, errno=%pe\n", + vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); } - drm_dbg(&vm->xe->drm, - "Get pages failed, falling back to retrying, asid=%u, gpusvm=%p, errno=%pe\n", - vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); - range_debug(range, "PAGE FAULT - RETRY PAGES"); - goto retry; } if (err) { range_debug(range, "PAGE FAULT - FAIL PAGE COLLECT"); @@ -842,9 +904,6 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, } drm_exec_fini(&exec); - if (xe_modparam.always_migrate_to_vram) - range->skip_migrate = false; - dma_fence_wait(fence, false); dma_fence_put(fence); diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 2881af1e60b23..30fc78b85b30f 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -39,11 +39,6 @@ struct xe_svm_range { * range. Protected by GPU SVM notifier lock. */ u8 tile_invalidated; - /** - * @skip_migrate: Skip migration to VRAM, protected by GPU fault handler - * locking. - */ - u8 skip_migrate :1; }; /** diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h index 9fd25fc880a49..653d48dbe1c11 100644 --- a/include/drm/drm_gpusvm.h +++ b/include/drm/drm_gpusvm.h @@ -185,6 +185,31 @@ struct drm_gpusvm_notifier { } flags; }; +/** + * struct drm_gpusvm_range_flags - Structure representing a GPU SVM range flags + * + * @migrate_devmem: Flag indicating whether the range can be migrated to device memory + * @unmapped: Flag indicating if the range has been unmapped + * @partial_unmap: Flag indicating if the range has been partially unmapped + * @has_devmem_pages: Flag indicating if the range has devmem pages + * @has_dma_mapping: Flag indicating if the range has a DMA mapping + * @__flags: Flags for range in u16 form (used for READ_ONCE) + */ +struct drm_gpusvm_range_flags { + union { + struct { + /* All flags below must be set upon creation */ + u16 migrate_devmem : 1; + /* All flags below must be set / cleared under notifier lock */ + u16 unmapped : 1; + u16 partial_unmap : 1; + u16 has_devmem_pages : 1; + u16 has_dma_mapping : 1; + }; + u16 __flags; + }; +}; + /** * struct drm_gpusvm_range - Structure representing a GPU SVM range * @@ -198,11 +223,6 @@ struct drm_gpusvm_notifier { * @dpagemap: The struct drm_pagemap of the device pages we're dma-mapping. * Note this is assuming only one drm_pagemap per range is allowed. * @flags: Flags for range - * @flags.migrate_devmem: Flag indicating whether the range can be migrated to device memory - * @flags.unmapped: Flag indicating if the range has been unmapped - * @flags.partial_unmap: Flag indicating if the range has been partially unmapped - * @flags.has_devmem_pages: Flag indicating if the range has devmem pages - * @flags.has_dma_mapping: Flag indicating if the range has a DMA mapping * * This structure represents a GPU SVM range used for tracking memory ranges * mapped in a DRM device. @@ -216,15 +236,7 @@ struct drm_gpusvm_range { unsigned long notifier_seq; struct drm_pagemap_device_addr *dma_addr; struct drm_pagemap *dpagemap; - struct { - /* All flags below must be set upon creation */ - u16 migrate_devmem : 1; - /* All flags below must be set / cleared under notifier lock */ - u16 unmapped : 1; - u16 partial_unmap : 1; - u16 has_devmem_pages : 1; - u16 has_dma_mapping : 1; - } flags; + struct drm_gpusvm_range_flags flags; }; /** -- GitLab From 8dc1812b5b3a42311d28eb385eed88e2053ad3cb Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Mon, 12 May 2025 06:54:57 -0700 Subject: [PATCH 0027/1479] drm/gpusvm: Add timeslicing support to GPU SVM Add timeslicing support to GPU SVM which will guarantee the GPU a minimum execution time on piece of physical memory before migration back to CPU. Intended to implement strict migration policies which require memory to be in a certain placement for correct execution. Required for shared CPU and GPU atomics on certain devices. Fixes: 99624bdff867 ("drm/gpusvm: Add support for GPU Shared Virtual Memory") Cc: stable@vger.kernel.org Signed-off-by: Matthew Brost Reviewed-by: Himal Prasad Ghimiray Link: https://lore.kernel.org/r/20250512135500.1405019-4-matthew.brost@intel.com --- drivers/gpu/drm/drm_gpusvm.c | 9 +++++++++ include/drm/drm_gpusvm.h | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index 41f6616bcf76f..4b2f32889f00f 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -1783,6 +1783,8 @@ int drm_gpusvm_migrate_to_devmem(struct drm_gpusvm *gpusvm, goto err_finalize; /* Upon success bind devmem allocation to range and zdd */ + devmem_allocation->timeslice_expiration = get_jiffies_64() + + msecs_to_jiffies(ctx->timeslice_ms); zdd->devmem_allocation = devmem_allocation; /* Owns ref */ err_finalize: @@ -2003,6 +2005,13 @@ static int __drm_gpusvm_migrate_to_ram(struct vm_area_struct *vas, void *buf; int i, err = 0; + if (page) { + zdd = page->zone_device_data; + if (time_before64(get_jiffies_64(), + zdd->devmem_allocation->timeslice_expiration)) + return 0; + } + start = ALIGN_DOWN(fault_addr, size); end = ALIGN(fault_addr + 1, size); diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h index 653d48dbe1c11..eaf704d3d05e8 100644 --- a/include/drm/drm_gpusvm.h +++ b/include/drm/drm_gpusvm.h @@ -89,6 +89,7 @@ struct drm_gpusvm_devmem_ops { * @ops: Pointer to the operations structure for GPU SVM device memory * @dpagemap: The struct drm_pagemap of the pages this allocation belongs to. * @size: Size of device memory allocation + * @timeslice_expiration: Timeslice expiration in jiffies */ struct drm_gpusvm_devmem { struct device *dev; @@ -97,6 +98,7 @@ struct drm_gpusvm_devmem { const struct drm_gpusvm_devmem_ops *ops; struct drm_pagemap *dpagemap; size_t size; + u64 timeslice_expiration; }; /** @@ -295,6 +297,8 @@ struct drm_gpusvm { * @check_pages_threshold: Check CPU pages for present if chunk is less than or * equal to threshold. If not present, reduce chunk * size. + * @timeslice_ms: The timeslice MS which in minimum time a piece of memory + * remains with either exclusive GPU or CPU access. * @in_notifier: entering from a MMU notifier * @read_only: operating on read-only memory * @devmem_possible: possible to use device memory @@ -304,6 +308,7 @@ struct drm_gpusvm { */ struct drm_gpusvm_ctx { unsigned long check_pages_threshold; + unsigned long timeslice_ms; unsigned int in_notifier :1; unsigned int read_only :1; unsigned int devmem_possible :1; -- GitLab From a5d8d3be1dea8154edbbea481081469627665659 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Mon, 12 May 2025 06:54:58 -0700 Subject: [PATCH 0028/1479] drm/xe: Timeslice GPU on atomic SVM fault Ensure GPU can make forward progress on an atomic SVM GPU fault by giving the GPU a timeslice of 5ms v2: - Reduce timeslice to 5ms - Double timeslice on retry - Split out GPU SVM changes into independent patch v5: - Double timeslice in a few more places Fixes: 2f118c949160 ("drm/xe: Add SVM VRAM migration") Cc: stable@vger.kernel.org Signed-off-by: Matthew Brost Reviewed-by: Himal Prasad Ghimiray Link: https://lore.kernel.org/r/20250512135500.1405019-5-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_svm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index d8e15259a8dfc..d934df622276a 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -797,6 +797,8 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ? SZ_64K : 0, .devmem_only = atomic && IS_DGFX(vm->xe) && IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR), + .timeslice_ms = atomic && IS_DGFX(vm->xe) && + IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ? 5 : 0, }; struct xe_svm_range *range; struct drm_gpusvm_range *r; @@ -836,6 +838,7 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, if (--migrate_try_count >= 0 && xe_svm_range_needs_migrate_to_vram(range, vma)) { err = xe_svm_alloc_vram(vm, tile, range, &ctx); + ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ if (err) { if (migrate_try_count || !ctx.devmem_only) { drm_dbg(&vm->xe->drm, @@ -855,6 +858,7 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, err = drm_gpusvm_range_get_pages(&vm->svm.gpusvm, r, &ctx); /* Corner where CPU mappings have changed */ if (err == -EOPNOTSUPP || err == -EFAULT || err == -EPERM) { + ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ if (migrate_try_count > 0 || !ctx.devmem_only) { if (err == -EOPNOTSUPP) { range_debug(range, "PAGE FAULT - EVICT PAGES"); @@ -894,6 +898,7 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, drm_exec_fini(&exec); err = PTR_ERR(fence); if (err == -EAGAIN) { + ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ range_debug(range, "PAGE FAULT - RETRY BIND"); goto retry; } -- GitLab From 1b894c22462f286537b934d4dfcb20e6a9f7f4ee Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Mon, 12 May 2025 06:54:59 -0700 Subject: [PATCH 0029/1479] drm/xe: Add atomic_svm_timeslice_ms debugfs entry Add some informal control for atomic SVM fault GPU timeslice to be able to play around with values and tweak performance. v2: - Reduce timeslice default value to 5ms Signed-off-by: Matthew Brost Reviewed-by: Himal Prasad Ghimiray Link: https://lore.kernel.org/r/20250512135500.1405019-6-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_debugfs.c | 38 ++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_device.c | 1 + drivers/gpu/drm/xe/xe_device_types.h | 3 +++ drivers/gpu/drm/xe/xe_svm.c | 3 ++- 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c index d0503959a8ed0..d83cd6ed3fa8a 100644 --- a/drivers/gpu/drm/xe/xe_debugfs.c +++ b/drivers/gpu/drm/xe/xe_debugfs.c @@ -191,6 +191,41 @@ static const struct file_operations wedged_mode_fops = { .write = wedged_mode_set, }; +static ssize_t atomic_svm_timeslice_ms_show(struct file *f, char __user *ubuf, + size_t size, loff_t *pos) +{ + struct xe_device *xe = file_inode(f)->i_private; + char buf[32]; + int len = 0; + + len = scnprintf(buf, sizeof(buf), "%d\n", xe->atomic_svm_timeslice_ms); + + return simple_read_from_buffer(ubuf, size, pos, buf, len); +} + +static ssize_t atomic_svm_timeslice_ms_set(struct file *f, + const char __user *ubuf, + size_t size, loff_t *pos) +{ + struct xe_device *xe = file_inode(f)->i_private; + u32 atomic_svm_timeslice_ms; + ssize_t ret; + + ret = kstrtouint_from_user(ubuf, size, 0, &atomic_svm_timeslice_ms); + if (ret) + return ret; + + xe->atomic_svm_timeslice_ms = atomic_svm_timeslice_ms; + + return size; +} + +static const struct file_operations atomic_svm_timeslice_ms_fops = { + .owner = THIS_MODULE, + .read = atomic_svm_timeslice_ms_show, + .write = atomic_svm_timeslice_ms_set, +}; + void xe_debugfs_register(struct xe_device *xe) { struct ttm_device *bdev = &xe->ttm; @@ -211,6 +246,9 @@ void xe_debugfs_register(struct xe_device *xe) debugfs_create_file("wedged_mode", 0600, root, xe, &wedged_mode_fops); + debugfs_create_file("atomic_svm_timeslice_ms", 0600, root, xe, + &atomic_svm_timeslice_ms_fops); + for (mem_type = XE_PL_VRAM0; mem_type <= XE_PL_VRAM1; ++mem_type) { man = ttm_manager_type(bdev, mem_type); diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 399ae5f40321a..d4b6e623aa48b 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -442,6 +442,7 @@ struct xe_device *xe_device_create(struct pci_dev *pdev, xe->info.devid = pdev->device; xe->info.revid = pdev->revision; xe->info.force_execlist = xe_modparam.force_execlist; + xe->atomic_svm_timeslice_ms = 5; err = xe_irq_init(xe); if (err) diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 495bc00ebed4c..59babadeb9d17 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -571,6 +571,9 @@ struct xe_device { /** @pmu: performance monitoring unit */ struct xe_pmu pmu; + /** @atomic_svm_timeslice_ms: Atomic SVM fault timeslice MS */ + u32 atomic_svm_timeslice_ms; + #ifdef TEST_VM_OPS_ERROR /** * @vm_inject_error_position: inject errors at different places in VM diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index d934df622276a..ab88b4194e574 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -798,7 +798,8 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, .devmem_only = atomic && IS_DGFX(vm->xe) && IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR), .timeslice_ms = atomic && IS_DGFX(vm->xe) && - IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ? 5 : 0, + IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ? + vm->xe->atomic_svm_timeslice_ms : 0, }; struct xe_svm_range *range; struct drm_gpusvm_range *r; -- GitLab From 38b14233e5deff51db8faec287b4acd227152246 Mon Sep 17 00:00:00 2001 From: Umesh Nerlige Ramappa Date: Fri, 9 May 2025 09:12:01 -0700 Subject: [PATCH 0030/1479] drm/xe: Save CTX_TIMESTAMP mmio value instead of LRC value For determining actual job execution time, save the current value of the CTX_TIMESTAMP register rather than the value saved in LRC since the current register value is the closest to the start time of the job. v2: Define MI_STORE_REGISTER_MEM to fix compile error v3: Place MI_STORE_REGISTER_MEM sorted by MI_INSTR (Lucas) Fixes: 65921374c48f ("drm/xe: Emit ctx timestamp copy in ring ops") Signed-off-by: Umesh Nerlige Ramappa Reviewed-by: Matthew Brost Reviewed-by: Lucas De Marchi Link: https://lore.kernel.org/r/20250509161159.2173069-6-umesh.nerlige.ramappa@intel.com --- drivers/gpu/drm/xe/instructions/xe_mi_commands.h | 4 ++++ drivers/gpu/drm/xe/xe_lrc.c | 2 +- drivers/gpu/drm/xe/xe_ring_ops.c | 7 ++----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/xe/instructions/xe_mi_commands.h b/drivers/gpu/drm/xe/instructions/xe_mi_commands.h index eba582058d550..e3f5e8bb3ebcd 100644 --- a/drivers/gpu/drm/xe/instructions/xe_mi_commands.h +++ b/drivers/gpu/drm/xe/instructions/xe_mi_commands.h @@ -48,6 +48,10 @@ #define MI_LRI_FORCE_POSTED REG_BIT(12) #define MI_LRI_LEN(x) (((x) & 0xff) + 1) +#define MI_STORE_REGISTER_MEM (__MI_INSTR(0x24) | XE_INSTR_NUM_DW(4)) +#define MI_SRM_USE_GGTT REG_BIT(22) +#define MI_SRM_ADD_CS_OFFSET REG_BIT(19) + #define MI_FLUSH_DW __MI_INSTR(0x26) #define MI_FLUSH_DW_PROTECTED_MEM_EN REG_BIT(22) #define MI_FLUSH_DW_STORE_INDEX REG_BIT(21) diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index 855c8acaf3f1e..015b00a73c0b7 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -687,7 +687,7 @@ static inline u32 __xe_lrc_start_seqno_offset(struct xe_lrc *lrc) static u32 __xe_lrc_ctx_job_timestamp_offset(struct xe_lrc *lrc) { - /* The start seqno is stored in the driver-defined portion of PPHWSP */ + /* This is stored in the driver-defined portion of PPHWSP */ return xe_lrc_pphwsp_offset(lrc) + LRC_CTX_JOB_TIMESTAMP_OFFSET; } diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c index a7582b097ae67..bc1689db4cd71 100644 --- a/drivers/gpu/drm/xe/xe_ring_ops.c +++ b/drivers/gpu/drm/xe/xe_ring_ops.c @@ -234,13 +234,10 @@ static u32 get_ppgtt_flag(struct xe_sched_job *job) static int emit_copy_timestamp(struct xe_lrc *lrc, u32 *dw, int i) { - dw[i++] = MI_COPY_MEM_MEM | MI_COPY_MEM_MEM_SRC_GGTT | - MI_COPY_MEM_MEM_DST_GGTT; + dw[i++] = MI_STORE_REGISTER_MEM | MI_SRM_USE_GGTT | MI_SRM_ADD_CS_OFFSET; + dw[i++] = RING_CTX_TIMESTAMP(0).addr; dw[i++] = xe_lrc_ctx_job_timestamp_ggtt_addr(lrc); dw[i++] = 0; - dw[i++] = xe_lrc_ctx_timestamp_ggtt_addr(lrc); - dw[i++] = 0; - dw[i++] = MI_NOOP; return i; } -- GitLab From 741d3ef8b8b88fab2729ca89de1180e49bc9cef0 Mon Sep 17 00:00:00 2001 From: Umesh Nerlige Ramappa Date: Fri, 9 May 2025 09:12:02 -0700 Subject: [PATCH 0031/1479] drm/xe: Save the gt pointer in lrc and drop the tile Save the gt pointer in the lrc so that it can used for gt based helpers. Signed-off-by: Umesh Nerlige Ramappa Reviewed-by: Matthew Brost Reviewed-by: Lucas De Marchi Link: https://lore.kernel.org/r/20250509161159.2173069-7-umesh.nerlige.ramappa@intel.com --- drivers/gpu/drm/xe/xe_lrc.c | 4 ++-- drivers/gpu/drm/xe/xe_lrc_types.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index 015b00a73c0b7..9d9be93832074 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -867,7 +867,7 @@ static void *empty_lrc_data(struct xe_hw_engine *hwe) static void xe_lrc_set_ppgtt(struct xe_lrc *lrc, struct xe_vm *vm) { - u64 desc = xe_vm_pdp4_descriptor(vm, lrc->tile); + u64 desc = xe_vm_pdp4_descriptor(vm, gt_to_tile(lrc->gt)); xe_lrc_write_ctx_reg(lrc, CTX_PDP0_UDW, upper_32_bits(desc)); xe_lrc_write_ctx_reg(lrc, CTX_PDP0_LDW, lower_32_bits(desc)); @@ -900,6 +900,7 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, int err; kref_init(&lrc->refcount); + lrc->gt = gt; lrc->flags = 0; lrc_size = ring_size + xe_gt_lrc_size(gt, hwe->class); if (xe_gt_has_indirect_ring_state(gt)) @@ -921,7 +922,6 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, return PTR_ERR(lrc->bo); lrc->size = lrc_size; - lrc->tile = gt_to_tile(hwe->gt); lrc->ring.size = ring_size; lrc->ring.tail = 0; lrc->ctx_timestamp = 0; diff --git a/drivers/gpu/drm/xe/xe_lrc_types.h b/drivers/gpu/drm/xe/xe_lrc_types.h index 71ecb453f811a..cd38586ae9893 100644 --- a/drivers/gpu/drm/xe/xe_lrc_types.h +++ b/drivers/gpu/drm/xe/xe_lrc_types.h @@ -25,8 +25,8 @@ struct xe_lrc { /** @size: size of lrc including any indirect ring state page */ u32 size; - /** @tile: tile which this LRC belongs to */ - struct xe_tile *tile; + /** @gt: gt which this LRC belongs to */ + struct xe_gt *gt; /** @flags: LRC flags */ #define XE_LRC_FLAG_INDIRECT_RING_STATE 0x1 -- GitLab From 82b98cadb01f63cdb159e596ec06866d00f8e8c7 Mon Sep 17 00:00:00 2001 From: Umesh Nerlige Ramappa Date: Fri, 9 May 2025 09:12:03 -0700 Subject: [PATCH 0032/1479] drm/xe: Add WA BB to capture active context utilization Context Timestamp (CTX_TIMESTAMP) in the LRC accumulates the run ticks of the context, but only gets updated when the context switches out. In order to check how long a context has been active before it switches out, two things are required: (1) Determine if the context is running: To do so, we program the WA BB to set an initial value for CTX_TIMESTAMP in the LRC. The value chosen is 1 since 0 is the initial value when the LRC is initialized. During a query, we just check for this value to determine if the context is active. If the context switched out, it would overwrite this location with the actual CTX_TIMESTAMP MMIO value. Note that WA BB runs as the last part of the context restore, so reusing this LRC location will not clobber anything. (2) Calculate the time that the context has been active for: The CTX_TIMESTAMP ticks only when the context is active. If a context is active, we just use the CTX_TIMESTAMP MMIO as the new value of utilization. While doing so, we need to read the CTX_TIMESTAMP MMIO for the specific engine instance. Since we do not know which instance the context is running on until it is scheduled, we also read the ENGINE_ID MMIO in the WA BB and store it in the PPHSWP. Using the above 2 instructions in a WA BB, capture active context utilization. v2: (Matt Brost) - This breaks TDR, fix it by saving the CTX_TIMESTAMP register "drm/xe: Save CTX_TIMESTAMP mmio value instead of LRC value" - Drop tile from LRC if using gt "drm/xe: Save the gt pointer in LRC and drop the tile" v3: - Remove helpers for bb_per_ctx_ptr (Matt) - Add define for context active value (Matt) - Use 64 bit CTX TIMESTAMP for platforms that support it. For platforms that don't, live with the rare race. (Matt, Lucas) - Convert engine id to hwe and get the MMIO value (Lucas) - Correct commit message on when WA BB runs (Lucas) v4: - s/GRAPHICS_VER(...)/xe->info.has_64bit_timestamp/ (Matt) - Drop support for active utilization on a VF (CI failure) - In xe_lrc_init ensure the lrc value is 0 to begin with (CI regression) v5: - Minor checkpatch fix - Squash into previous commit and make TDR use 32-bit time - Update code comment to match commit msg Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/4532 Suggested-by: Lucas De Marchi Signed-off-by: Umesh Nerlige Ramappa Reviewed-by: Lucas De Marchi Link: https://lore.kernel.org/r/20250509161159.2173069-8-umesh.nerlige.ramappa@intel.com --- drivers/gpu/drm/xe/regs/xe_engine_regs.h | 5 + drivers/gpu/drm/xe/regs/xe_lrc_layout.h | 2 + drivers/gpu/drm/xe/xe_device_types.h | 2 + drivers/gpu/drm/xe/xe_exec_queue.c | 2 +- drivers/gpu/drm/xe/xe_guc_submit.c | 2 +- drivers/gpu/drm/xe/xe_lrc.c | 185 ++++++++++++++++++++++- drivers/gpu/drm/xe/xe_lrc.h | 5 +- drivers/gpu/drm/xe/xe_lrc_types.h | 5 +- drivers/gpu/drm/xe/xe_pci.c | 2 + drivers/gpu/drm/xe/xe_pci_types.h | 1 + drivers/gpu/drm/xe/xe_trace_lrc.h | 8 +- 11 files changed, 203 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/xe/regs/xe_engine_regs.h b/drivers/gpu/drm/xe/regs/xe_engine_regs.h index da713634d6a0c..7ade41e2b7b3b 100644 --- a/drivers/gpu/drm/xe/regs/xe_engine_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_engine_regs.h @@ -43,6 +43,10 @@ #define XEHPC_BCS8_RING_BASE 0x3ee000 #define GSCCS_RING_BASE 0x11a000 +#define ENGINE_ID(base) XE_REG((base) + 0x8c) +#define ENGINE_INSTANCE_ID REG_GENMASK(9, 4) +#define ENGINE_CLASS_ID REG_GENMASK(2, 0) + #define RING_TAIL(base) XE_REG((base) + 0x30) #define TAIL_ADDR REG_GENMASK(20, 3) @@ -154,6 +158,7 @@ #define STOP_RING REG_BIT(8) #define RING_CTX_TIMESTAMP(base) XE_REG((base) + 0x3a8) +#define RING_CTX_TIMESTAMP_UDW(base) XE_REG((base) + 0x3ac) #define CSBE_DEBUG_STATUS(base) XE_REG((base) + 0x3fc) #define RING_FORCE_TO_NONPRIV(base, i) XE_REG(((base) + 0x4d0) + (i) * 4) diff --git a/drivers/gpu/drm/xe/regs/xe_lrc_layout.h b/drivers/gpu/drm/xe/regs/xe_lrc_layout.h index 57944f90bbf6e..994af591a2e85 100644 --- a/drivers/gpu/drm/xe/regs/xe_lrc_layout.h +++ b/drivers/gpu/drm/xe/regs/xe_lrc_layout.h @@ -11,7 +11,9 @@ #define CTX_RING_TAIL (0x06 + 1) #define CTX_RING_START (0x08 + 1) #define CTX_RING_CTL (0x0a + 1) +#define CTX_BB_PER_CTX_PTR (0x12 + 1) #define CTX_TIMESTAMP (0x22 + 1) +#define CTX_TIMESTAMP_UDW (0x24 + 1) #define CTX_INDIRECT_RING_STATE (0x26 + 1) #define CTX_PDP0_UDW (0x30 + 1) #define CTX_PDP0_LDW (0x32 + 1) diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 59babadeb9d17..f81be293b260e 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -334,6 +334,8 @@ struct xe_device { u8 has_sriov:1; /** @info.has_usm: Device has unified shared memory support */ u8 has_usm:1; + /** @info.has_64bit_timestamp: Device supports 64-bit timestamps */ + u8 has_64bit_timestamp:1; /** @info.is_dgfx: is discrete device */ u8 is_dgfx:1; /** @info.needs_scratch: needs scratch page for oob prefetch to work */ diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c index 21d4ced31dd9b..ce78cee5dec68 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.c +++ b/drivers/gpu/drm/xe/xe_exec_queue.c @@ -829,7 +829,7 @@ void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q) { struct xe_device *xe = gt_to_xe(q->gt); struct xe_lrc *lrc; - u32 old_ts, new_ts; + u64 old_ts, new_ts; int idx; /* diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 06e2998b0e214..fb125f940de8f 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -967,7 +967,7 @@ static bool check_timeout(struct xe_exec_queue *q, struct xe_sched_job *job) return xe_sched_invalidate_job(job, 2); } - ctx_timestamp = xe_lrc_ctx_timestamp(q->lrc[0]); + ctx_timestamp = lower_32_bits(xe_lrc_ctx_timestamp(q->lrc[0])); ctx_job_timestamp = xe_lrc_ctx_job_timestamp(q->lrc[0]); /* diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index 9d9be93832074..61a2e87990a9d 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -24,6 +24,7 @@ #include "xe_hw_fence.h" #include "xe_map.h" #include "xe_memirq.h" +#include "xe_mmio.h" #include "xe_sriov.h" #include "xe_trace_lrc.h" #include "xe_vm.h" @@ -654,6 +655,7 @@ u32 xe_lrc_pphwsp_offset(struct xe_lrc *lrc) #define LRC_START_SEQNO_PPHWSP_OFFSET (LRC_SEQNO_PPHWSP_OFFSET + 8) #define LRC_CTX_JOB_TIMESTAMP_OFFSET (LRC_START_SEQNO_PPHWSP_OFFSET + 8) #define LRC_PARALLEL_PPHWSP_OFFSET 2048 +#define LRC_ENGINE_ID_PPHWSP_OFFSET 2096 u32 xe_lrc_regs_offset(struct xe_lrc *lrc) { @@ -697,11 +699,21 @@ static inline u32 __xe_lrc_parallel_offset(struct xe_lrc *lrc) return xe_lrc_pphwsp_offset(lrc) + LRC_PARALLEL_PPHWSP_OFFSET; } +static inline u32 __xe_lrc_engine_id_offset(struct xe_lrc *lrc) +{ + return xe_lrc_pphwsp_offset(lrc) + LRC_ENGINE_ID_PPHWSP_OFFSET; +} + static u32 __xe_lrc_ctx_timestamp_offset(struct xe_lrc *lrc) { return __xe_lrc_regs_offset(lrc) + CTX_TIMESTAMP * sizeof(u32); } +static u32 __xe_lrc_ctx_timestamp_udw_offset(struct xe_lrc *lrc) +{ + return __xe_lrc_regs_offset(lrc) + CTX_TIMESTAMP_UDW * sizeof(u32); +} + static inline u32 __xe_lrc_indirect_ring_offset(struct xe_lrc *lrc) { /* Indirect ring state page is at the very end of LRC */ @@ -729,8 +741,10 @@ DECL_MAP_ADDR_HELPERS(regs) DECL_MAP_ADDR_HELPERS(start_seqno) DECL_MAP_ADDR_HELPERS(ctx_job_timestamp) DECL_MAP_ADDR_HELPERS(ctx_timestamp) +DECL_MAP_ADDR_HELPERS(ctx_timestamp_udw) DECL_MAP_ADDR_HELPERS(parallel) DECL_MAP_ADDR_HELPERS(indirect_ring) +DECL_MAP_ADDR_HELPERS(engine_id) #undef DECL_MAP_ADDR_HELPERS @@ -745,19 +759,38 @@ u32 xe_lrc_ctx_timestamp_ggtt_addr(struct xe_lrc *lrc) return __xe_lrc_ctx_timestamp_ggtt_addr(lrc); } +/** + * xe_lrc_ctx_timestamp_udw_ggtt_addr() - Get ctx timestamp udw GGTT address + * @lrc: Pointer to the lrc. + * + * Returns: ctx timestamp udw GGTT address + */ +u32 xe_lrc_ctx_timestamp_udw_ggtt_addr(struct xe_lrc *lrc) +{ + return __xe_lrc_ctx_timestamp_udw_ggtt_addr(lrc); +} + /** * xe_lrc_ctx_timestamp() - Read ctx timestamp value * @lrc: Pointer to the lrc. * * Returns: ctx timestamp value */ -u32 xe_lrc_ctx_timestamp(struct xe_lrc *lrc) +u64 xe_lrc_ctx_timestamp(struct xe_lrc *lrc) { struct xe_device *xe = lrc_to_xe(lrc); struct iosys_map map; + u32 ldw, udw = 0; map = __xe_lrc_ctx_timestamp_map(lrc); - return xe_map_read32(xe, &map); + ldw = xe_map_read32(xe, &map); + + if (xe->info.has_64bit_timestamp) { + map = __xe_lrc_ctx_timestamp_udw_map(lrc); + udw = xe_map_read32(xe, &map); + } + + return (u64)udw << 32 | ldw; } /** @@ -880,6 +913,65 @@ static void xe_lrc_finish(struct xe_lrc *lrc) xe_bo_unpin(lrc->bo); xe_bo_unlock(lrc->bo); xe_bo_put(lrc->bo); + xe_bo_unpin_map_no_vm(lrc->bb_per_ctx_bo); +} + +/* + * xe_lrc_setup_utilization() - Setup wa bb to assist in calculating active + * context run ticks. + * @lrc: Pointer to the lrc. + * + * Context Timestamp (CTX_TIMESTAMP) in the LRC accumulates the run ticks of the + * context, but only gets updated when the context switches out. In order to + * check how long a context has been active before it switches out, two things + * are required: + * + * (1) Determine if the context is running: + * To do so, we program the WA BB to set an initial value for CTX_TIMESTAMP in + * the LRC. The value chosen is 1 since 0 is the initial value when the LRC is + * initialized. During a query, we just check for this value to determine if the + * context is active. If the context switched out, it would overwrite this + * location with the actual CTX_TIMESTAMP MMIO value. Note that WA BB runs as + * the last part of context restore, so reusing this LRC location will not + * clobber anything. + * + * (2) Calculate the time that the context has been active for: + * The CTX_TIMESTAMP ticks only when the context is active. If a context is + * active, we just use the CTX_TIMESTAMP MMIO as the new value of utilization. + * While doing so, we need to read the CTX_TIMESTAMP MMIO for the specific + * engine instance. Since we do not know which instance the context is running + * on until it is scheduled, we also read the ENGINE_ID MMIO in the WA BB and + * store it in the PPHSWP. + */ +#define CONTEXT_ACTIVE 1ULL +static void xe_lrc_setup_utilization(struct xe_lrc *lrc) +{ + u32 *cmd; + + cmd = lrc->bb_per_ctx_bo->vmap.vaddr; + + *cmd++ = MI_STORE_REGISTER_MEM | MI_SRM_USE_GGTT | MI_SRM_ADD_CS_OFFSET; + *cmd++ = ENGINE_ID(0).addr; + *cmd++ = __xe_lrc_engine_id_ggtt_addr(lrc); + *cmd++ = 0; + + *cmd++ = MI_STORE_DATA_IMM | MI_SDI_GGTT | MI_SDI_NUM_DW(1); + *cmd++ = __xe_lrc_ctx_timestamp_ggtt_addr(lrc); + *cmd++ = 0; + *cmd++ = lower_32_bits(CONTEXT_ACTIVE); + + if (lrc_to_xe(lrc)->info.has_64bit_timestamp) { + *cmd++ = MI_STORE_DATA_IMM | MI_SDI_GGTT | MI_SDI_NUM_DW(1); + *cmd++ = __xe_lrc_ctx_timestamp_udw_ggtt_addr(lrc); + *cmd++ = 0; + *cmd++ = upper_32_bits(CONTEXT_ACTIVE); + } + + *cmd++ = MI_BATCH_BUFFER_END; + + xe_lrc_write_ctx_reg(lrc, CTX_BB_PER_CTX_PTR, + xe_bo_ggtt_addr(lrc->bb_per_ctx_bo) | 1); + } #define PVC_CTX_ASID (0x2e + 1) @@ -921,10 +1013,17 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, if (IS_ERR(lrc->bo)) return PTR_ERR(lrc->bo); + lrc->bb_per_ctx_bo = xe_bo_create_pin_map(xe, tile, NULL, SZ_4K, + ttm_bo_type_kernel, + bo_flags); + if (IS_ERR(lrc->bb_per_ctx_bo)) { + err = PTR_ERR(lrc->bb_per_ctx_bo); + goto err_lrc_finish; + } + lrc->size = lrc_size; lrc->ring.size = ring_size; lrc->ring.tail = 0; - lrc->ctx_timestamp = 0; xe_hw_fence_ctx_init(&lrc->fence_ctx, hwe->gt, hwe->fence_irq, hwe->name); @@ -997,7 +1096,10 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, xe_lrc_read_ctx_reg(lrc, CTX_CONTEXT_CONTROL) | _MASKED_BIT_ENABLE(CTX_CTRL_PXP_ENABLE)); + lrc->ctx_timestamp = 0; xe_lrc_write_ctx_reg(lrc, CTX_TIMESTAMP, 0); + if (lrc_to_xe(lrc)->info.has_64bit_timestamp) + xe_lrc_write_ctx_reg(lrc, CTX_TIMESTAMP_UDW, 0); if (xe->info.has_asid && vm) xe_lrc_write_ctx_reg(lrc, PVC_CTX_ASID, vm->usm.asid); @@ -1026,6 +1128,8 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, map = __xe_lrc_start_seqno_map(lrc); xe_map_write32(lrc_to_xe(lrc), &map, lrc->fence_ctx.next_seqno - 1); + xe_lrc_setup_utilization(lrc); + return 0; err_lrc_finish: @@ -1245,6 +1349,21 @@ struct iosys_map xe_lrc_parallel_map(struct xe_lrc *lrc) return __xe_lrc_parallel_map(lrc); } +/** + * xe_lrc_engine_id() - Read engine id value + * @lrc: Pointer to the lrc. + * + * Returns: context id value + */ +static u32 xe_lrc_engine_id(struct xe_lrc *lrc) +{ + struct xe_device *xe = lrc_to_xe(lrc); + struct iosys_map map; + + map = __xe_lrc_engine_id_map(lrc); + return xe_map_read32(xe, &map); +} + static int instr_dw(u32 cmd_header) { /* GFXPIPE "SINGLE_DW" opcodes are a single dword */ @@ -1692,7 +1811,7 @@ struct xe_lrc_snapshot *xe_lrc_snapshot_capture(struct xe_lrc *lrc) snapshot->lrc_offset = xe_lrc_pphwsp_offset(lrc); snapshot->lrc_size = lrc->bo->size - snapshot->lrc_offset; snapshot->lrc_snapshot = NULL; - snapshot->ctx_timestamp = xe_lrc_ctx_timestamp(lrc); + snapshot->ctx_timestamp = lower_32_bits(xe_lrc_ctx_timestamp(lrc)); snapshot->ctx_job_timestamp = xe_lrc_ctx_job_timestamp(lrc); return snapshot; } @@ -1792,22 +1911,74 @@ void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot) kfree(snapshot); } +static int get_ctx_timestamp(struct xe_lrc *lrc, u32 engine_id, u64 *reg_ctx_ts) +{ + u16 class = REG_FIELD_GET(ENGINE_CLASS_ID, engine_id); + u16 instance = REG_FIELD_GET(ENGINE_INSTANCE_ID, engine_id); + struct xe_hw_engine *hwe; + u64 val; + + hwe = xe_gt_hw_engine(lrc->gt, class, instance, false); + if (xe_gt_WARN_ONCE(lrc->gt, !hwe || xe_hw_engine_is_reserved(hwe), + "Unexpected engine class:instance %d:%d for context utilization\n", + class, instance)) + return -1; + + if (lrc_to_xe(lrc)->info.has_64bit_timestamp) + val = xe_mmio_read64_2x32(&hwe->gt->mmio, + RING_CTX_TIMESTAMP(hwe->mmio_base)); + else + val = xe_mmio_read32(&hwe->gt->mmio, + RING_CTX_TIMESTAMP(hwe->mmio_base)); + + *reg_ctx_ts = val; + + return 0; +} + /** * xe_lrc_update_timestamp() - Update ctx timestamp * @lrc: Pointer to the lrc. * @old_ts: Old timestamp value * * Populate @old_ts current saved ctx timestamp, read new ctx timestamp and - * update saved value. + * update saved value. With support for active contexts, the calculation may be + * slightly racy, so follow a read-again logic to ensure that the context is + * still active before returning the right timestamp. * * Returns: New ctx timestamp value */ -u32 xe_lrc_update_timestamp(struct xe_lrc *lrc, u32 *old_ts) +u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts) { + u64 lrc_ts, reg_ts; + u32 engine_id; + *old_ts = lrc->ctx_timestamp; - lrc->ctx_timestamp = xe_lrc_ctx_timestamp(lrc); + lrc_ts = xe_lrc_ctx_timestamp(lrc); + /* CTX_TIMESTAMP mmio read is invalid on VF, so return the LRC value */ + if (IS_SRIOV_VF(lrc_to_xe(lrc))) { + lrc->ctx_timestamp = lrc_ts; + goto done; + } + + if (lrc_ts == CONTEXT_ACTIVE) { + engine_id = xe_lrc_engine_id(lrc); + if (!get_ctx_timestamp(lrc, engine_id, ®_ts)) + lrc->ctx_timestamp = reg_ts; + + /* read lrc again to ensure context is still active */ + lrc_ts = xe_lrc_ctx_timestamp(lrc); + } + + /* + * If context switched out, just use the lrc_ts. Note that this needs to + * be a separate if condition. + */ + if (lrc_ts != CONTEXT_ACTIVE) + lrc->ctx_timestamp = lrc_ts; +done: trace_xe_lrc_update_timestamp(lrc, *old_ts); return lrc->ctx_timestamp; diff --git a/drivers/gpu/drm/xe/xe_lrc.h b/drivers/gpu/drm/xe/xe_lrc.h index 0b40f349ab95d..eb6e8de8c939e 100644 --- a/drivers/gpu/drm/xe/xe_lrc.h +++ b/drivers/gpu/drm/xe/xe_lrc.h @@ -120,7 +120,8 @@ void xe_lrc_snapshot_print(struct xe_lrc_snapshot *snapshot, struct drm_printer void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot); u32 xe_lrc_ctx_timestamp_ggtt_addr(struct xe_lrc *lrc); -u32 xe_lrc_ctx_timestamp(struct xe_lrc *lrc); +u32 xe_lrc_ctx_timestamp_udw_ggtt_addr(struct xe_lrc *lrc); +u64 xe_lrc_ctx_timestamp(struct xe_lrc *lrc); u32 xe_lrc_ctx_job_timestamp_ggtt_addr(struct xe_lrc *lrc); u32 xe_lrc_ctx_job_timestamp(struct xe_lrc *lrc); @@ -136,6 +137,6 @@ u32 xe_lrc_ctx_job_timestamp(struct xe_lrc *lrc); * * Returns the current LRC timestamp */ -u32 xe_lrc_update_timestamp(struct xe_lrc *lrc, u32 *old_ts); +u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts); #endif diff --git a/drivers/gpu/drm/xe/xe_lrc_types.h b/drivers/gpu/drm/xe/xe_lrc_types.h index cd38586ae9893..ae24cf6f8dd99 100644 --- a/drivers/gpu/drm/xe/xe_lrc_types.h +++ b/drivers/gpu/drm/xe/xe_lrc_types.h @@ -52,7 +52,10 @@ struct xe_lrc { struct xe_hw_fence_ctx fence_ctx; /** @ctx_timestamp: readout value of CTX_TIMESTAMP on last update */ - u32 ctx_timestamp; + u64 ctx_timestamp; + + /** @bb_per_ctx_bo: buffer object for per context batch wa buffer */ + struct xe_bo *bb_per_ctx_bo; }; struct xe_lrc_snapshot; diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index 882398e09b7e3..024175cfe61e6 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -142,6 +142,7 @@ static const struct xe_graphics_desc graphics_xelpg = { .has_indirect_ring_state = 1, \ .has_range_tlb_invalidation = 1, \ .has_usm = 1, \ + .has_64bit_timestamp = 1, \ .va_bits = 48, \ .vm_max_level = 4, \ .hw_engine_mask = \ @@ -677,6 +678,7 @@ static int xe_info_init(struct xe_device *xe, xe->info.has_range_tlb_invalidation = graphics_desc->has_range_tlb_invalidation; xe->info.has_usm = graphics_desc->has_usm; + xe->info.has_64bit_timestamp = graphics_desc->has_64bit_timestamp; for_each_remote_tile(tile, xe, id) { int err; diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h index e9b9bbc138d37..ca6b10d355734 100644 --- a/drivers/gpu/drm/xe/xe_pci_types.h +++ b/drivers/gpu/drm/xe/xe_pci_types.h @@ -21,6 +21,7 @@ struct xe_graphics_desc { u8 has_indirect_ring_state:1; u8 has_range_tlb_invalidation:1; u8 has_usm:1; + u8 has_64bit_timestamp:1; }; struct xe_media_desc { diff --git a/drivers/gpu/drm/xe/xe_trace_lrc.h b/drivers/gpu/drm/xe/xe_trace_lrc.h index 5c669a0b21808..d525cbee1e341 100644 --- a/drivers/gpu/drm/xe/xe_trace_lrc.h +++ b/drivers/gpu/drm/xe/xe_trace_lrc.h @@ -19,12 +19,12 @@ #define __dev_name_lrc(lrc) dev_name(gt_to_xe((lrc)->fence_ctx.gt)->drm.dev) TRACE_EVENT(xe_lrc_update_timestamp, - TP_PROTO(struct xe_lrc *lrc, uint32_t old), + TP_PROTO(struct xe_lrc *lrc, uint64_t old), TP_ARGS(lrc, old), TP_STRUCT__entry( __field(struct xe_lrc *, lrc) - __field(u32, old) - __field(u32, new) + __field(u64, old) + __field(u64, new) __string(name, lrc->fence_ctx.name) __string(device_id, __dev_name_lrc(lrc)) ), @@ -36,7 +36,7 @@ TRACE_EVENT(xe_lrc_update_timestamp, __assign_str(name); __assign_str(device_id); ), - TP_printk("lrc=:%p lrc->name=%s old=%u new=%u device_id:%s", + TP_printk("lrc=:%p lrc->name=%s old=%llu new=%llu device_id:%s", __entry->lrc, __get_str(name), __entry->old, __entry->new, __get_str(device_id)) -- GitLab From 6819b5a67e7014352906f82ddedafb602ac8d45d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 May 2025 17:56:52 +0300 Subject: [PATCH 0033/1479] drm/i915: rename vlv_sideband*.[ch] to vlv_iosf_sb*.[ch] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Be more specific in the naming, and follow the existing function naming pattern of vlv_iosf_sb_*() in the file. Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/d3d97d34a197ba801c558c3fd72b29f9e5c783af.1747061743.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 2 +- drivers/gpu/drm/i915/display/i9xx_wm.c | 2 +- drivers/gpu/drm/i915/display/intel_cdclk.c | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/display/intel_display_power.c | 2 +- drivers/gpu/drm/i915/display/intel_display_power_map.c | 2 +- drivers/gpu/drm/i915/display/intel_display_power_well.c | 4 ++-- drivers/gpu/drm/i915/display/intel_dpio_phy.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll.c | 2 +- drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 2 +- drivers/gpu/drm/i915/display/vlv_dsi.c | 2 +- drivers/gpu/drm/i915/display/vlv_dsi_pll.c | 2 +- drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c | 2 +- drivers/gpu/drm/i915/gt/intel_rps.c | 2 +- drivers/gpu/drm/i915/i915_driver.c | 2 +- drivers/gpu/drm/i915/intel_clock_gating.c | 2 +- drivers/gpu/drm/i915/soc/intel_dram.c | 2 +- drivers/gpu/drm/i915/{vlv_sideband.c => vlv_iosf_sb.c} | 2 +- drivers/gpu/drm/i915/{vlv_sideband.h => vlv_iosf_sb.h} | 8 ++++---- .../drm/i915/{vlv_sideband_reg.h => vlv_iosf_sb_reg.h} | 6 +++--- .../compat-i915-headers/{vlv_sideband.h => vlv_iosf_sb.h} | 8 ++++---- .../{vlv_sideband_reg.h => vlv_iosf_sb_reg.h} | 2 +- 22 files changed, 31 insertions(+), 31 deletions(-) rename drivers/gpu/drm/i915/{vlv_sideband.c => vlv_iosf_sb.c} (99%) rename drivers/gpu/drm/i915/{vlv_sideband.h => vlv_iosf_sb.h} (96%) rename drivers/gpu/drm/i915/{vlv_sideband_reg.h => vlv_iosf_sb_reg.h} (98%) rename drivers/gpu/drm/xe/compat-i915-headers/{vlv_sideband.h => vlv_iosf_sb.h} (96%) rename drivers/gpu/drm/xe/compat-i915-headers/{vlv_sideband_reg.h => vlv_iosf_sb_reg.h} (66%) diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 13d4a16f7d33a..3e3e4f4bfa4e2 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -45,7 +45,7 @@ i915-y += \ intel_uncore.o \ intel_uncore_trace.o \ intel_wakeref.o \ - vlv_sideband.o \ + vlv_iosf_sb.o \ vlv_suspend.o # core peripheral code diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 77876ef735b74..02f33cbe6765c 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -16,7 +16,7 @@ #include "intel_mchbar_regs.h" #include "intel_wm.h" #include "skl_watermark.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" struct intel_watermark_params { u16 fifo_size; diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index b1718b491ffda..501b794984149 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -47,7 +47,7 @@ #include "skl_watermark.h" #include "skl_watermark_regs.h" #include "vlv_dsi.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" /** * DOC: CDCLK / RAWCLK diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 704ca079980c2..c7a6b710b7c0a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -131,7 +131,7 @@ #include "vlv_dsi.h" #include "vlv_dsi_pll.h" #include "vlv_dsi_regs.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state); static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 16356523816fb..b3b05d7610e8a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -27,7 +27,7 @@ #include "intel_snps_phy.h" #include "skl_watermark.h" #include "skl_watermark_regs.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" #define for_each_power_domain_well(__display, __power_well, __domain) \ for_each_power_well((__display), __power_well) \ diff --git a/drivers/gpu/drm/i915/display/intel_display_power_map.c b/drivers/gpu/drm/i915/display/intel_display_power_map.c index ab1163744bc59..b4c302544909d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_map.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_map.c @@ -10,7 +10,7 @@ #include "intel_display_power_map.h" #include "intel_display_power_well.h" #include "intel_display_types.h" -#include "vlv_sideband_reg.h" +#include "vlv_iosf_sb_reg.h" #define __LIST_INLINE_ELEMS(__elem_type, ...) \ ((__elem_type[]) { __VA_ARGS__ }) diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index b104bce0e14df..6772ac0c3f84c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -30,8 +30,8 @@ #include "intel_vga.h" #include "skl_watermark.h" #include "vlv_dpio_phy_regs.h" -#include "vlv_sideband.h" -#include "vlv_sideband_reg.h" +#include "vlv_iosf_sb.h" +#include "vlv_iosf_sb_reg.h" struct i915_power_well_regs { i915_reg_t bios; diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 69f2421394205..5b9c0852da2cf 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -32,7 +32,7 @@ #include "intel_dp.h" #include "intel_dpio_phy.h" #include "vlv_dpio_phy_regs.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" /** * DOC: DPIO diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index a9e9b98d0bf9c..055dd2b4a9043 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -22,7 +22,7 @@ #include "intel_pps.h" #include "intel_snps_phy.h" #include "vlv_dpio_phy_regs.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" struct intel_dpll_funcs { int (*crtc_compute_clock)(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c index 29c9209834138..dce4fdf091f67 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c @@ -49,7 +49,7 @@ #include "intel_pps_regs.h" #include "vlv_dsi.h" #include "vlv_dsi_regs.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" #define MIPI_TRANSFER_MODE_SHIFT 0 #define MIPI_VIRTUAL_CHANNEL_SHIFT 1 diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 346737f15fa93..110914bbc1348 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -49,7 +49,7 @@ #include "vlv_dsi.h" #include "vlv_dsi_pll.h" #include "vlv_dsi_regs.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" /* return pixels in terms of txbyteclkhs */ static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count, diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c index 7ce924a5ef90b..79438cdfc3f9d 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c @@ -34,7 +34,7 @@ #include "intel_dsi.h" #include "vlv_dsi_pll.h" #include "vlv_dsi_pll_regs.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" static const u16 lfsr_converts[] = { 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 62 - 70 */ diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c index b635aa2820d9f..0704fe763afed 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c @@ -22,7 +22,7 @@ #include "intel_rps.h" #include "intel_runtime_pm.h" #include "intel_uncore.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" void intel_gt_pm_debugfs_forcewake_user_open(struct intel_gt *gt) { diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 461708f1ac543..7fa341d2bfe4f 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -23,7 +23,7 @@ #include "intel_mchbar_regs.h" #include "intel_pcode.h" #include "intel_rps.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" #include "../../../platform/x86/intel_ips.h" #define BUSY_MAX_EI 20u /* ms */ diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 273bc43468a0f..2b0bcb9aa3c72 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -108,7 +108,7 @@ #include "intel_pcode.h" #include "intel_region_ttm.h" #include "intel_sbi.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" #include "vlv_suspend.h" static const struct drm_driver i915_drm_driver; diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index 387b264001690..8aec8c638fd81 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -37,7 +37,7 @@ #include "i915_reg.h" #include "intel_clock_gating.h" #include "intel_mchbar_regs.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" struct drm_i915_clock_gating_funcs { void (*init_clock_gating)(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index eee5c4f45a43c..0b92ab4e9fb9b 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -10,7 +10,7 @@ #include "intel_dram.h" #include "intel_mchbar_regs.h" #include "intel_pcode.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" struct dram_dimm_info { u16 size; diff --git a/drivers/gpu/drm/i915/vlv_sideband.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c similarity index 99% rename from drivers/gpu/drm/i915/vlv_sideband.c rename to drivers/gpu/drm/i915/vlv_iosf_sb.c index 114ae8eb9cd51..91703c6c478c5 100644 --- a/drivers/gpu/drm/i915/vlv_sideband.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -6,7 +6,7 @@ #include "i915_drv.h" #include "i915_iosf_mbi.h" #include "i915_reg.h" -#include "vlv_sideband.h" +#include "vlv_iosf_sb.h" #include "display/intel_dpio_phy.h" diff --git a/drivers/gpu/drm/i915/vlv_sideband.h b/drivers/gpu/drm/i915/vlv_iosf_sb.h similarity index 96% rename from drivers/gpu/drm/i915/vlv_sideband.h rename to drivers/gpu/drm/i915/vlv_iosf_sb.h index 31813e07c56fb..380b96089cda8 100644 --- a/drivers/gpu/drm/i915/vlv_sideband.h +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.h @@ -3,13 +3,13 @@ * Copyright © 2013-2021 Intel Corporation */ -#ifndef _VLV_SIDEBAND_H_ -#define _VLV_SIDEBAND_H_ +#ifndef _VLV_IOSF_SB_H_ +#define _VLV_IOSF_SB_H_ #include #include -#include "vlv_sideband_reg.h" +#include "vlv_iosf_sb_reg.h" enum dpio_phy; struct drm_i915_private; @@ -122,4 +122,4 @@ static inline void vlv_punit_put(struct drm_i915_private *i915) vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); } -#endif /* _VLV_SIDEBAND_H_ */ +#endif /* _VLV_IOSF_SB_H_ */ diff --git a/drivers/gpu/drm/i915/vlv_sideband_reg.h b/drivers/gpu/drm/i915/vlv_iosf_sb_reg.h similarity index 98% rename from drivers/gpu/drm/i915/vlv_sideband_reg.h rename to drivers/gpu/drm/i915/vlv_iosf_sb_reg.h index b7fbff3d04099..f977fb3b6e173 100644 --- a/drivers/gpu/drm/i915/vlv_sideband_reg.h +++ b/drivers/gpu/drm/i915/vlv_iosf_sb_reg.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _VLV_SIDEBAND_REG_H_ -#define _VLV_SIDEBAND_REG_H_ +#ifndef _VLV_IOSF_SB_REG_H_ +#define _VLV_IOSF_SB_REG_H_ /* See configdb bunit SB addr map */ #define BUNIT_REG_BISOC 0x11 @@ -177,4 +177,4 @@ #define CCK_FREQUENCY_STATUS_SHIFT 8 #define CCK_FREQUENCY_VALUES (0x1f << 0) -#endif /* _VLV_SIDEBAND_REG_H_ */ +#endif /* _VLV_IOSF_SB_REG_H_ */ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/vlv_sideband.h b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h similarity index 96% rename from drivers/gpu/drm/xe/compat-i915-headers/vlv_sideband.h rename to drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h index ec6f12de57274..b42a518a79e0a 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/vlv_sideband.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h @@ -3,12 +3,12 @@ * Copyright © 2013-2021 Intel Corporation */ -#ifndef _VLV_SIDEBAND_H_ -#define _VLV_SIDEBAND_H_ +#ifndef _VLV_IOSF_SB_H_ +#define _VLV_IOSF_SB_H_ #include -#include "vlv_sideband_reg.h" +#include "vlv_iosf_sb_reg.h" enum pipe; struct drm_i915_private; @@ -129,4 +129,4 @@ static inline void vlv_punit_put(struct drm_i915_private *i915) { } -#endif /* _VLV_SIDEBAND_H_ */ +#endif /* _VLV_IOSF_SB_H_ */ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/vlv_sideband_reg.h b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb_reg.h similarity index 66% rename from drivers/gpu/drm/xe/compat-i915-headers/vlv_sideband_reg.h rename to drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb_reg.h index 949f134ce3cf3..cb7fa8e794a60 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/vlv_sideband_reg.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb_reg.h @@ -3,4 +3,4 @@ * Copyright © 2023 Intel Corporation */ -#include "../../i915/vlv_sideband_reg.h" +#include "../../i915/vlv_iosf_sb_reg.h" -- GitLab From 7e9f0cc24bb6a2121a6abaef401d429f94ea2e8b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 May 2025 17:56:53 +0300 Subject: [PATCH 0034/1479] drm/i915: add generic read/write functions for VLV IOSF SB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The read/write functions will be helpful for rewriting the unit specific functions. v2: Fix checkpatch complaint on indent Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/babe42609c7a2056aff301320efbda534d20ad82.1747061743.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/vlv_iosf_sb.c | 73 +++++++++++++++++++ drivers/gpu/drm/i915/vlv_iosf_sb.h | 6 +- .../drm/xe/compat-i915-headers/vlv_iosf_sb.h | 9 ++- 3 files changed, 83 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c index 91703c6c478c5..aaed876a1f2e7 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -123,6 +123,79 @@ static int vlv_sideband_rw(struct drm_i915_private *i915, return err; } +static u32 unit_to_devfn(enum vlv_iosf_sb_unit unit) +{ + if (unit == VLV_IOSF_SB_DPIO || unit == VLV_IOSF_SB_DPIO_2 || + unit == VLV_IOSF_SB_FLISDSI) + return DPIO_DEVFN; + else + return PCI_DEVFN(0, 0); +} + +static u32 unit_to_port(enum vlv_iosf_sb_unit unit) +{ + switch (unit) { + case VLV_IOSF_SB_BUNIT: + return IOSF_PORT_BUNIT; + case VLV_IOSF_SB_CCK: + return IOSF_PORT_CCK; + case VLV_IOSF_SB_CCU: + return IOSF_PORT_CCU; + case VLV_IOSF_SB_DPIO: + return IOSF_PORT_DPIO; + case VLV_IOSF_SB_DPIO_2: + return IOSF_PORT_DPIO_2; + case VLV_IOSF_SB_FLISDSI: + return IOSF_PORT_FLISDSI; + case VLV_IOSF_SB_GPIO: + return 0; /* FIXME: unused */ + case VLV_IOSF_SB_NC: + return IOSF_PORT_NC; + case VLV_IOSF_SB_PUNIT: + return IOSF_PORT_PUNIT; + default: + return 0; + } +} + +static u32 unit_to_opcode(enum vlv_iosf_sb_unit unit, bool write) +{ + if (unit == VLV_IOSF_SB_DPIO || unit == VLV_IOSF_SB_DPIO_2) + return write ? SB_MWR_NP : SB_MRD_NP; + else + return write ? SB_CRWRDA_NP : SB_CRRDDA_NP; +} + +u32 vlv_iosf_sb_read(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr) +{ + u32 devfn, port, opcode, val = 0; + + devfn = unit_to_devfn(unit); + port = unit_to_port(unit); + opcode = unit_to_opcode(unit, false); + + if (drm_WARN_ONCE(&i915->drm, !port, "invalid unit %d\n", unit)) + return 0; + + vlv_sideband_rw(i915, devfn, port, opcode, addr, &val); + + return val; +} + +int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr, u32 val) +{ + u32 devfn, port, opcode; + + devfn = unit_to_devfn(unit); + port = unit_to_port(unit); + opcode = unit_to_opcode(unit, true); + + if (drm_WARN_ONCE(&i915->drm, !port, "invalid unit %d\n", unit)) + return -EINVAL; + + return vlv_sideband_rw(i915, devfn, port, opcode, addr, &val); +} + u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr) { u32 val = 0; diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.h b/drivers/gpu/drm/i915/vlv_iosf_sb.h index 380b96089cda8..26af3aa973f8b 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.h +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.h @@ -14,11 +14,12 @@ enum dpio_phy; struct drm_i915_private; -enum { +enum vlv_iosf_sb_unit { VLV_IOSF_SB_BUNIT, VLV_IOSF_SB_CCK, VLV_IOSF_SB_CCU, VLV_IOSF_SB_DPIO, + VLV_IOSF_SB_DPIO_2, VLV_IOSF_SB_FLISDSI, VLV_IOSF_SB_GPIO, VLV_IOSF_SB_NC, @@ -31,6 +32,9 @@ void vlv_iosf_sb_fini(struct drm_i915_private *i915); void vlv_iosf_sb_get(struct drm_i915_private *i915, unsigned long ports); void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports); +u32 vlv_iosf_sb_read(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr); +int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr, u32 val); + static inline void vlv_bunit_get(struct drm_i915_private *i915) { vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_BUNIT)); diff --git a/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h index b42a518a79e0a..57f7dde90ced8 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h @@ -13,11 +13,12 @@ enum pipe; struct drm_i915_private; -enum { +enum vlv_iosf_sb_unit { VLV_IOSF_SB_BUNIT, VLV_IOSF_SB_CCK, VLV_IOSF_SB_CCU, VLV_IOSF_SB_DPIO, + VLV_IOSF_SB_DPIO_2, VLV_IOSF_SB_FLISDSI, VLV_IOSF_SB_GPIO, VLV_IOSF_SB_NC, @@ -27,13 +28,13 @@ enum { static inline void vlv_iosf_sb_get(struct drm_i915_private *i915, unsigned long ports) { } -static inline u32 vlv_iosf_sb_read(struct drm_i915_private *i915, u8 port, u32 reg) +static inline u32 vlv_iosf_sb_read(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr) { return 0; } -static inline void vlv_iosf_sb_write(struct drm_i915_private *i915, - u8 port, u32 reg, u32 val) +static inline int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr, u32 val) { + return 0; } static inline void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports) { -- GitLab From 5c76b7178b511019c0c5f5544d9bfc4b9589f0d4 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 May 2025 17:56:54 +0300 Subject: [PATCH 0035/1479] drm/i915: rewrite VLV IOSF SB unit specific read/write functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite the VLV IOSF SB unit specific helpers in terms of the new generic read/write functions. They become even simpler than they were. The DPIO get/put helpers need to get/put both DPIO units. v2: get/put both DPIO units Reviewed-by: Ville Syrjälä # v1 Link: https://lore.kernel.org/r/df97dafa0f7b665e2078c392f0dc3edc59655b0a.1747061743.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/vlv_iosf_sb.c | 73 ++++++++---------------------- drivers/gpu/drm/i915/vlv_iosf_sb.h | 4 +- 2 files changed, 22 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c index aaed876a1f2e7..efb5ee39dbbb2 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -198,96 +198,68 @@ int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr) { - u32 val = 0; - - vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT, - SB_CRRDDA_NP, addr, &val); - - return val; + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, addr); } int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val) { - return vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT, - SB_CRWRDA_NP, addr, &val); + return vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, addr, val); } u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg) { - u32 val = 0; - - vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_BUNIT, - SB_CRRDDA_NP, reg, &val); - - return val; + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_BUNIT, reg); } void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val) { - vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_BUNIT, - SB_CRWRDA_NP, reg, &val); + vlv_iosf_sb_write(i915, VLV_IOSF_SB_BUNIT, reg, val); } u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr) { - u32 val = 0; - - vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_NC, - SB_CRRDDA_NP, addr, &val); - - return val; + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, addr); } u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg) { - u32 val = 0; - - vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCK, - SB_CRRDDA_NP, reg, &val); - - return val; + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCK, reg); } void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val) { - vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCK, - SB_CRWRDA_NP, reg, &val); + vlv_iosf_sb_write(i915, VLV_IOSF_SB_CCK, reg, val); } u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg) { - u32 val = 0; - - vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCU, - SB_CRRDDA_NP, reg, &val); - - return val; + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCU, reg); } void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val) { - vlv_sideband_rw(i915, PCI_DEVFN(0, 0), IOSF_PORT_CCU, - SB_CRWRDA_NP, reg, &val); + vlv_iosf_sb_write(i915, VLV_IOSF_SB_CCU, reg, val); } -static u32 vlv_dpio_phy_iosf_port(struct drm_i915_private *i915, enum dpio_phy phy) +static enum vlv_iosf_sb_unit vlv_dpio_phy_to_unit(struct drm_i915_private *i915, + enum dpio_phy phy) { /* * IOSF_PORT_DPIO: VLV x2 PHY (DP/HDMI B and C), CHV x1 PHY (DP/HDMI D) * IOSF_PORT_DPIO_2: CHV x2 PHY (DP/HDMI B and C) */ if (IS_CHERRYVIEW(i915)) - return phy == DPIO_PHY0 ? IOSF_PORT_DPIO_2 : IOSF_PORT_DPIO; + return phy == DPIO_PHY0 ? VLV_IOSF_SB_DPIO_2 : VLV_IOSF_SB_DPIO; else - return IOSF_PORT_DPIO; + return VLV_IOSF_SB_DPIO; } u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg) { - u32 port = vlv_dpio_phy_iosf_port(i915, phy); - u32 val = 0; + enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(i915, phy); + u32 val; - vlv_sideband_rw(i915, DPIO_DEVFN, port, SB_MRD_NP, reg, &val); + val = vlv_iosf_sb_read(i915, unit, reg); /* * FIXME: There might be some registers where all 1's is a valid value, @@ -303,24 +275,19 @@ u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg) void vlv_dpio_write(struct drm_i915_private *i915, enum dpio_phy phy, int reg, u32 val) { - u32 port = vlv_dpio_phy_iosf_port(i915, phy); + enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(i915, phy); - vlv_sideband_rw(i915, DPIO_DEVFN, port, SB_MWR_NP, reg, &val); + vlv_iosf_sb_write(i915, unit, reg, val); } u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg) { - u32 val = 0; - - vlv_sideband_rw(i915, DPIO_DEVFN, IOSF_PORT_FLISDSI, SB_CRRDDA_NP, - reg, &val); - return val; + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_FLISDSI, reg); } void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val) { - vlv_sideband_rw(i915, DPIO_DEVFN, IOSF_PORT_FLISDSI, SB_CRWRDA_NP, - reg, &val); + vlv_iosf_sb_write(i915, VLV_IOSF_SB_FLISDSI, reg, val); } void vlv_iosf_sb_init(struct drm_i915_private *i915) diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.h b/drivers/gpu/drm/i915/vlv_iosf_sb.h index 26af3aa973f8b..66f8918d49743 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.h +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.h @@ -76,7 +76,7 @@ static inline void vlv_ccu_put(struct drm_i915_private *i915) static inline void vlv_dpio_get(struct drm_i915_private *i915) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_DPIO)); + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); } u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg); @@ -85,7 +85,7 @@ void vlv_dpio_write(struct drm_i915_private *i915, static inline void vlv_dpio_put(struct drm_i915_private *i915) { - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_DPIO)); + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); } static inline void vlv_flisdsi_get(struct drm_i915_private *i915) -- GitLab From ead7a1a59e37cc7134e98e3121d0962940a1c1d9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 May 2025 17:56:55 +0300 Subject: [PATCH 0036/1479] drm/i915: switch i915 core to generic VLV IOSF SB functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We'll want to relocate the unit specific functions to display, making them inaccessible to i915 core. As there aren't that many users in i915 core, we can just convert them to the generic VLV IOSF SB read/write functions. v2: Use BIT(unit) for get/put Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/3162c8768eeeba928bbc3d4aa2ddfc6a1030a451.1747061743.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c | 6 +-- drivers/gpu/drm/i915/gt/intel_rps.c | 46 +++++++++---------- drivers/gpu/drm/i915/soc/intel_dram.c | 4 +- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c index 0704fe763afed..a059c6488b3db 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c @@ -366,9 +366,9 @@ void intel_gt_pm_frequency_dump(struct intel_gt *gt, struct drm_printer *p) drm_printf(p, "SW control enabled: %s\n", str_yes_no((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == GEN6_RP_MEDIA_SW_MODE)); - vlv_punit_get(i915); - freq_sts = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS); - vlv_punit_put(i915); + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); + freq_sts = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); drm_printf(p, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts); diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 7fa341d2bfe4f..37487d2f121dc 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -820,9 +820,9 @@ static int vlv_rps_set(struct intel_rps *rps, u8 val) struct drm_i915_private *i915 = rps_to_i915(rps); int err; - vlv_punit_get(i915); - err = vlv_punit_write(i915, PUNIT_REG_GPU_FREQ_REQ, val); - vlv_punit_put(i915); + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); + err = vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_REQ, val); + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); GT_TRACE(rps_to_gt(rps), "set val:%x, freq:%d\n", val, intel_gpu_freq(rps, val)); @@ -1268,7 +1268,7 @@ static int chv_rps_max_freq(struct intel_rps *rps) struct intel_gt *gt = rps_to_gt(rps); u32 val; - val = vlv_punit_read(i915, FB_GFX_FMAX_AT_VMAX_FUSE); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, FB_GFX_FMAX_AT_VMAX_FUSE); switch (gt->info.sseu.eu_total) { case 8: @@ -1295,7 +1295,7 @@ static int chv_rps_rpe_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val; - val = vlv_punit_read(i915, PUNIT_GPU_DUTYCYCLE_REG); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_GPU_DUTYCYCLE_REG); val >>= PUNIT_GPU_DUTYCYCLE_RPE_FREQ_SHIFT; return val & PUNIT_GPU_DUTYCYCLE_RPE_FREQ_MASK; @@ -1306,7 +1306,7 @@ static int chv_rps_guar_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val; - val = vlv_punit_read(i915, FB_GFX_FMAX_AT_VMAX_FUSE); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, FB_GFX_FMAX_AT_VMAX_FUSE); return val & FB_GFX_FREQ_FUSE_MASK; } @@ -1316,7 +1316,7 @@ static u32 chv_rps_min_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val; - val = vlv_punit_read(i915, FB_GFX_FMIN_AT_VMIN_FUSE); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, FB_GFX_FMIN_AT_VMIN_FUSE); val >>= FB_GFX_FMIN_AT_VMIN_FUSE_SHIFT; return val & FB_GFX_FREQ_FUSE_MASK; @@ -1350,14 +1350,14 @@ static bool chv_rps_enable(struct intel_rps *rps) GEN6_PM_RP_DOWN_TIMEOUT); /* Setting Fixed Bias */ - vlv_punit_get(i915); + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); val = VLV_OVERRIDE_EN | VLV_SOC_TDP_EN | CHV_BIAS_CPU_50_SOC_50; - vlv_punit_write(i915, VLV_TURBO_SOC_OVERRIDE, val); + vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, VLV_TURBO_SOC_OVERRIDE, val); - val = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_punit_put(i915); + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); /* RPS code assumes GPLL is used */ drm_WARN_ONCE(&i915->drm, (val & GPLLENABLE) == 0, @@ -1375,7 +1375,7 @@ static int vlv_rps_guar_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val, rp1; - val = vlv_nc_read(i915, IOSF_NC_FB_GFX_FREQ_FUSE); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FREQ_FUSE); rp1 = val & FB_GFX_FGUARANTEED_FREQ_FUSE_MASK; rp1 >>= FB_GFX_FGUARANTEED_FREQ_FUSE_SHIFT; @@ -1388,7 +1388,7 @@ static int vlv_rps_max_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val, rp0; - val = vlv_nc_read(i915, IOSF_NC_FB_GFX_FREQ_FUSE); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FREQ_FUSE); rp0 = (val & FB_GFX_MAX_FREQ_FUSE_MASK) >> FB_GFX_MAX_FREQ_FUSE_SHIFT; /* Clamp to max */ @@ -1402,9 +1402,9 @@ static int vlv_rps_rpe_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val, rpe; - val = vlv_nc_read(i915, IOSF_NC_FB_GFX_FMAX_FUSE_LO); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FMAX_FUSE_LO); rpe = (val & FB_FMAX_VMIN_FREQ_LO_MASK) >> FB_FMAX_VMIN_FREQ_LO_SHIFT; - val = vlv_nc_read(i915, IOSF_NC_FB_GFX_FMAX_FUSE_HI); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FMAX_FUSE_HI); rpe |= (val & FB_FMAX_VMIN_FREQ_HI_MASK) << 5; return rpe; @@ -1415,7 +1415,7 @@ static int vlv_rps_min_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val; - val = vlv_punit_read(i915, PUNIT_REG_GPU_LFM) & 0xff; + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_LFM) & 0xff; /* * According to the BYT Punit GPU turbo HAS 1.1.6.3 the minimum value * for the minimum frequency in GPLL mode is 0xc1. Contrary to this on @@ -1451,15 +1451,15 @@ static bool vlv_rps_enable(struct intel_rps *rps) /* WaGsvRC0ResidencyMethod:vlv */ rps->pm_events = GEN6_PM_RP_UP_EI_EXPIRED; - vlv_punit_get(i915); + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); /* Setting Fixed Bias */ val = VLV_OVERRIDE_EN | VLV_SOC_TDP_EN | VLV_BIAS_CPU_125_SOC_875; - vlv_punit_write(i915, VLV_TURBO_SOC_OVERRIDE, val); + vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, VLV_TURBO_SOC_OVERRIDE, val); - val = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_punit_put(i915); + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); /* RPS code assumes GPLL is used */ drm_WARN_ONCE(&i915->drm, (val & GPLLENABLE) == 0, @@ -2107,9 +2107,9 @@ static u32 __read_cagf(struct intel_rps *rps, bool take_fw) } else if (GRAPHICS_VER(i915) >= 12) { r = GEN12_RPSTAT1; } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { - vlv_punit_get(i915); - freq = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS); - vlv_punit_put(i915); + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); + freq = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); } else if (GRAPHICS_VER(i915) >= 6) { r = GEN6_RPSTAT1; } else { diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index 0b92ab4e9fb9b..e8d6bd116b446 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -98,7 +98,7 @@ static unsigned int chv_mem_freq(struct drm_i915_private *i915) u32 val; vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCK)); - val = vlv_cck_read(i915, CCK_FUSE_REG); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCK, CCK_FUSE_REG); vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCK)); switch ((val >> 2) & 0x7) { @@ -114,7 +114,7 @@ static unsigned int vlv_mem_freq(struct drm_i915_private *i915) u32 val; vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); - val = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS); + val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); switch ((val >> 6) & 3) { -- GitLab From 8393253b850b6a5c62d4bb875b582e1582103db8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 May 2025 17:56:56 +0300 Subject: [PATCH 0037/1479] drm/i915: move VLV IOSF SB unit specific helpers under display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that all the VLV IOSF SB unit specific helper users are under display, relocate the helpers themselves under display as well. Resurrect the vlv_sideband.[ch] name for this. Make everything except DPIO helpers static inlines, as their implementations are trivial. All of this considerably simplifies the xe compat header. v2: Rebase Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/e86c2498c9f1c1d30f8e83fa5f1c23526b87b9ab.1747061743.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 3 +- drivers/gpu/drm/i915/display/i9xx_wm.c | 2 +- drivers/gpu/drm/i915/display/intel_cdclk.c | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 2 +- .../drm/i915/display/intel_display_power.c | 2 +- .../i915/display/intel_display_power_well.c | 2 +- drivers/gpu/drm/i915/display/intel_dpio_phy.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll.c | 2 +- drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 2 +- drivers/gpu/drm/i915/display/vlv_dsi.c | 2 +- drivers/gpu/drm/i915/display/vlv_dsi_pll.c | 2 +- drivers/gpu/drm/i915/display/vlv_sideband.c | 45 +++++ drivers/gpu/drm/i915/display/vlv_sideband.h | 156 ++++++++++++++++++ drivers/gpu/drm/i915/vlv_iosf_sb.c | 94 ----------- drivers/gpu/drm/i915/vlv_iosf_sb.h | 93 ----------- .../drm/xe/compat-i915-headers/vlv_iosf_sb.h | 91 ---------- 16 files changed, 213 insertions(+), 289 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/vlv_sideband.c create mode 100644 drivers/gpu/drm/i915/display/vlv_sideband.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 3e3e4f4bfa4e2..1a90eb1f180aa 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -296,7 +296,8 @@ i915-y += \ display/intel_wm.o \ display/skl_scaler.o \ display/skl_universal_plane.o \ - display/skl_watermark.o + display/skl_watermark.o \ + display/vlv_sideband.o i915-$(CONFIG_ACPI) += \ display/intel_acpi.o \ display/intel_opregion.o diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 02f33cbe6765c..77876ef735b74 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -16,7 +16,7 @@ #include "intel_mchbar_regs.h" #include "intel_wm.h" #include "skl_watermark.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" struct intel_watermark_params { u16 fifo_size; diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 501b794984149..b1718b491ffda 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -47,7 +47,7 @@ #include "skl_watermark.h" #include "skl_watermark_regs.h" #include "vlv_dsi.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" /** * DOC: CDCLK / RAWCLK diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c7a6b710b7c0a..704ca079980c2 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -131,7 +131,7 @@ #include "vlv_dsi.h" #include "vlv_dsi_pll.h" #include "vlv_dsi_regs.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state); static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index b3b05d7610e8a..16356523816fb 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -27,7 +27,7 @@ #include "intel_snps_phy.h" #include "skl_watermark.h" #include "skl_watermark_regs.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" #define for_each_power_domain_well(__display, __power_well, __domain) \ for_each_power_well((__display), __power_well) \ diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index 6772ac0c3f84c..0a3d302f9d1b1 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -30,7 +30,7 @@ #include "intel_vga.h" #include "skl_watermark.h" #include "vlv_dpio_phy_regs.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" #include "vlv_iosf_sb_reg.h" struct i915_power_well_regs { diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 5b9c0852da2cf..69f2421394205 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -32,7 +32,7 @@ #include "intel_dp.h" #include "intel_dpio_phy.h" #include "vlv_dpio_phy_regs.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" /** * DOC: DPIO diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 055dd2b4a9043..a9e9b98d0bf9c 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -22,7 +22,7 @@ #include "intel_pps.h" #include "intel_snps_phy.h" #include "vlv_dpio_phy_regs.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" struct intel_dpll_funcs { int (*crtc_compute_clock)(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c index dce4fdf091f67..29c9209834138 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c @@ -49,7 +49,7 @@ #include "intel_pps_regs.h" #include "vlv_dsi.h" #include "vlv_dsi_regs.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" #define MIPI_TRANSFER_MODE_SHIFT 0 #define MIPI_VIRTUAL_CHANNEL_SHIFT 1 diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 110914bbc1348..346737f15fa93 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -49,7 +49,7 @@ #include "vlv_dsi.h" #include "vlv_dsi_pll.h" #include "vlv_dsi_regs.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" /* return pixels in terms of txbyteclkhs */ static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count, diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c index 79438cdfc3f9d..7ce924a5ef90b 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c @@ -34,7 +34,7 @@ #include "intel_dsi.h" #include "vlv_dsi_pll.h" #include "vlv_dsi_pll_regs.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" static const u16 lfsr_converts[] = { 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 62 - 70 */ diff --git a/drivers/gpu/drm/i915/display/vlv_sideband.c b/drivers/gpu/drm/i915/display/vlv_sideband.c new file mode 100644 index 0000000000000..f1caee32f6232 --- /dev/null +++ b/drivers/gpu/drm/i915/display/vlv_sideband.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +/* Copyright © 2025 Intel Corporation */ + +#include "i915_drv.h" +#include "intel_dpio_phy.h" +#include "vlv_sideband.h" + +static enum vlv_iosf_sb_unit vlv_dpio_phy_to_unit(struct drm_i915_private *i915, + enum dpio_phy phy) +{ + /* + * IOSF_PORT_DPIO: VLV x2 PHY (DP/HDMI B and C), CHV x1 PHY (DP/HDMI D) + * IOSF_PORT_DPIO_2: CHV x2 PHY (DP/HDMI B and C) + */ + if (IS_CHERRYVIEW(i915)) + return phy == DPIO_PHY0 ? VLV_IOSF_SB_DPIO_2 : VLV_IOSF_SB_DPIO; + else + return VLV_IOSF_SB_DPIO; +} + +u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg) +{ + enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(i915, phy); + u32 val; + + val = vlv_iosf_sb_read(i915, unit, reg); + + /* + * FIXME: There might be some registers where all 1's is a valid value, + * so ideally we should check the register offset instead... + */ + drm_WARN(&i915->drm, val == 0xffffffff, + "DPIO PHY%d read reg 0x%x == 0x%x\n", + phy, reg, val); + + return val; +} + +void vlv_dpio_write(struct drm_i915_private *i915, + enum dpio_phy phy, int reg, u32 val) +{ + enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(i915, phy); + + vlv_iosf_sb_write(i915, unit, reg, val); +} diff --git a/drivers/gpu/drm/i915/display/vlv_sideband.h b/drivers/gpu/drm/i915/display/vlv_sideband.h new file mode 100644 index 0000000000000..beac69157d24b --- /dev/null +++ b/drivers/gpu/drm/i915/display/vlv_sideband.h @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2025 Intel Corporation */ + +#ifndef _VLV_SIDEBAND_H_ +#define _VLV_SIDEBAND_H_ + +#include +#include + +#include "vlv_iosf_sb.h" +#include "vlv_iosf_sb_reg.h" + +enum dpio_phy; +struct drm_i915_private; + +static inline void vlv_bunit_get(struct drm_i915_private *i915) +{ + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_BUNIT)); +} + +static inline u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg) +{ + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_BUNIT, reg); +} + +static inline void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val) +{ + vlv_iosf_sb_write(i915, VLV_IOSF_SB_BUNIT, reg, val); +} + +static inline void vlv_bunit_put(struct drm_i915_private *i915) +{ + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_BUNIT)); +} + +static inline void vlv_cck_get(struct drm_i915_private *i915) +{ + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCK)); +} + +static inline u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg) +{ + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCK, reg); +} + +static inline void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val) +{ + vlv_iosf_sb_write(i915, VLV_IOSF_SB_CCK, reg, val); +} + +static inline void vlv_cck_put(struct drm_i915_private *i915) +{ + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCK)); +} + +static inline void vlv_ccu_get(struct drm_i915_private *i915) +{ + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCU)); +} + +static inline u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg) +{ + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCU, reg); +} + +static inline void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val) +{ + vlv_iosf_sb_write(i915, VLV_IOSF_SB_CCU, reg, val); +} + +static inline void vlv_ccu_put(struct drm_i915_private *i915) +{ + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCU)); +} + +static inline void vlv_dpio_get(struct drm_i915_private *i915) +{ + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); +} + +#ifdef I915 +u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg); +void vlv_dpio_write(struct drm_i915_private *i915, + enum dpio_phy phy, int reg, u32 val); +#else +static inline u32 vlv_dpio_read(struct drm_i915_private *i915, int phy, int reg) +{ + return 0; +} +static inline void vlv_dpio_write(struct drm_i915_private *i915, + int phy, int reg, u32 val) +{ +} +#endif + +static inline void vlv_dpio_put(struct drm_i915_private *i915) +{ + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); +} + +static inline void vlv_flisdsi_get(struct drm_i915_private *i915) +{ + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_FLISDSI)); +} + +static inline u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg) +{ + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_FLISDSI, reg); +} + +static inline void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val) +{ + vlv_iosf_sb_write(i915, VLV_IOSF_SB_FLISDSI, reg, val); +} + +static inline void vlv_flisdsi_put(struct drm_i915_private *i915) +{ + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_FLISDSI)); +} + +static inline void vlv_nc_get(struct drm_i915_private *i915) +{ + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_NC)); +} + +static inline u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr) +{ + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, addr); +} + +static inline void vlv_nc_put(struct drm_i915_private *i915) +{ + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_NC)); +} + +static inline void vlv_punit_get(struct drm_i915_private *i915) +{ + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); +} + +static inline u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr) +{ + return vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, addr); +} + +static inline int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val) +{ + return vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, addr, val); +} + +static inline void vlv_punit_put(struct drm_i915_private *i915) +{ + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); +} + +#endif /* _VLV_SIDEBAND_H_ */ diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c index efb5ee39dbbb2..c6418d54dae9f 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -196,100 +196,6 @@ int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, return vlv_sideband_rw(i915, devfn, port, opcode, addr, &val); } -u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr) -{ - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, addr); -} - -int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val) -{ - return vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, addr, val); -} - -u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg) -{ - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_BUNIT, reg); -} - -void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val) -{ - vlv_iosf_sb_write(i915, VLV_IOSF_SB_BUNIT, reg, val); -} - -u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr) -{ - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, addr); -} - -u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg) -{ - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCK, reg); -} - -void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val) -{ - vlv_iosf_sb_write(i915, VLV_IOSF_SB_CCK, reg, val); -} - -u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg) -{ - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCU, reg); -} - -void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val) -{ - vlv_iosf_sb_write(i915, VLV_IOSF_SB_CCU, reg, val); -} - -static enum vlv_iosf_sb_unit vlv_dpio_phy_to_unit(struct drm_i915_private *i915, - enum dpio_phy phy) -{ - /* - * IOSF_PORT_DPIO: VLV x2 PHY (DP/HDMI B and C), CHV x1 PHY (DP/HDMI D) - * IOSF_PORT_DPIO_2: CHV x2 PHY (DP/HDMI B and C) - */ - if (IS_CHERRYVIEW(i915)) - return phy == DPIO_PHY0 ? VLV_IOSF_SB_DPIO_2 : VLV_IOSF_SB_DPIO; - else - return VLV_IOSF_SB_DPIO; -} - -u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg) -{ - enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(i915, phy); - u32 val; - - val = vlv_iosf_sb_read(i915, unit, reg); - - /* - * FIXME: There might be some registers where all 1's is a valid value, - * so ideally we should check the register offset instead... - */ - drm_WARN(&i915->drm, val == 0xffffffff, - "DPIO PHY%d read reg 0x%x == 0x%x\n", - phy, reg, val); - - return val; -} - -void vlv_dpio_write(struct drm_i915_private *i915, - enum dpio_phy phy, int reg, u32 val) -{ - enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(i915, phy); - - vlv_iosf_sb_write(i915, unit, reg, val); -} - -u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg) -{ - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_FLISDSI, reg); -} - -void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val) -{ - vlv_iosf_sb_write(i915, VLV_IOSF_SB_FLISDSI, reg, val); -} - void vlv_iosf_sb_init(struct drm_i915_private *i915) { if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.h b/drivers/gpu/drm/i915/vlv_iosf_sb.h index 66f8918d49743..f4fb7213fe377 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.h +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.h @@ -6,12 +6,10 @@ #ifndef _VLV_IOSF_SB_H_ #define _VLV_IOSF_SB_H_ -#include #include #include "vlv_iosf_sb_reg.h" -enum dpio_phy; struct drm_i915_private; enum vlv_iosf_sb_unit { @@ -35,95 +33,4 @@ void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports); u32 vlv_iosf_sb_read(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr); int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr, u32 val); -static inline void vlv_bunit_get(struct drm_i915_private *i915) -{ - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_BUNIT)); -} - -u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg); -void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val); - -static inline void vlv_bunit_put(struct drm_i915_private *i915) -{ - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_BUNIT)); -} - -static inline void vlv_cck_get(struct drm_i915_private *i915) -{ - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCK)); -} - -u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg); -void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val); - -static inline void vlv_cck_put(struct drm_i915_private *i915) -{ - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCK)); -} - -static inline void vlv_ccu_get(struct drm_i915_private *i915) -{ - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCU)); -} - -u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg); -void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val); - -static inline void vlv_ccu_put(struct drm_i915_private *i915) -{ - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCU)); -} - -static inline void vlv_dpio_get(struct drm_i915_private *i915) -{ - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); -} - -u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg); -void vlv_dpio_write(struct drm_i915_private *i915, - enum dpio_phy phy, int reg, u32 val); - -static inline void vlv_dpio_put(struct drm_i915_private *i915) -{ - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); -} - -static inline void vlv_flisdsi_get(struct drm_i915_private *i915) -{ - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_FLISDSI)); -} - -u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg); -void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val); - -static inline void vlv_flisdsi_put(struct drm_i915_private *i915) -{ - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_FLISDSI)); -} - -static inline void vlv_nc_get(struct drm_i915_private *i915) -{ - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_NC)); -} - -u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr); - -static inline void vlv_nc_put(struct drm_i915_private *i915) -{ - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_NC)); -} - -static inline void vlv_punit_get(struct drm_i915_private *i915) -{ - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); -} - -u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr); -int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val); - -static inline void vlv_punit_put(struct drm_i915_private *i915) -{ - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); -} - #endif /* _VLV_IOSF_SB_H_ */ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h index 57f7dde90ced8..e34d9c72a587f 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h @@ -10,7 +10,6 @@ #include "vlv_iosf_sb_reg.h" -enum pipe; struct drm_i915_private; enum vlv_iosf_sb_unit { @@ -39,95 +38,5 @@ static inline int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf static inline void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports) { } -static inline void vlv_bunit_get(struct drm_i915_private *i915) -{ -} -static inline u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg) -{ - return 0; -} -static inline void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val) -{ -} -static inline void vlv_bunit_put(struct drm_i915_private *i915) -{ -} -static inline void vlv_cck_get(struct drm_i915_private *i915) -{ -} -static inline u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg) -{ - return 0; -} -static inline void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val) -{ -} -static inline void vlv_cck_put(struct drm_i915_private *i915) -{ -} -static inline void vlv_ccu_get(struct drm_i915_private *i915) -{ -} -static inline u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg) -{ - return 0; -} -static inline void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val) -{ -} -static inline void vlv_ccu_put(struct drm_i915_private *i915) -{ -} -static inline void vlv_dpio_get(struct drm_i915_private *i915) -{ -} -static inline u32 vlv_dpio_read(struct drm_i915_private *i915, int pipe, int reg) -{ - return 0; -} -static inline void vlv_dpio_write(struct drm_i915_private *i915, - int pipe, int reg, u32 val) -{ -} -static inline void vlv_dpio_put(struct drm_i915_private *i915) -{ -} -static inline void vlv_flisdsi_get(struct drm_i915_private *i915) -{ -} -static inline u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg) -{ - return 0; -} -static inline void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val) -{ -} -static inline void vlv_flisdsi_put(struct drm_i915_private *i915) -{ -} -static inline void vlv_nc_get(struct drm_i915_private *i915) -{ -} -static inline u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr) -{ - return 0; -} -static inline void vlv_nc_put(struct drm_i915_private *i915) -{ -} -static inline void vlv_punit_get(struct drm_i915_private *i915) -{ -} -static inline u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr) -{ - return 0; -} -static inline int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val) -{ - return 0; -} -static inline void vlv_punit_put(struct drm_i915_private *i915) -{ -} #endif /* _VLV_IOSF_SB_H_ */ -- GitLab From bd4d1856f5fe427ad20d54c57bd0f2724f7be47e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 May 2025 17:56:57 +0300 Subject: [PATCH 0038/1479] drm/i915: convert VLV IOSF SB interface to struct drm_device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With users both in i915 core and display, struct drm_device is the common denominator for the VLV IOSF SB users. Also use drm_device for the helpers on the display side to keep the static inlines as simple as possible. We can drop a number of dependencies on i915_drv.h with this. v2,v3: Rebase Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/c1d013ed88ce2e3e5bdc15ce3bf01a3960b1e817.1747061743.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/i9xx_wm.c | 35 ++- drivers/gpu/drm/i915/display/intel_cdclk.c | 47 ++--- drivers/gpu/drm/i915/display/intel_display.c | 23 +- drivers/gpu/drm/i915/display/intel_display.h | 7 +- .../drm/i915/display/intel_display_power.c | 7 +- .../i915/display/intel_display_power_well.c | 69 +++--- drivers/gpu/drm/i915/display/intel_dpio_phy.c | 199 +++++++++--------- drivers/gpu/drm/i915/display/intel_dpll.c | 135 ++++++------ drivers/gpu/drm/i915/display/vlv_dsi.c | 26 ++- drivers/gpu/drm/i915/display/vlv_dsi_pll.c | 46 ++-- drivers/gpu/drm/i915/display/vlv_sideband.c | 25 ++- drivers/gpu/drm/i915/display/vlv_sideband.h | 110 +++++----- drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c | 6 +- drivers/gpu/drm/i915/gt/intel_rps.c | 56 ++--- drivers/gpu/drm/i915/soc/intel_dram.c | 12 +- drivers/gpu/drm/i915/vlv_iosf_sb.c | 14 +- drivers/gpu/drm/i915/vlv_iosf_sb.h | 9 +- .../drm/xe/compat-i915-headers/vlv_iosf_sb.h | 10 +- 18 files changed, 410 insertions(+), 426 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 77876ef735b74..8e4e938f1ee5e 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -107,43 +107,41 @@ static const struct cxsr_latency *pnv_get_cxsr_latency(struct intel_display *dis static void chv_set_memory_dvfs(struct intel_display *display, bool enable) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 val; - vlv_punit_get(dev_priv); + vlv_punit_get(display->drm); - val = vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2); + val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2); if (enable) val &= ~FORCE_DDR_HIGH_FREQ; else val |= FORCE_DDR_HIGH_FREQ; val &= ~FORCE_DDR_LOW_FREQ; val |= FORCE_DDR_FREQ_REQ_ACK; - vlv_punit_write(dev_priv, PUNIT_REG_DDR_SETUP2, val); + vlv_punit_write(display->drm, PUNIT_REG_DDR_SETUP2, val); - if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2) & + if (wait_for((vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2) & FORCE_DDR_FREQ_REQ_ACK) == 0, 3)) drm_err(display->drm, "timed out waiting for Punit DDR DVFS request\n"); - vlv_punit_put(dev_priv); + vlv_punit_put(display->drm); } static void chv_set_memory_pm5(struct intel_display *display, bool enable) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 val; - vlv_punit_get(dev_priv); + vlv_punit_get(display->drm); - val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM); + val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); if (enable) val |= DSP_MAXFIFO_PM5_ENABLE; else val &= ~DSP_MAXFIFO_PM5_ENABLE; - vlv_punit_write(dev_priv, PUNIT_REG_DSPSSPM, val); + vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val); - vlv_punit_put(dev_priv); + vlv_punit_put(display->drm); } #define FW_WM(value, plane) \ @@ -3900,7 +3898,6 @@ static void g4x_wm_sanitize(struct intel_display *display) static void vlv_wm_get_hw_state(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); struct vlv_wm_values *wm = &display->wm.vlv; struct intel_crtc *crtc; u32 val; @@ -3911,9 +3908,9 @@ static void vlv_wm_get_hw_state(struct intel_display *display) wm->level = VLV_WM_LEVEL_PM2; if (display->platform.cherryview) { - vlv_punit_get(dev_priv); + vlv_punit_get(display->drm); - val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM); + val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); if (val & DSP_MAXFIFO_PM5_ENABLE) wm->level = VLV_WM_LEVEL_PM5; @@ -3926,23 +3923,23 @@ static void vlv_wm_get_hw_state(struct intel_display *display) * HIGH/LOW bits so that we don't actually change * the current state. */ - val = vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2); + val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2); val |= FORCE_DDR_FREQ_REQ_ACK; - vlv_punit_write(dev_priv, PUNIT_REG_DDR_SETUP2, val); + vlv_punit_write(display->drm, PUNIT_REG_DDR_SETUP2, val); - if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2) & + if (wait_for((vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2) & FORCE_DDR_FREQ_REQ_ACK) == 0, 3)) { drm_dbg_kms(display->drm, "Punit not acking DDR DVFS request, " "assuming DDR DVFS is disabled\n"); display->wm.num_levels = VLV_WM_LEVEL_PM5 + 1; } else { - val = vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2); + val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2); if ((val & FORCE_DDR_HIGH_FREQ) == 0) wm->level = VLV_WM_LEVEL_DDR_DVFS; } - vlv_punit_put(dev_priv); + vlv_punit_put(display->drm); } for_each_intel_crtc(display->drm, crtc) { diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index b1718b491ffda..f0c673e40ce55 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -567,20 +567,18 @@ static u8 vlv_calc_voltage_level(struct intel_display *display, int cdclk) static void vlv_get_cdclk(struct intel_display *display, struct intel_cdclk_config *cdclk_config) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 val; - vlv_iosf_sb_get(dev_priv, - BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT)); - cdclk_config->vco = vlv_get_hpll_vco(dev_priv); - cdclk_config->cdclk = vlv_get_cck_clock(dev_priv, "cdclk", + cdclk_config->vco = vlv_get_hpll_vco(display->drm); + cdclk_config->cdclk = vlv_get_cck_clock(display->drm, "cdclk", CCK_DISPLAY_CLOCK_CONTROL, cdclk_config->vco); - val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM); + val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); - vlv_iosf_sb_put(dev_priv, + vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT)); if (display->platform.valleyview) @@ -658,16 +656,16 @@ static void vlv_set_cdclk(struct intel_display *display, */ wakeref = intel_display_power_get(display, POWER_DOMAIN_DISPLAY_CORE); - vlv_iosf_sb_get(dev_priv, + vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_BUNIT) | BIT(VLV_IOSF_SB_PUNIT)); - val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM); + val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); val &= ~DSPFREQGUAR_MASK; val |= (cmd << DSPFREQGUAR_SHIFT); - vlv_punit_write(dev_priv, PUNIT_REG_DSPSSPM, val); - if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) & + vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val); + if (wait_for((vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT), 50)) { drm_err(display->drm, @@ -681,12 +679,12 @@ static void vlv_set_cdclk(struct intel_display *display, cdclk) - 1; /* adjust cdclk divider */ - val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL); + val = vlv_cck_read(display->drm, CCK_DISPLAY_CLOCK_CONTROL); val &= ~CCK_FREQUENCY_VALUES; val |= divider; - vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val); + vlv_cck_write(display->drm, CCK_DISPLAY_CLOCK_CONTROL, val); - if (wait_for((vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL) & + if (wait_for((vlv_cck_read(display->drm, CCK_DISPLAY_CLOCK_CONTROL) & CCK_FREQUENCY_STATUS) == (divider << CCK_FREQUENCY_STATUS_SHIFT), 50)) drm_err(display->drm, @@ -694,7 +692,7 @@ static void vlv_set_cdclk(struct intel_display *display, } /* adjust self-refresh exit latency value */ - val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC); + val = vlv_bunit_read(display->drm, BUNIT_REG_BISOC); val &= ~0x7f; /* @@ -705,9 +703,9 @@ static void vlv_set_cdclk(struct intel_display *display, val |= 4500 / 250; /* 4.5 usec */ else val |= 3000 / 250; /* 3.0 usec */ - vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val); + vlv_bunit_write(display->drm, BUNIT_REG_BISOC, val); - vlv_iosf_sb_put(dev_priv, + vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_BUNIT) | BIT(VLV_IOSF_SB_PUNIT)); @@ -723,7 +721,6 @@ static void chv_set_cdclk(struct intel_display *display, const struct intel_cdclk_config *cdclk_config, enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(display->drm); int cdclk = cdclk_config->cdclk; u32 val, cmd = cdclk_config->voltage_level; intel_wakeref_t wakeref; @@ -747,19 +744,19 @@ static void chv_set_cdclk(struct intel_display *display, */ wakeref = intel_display_power_get(display, POWER_DOMAIN_DISPLAY_CORE); - vlv_punit_get(dev_priv); - val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM); + vlv_punit_get(display->drm); + val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); val &= ~DSPFREQGUAR_MASK_CHV; val |= (cmd << DSPFREQGUAR_SHIFT_CHV); - vlv_punit_write(dev_priv, PUNIT_REG_DSPSSPM, val); - if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) & + vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val); + if (wait_for((vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DSPFREQSTAT_MASK_CHV) == (cmd << DSPFREQSTAT_SHIFT_CHV), 50)) { drm_err(display->drm, "timed out waiting for CDclk change\n"); } - vlv_punit_put(dev_priv); + vlv_punit_put(display->drm); intel_update_cdclk(display); @@ -3528,10 +3525,8 @@ static int pch_rawclk(struct intel_display *display) static int vlv_hrawclk(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - /* RAWCLK_FREQ_VLV register updated from power well code */ - return vlv_get_cck_clock_hpll(dev_priv, "hrawclk", + return vlv_get_cck_clock_hpll(display->drm, "hrawclk", CCK_DISPLAY_REF_CLOCK_CONTROL); } diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 704ca079980c2..e0928f28d7116 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -140,46 +140,47 @@ static void bdw_set_pipe_misc(struct intel_dsb *dsb, const struct intel_crtc_state *crtc_state); /* returns HPLL frequency in kHz */ -int vlv_get_hpll_vco(struct drm_i915_private *dev_priv) +int vlv_get_hpll_vco(struct drm_device *drm) { int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 }; /* Obtain SKU information */ - hpll_freq = vlv_cck_read(dev_priv, CCK_FUSE_REG) & + hpll_freq = vlv_cck_read(drm, CCK_FUSE_REG) & CCK_FUSE_HPLL_FREQ_MASK; return vco_freq[hpll_freq] * 1000; } -int vlv_get_cck_clock(struct drm_i915_private *dev_priv, +int vlv_get_cck_clock(struct drm_device *drm, const char *name, u32 reg, int ref_freq) { u32 val; int divider; - val = vlv_cck_read(dev_priv, reg); + val = vlv_cck_read(drm, reg); divider = val & CCK_FREQUENCY_VALUES; - drm_WARN(&dev_priv->drm, (val & CCK_FREQUENCY_STATUS) != + drm_WARN(drm, (val & CCK_FREQUENCY_STATUS) != (divider << CCK_FREQUENCY_STATUS_SHIFT), "%s change in progress\n", name); return DIV_ROUND_CLOSEST(ref_freq << 1, divider + 1); } -int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv, +int vlv_get_cck_clock_hpll(struct drm_device *drm, const char *name, u32 reg) { + struct drm_i915_private *dev_priv = to_i915(drm); int hpll; - vlv_cck_get(dev_priv); + vlv_cck_get(drm); if (dev_priv->hpll_freq == 0) - dev_priv->hpll_freq = vlv_get_hpll_vco(dev_priv); + dev_priv->hpll_freq = vlv_get_hpll_vco(drm); - hpll = vlv_get_cck_clock(dev_priv, name, reg, dev_priv->hpll_freq); + hpll = vlv_get_cck_clock(drm, name, reg, dev_priv->hpll_freq); - vlv_cck_put(dev_priv); + vlv_cck_put(drm); return hpll; } @@ -191,7 +192,7 @@ void intel_update_czclk(struct intel_display *display) if (!display->platform.valleyview && !display->platform.cherryview) return; - dev_priv->czclk_freq = vlv_get_cck_clock_hpll(dev_priv, "czclk", + dev_priv->czclk_freq = vlv_get_cck_clock_hpll(display->drm, "czclk", CCK_CZ_CLOCK_CONTROL); drm_dbg_kms(display->drm, "CZ clock rate: %d kHz\n", dev_priv->czclk_freq); diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index b6610e9175a7a..fa857c0e03c70 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -40,7 +40,6 @@ struct drm_encoder; struct drm_file; struct drm_format_info; struct drm_framebuffer; -struct drm_i915_private; struct drm_mode_fb_cmd2; struct drm_modeset_acquire_ctx; struct drm_plane; @@ -452,10 +451,10 @@ void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state); void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state); void i830_enable_pipe(struct intel_display *display, enum pipe pipe); void i830_disable_pipe(struct intel_display *display, enum pipe pipe); -int vlv_get_hpll_vco(struct drm_i915_private *dev_priv); -int vlv_get_cck_clock(struct drm_i915_private *dev_priv, +int vlv_get_hpll_vco(struct drm_device *drm); +int vlv_get_cck_clock(struct drm_device *drm, const char *name, u32 reg, int ref_freq); -int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv, +int vlv_get_cck_clock_hpll(struct drm_device *drm, const char *name, u32 reg); bool intel_has_pending_fb_unpin(struct intel_display *display); void intel_encoder_destroy(struct drm_encoder *encoder); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 16356523816fb..d7f5d3dbb8a10 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -1883,12 +1883,11 @@ static void vlv_cmnlane_wa(struct intel_display *display) static bool vlv_punit_is_power_gated(struct intel_display *display, u32 reg0) { - struct drm_i915_private *dev_priv = to_i915(display->drm); bool ret; - vlv_punit_get(dev_priv); - ret = (vlv_punit_read(dev_priv, reg0) & SSPM0_SSC_MASK) == SSPM0_SSC_PWR_GATE; - vlv_punit_put(dev_priv); + vlv_punit_get(display->drm); + ret = (vlv_punit_read(display->drm, reg0) & SSPM0_SSC_MASK) == SSPM0_SSC_PWR_GATE; + vlv_punit_put(display->drm); return ret; } diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index 0a3d302f9d1b1..02e3c22be21e0 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -809,7 +809,6 @@ static void tgl_disable_dc3co(struct intel_display *display) static void assert_can_enable_dc5(struct intel_display *display) { - struct drm_i915_private __maybe_unused *dev_priv = to_i915(display->drm); enum i915_power_well_id high_pg; /* Power wells at this level and above must be disabled for DC5 entry */ @@ -1102,7 +1101,6 @@ static void i830_pipes_power_well_sync_hw(struct intel_display *display, static void vlv_set_power_well(struct intel_display *display, struct i915_power_well *power_well, bool enable) { - struct drm_i915_private *dev_priv = to_i915(display->drm); int pw_idx = i915_power_well_instance(power_well)->vlv.idx; u32 mask; u32 state; @@ -1112,29 +1110,29 @@ static void vlv_set_power_well(struct intel_display *display, state = enable ? PUNIT_PWRGT_PWR_ON(pw_idx) : PUNIT_PWRGT_PWR_GATE(pw_idx); - vlv_punit_get(dev_priv); + vlv_punit_get(display->drm); #define COND \ - ((vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask) == state) + ((vlv_punit_read(display->drm, PUNIT_REG_PWRGT_STATUS) & mask) == state) if (COND) goto out; - ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL); + ctrl = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_CTRL); ctrl &= ~mask; ctrl |= state; - vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, ctrl); + vlv_punit_write(display->drm, PUNIT_REG_PWRGT_CTRL, ctrl); if (wait_for(COND, 100)) drm_err(display->drm, "timeout setting power well state %08x (%08x)\n", state, - vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL)); + vlv_punit_read(display->drm, PUNIT_REG_PWRGT_CTRL)); #undef COND out: - vlv_punit_put(dev_priv); + vlv_punit_put(display->drm); } static void vlv_power_well_enable(struct intel_display *display, @@ -1152,7 +1150,6 @@ static void vlv_power_well_disable(struct intel_display *display, static bool vlv_power_well_enabled(struct intel_display *display, struct i915_power_well *power_well) { - struct drm_i915_private *dev_priv = to_i915(display->drm); int pw_idx = i915_power_well_instance(power_well)->vlv.idx; bool enabled = false; u32 mask; @@ -1162,9 +1159,9 @@ static bool vlv_power_well_enabled(struct intel_display *display, mask = PUNIT_PWRGT_MASK(pw_idx); ctrl = PUNIT_PWRGT_PWR_ON(pw_idx); - vlv_punit_get(dev_priv); + vlv_punit_get(display->drm); - state = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask; + state = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_STATUS) & mask; /* * We only ever set the power-on and power-gate states, anything * else is unexpected. @@ -1178,10 +1175,10 @@ static bool vlv_power_well_enabled(struct intel_display *display, * A transient state at this point would mean some unexpected party * is poking at the power controls too. */ - ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL) & mask; + ctrl = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_CTRL) & mask; drm_WARN_ON(display->drm, ctrl != state); - vlv_punit_put(dev_priv); + vlv_punit_put(display->drm); return enabled; } @@ -1437,7 +1434,6 @@ static void assert_chv_phy_status(struct intel_display *display) static void chv_dpio_cmn_power_well_enable(struct intel_display *display, struct i915_power_well *power_well) { - struct drm_i915_private *dev_priv = to_i915(display->drm); enum i915_power_well_id id = i915_power_well_instance(power_well)->id; enum dpio_phy phy; u32 tmp; @@ -1461,30 +1457,30 @@ static void chv_dpio_cmn_power_well_enable(struct intel_display *display, drm_err(display->drm, "Display PHY %d is not power up\n", phy); - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* Enable dynamic power down */ - tmp = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW28); + tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW28); tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN | DPIO_SUS_CLK_CONFIG_GATE_CLKREQ; - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW28, tmp); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW28, tmp); if (id == VLV_DISP_PW_DPIO_CMN_BC) { - tmp = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW6_CH1); + tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW6_CH1); tmp |= DPIO_DYNPWRDOWNEN_CH1; - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW6_CH1, tmp); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW6_CH1, tmp); } else { /* * Force the non-existing CL2 off. BXT does this * too, so maybe it saves some power even though * CL2 doesn't exist? */ - tmp = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW30); + tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW30); tmp |= DPIO_CL2_LDOFUSE_PWRENB; - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW30, tmp); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW30, tmp); } - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); display->power.chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(phy); intel_de_write(display, DISPLAY_PHY_CONTROL, @@ -1535,7 +1531,6 @@ static void chv_dpio_cmn_power_well_disable(struct intel_display *display, static void assert_chv_phy_powergate(struct intel_display *display, enum dpio_phy phy, enum dpio_channel ch, bool override, unsigned int mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 reg, val, expected, actual; /* @@ -1553,9 +1548,9 @@ static void assert_chv_phy_powergate(struct intel_display *display, enum dpio_ph else reg = CHV_CMN_DW6_CH1; - vlv_dpio_get(dev_priv); - val = vlv_dpio_read(dev_priv, phy, reg); - vlv_dpio_put(dev_priv); + vlv_dpio_get(display->drm); + val = vlv_dpio_read(display->drm, phy, reg); + vlv_dpio_put(display->drm); /* * This assumes !override is only used when the port is disabled. @@ -1665,14 +1660,13 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder, static bool chv_pipe_power_well_enabled(struct intel_display *display, struct i915_power_well *power_well) { - struct drm_i915_private *dev_priv = to_i915(display->drm); enum pipe pipe = PIPE_A; bool enabled; u32 state, ctrl; - vlv_punit_get(dev_priv); + vlv_punit_get(display->drm); - state = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) & DP_SSS_MASK(pipe); + state = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DP_SSS_MASK(pipe); /* * We only ever set the power-on and power-gate states, anything * else is unexpected. @@ -1685,10 +1679,10 @@ static bool chv_pipe_power_well_enabled(struct intel_display *display, * A transient state at this point would mean some unexpected party * is poking at the power controls too. */ - ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) & DP_SSC_MASK(pipe); + ctrl = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DP_SSC_MASK(pipe); drm_WARN_ON(display->drm, ctrl << 16 != state); - vlv_punit_put(dev_priv); + vlv_punit_put(display->drm); return enabled; } @@ -1697,36 +1691,35 @@ static void chv_set_pipe_power_well(struct intel_display *display, struct i915_power_well *power_well, bool enable) { - struct drm_i915_private *dev_priv = to_i915(display->drm); enum pipe pipe = PIPE_A; u32 state; u32 ctrl; state = enable ? DP_SSS_PWR_ON(pipe) : DP_SSS_PWR_GATE(pipe); - vlv_punit_get(dev_priv); + vlv_punit_get(display->drm); #define COND \ - ((vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM) & DP_SSS_MASK(pipe)) == state) + ((vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DP_SSS_MASK(pipe)) == state) if (COND) goto out; - ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM); + ctrl = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); ctrl &= ~DP_SSC_MASK(pipe); ctrl |= enable ? DP_SSC_PWR_ON(pipe) : DP_SSC_PWR_GATE(pipe); - vlv_punit_write(dev_priv, PUNIT_REG_DSPSSPM, ctrl); + vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, ctrl); if (wait_for(COND, 100)) drm_err(display->drm, "timeout setting power well state %08x (%08x)\n", state, - vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM)); + vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM)); #undef COND out: - vlv_punit_put(dev_priv); + vlv_punit_put(display->drm); } static void chv_pipe_power_well_sync_hw(struct intel_display *display, diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 69f2421394205..552dd984ade95 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -21,9 +21,11 @@ * DEALINGS IN THE SOFTWARE. */ +#include + #include "bxt_dpio_phy_regs.h" -#include "i915_drv.h" #include "i915_reg.h" +#include "i915_utils.h" #include "intel_ddi.h" #include "intel_ddi_buf_trans.h" #include "intel_de.h" @@ -715,53 +717,53 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, u32 deemph_reg_value, u32 margin_reg_value, bool uniq_trans_scale) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); u32 val; int i; - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* Clear calc init */ - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW10(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW10(ch)); val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK); val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW10(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW10(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW10(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW10(ch)); val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK); val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW10(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW10(ch), val); } - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW9(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW9(ch)); val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW9(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW9(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW9(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW9(ch)); val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW9(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW9(ch), val); } /* Program swing deemph */ for (i = 0; i < crtc_state->lane_count; i++) { - val = vlv_dpio_read(dev_priv, phy, CHV_TX_DW4(ch, i)); + val = vlv_dpio_read(display->drm, phy, CHV_TX_DW4(ch, i)); val &= ~DPIO_SWING_DEEMPH9P5_MASK; val |= DPIO_SWING_DEEMPH9P5(deemph_reg_value); - vlv_dpio_write(dev_priv, phy, CHV_TX_DW4(ch, i), val); + vlv_dpio_write(display->drm, phy, CHV_TX_DW4(ch, i), val); } /* Program swing margin */ for (i = 0; i < crtc_state->lane_count; i++) { - val = vlv_dpio_read(dev_priv, phy, CHV_TX_DW2(ch, i)); + val = vlv_dpio_read(display->drm, phy, CHV_TX_DW2(ch, i)); val &= ~DPIO_SWING_MARGIN000_MASK; val |= DPIO_SWING_MARGIN000(margin_reg_value); @@ -774,7 +776,7 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, val &= ~DPIO_UNIQ_TRANS_SCALE_MASK; val |= DPIO_UNIQ_TRANS_SCALE(0x9a); - vlv_dpio_write(dev_priv, phy, CHV_TX_DW2(ch, i), val); + vlv_dpio_write(display->drm, phy, CHV_TX_DW2(ch, i), val); } /* @@ -784,70 +786,70 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, * 27 for ch0 and ch1. */ for (i = 0; i < crtc_state->lane_count; i++) { - val = vlv_dpio_read(dev_priv, phy, CHV_TX_DW3(ch, i)); + val = vlv_dpio_read(display->drm, phy, CHV_TX_DW3(ch, i)); if (uniq_trans_scale) val |= DPIO_TX_UNIQ_TRANS_SCALE_EN; else val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN; - vlv_dpio_write(dev_priv, phy, CHV_TX_DW3(ch, i), val); + vlv_dpio_write(display->drm, phy, CHV_TX_DW3(ch, i), val); } /* Start swing calculation */ - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW10(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW10(ch)); val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW10(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW10(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW10(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW10(ch)); val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW10(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW10(ch), val); } - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } static void __chv_data_lane_soft_reset(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, bool reset) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); u32 val; - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW0(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW0(ch)); if (reset) val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); else val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW0(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW0(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW0(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW0(ch)); if (reset) val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); else val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW0(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW0(ch), val); } - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW1(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW1(ch)); val |= CHV_PCS_REQ_SOFTRESET_EN; if (reset) val &= ~DPIO_PCS_CLK_SOFT_RESET; else val |= DPIO_PCS_CLK_SOFT_RESET; - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW1(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW1(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW1(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW1(ch)); val |= CHV_PCS_REQ_SOFTRESET_EN; if (reset) val &= ~DPIO_PCS_CLK_SOFT_RESET; else val |= DPIO_PCS_CLK_SOFT_RESET; - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW1(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW1(ch), val); } } @@ -855,11 +857,11 @@ void chv_data_lane_soft_reset(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, bool reset) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); - vlv_dpio_get(i915); + vlv_dpio_get(display->drm); __chv_data_lane_soft_reset(encoder, crtc_state, reset); - vlv_dpio_put(i915); + vlv_dpio_put(display->drm); } void chv_phy_pre_pll_enable(struct intel_encoder *encoder, @@ -867,7 +869,6 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder, { struct intel_display *display = to_intel_display(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); @@ -886,47 +887,47 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder, chv_phy_powergate_lanes(encoder, true, lane_mask); - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* Assert data lane reset */ __chv_data_lane_soft_reset(encoder, crtc_state, true); /* program left/right clock distribution */ if (pipe != PIPE_B) { - val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW5_CH0); + val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW5_CH0); val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK); if (ch == DPIO_CH0) val |= CHV_BUFLEFTENA1_FORCE; if (ch == DPIO_CH1) val |= CHV_BUFRIGHTENA1_FORCE; - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW5_CH0, val); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW5_CH0, val); } else { - val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW1_CH1); + val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW1_CH1); val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK); if (ch == DPIO_CH0) val |= CHV_BUFLEFTENA2_FORCE; if (ch == DPIO_CH1) val |= CHV_BUFRIGHTENA2_FORCE; - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW1_CH1, val); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW1_CH1, val); } /* program clock channel usage */ - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW8(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW8(ch)); val |= DPIO_PCS_USEDCLKCHANNEL_OVRRIDE; if (pipe == PIPE_B) val |= DPIO_PCS_USEDCLKCHANNEL; else val &= ~DPIO_PCS_USEDCLKCHANNEL; - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW8(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW8(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW8(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW8(ch)); val |= DPIO_PCS_USEDCLKCHANNEL_OVRRIDE; if (pipe == PIPE_B) val |= DPIO_PCS_USEDCLKCHANNEL; else val &= ~DPIO_PCS_USEDCLKCHANNEL; - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW8(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW8(ch), val); } /* @@ -934,38 +935,38 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder, * matches the pipe, but here we need to * pick the CL based on the port. */ - val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW19(ch)); + val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW19(ch)); if (pipe == PIPE_B) val |= CHV_CMN_USEDCLKCHANNEL; else val &= ~CHV_CMN_USEDCLKCHANNEL; - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW19(ch), val); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW19(ch), val); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(encoder); struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); int data, i, stagger; u32 val; - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* allow hardware to manage TX FIFO reset source */ - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW11(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW11(ch)); val &= ~DPIO_LANEDESKEW_STRAP_OVRD; - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW11(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW11(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW11(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW11(ch)); val &= ~DPIO_LANEDESKEW_STRAP_OVRD; - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW11(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW11(ch), val); } /* Program Tx lane latency optimal setting*/ @@ -975,7 +976,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, data = 0; else data = (i == 1) ? 0 : DPIO_UPAR; - vlv_dpio_write(dev_priv, phy, CHV_TX_DW14(ch, i), data); + vlv_dpio_write(display->drm, phy, CHV_TX_DW14(ch, i), data); } /* Data lane stagger programming */ @@ -990,17 +991,17 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, else stagger = 0x2; - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW11(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW11(ch)); val |= DPIO_TX2_STAGGER_MASK(0x1f); - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW11(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW11(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW11(ch)); + val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW11(ch)); val |= DPIO_TX2_STAGGER_MASK(0x1f); - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW11(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW11(ch), val); } - vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW12(ch), + vlv_dpio_write(display->drm, phy, VLV_PCS01_DW12(ch), DPIO_LANESTAGGER_STRAP(stagger) | DPIO_LANESTAGGER_STRAP_OVRD | DPIO_TX1_STAGGER_MASK(0x1f) | @@ -1008,7 +1009,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, DPIO_TX2_STAGGER_MULT(0)); if (crtc_state->lane_count > 2) { - vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW12(ch), + vlv_dpio_write(display->drm, phy, VLV_PCS23_DW12(ch), DPIO_LANESTAGGER_STRAP(stagger) | DPIO_LANESTAGGER_STRAP_OVRD | DPIO_TX1_STAGGER_MASK(0x1f) | @@ -1019,7 +1020,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, /* Deassert data lane reset */ __chv_data_lane_soft_reset(encoder, crtc_state, false); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } void chv_phy_release_cl2_override(struct intel_encoder *encoder) @@ -1036,25 +1037,25 @@ void chv_phy_release_cl2_override(struct intel_encoder *encoder) void chv_phy_post_pll_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); enum dpio_phy phy = vlv_dig_port_to_phy(enc_to_dig_port(encoder)); enum pipe pipe = to_intel_crtc(old_crtc_state->uapi.crtc)->pipe; u32 val; - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* disable left/right clock distribution */ if (pipe != PIPE_B) { - val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW5_CH0); + val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW5_CH0); val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK); - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW5_CH0, val); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW5_CH0, val); } else { - val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW1_CH1); + val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW1_CH1); val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK); - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW1_CH1, val); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW1_CH1, val); } - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); /* * Leave the power down bit cleared for at least one @@ -1073,97 +1074,97 @@ void vlv_set_phy_signal_level(struct intel_encoder *encoder, u32 demph_reg_value, u32 preemph_reg_value, u32 uniqtranscale_reg_value, u32 tx3_demph) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW5_GRP(ch), 0x00000000); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW4_GRP(ch), demph_reg_value); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW2_GRP(ch), - uniqtranscale_reg_value); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW3_GRP(ch), 0x0C782040); + vlv_dpio_write(display->drm, phy, VLV_TX_DW5_GRP(ch), 0x00000000); + vlv_dpio_write(display->drm, phy, VLV_TX_DW4_GRP(ch), demph_reg_value); + vlv_dpio_write(display->drm, phy, VLV_TX_DW2_GRP(ch), + uniqtranscale_reg_value); + vlv_dpio_write(display->drm, phy, VLV_TX_DW3_GRP(ch), 0x0C782040); if (tx3_demph) - vlv_dpio_write(dev_priv, phy, VLV_TX_DW4(ch, 3), tx3_demph); + vlv_dpio_write(display->drm, phy, VLV_TX_DW4(ch, 3), tx3_demph); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW11_GRP(ch), 0x00030000); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW9_GRP(ch), preemph_reg_value); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW5_GRP(ch), DPIO_TX_OCALINIT_EN); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW11_GRP(ch), 0x00030000); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW9_GRP(ch), preemph_reg_value); + vlv_dpio_write(display->drm, phy, VLV_TX_DW5_GRP(ch), DPIO_TX_OCALINIT_EN); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } void vlv_phy_pre_pll_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); /* Program Tx lane resets to default */ - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW0_GRP(ch), + vlv_dpio_write(display->drm, phy, VLV_PCS_DW0_GRP(ch), DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW1_GRP(ch), + vlv_dpio_write(display->drm, phy, VLV_PCS_DW1_GRP(ch), DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | DPIO_PCS_CLK_DATAWIDTH_8_10 | DPIO_PCS_CLK_SOFT_RESET); /* Fix up inter-pair skew failure */ - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW12_GRP(ch), 0x00750f00); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW11_GRP(ch), 0x00001500); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW14_GRP(ch), 0x40400000); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW12_GRP(ch), 0x00750f00); + vlv_dpio_write(display->drm, phy, VLV_TX_DW11_GRP(ch), 0x00001500); + vlv_dpio_write(display->drm, phy, VLV_TX_DW14_GRP(ch), 0x40400000); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(encoder); struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); enum pipe pipe = crtc->pipe; u32 val; - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* Enable clock channels for this port */ val = DPIO_PCS_USEDCLKCHANNEL_OVRRIDE; if (pipe == PIPE_B) val |= DPIO_PCS_USEDCLKCHANNEL; val |= 0xc4; - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW8_GRP(ch), val); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW8_GRP(ch), val); /* Program lane clock */ - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW14_GRP(ch), 0x00760018); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW23_GRP(ch), 0x00400888); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW14_GRP(ch), 0x00760018); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW23_GRP(ch), 0x00400888); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } void vlv_phy_reset_lanes(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state) { + struct intel_display *display = to_intel_display(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); - vlv_dpio_get(dev_priv); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW0_GRP(ch), 0x00000000); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW1_GRP(ch), 0x00e00060); - vlv_dpio_put(dev_priv); + vlv_dpio_get(display->drm); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW0_GRP(ch), 0x00000000); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW1_GRP(ch), 0x00e00060); + vlv_dpio_put(display->drm); } void vlv_wait_port_ready(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index a9e9b98d0bf9c..dd7a29c10b5d8 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -6,7 +6,8 @@ #include #include -#include "i915_drv.h" +#include + #include "i915_reg.h" #include "intel_atomic.h" #include "intel_crtc.h" @@ -513,8 +514,8 @@ void i9xx_crtc_clock_get(struct intel_crtc_state *crtc_state) void vlv_crtc_clock_get(struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum dpio_channel ch = vlv_pipe_to_channel(crtc->pipe); enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; @@ -526,9 +527,9 @@ void vlv_crtc_clock_get(struct intel_crtc_state *crtc_state) if ((hw_state->dpll & DPLL_VCO_ENABLE) == 0) return; - vlv_dpio_get(dev_priv); - tmp = vlv_dpio_read(dev_priv, phy, VLV_PLL_DW3(ch)); - vlv_dpio_put(dev_priv); + vlv_dpio_get(display->drm); + tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW3(ch)); + vlv_dpio_put(display->drm); clock.m1 = REG_FIELD_GET(DPIO_M1_DIV_MASK, tmp); clock.m2 = REG_FIELD_GET(DPIO_M2_DIV_MASK, tmp); @@ -541,8 +542,8 @@ void vlv_crtc_clock_get(struct intel_crtc_state *crtc_state) void chv_crtc_clock_get(struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum dpio_channel ch = vlv_pipe_to_channel(crtc->pipe); enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; @@ -554,13 +555,13 @@ void chv_crtc_clock_get(struct intel_crtc_state *crtc_state) if ((hw_state->dpll & DPLL_VCO_ENABLE) == 0) return; - vlv_dpio_get(dev_priv); - cmn_dw13 = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW13(ch)); - pll_dw0 = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW0(ch)); - pll_dw1 = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW1(ch)); - pll_dw2 = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW2(ch)); - pll_dw3 = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW3(ch)); - vlv_dpio_put(dev_priv); + vlv_dpio_get(display->drm); + cmn_dw13 = vlv_dpio_read(display->drm, phy, CHV_CMN_DW13(ch)); + pll_dw0 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW0(ch)); + pll_dw1 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW1(ch)); + pll_dw2 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW2(ch)); + pll_dw3 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW3(ch)); + vlv_dpio_put(display->drm); clock.m1 = REG_FIELD_GET(DPIO_CHV_M1_DIV_MASK, pll_dw1) == DPIO_CHV_M1_DIV_BY_2 ? 2 : 0; clock.m2 = REG_FIELD_GET(DPIO_CHV_M2_DIV_MASK, pll_dw0) << 22; @@ -1871,45 +1872,43 @@ void i9xx_enable_pll(const struct intel_crtc_state *crtc_state) static void vlv_pllb_recal_opamp(struct intel_display *display, enum dpio_phy phy, enum dpio_channel ch) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 tmp; /* * PLLB opamp always calibrates to max value of 0x3f, force enable it * and set it to a reasonable value instead. */ - tmp = vlv_dpio_read(dev_priv, phy, VLV_PLL_DW17(ch)); + tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW17(ch)); tmp &= 0xffffff00; tmp |= 0x00000030; - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW17(ch), tmp); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW17(ch), tmp); - tmp = vlv_dpio_read(dev_priv, phy, VLV_REF_DW11); + tmp = vlv_dpio_read(display->drm, phy, VLV_REF_DW11); tmp &= 0x00ffffff; tmp |= 0x8c000000; - vlv_dpio_write(dev_priv, phy, VLV_REF_DW11, tmp); + vlv_dpio_write(display->drm, phy, VLV_REF_DW11, tmp); - tmp = vlv_dpio_read(dev_priv, phy, VLV_PLL_DW17(ch)); + tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW17(ch)); tmp &= 0xffffff00; - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW17(ch), tmp); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW17(ch), tmp); - tmp = vlv_dpio_read(dev_priv, phy, VLV_REF_DW11); + tmp = vlv_dpio_read(display->drm, phy, VLV_REF_DW11); tmp &= 0x00ffffff; tmp |= 0xb0000000; - vlv_dpio_write(dev_priv, phy, VLV_REF_DW11, tmp); + vlv_dpio_write(display->drm, phy, VLV_REF_DW11, tmp); } static void vlv_prepare_pll(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct dpll *clock = &crtc_state->dpll; enum dpio_channel ch = vlv_pipe_to_channel(crtc->pipe); enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); enum pipe pipe = crtc->pipe; u32 tmp, coreclk; - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* See eDP HDMI DPIO driver vbios notes doc */ @@ -1918,15 +1917,15 @@ static void vlv_prepare_pll(const struct intel_crtc_state *crtc_state) vlv_pllb_recal_opamp(display, phy, ch); /* Set up Tx target for periodic Rcomp update */ - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW17_BCAST, 0x0100000f); + vlv_dpio_write(display->drm, phy, VLV_PCS_DW17_BCAST, 0x0100000f); /* Disable target IRef on PLL */ - tmp = vlv_dpio_read(dev_priv, phy, VLV_PLL_DW16(ch)); + tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW16(ch)); tmp &= 0x00ffffff; - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW16(ch), tmp); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW16(ch), tmp); /* Disable fast lock */ - vlv_dpio_write(dev_priv, phy, VLV_CMN_DW0, 0x610); + vlv_dpio_write(display->drm, phy, VLV_CMN_DW0, 0x610); /* Set idtafcrecal before PLL is enabled */ tmp = DPIO_M1_DIV(clock->m1) | @@ -1942,48 +1941,42 @@ static void vlv_prepare_pll(const struct intel_crtc_state *crtc_state) * Note: don't use the DAC post divider as it seems unstable. */ tmp |= DPIO_S1_DIV(DPIO_S1_DIV_HDMIDP); - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW3(ch), tmp); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW3(ch), tmp); tmp |= DPIO_ENABLE_CALIBRATION; - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW3(ch), tmp); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW3(ch), tmp); /* Set HBR and RBR LPF coefficients */ if (crtc_state->port_clock == 162000 || intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG) || intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW18(ch), - 0x009f0003); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW18(ch), 0x009f0003); else - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW18(ch), - 0x00d0000f); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW18(ch), 0x00d0000f); if (intel_crtc_has_dp_encoder(crtc_state)) { /* Use SSC source */ if (pipe == PIPE_A) - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW5(ch), - 0x0df40000); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df40000); else - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW5(ch), - 0x0df70000); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df70000); } else { /* HDMI or VGA */ /* Use bend source */ if (pipe == PIPE_A) - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW5(ch), - 0x0df70000); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df70000); else - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW5(ch), - 0x0df40000); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df40000); } - coreclk = vlv_dpio_read(dev_priv, phy, VLV_PLL_DW7(ch)); + coreclk = vlv_dpio_read(display->drm, phy, VLV_PLL_DW7(ch)); coreclk = (coreclk & 0x0000ff00) | 0x01c00000; if (intel_crtc_has_dp_encoder(crtc_state)) coreclk |= 0x01000000; - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW7(ch), coreclk); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW7(ch), coreclk); - vlv_dpio_write(dev_priv, phy, VLV_PLL_DW19(ch), 0x87871000); + vlv_dpio_write(display->drm, phy, VLV_PLL_DW19(ch), 0x87871000); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } static void _vlv_enable_pll(const struct intel_crtc_state *crtc_state) @@ -2028,8 +2021,8 @@ void vlv_enable_pll(const struct intel_crtc_state *crtc_state) static void chv_prepare_pll(const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct dpll *clock = &crtc_state->dpll; enum dpio_channel ch = vlv_pipe_to_channel(crtc->pipe); enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); @@ -2038,44 +2031,44 @@ static void chv_prepare_pll(const struct intel_crtc_state *crtc_state) m2_frac = clock->m2 & 0x3fffff; - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* p1 and p2 divider */ - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW13(ch), + vlv_dpio_write(display->drm, phy, CHV_CMN_DW13(ch), DPIO_CHV_S1_DIV(5) | DPIO_CHV_P1_DIV(clock->p1) | DPIO_CHV_P2_DIV(clock->p2) | DPIO_CHV_K_DIV(1)); /* Feedback post-divider - m2 */ - vlv_dpio_write(dev_priv, phy, CHV_PLL_DW0(ch), + vlv_dpio_write(display->drm, phy, CHV_PLL_DW0(ch), DPIO_CHV_M2_DIV(clock->m2 >> 22)); /* Feedback refclk divider - n and m1 */ - vlv_dpio_write(dev_priv, phy, CHV_PLL_DW1(ch), + vlv_dpio_write(display->drm, phy, CHV_PLL_DW1(ch), DPIO_CHV_M1_DIV(DPIO_CHV_M1_DIV_BY_2) | DPIO_CHV_N_DIV(1)); /* M2 fraction division */ - vlv_dpio_write(dev_priv, phy, CHV_PLL_DW2(ch), + vlv_dpio_write(display->drm, phy, CHV_PLL_DW2(ch), DPIO_CHV_M2_FRAC_DIV(m2_frac)); /* M2 fraction division enable */ - tmp = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW3(ch)); + tmp = vlv_dpio_read(display->drm, phy, CHV_PLL_DW3(ch)); tmp &= ~(DPIO_CHV_FEEDFWD_GAIN_MASK | DPIO_CHV_FRAC_DIV_EN); tmp |= DPIO_CHV_FEEDFWD_GAIN(2); if (m2_frac) tmp |= DPIO_CHV_FRAC_DIV_EN; - vlv_dpio_write(dev_priv, phy, CHV_PLL_DW3(ch), tmp); + vlv_dpio_write(display->drm, phy, CHV_PLL_DW3(ch), tmp); /* Program digital lock detect threshold */ - tmp = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW9(ch)); + tmp = vlv_dpio_read(display->drm, phy, CHV_PLL_DW9(ch)); tmp &= ~(DPIO_CHV_INT_LOCK_THRESHOLD_MASK | DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE); tmp |= DPIO_CHV_INT_LOCK_THRESHOLD(0x5); if (!m2_frac) tmp |= DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE; - vlv_dpio_write(dev_priv, phy, CHV_PLL_DW9(ch), tmp); + vlv_dpio_write(display->drm, phy, CHV_PLL_DW9(ch), tmp); /* Loop filter */ if (clock->vco == 5400000) { @@ -2100,40 +2093,39 @@ static void chv_prepare_pll(const struct intel_crtc_state *crtc_state) DPIO_CHV_GAIN_CTRL(0x3); tribuf_calcntr = 0; } - vlv_dpio_write(dev_priv, phy, CHV_PLL_DW6(ch), loopfilter); + vlv_dpio_write(display->drm, phy, CHV_PLL_DW6(ch), loopfilter); - tmp = vlv_dpio_read(dev_priv, phy, CHV_PLL_DW8(ch)); + tmp = vlv_dpio_read(display->drm, phy, CHV_PLL_DW8(ch)); tmp &= ~DPIO_CHV_TDC_TARGET_CNT_MASK; tmp |= DPIO_CHV_TDC_TARGET_CNT(tribuf_calcntr); - vlv_dpio_write(dev_priv, phy, CHV_PLL_DW8(ch), tmp); + vlv_dpio_write(display->drm, phy, CHV_PLL_DW8(ch), tmp); /* AFC Recal */ - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW14(ch), - vlv_dpio_read(dev_priv, phy, CHV_CMN_DW14(ch)) | + vlv_dpio_write(display->drm, phy, CHV_CMN_DW14(ch), + vlv_dpio_read(display->drm, phy, CHV_CMN_DW14(ch)) | DPIO_AFC_RECAL); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } static void _chv_enable_pll(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; enum dpio_channel ch = vlv_pipe_to_channel(crtc->pipe); enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); enum pipe pipe = crtc->pipe; u32 tmp; - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* Enable back the 10bit clock to display controller */ - tmp = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW14(ch)); + tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW14(ch)); tmp |= DPIO_DCLKP_EN; - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW14(ch), tmp); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW14(ch), tmp); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); /* * Need to wait > 100ns between dclkp clock enable bit and PLL enable. @@ -2252,7 +2244,6 @@ void vlv_disable_pll(struct intel_display *display, enum pipe pipe) void chv_disable_pll(struct intel_display *display, enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(display->drm); enum dpio_channel ch = vlv_pipe_to_channel(pipe); enum dpio_phy phy = vlv_pipe_to_phy(pipe); u32 val; @@ -2268,14 +2259,14 @@ void chv_disable_pll(struct intel_display *display, enum pipe pipe) intel_de_write(display, DPLL(display, pipe), val); intel_de_posting_read(display, DPLL(display, pipe)); - vlv_dpio_get(dev_priv); + vlv_dpio_get(display->drm); /* Disable 10bit clock to display controller */ - val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW14(ch)); + val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW14(ch)); val &= ~DPIO_DCLKP_EN; - vlv_dpio_write(dev_priv, phy, CHV_CMN_DW14(ch), val); + vlv_dpio_write(display->drm, phy, CHV_CMN_DW14(ch), val); - vlv_dpio_put(dev_priv); + vlv_dpio_put(display->drm); } void i9xx_disable_pll(const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 346737f15fa93..5eb81f1d2f977 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -30,10 +30,11 @@ #include #include #include +#include #include -#include "i915_drv.h" #include "i915_reg.h" +#include "i915_utils.h" #include "intel_atomic.h" #include "intel_backlight.h" #include "intel_connector.h" @@ -253,18 +254,16 @@ static int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs, static void band_gap_reset(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); + vlv_flisdsi_get(display->drm); - vlv_flisdsi_get(dev_priv); - - vlv_flisdsi_write(dev_priv, 0x08, 0x0001); - vlv_flisdsi_write(dev_priv, 0x0F, 0x0005); - vlv_flisdsi_write(dev_priv, 0x0F, 0x0025); + vlv_flisdsi_write(display->drm, 0x08, 0x0001); + vlv_flisdsi_write(display->drm, 0x0F, 0x0005); + vlv_flisdsi_write(display->drm, 0x0F, 0x0025); udelay(150); - vlv_flisdsi_write(dev_priv, 0x0F, 0x0000); - vlv_flisdsi_write(dev_priv, 0x08, 0x0000); + vlv_flisdsi_write(display->drm, 0x0F, 0x0000); + vlv_flisdsi_write(display->drm, 0x08, 0x0000); - vlv_flisdsi_put(dev_priv); + vlv_flisdsi_put(display->drm); } static int intel_dsi_compute_config(struct intel_encoder *encoder, @@ -457,17 +456,16 @@ static void bxt_dsi_device_ready(struct intel_encoder *encoder) static void vlv_dsi_device_ready(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); enum port port; drm_dbg_kms(display->drm, "\n"); - vlv_flisdsi_get(dev_priv); + vlv_flisdsi_get(display->drm); /* program rcomp for compliance, reduce from 50 ohms to 45 ohms * needed everytime after power gate */ - vlv_flisdsi_write(dev_priv, 0x04, 0x0004); - vlv_flisdsi_put(dev_priv); + vlv_flisdsi_write(display->drm, 0x04, 0x0004); + vlv_flisdsi_put(display->drm); /* bandgap reset is needed after everytime we do power gate */ band_gap_reset(display); diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c index 7ce924a5ef90b..d42b61e6f0764 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c @@ -28,7 +28,9 @@ #include #include -#include "i915_drv.h" +#include + +#include "i915_utils.h" #include "intel_de.h" #include "intel_display_types.h" #include "intel_dsi.h" @@ -214,15 +216,14 @@ void vlv_dsi_pll_enable(struct intel_encoder *encoder, const struct intel_crtc_state *config) { struct intel_display *display = to_intel_display(encoder); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); drm_dbg_kms(display->drm, "\n"); - vlv_cck_get(dev_priv); + vlv_cck_get(display->drm); - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, 0); - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_DIVIDER, config->dsi_pll.div); - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, + vlv_cck_write(display->drm, CCK_REG_DSI_PLL_CONTROL, 0); + vlv_cck_write(display->drm, CCK_REG_DSI_PLL_DIVIDER, config->dsi_pll.div); + vlv_cck_write(display->drm, CCK_REG_DSI_PLL_CONTROL, config->dsi_pll.ctrl & ~DSI_PLL_VCO_EN); /* wait at least 0.5 us after ungating before enabling VCO, @@ -230,16 +231,16 @@ void vlv_dsi_pll_enable(struct intel_encoder *encoder, */ usleep_range(10, 50); - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, config->dsi_pll.ctrl); + vlv_cck_write(display->drm, CCK_REG_DSI_PLL_CONTROL, config->dsi_pll.ctrl); - if (wait_for(vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL) & + if (wait_for(vlv_cck_read(display->drm, CCK_REG_DSI_PLL_CONTROL) & DSI_PLL_LOCK, 20)) { - vlv_cck_put(dev_priv); + vlv_cck_put(display->drm); drm_err(display->drm, "DSI PLL lock failed\n"); return; } - vlv_cck_put(dev_priv); + vlv_cck_put(display->drm); drm_dbg_kms(display->drm, "DSI PLL locked\n"); } @@ -247,19 +248,18 @@ void vlv_dsi_pll_enable(struct intel_encoder *encoder, void vlv_dsi_pll_disable(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); u32 tmp; drm_dbg_kms(display->drm, "\n"); - vlv_cck_get(dev_priv); + vlv_cck_get(display->drm); - tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); + tmp = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_CONTROL); tmp &= ~DSI_PLL_VCO_EN; tmp |= DSI_PLL_LDO_GATE; - vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp); + vlv_cck_write(display->drm, CCK_REG_DSI_PLL_CONTROL, tmp); - vlv_cck_put(dev_priv); + vlv_cck_put(display->drm); } bool bxt_dsi_pll_is_enabled(struct intel_display *display) @@ -323,15 +323,14 @@ u32 vlv_dsi_get_pclk(struct intel_encoder *encoder, struct intel_crtc_state *config) { struct intel_display *display = to_intel_display(encoder); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); u32 pll_ctl, pll_div; drm_dbg_kms(display->drm, "\n"); - vlv_cck_get(dev_priv); - pll_ctl = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); - pll_div = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_DIVIDER); - vlv_cck_put(dev_priv); + vlv_cck_get(display->drm); + pll_ctl = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_CONTROL); + pll_div = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_DIVIDER); + vlv_cck_put(display->drm); config->dsi_pll.ctrl = pll_ctl & ~DSI_PLL_LOCK; config->dsi_pll.div = pll_div; @@ -592,12 +591,11 @@ void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port) static void assert_dsi_pll(struct intel_display *display, bool state) { - struct drm_i915_private *i915 = to_i915(display->drm); bool cur_state; - vlv_cck_get(i915); - cur_state = vlv_cck_read(i915, CCK_REG_DSI_PLL_CONTROL) & DSI_PLL_VCO_EN; - vlv_cck_put(i915); + vlv_cck_get(display->drm); + cur_state = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_CONTROL) & DSI_PLL_VCO_EN; + vlv_cck_put(display->drm); INTEL_DISPLAY_STATE_WARN(display, cur_state != state, "DSI PLL state assertion failure (expected %s, current %s)\n", diff --git a/drivers/gpu/drm/i915/display/vlv_sideband.c b/drivers/gpu/drm/i915/display/vlv_sideband.c index f1caee32f6232..e18045f2b89d2 100644 --- a/drivers/gpu/drm/i915/display/vlv_sideband.c +++ b/drivers/gpu/drm/i915/display/vlv_sideband.c @@ -1,45 +1,50 @@ // SPDX-License-Identifier: MIT /* Copyright © 2025 Intel Corporation */ -#include "i915_drv.h" +#include + +#include "intel_display_core.h" +#include "intel_display_types.h" #include "intel_dpio_phy.h" #include "vlv_sideband.h" -static enum vlv_iosf_sb_unit vlv_dpio_phy_to_unit(struct drm_i915_private *i915, +static enum vlv_iosf_sb_unit vlv_dpio_phy_to_unit(struct intel_display *display, enum dpio_phy phy) { /* * IOSF_PORT_DPIO: VLV x2 PHY (DP/HDMI B and C), CHV x1 PHY (DP/HDMI D) * IOSF_PORT_DPIO_2: CHV x2 PHY (DP/HDMI B and C) */ - if (IS_CHERRYVIEW(i915)) + if (display->platform.cherryview) return phy == DPIO_PHY0 ? VLV_IOSF_SB_DPIO_2 : VLV_IOSF_SB_DPIO; else return VLV_IOSF_SB_DPIO; } -u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg) +u32 vlv_dpio_read(struct drm_device *drm, enum dpio_phy phy, int reg) { - enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(i915, phy); + struct intel_display *display = to_intel_display(drm); + enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(display, phy); u32 val; - val = vlv_iosf_sb_read(i915, unit, reg); + val = vlv_iosf_sb_read(drm, unit, reg); /* * FIXME: There might be some registers where all 1's is a valid value, * so ideally we should check the register offset instead... */ - drm_WARN(&i915->drm, val == 0xffffffff, + drm_WARN(display->drm, val == 0xffffffff, "DPIO PHY%d read reg 0x%x == 0x%x\n", phy, reg, val); return val; } -void vlv_dpio_write(struct drm_i915_private *i915, +void vlv_dpio_write(struct drm_device *drm, enum dpio_phy phy, int reg, u32 val) { - enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(i915, phy); + struct intel_display *display = to_intel_display(drm); + enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(display, phy); - vlv_iosf_sb_write(i915, unit, reg, val); + vlv_iosf_sb_write(drm, unit, reg, val); } diff --git a/drivers/gpu/drm/i915/display/vlv_sideband.h b/drivers/gpu/drm/i915/display/vlv_sideband.h index beac69157d24b..2c240d81fead6 100644 --- a/drivers/gpu/drm/i915/display/vlv_sideband.h +++ b/drivers/gpu/drm/i915/display/vlv_sideband.h @@ -11,146 +11,146 @@ #include "vlv_iosf_sb_reg.h" enum dpio_phy; -struct drm_i915_private; +struct drm_device; -static inline void vlv_bunit_get(struct drm_i915_private *i915) +static inline void vlv_bunit_get(struct drm_device *drm) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_BUNIT)); + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_BUNIT)); } -static inline u32 vlv_bunit_read(struct drm_i915_private *i915, u32 reg) +static inline u32 vlv_bunit_read(struct drm_device *drm, u32 reg) { - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_BUNIT, reg); + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_BUNIT, reg); } -static inline void vlv_bunit_write(struct drm_i915_private *i915, u32 reg, u32 val) +static inline void vlv_bunit_write(struct drm_device *drm, u32 reg, u32 val) { - vlv_iosf_sb_write(i915, VLV_IOSF_SB_BUNIT, reg, val); + vlv_iosf_sb_write(drm, VLV_IOSF_SB_BUNIT, reg, val); } -static inline void vlv_bunit_put(struct drm_i915_private *i915) +static inline void vlv_bunit_put(struct drm_device *drm) { - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_BUNIT)); + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_BUNIT)); } -static inline void vlv_cck_get(struct drm_i915_private *i915) +static inline void vlv_cck_get(struct drm_device *drm) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCK)); + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_CCK)); } -static inline u32 vlv_cck_read(struct drm_i915_private *i915, u32 reg) +static inline u32 vlv_cck_read(struct drm_device *drm, u32 reg) { - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCK, reg); + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_CCK, reg); } -static inline void vlv_cck_write(struct drm_i915_private *i915, u32 reg, u32 val) +static inline void vlv_cck_write(struct drm_device *drm, u32 reg, u32 val) { - vlv_iosf_sb_write(i915, VLV_IOSF_SB_CCK, reg, val); + vlv_iosf_sb_write(drm, VLV_IOSF_SB_CCK, reg, val); } -static inline void vlv_cck_put(struct drm_i915_private *i915) +static inline void vlv_cck_put(struct drm_device *drm) { - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCK)); + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_CCK)); } -static inline void vlv_ccu_get(struct drm_i915_private *i915) +static inline void vlv_ccu_get(struct drm_device *drm) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCU)); + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_CCU)); } -static inline u32 vlv_ccu_read(struct drm_i915_private *i915, u32 reg) +static inline u32 vlv_ccu_read(struct drm_device *drm, u32 reg) { - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCU, reg); + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_CCU, reg); } -static inline void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val) +static inline void vlv_ccu_write(struct drm_device *drm, u32 reg, u32 val) { - vlv_iosf_sb_write(i915, VLV_IOSF_SB_CCU, reg, val); + vlv_iosf_sb_write(drm, VLV_IOSF_SB_CCU, reg, val); } -static inline void vlv_ccu_put(struct drm_i915_private *i915) +static inline void vlv_ccu_put(struct drm_device *drm) { - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCU)); + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_CCU)); } -static inline void vlv_dpio_get(struct drm_i915_private *i915) +static inline void vlv_dpio_get(struct drm_device *drm) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); } #ifdef I915 -u32 vlv_dpio_read(struct drm_i915_private *i915, enum dpio_phy phy, int reg); -void vlv_dpio_write(struct drm_i915_private *i915, +u32 vlv_dpio_read(struct drm_device *drm, enum dpio_phy phy, int reg); +void vlv_dpio_write(struct drm_device *drm, enum dpio_phy phy, int reg, u32 val); #else -static inline u32 vlv_dpio_read(struct drm_i915_private *i915, int phy, int reg) +static inline u32 vlv_dpio_read(struct drm_device *drm, int phy, int reg) { return 0; } -static inline void vlv_dpio_write(struct drm_i915_private *i915, +static inline void vlv_dpio_write(struct drm_device *drm, int phy, int reg, u32 val) { } #endif -static inline void vlv_dpio_put(struct drm_i915_private *i915) +static inline void vlv_dpio_put(struct drm_device *drm) { - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); } -static inline void vlv_flisdsi_get(struct drm_i915_private *i915) +static inline void vlv_flisdsi_get(struct drm_device *drm) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_FLISDSI)); + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_FLISDSI)); } -static inline u32 vlv_flisdsi_read(struct drm_i915_private *i915, u32 reg) +static inline u32 vlv_flisdsi_read(struct drm_device *drm, u32 reg) { - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_FLISDSI, reg); + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_FLISDSI, reg); } -static inline void vlv_flisdsi_write(struct drm_i915_private *i915, u32 reg, u32 val) +static inline void vlv_flisdsi_write(struct drm_device *drm, u32 reg, u32 val) { - vlv_iosf_sb_write(i915, VLV_IOSF_SB_FLISDSI, reg, val); + vlv_iosf_sb_write(drm, VLV_IOSF_SB_FLISDSI, reg, val); } -static inline void vlv_flisdsi_put(struct drm_i915_private *i915) +static inline void vlv_flisdsi_put(struct drm_device *drm) { - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_FLISDSI)); + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_FLISDSI)); } -static inline void vlv_nc_get(struct drm_i915_private *i915) +static inline void vlv_nc_get(struct drm_device *drm) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_NC)); + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_NC)); } -static inline u32 vlv_nc_read(struct drm_i915_private *i915, u8 addr) +static inline u32 vlv_nc_read(struct drm_device *drm, u8 addr) { - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, addr); + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_NC, addr); } -static inline void vlv_nc_put(struct drm_i915_private *i915) +static inline void vlv_nc_put(struct drm_device *drm) { - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_NC)); + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_NC)); } -static inline void vlv_punit_get(struct drm_i915_private *i915) +static inline void vlv_punit_get(struct drm_device *drm) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_PUNIT)); } -static inline u32 vlv_punit_read(struct drm_i915_private *i915, u32 addr) +static inline u32 vlv_punit_read(struct drm_device *drm, u32 addr) { - return vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, addr); + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_PUNIT, addr); } -static inline int vlv_punit_write(struct drm_i915_private *i915, u32 addr, u32 val) +static inline int vlv_punit_write(struct drm_device *drm, u32 addr, u32 val) { - return vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, addr, val); + return vlv_iosf_sb_write(drm, VLV_IOSF_SB_PUNIT, addr, val); } -static inline void vlv_punit_put(struct drm_i915_private *i915) +static inline void vlv_punit_put(struct drm_device *drm) { - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_PUNIT)); } #endif /* _VLV_SIDEBAND_H_ */ diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c index a059c6488b3db..87ef85483baec 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c @@ -366,9 +366,9 @@ void intel_gt_pm_frequency_dump(struct intel_gt *gt, struct drm_printer *p) drm_printf(p, "SW control enabled: %s\n", str_yes_no((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == GEN6_RP_MEDIA_SW_MODE)); - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); - freq_sts = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); + freq_sts = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); drm_printf(p, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts); diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 37487d2f121dc..5db3a0e24b226 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -820,9 +820,9 @@ static int vlv_rps_set(struct intel_rps *rps, u8 val) struct drm_i915_private *i915 = rps_to_i915(rps); int err; - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); - err = vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_REQ, val); - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); + err = vlv_iosf_sb_write(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_REQ, val); + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); GT_TRACE(rps_to_gt(rps), "set val:%x, freq:%d\n", val, intel_gpu_freq(rps, val)); @@ -1268,7 +1268,7 @@ static int chv_rps_max_freq(struct intel_rps *rps) struct intel_gt *gt = rps_to_gt(rps); u32 val; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, FB_GFX_FMAX_AT_VMAX_FUSE); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, FB_GFX_FMAX_AT_VMAX_FUSE); switch (gt->info.sseu.eu_total) { case 8: @@ -1295,7 +1295,7 @@ static int chv_rps_rpe_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_GPU_DUTYCYCLE_REG); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_GPU_DUTYCYCLE_REG); val >>= PUNIT_GPU_DUTYCYCLE_RPE_FREQ_SHIFT; return val & PUNIT_GPU_DUTYCYCLE_RPE_FREQ_MASK; @@ -1306,7 +1306,7 @@ static int chv_rps_guar_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, FB_GFX_FMAX_AT_VMAX_FUSE); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, FB_GFX_FMAX_AT_VMAX_FUSE); return val & FB_GFX_FREQ_FUSE_MASK; } @@ -1316,7 +1316,7 @@ static u32 chv_rps_min_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, FB_GFX_FMIN_AT_VMIN_FUSE); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, FB_GFX_FMIN_AT_VMIN_FUSE); val >>= FB_GFX_FMIN_AT_VMIN_FUSE_SHIFT; return val & FB_GFX_FREQ_FUSE_MASK; @@ -1350,14 +1350,14 @@ static bool chv_rps_enable(struct intel_rps *rps) GEN6_PM_RP_DOWN_TIMEOUT); /* Setting Fixed Bias */ - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); val = VLV_OVERRIDE_EN | VLV_SOC_TDP_EN | CHV_BIAS_CPU_50_SOC_50; - vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, VLV_TURBO_SOC_OVERRIDE, val); + vlv_iosf_sb_write(&i915->drm, VLV_IOSF_SB_PUNIT, VLV_TURBO_SOC_OVERRIDE, val); - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); /* RPS code assumes GPLL is used */ drm_WARN_ONCE(&i915->drm, (val & GPLLENABLE) == 0, @@ -1375,7 +1375,7 @@ static int vlv_rps_guar_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val, rp1; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FREQ_FUSE); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FREQ_FUSE); rp1 = val & FB_GFX_FGUARANTEED_FREQ_FUSE_MASK; rp1 >>= FB_GFX_FGUARANTEED_FREQ_FUSE_SHIFT; @@ -1388,7 +1388,7 @@ static int vlv_rps_max_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val, rp0; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FREQ_FUSE); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FREQ_FUSE); rp0 = (val & FB_GFX_MAX_FREQ_FUSE_MASK) >> FB_GFX_MAX_FREQ_FUSE_SHIFT; /* Clamp to max */ @@ -1402,9 +1402,9 @@ static int vlv_rps_rpe_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val, rpe; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FMAX_FUSE_LO); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FMAX_FUSE_LO); rpe = (val & FB_FMAX_VMIN_FREQ_LO_MASK) >> FB_FMAX_VMIN_FREQ_LO_SHIFT; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FMAX_FUSE_HI); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_NC, IOSF_NC_FB_GFX_FMAX_FUSE_HI); rpe |= (val & FB_FMAX_VMIN_FREQ_HI_MASK) << 5; return rpe; @@ -1415,7 +1415,7 @@ static int vlv_rps_min_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); u32 val; - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_LFM) & 0xff; + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_LFM) & 0xff; /* * According to the BYT Punit GPU turbo HAS 1.1.6.3 the minimum value * for the minimum frequency in GPLL mode is 0xc1. Contrary to this on @@ -1451,15 +1451,15 @@ static bool vlv_rps_enable(struct intel_rps *rps) /* WaGsvRC0ResidencyMethod:vlv */ rps->pm_events = GEN6_PM_RP_UP_EI_EXPIRED; - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); /* Setting Fixed Bias */ val = VLV_OVERRIDE_EN | VLV_SOC_TDP_EN | VLV_BIAS_CPU_125_SOC_875; - vlv_iosf_sb_write(i915, VLV_IOSF_SB_PUNIT, VLV_TURBO_SOC_OVERRIDE, val); + vlv_iosf_sb_write(&i915->drm, VLV_IOSF_SB_PUNIT, VLV_TURBO_SOC_OVERRIDE, val); - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); /* RPS code assumes GPLL is used */ drm_WARN_ONCE(&i915->drm, (val & GPLLENABLE) == 0, @@ -1672,7 +1672,7 @@ static void vlv_init_gpll_ref_freq(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); rps->gpll_ref_freq = - vlv_get_cck_clock(i915, "GPLL ref", + vlv_get_cck_clock(&i915->drm, "GPLL ref", CCK_GPLL_CLOCK_CONTROL, i915->czclk_freq); @@ -1684,7 +1684,7 @@ static void vlv_rps_init(struct intel_rps *rps) { struct drm_i915_private *i915 = rps_to_i915(rps); - vlv_iosf_sb_get(i915, + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT) | BIT(VLV_IOSF_SB_NC) | BIT(VLV_IOSF_SB_CCK)); @@ -1708,7 +1708,7 @@ static void vlv_rps_init(struct intel_rps *rps) drm_dbg(&i915->drm, "min GPU freq: %d MHz (%u)\n", intel_gpu_freq(rps, rps->min_freq), rps->min_freq); - vlv_iosf_sb_put(i915, + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT) | BIT(VLV_IOSF_SB_NC) | BIT(VLV_IOSF_SB_CCK)); @@ -1718,7 +1718,7 @@ static void chv_rps_init(struct intel_rps *rps) { struct drm_i915_private *i915 = rps_to_i915(rps); - vlv_iosf_sb_get(i915, + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT) | BIT(VLV_IOSF_SB_NC) | BIT(VLV_IOSF_SB_CCK)); @@ -1742,7 +1742,7 @@ static void chv_rps_init(struct intel_rps *rps) drm_dbg(&i915->drm, "min GPU freq: %d MHz (%u)\n", intel_gpu_freq(rps, rps->min_freq), rps->min_freq); - vlv_iosf_sb_put(i915, + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT) | BIT(VLV_IOSF_SB_NC) | BIT(VLV_IOSF_SB_CCK)); @@ -2107,9 +2107,9 @@ static u32 __read_cagf(struct intel_rps *rps, bool take_fw) } else if (GRAPHICS_VER(i915) >= 12) { r = GEN12_RPSTAT1; } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); - freq = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); + freq = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); } else if (GRAPHICS_VER(i915) >= 6) { r = GEN6_RPSTAT1; } else { diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index e8d6bd116b446..efee955ae8a3d 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -97,9 +97,9 @@ static unsigned int chv_mem_freq(struct drm_i915_private *i915) { u32 val; - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCK)); - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_CCK, CCK_FUSE_REG); - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCK)); + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_CCK)); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_CCK, CCK_FUSE_REG); + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_CCK)); switch ((val >> 2) & 0x7) { case 3: @@ -113,9 +113,9 @@ static unsigned int vlv_mem_freq(struct drm_i915_private *i915) { u32 val; - vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); - val = vlv_iosf_sb_read(i915, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); switch ((val >> 6) & 3) { case 0: diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c index c6418d54dae9f..9101b5c97bf17 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -57,16 +57,20 @@ static void __vlv_punit_put(struct drm_i915_private *i915) iosf_mbi_punit_release(); } -void vlv_iosf_sb_get(struct drm_i915_private *i915, unsigned long ports) +void vlv_iosf_sb_get(struct drm_device *drm, unsigned long ports) { + struct drm_i915_private *i915 = to_i915(drm); + if (ports & BIT(VLV_IOSF_SB_PUNIT)) __vlv_punit_get(i915); mutex_lock(&i915->vlv_iosf_sb.lock); } -void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports) +void vlv_iosf_sb_put(struct drm_device *drm, unsigned long ports) { + struct drm_i915_private *i915 = to_i915(drm); + mutex_unlock(&i915->vlv_iosf_sb.lock); if (ports & BIT(VLV_IOSF_SB_PUNIT)) @@ -166,8 +170,9 @@ static u32 unit_to_opcode(enum vlv_iosf_sb_unit unit, bool write) return write ? SB_CRWRDA_NP : SB_CRRDDA_NP; } -u32 vlv_iosf_sb_read(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr) +u32 vlv_iosf_sb_read(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr) { + struct drm_i915_private *i915 = to_i915(drm); u32 devfn, port, opcode, val = 0; devfn = unit_to_devfn(unit); @@ -182,8 +187,9 @@ u32 vlv_iosf_sb_read(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, return val; } -int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr, u32 val) +int vlv_iosf_sb_write(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr, u32 val) { + struct drm_i915_private *i915 = to_i915(drm); u32 devfn, port, opcode; devfn = unit_to_devfn(unit); diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.h b/drivers/gpu/drm/i915/vlv_iosf_sb.h index f4fb7213fe377..6c9b94922de96 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.h +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.h @@ -10,6 +10,7 @@ #include "vlv_iosf_sb_reg.h" +struct drm_device; struct drm_i915_private; enum vlv_iosf_sb_unit { @@ -27,10 +28,10 @@ enum vlv_iosf_sb_unit { void vlv_iosf_sb_init(struct drm_i915_private *i915); void vlv_iosf_sb_fini(struct drm_i915_private *i915); -void vlv_iosf_sb_get(struct drm_i915_private *i915, unsigned long ports); -void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports); +void vlv_iosf_sb_get(struct drm_device *drm, unsigned long ports); +void vlv_iosf_sb_put(struct drm_device *drm, unsigned long ports); -u32 vlv_iosf_sb_read(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr); -int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr, u32 val); +u32 vlv_iosf_sb_read(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr); +int vlv_iosf_sb_write(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr, u32 val); #endif /* _VLV_IOSF_SB_H_ */ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h index e34d9c72a587f..69e1935e9cdf5 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h @@ -10,7 +10,7 @@ #include "vlv_iosf_sb_reg.h" -struct drm_i915_private; +struct drm_device; enum vlv_iosf_sb_unit { VLV_IOSF_SB_BUNIT, @@ -24,18 +24,18 @@ enum vlv_iosf_sb_unit { VLV_IOSF_SB_PUNIT, }; -static inline void vlv_iosf_sb_get(struct drm_i915_private *i915, unsigned long ports) +static inline void vlv_iosf_sb_get(struct drm_device *drm, unsigned long ports) { } -static inline u32 vlv_iosf_sb_read(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr) +static inline u32 vlv_iosf_sb_read(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr) { return 0; } -static inline int vlv_iosf_sb_write(struct drm_i915_private *i915, enum vlv_iosf_sb_unit unit, u32 addr, u32 val) +static inline int vlv_iosf_sb_write(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr, u32 val) { return 0; } -static inline void vlv_iosf_sb_put(struct drm_i915_private *i915, unsigned long ports) +static inline void vlv_iosf_sb_put(struct drm_device *drm, unsigned long ports) { } -- GitLab From 52d8361531d605d6a3f9b40203412c439eb52b0c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 May 2025 17:56:58 +0300 Subject: [PATCH 0039/1479] drm/i915: rename VLV IOSF SB ports parameter to unit_mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clarify what the parameter is about through proper naming. Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/b1be9a4089dfbf48ea1434944a4841d2ac4c4acc.1747061743.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/vlv_iosf_sb.c | 8 ++++---- drivers/gpu/drm/i915/vlv_iosf_sb.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c index 9101b5c97bf17..c8f8589ee0be6 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -57,23 +57,23 @@ static void __vlv_punit_put(struct drm_i915_private *i915) iosf_mbi_punit_release(); } -void vlv_iosf_sb_get(struct drm_device *drm, unsigned long ports) +void vlv_iosf_sb_get(struct drm_device *drm, unsigned long unit_mask) { struct drm_i915_private *i915 = to_i915(drm); - if (ports & BIT(VLV_IOSF_SB_PUNIT)) + if (unit_mask & BIT(VLV_IOSF_SB_PUNIT)) __vlv_punit_get(i915); mutex_lock(&i915->vlv_iosf_sb.lock); } -void vlv_iosf_sb_put(struct drm_device *drm, unsigned long ports) +void vlv_iosf_sb_put(struct drm_device *drm, unsigned long unit_mask) { struct drm_i915_private *i915 = to_i915(drm); mutex_unlock(&i915->vlv_iosf_sb.lock); - if (ports & BIT(VLV_IOSF_SB_PUNIT)) + if (unit_mask & BIT(VLV_IOSF_SB_PUNIT)) __vlv_punit_put(i915); } diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.h b/drivers/gpu/drm/i915/vlv_iosf_sb.h index 6c9b94922de96..e2fea29a30ea2 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.h +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.h @@ -28,8 +28,8 @@ enum vlv_iosf_sb_unit { void vlv_iosf_sb_init(struct drm_i915_private *i915); void vlv_iosf_sb_fini(struct drm_i915_private *i915); -void vlv_iosf_sb_get(struct drm_device *drm, unsigned long ports); -void vlv_iosf_sb_put(struct drm_device *drm, unsigned long ports); +void vlv_iosf_sb_get(struct drm_device *drm, unsigned long unit_mask); +void vlv_iosf_sb_put(struct drm_device *drm, unsigned long unit_mask); u32 vlv_iosf_sb_read(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr); int vlv_iosf_sb_write(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr, u32 val); -- GitLab From 11b5b1bd97ef927ab8c5c41ce35d3397f590384a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 12 May 2025 17:56:59 +0300 Subject: [PATCH 0040/1479] drm/i915: ensure correct VLV IOSF SB units have been get/put MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add some extra paranoia to check correct use of the VLV IOSF SB get/put/read/write. Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/be6f029adf7148198821e5fe01dcf5d5406aa1fe.1747061743.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/vlv_iosf_sb.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d0e1980dcba2c..93b4c504b7100 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -230,6 +230,7 @@ struct drm_i915_private { /* VLV/CHV IOSF sideband */ struct { struct mutex lock; /* protect sideband access */ + unsigned long locked_unit_mask; struct pm_qos_request qos; } vlv_iosf_sb; diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c index c8f8589ee0be6..f4b435555f3bd 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -65,12 +65,18 @@ void vlv_iosf_sb_get(struct drm_device *drm, unsigned long unit_mask) __vlv_punit_get(i915); mutex_lock(&i915->vlv_iosf_sb.lock); + + i915->vlv_iosf_sb.locked_unit_mask |= unit_mask; } void vlv_iosf_sb_put(struct drm_device *drm, unsigned long unit_mask) { struct drm_i915_private *i915 = to_i915(drm); + i915->vlv_iosf_sb.locked_unit_mask &= ~unit_mask; + + drm_WARN_ON(drm, i915->vlv_iosf_sb.locked_unit_mask); + mutex_unlock(&i915->vlv_iosf_sb.lock); if (unit_mask & BIT(VLV_IOSF_SB_PUNIT)) @@ -182,6 +188,8 @@ u32 vlv_iosf_sb_read(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 add if (drm_WARN_ONCE(&i915->drm, !port, "invalid unit %d\n", unit)) return 0; + drm_WARN_ON(&i915->drm, !(i915->vlv_iosf_sb.locked_unit_mask & BIT(unit))); + vlv_sideband_rw(i915, devfn, port, opcode, addr, &val); return val; @@ -199,6 +207,8 @@ int vlv_iosf_sb_write(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 ad if (drm_WARN_ONCE(&i915->drm, !port, "invalid unit %d\n", unit)) return -EINVAL; + drm_WARN_ON(&i915->drm, !(i915->vlv_iosf_sb.locked_unit_mask & BIT(unit))); + return vlv_sideband_rw(i915, devfn, port, opcode, addr, &val); } -- GitLab From 16fa6b89990a76302446f5c4e866991ef08bcf1e Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 12 May 2025 08:20:47 +0100 Subject: [PATCH 0041/1479] drm/i915: Use provided dma_fence_is_chain Replace open-coded helper with the subsystem one. Signed-off-by: Tvrtko Ursulin Reviewed-by: Matthew Brost Signed-off-by: Tvrtko Ursulin Link: https://lore.kernel.org/r/20250512072047.56851-1-tvrtko.ursulin@igalia.com --- drivers/gpu/drm/i915/gem/i915_gem_wait.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c index 7127e90c1a8f1..991666fd9f85f 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c @@ -106,11 +106,6 @@ static void fence_set_priority(struct dma_fence *fence, rcu_read_unlock(); } -static inline bool __dma_fence_is_chain(const struct dma_fence *fence) -{ - return fence->ops == &dma_fence_chain_ops; -} - void i915_gem_fence_wait_priority(struct dma_fence *fence, const struct i915_sched_attr *attr) { @@ -126,7 +121,7 @@ void i915_gem_fence_wait_priority(struct dma_fence *fence, for (i = 0; i < array->num_fences; i++) fence_set_priority(array->fences[i], attr); - } else if (__dma_fence_is_chain(fence)) { + } else if (dma_fence_is_chain(fence)) { struct dma_fence *iter; /* The chain is ordered; if we boost the last, we boost all */ -- GitLab From 46462c4e0fa469ca83e0bfea463ab3d14147e8d1 Mon Sep 17 00:00:00 2001 From: Jocelyn Falempe Date: Wed, 7 May 2025 09:51:47 +0200 Subject: [PATCH 0042/1479] MAINTAINERS: Add entries for drm_panic, drm_panic_qr_code and drm_log Add myself and Javier as maintainer for drm_panic, drm_panic_qr_code and drm_log. Acked-by: Thomas Zimmermann Acked-by: Javier Martinez Canillas Link: https://lore.kernel.org/r/20250507075529.263355-1-jfalempe@redhat.com Signed-off-by: Jocelyn Falempe --- MAINTAINERS | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index fe9773af465a8..ef7f0d002a092 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8172,6 +8172,14 @@ T: git https://gitlab.freedesktop.org/drm/misc/kernel.git F: drivers/gpu/drm/scheduler/ F: include/drm/gpu_scheduler.h +DRM LOG +M: Jocelyn Falempe +M: Javier Martinez Canillas +L: dri-devel@lists.freedesktop.org +S: Supported +T: git https://gitlab.freedesktop.org/drm/misc/kernel.git +F: drivers/gpu/drm/clients/drm_log.c + DRM PANEL DRIVERS M: Neil Armstrong R: Jessica Zhang @@ -8183,6 +8191,26 @@ F: drivers/gpu/drm/drm_panel.c F: drivers/gpu/drm/panel/ F: include/drm/drm_panel.h +DRM PANIC +M: Jocelyn Falempe +M: Javier Martinez Canillas +L: dri-devel@lists.freedesktop.org +S: Supported +T: git https://gitlab.freedesktop.org/drm/misc/kernel.git +F: drivers/gpu/drm/drm_draw.c +F: drivers/gpu/drm/drm_draw_internal.h +F: drivers/gpu/drm/drm_panic*.c +F: include/drm/drm_panic* + +DRM PANIC QR CODE +M: Jocelyn Falempe +M: Javier Martinez Canillas +L: dri-devel@lists.freedesktop.org +L: rust-for-linux@vger.kernel.org +S: Supported +T: git https://gitlab.freedesktop.org/drm/misc/kernel.git +F: drivers/gpu/drm/drm_panic_qr.rs + DRM PRIVACY-SCREEN CLASS M: Hans de Goede L: dri-devel@lists.freedesktop.org -- GitLab From 1773ea5caf0b6640aada70411eba6d33fef8e1d5 Mon Sep 17 00:00:00 2001 From: Philipp Stanner Date: Fri, 14 Mar 2025 11:10:23 +0100 Subject: [PATCH 0043/1479] drm/sched: Fix outdated comments referencing thread The GPU scheduler's comments refer to a "thread" at various places. Those are leftovers from commit a6149f039369 ("drm/sched: Convert drm scheduler to use a work queue rather than kthread"). Replace all references to kthreads. Reviewed-by: Tvrtko Ursulin Signed-off-by: Philipp Stanner Link: https://lore.kernel.org/r/20250314101023.111248-2-phasta@kernel.org --- drivers/gpu/drm/scheduler/sched_entity.c | 8 ++++---- drivers/gpu/drm/scheduler/sched_main.c | 24 +++++++++++++----------- include/drm/gpu_scheduler.h | 2 +- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index bd39db7bb2408..a9ec77a10d931 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -545,10 +545,10 @@ void drm_sched_entity_select_rq(struct drm_sched_entity *entity) return; /* - * Only when the queue is empty are we guaranteed that the scheduler - * thread cannot change ->last_scheduled. To enforce ordering we need - * a read barrier here. See drm_sched_entity_pop_job() for the other - * side. + * Only when the queue is empty are we guaranteed that + * drm_sched_run_job_work() cannot change entity->last_scheduled. To + * enforce ordering we need a read barrier here. See + * drm_sched_entity_pop_job() for the other side. */ smp_rmb(); diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 829579c41c6b5..f7118497e47a8 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -391,7 +391,7 @@ static void drm_sched_run_free_queue(struct drm_gpu_scheduler *sched) * drm_sched_job_done - complete a job * @s_job: pointer to the job which is done * - * Finish the job's fence and wake up the worker thread. + * Finish the job's fence and resubmit the work items. */ static void drm_sched_job_done(struct drm_sched_job *s_job, int result) { @@ -551,9 +551,10 @@ static void drm_sched_job_timedout(struct work_struct *work) if (job) { /* - * Remove the bad job so it cannot be freed by concurrent - * drm_sched_cleanup_jobs. It will be reinserted back after sched->thread - * is parked at which point it's safe. + * Remove the bad job so it cannot be freed by a concurrent + * &struct drm_sched_backend_ops.free_job. It will be + * reinserted after the scheduler's work items have been + * cancelled, at which point it's safe. */ list_del_init(&job->list); spin_unlock(&sched->job_list_lock); @@ -599,10 +600,10 @@ void drm_sched_stop(struct drm_gpu_scheduler *sched, struct drm_sched_job *bad) /* * Reinsert back the bad job here - now it's safe as - * drm_sched_get_finished_job cannot race against us and release the + * drm_sched_get_finished_job() cannot race against us and release the * bad job at this point - we parked (waited for) any in progress - * (earlier) cleanups and drm_sched_get_finished_job will not be called - * now until the scheduler thread is unparked. + * (earlier) cleanups and drm_sched_get_finished_job() will not be + * called now until the scheduler's work items are submitted again. */ if (bad && bad->sched == sched) /* @@ -615,7 +616,8 @@ void drm_sched_stop(struct drm_gpu_scheduler *sched, struct drm_sched_job *bad) * Iterate the job list from later to earlier one and either deactive * their HW callbacks or remove them from pending list if they already * signaled. - * This iteration is thread safe as sched thread is stopped. + * This iteration is thread safe as the scheduler's work items have been + * cancelled. */ list_for_each_entry_safe_reverse(s_job, tmp, &sched->pending_list, list) { @@ -680,9 +682,9 @@ void drm_sched_start(struct drm_gpu_scheduler *sched, int errno) struct drm_sched_job *s_job, *tmp; /* - * Locking the list is not required here as the sched thread is parked - * so no new jobs are being inserted or removed. Also concurrent - * GPU recovers can't run in parallel. + * Locking the list is not required here as the scheduler's work items + * are currently not running, so no new jobs are being inserted or + * removed. Also concurrent GPU recovers can't run in parallel. */ list_for_each_entry_safe(s_job, tmp, &sched->pending_list, list) { struct dma_fence *fence = s_job->s_fence->parent; diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index 1a7e377d4cbb4..d860db087ea5f 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -192,7 +192,7 @@ struct drm_sched_entity { * @last_scheduled: * * Points to the finished fence of the last scheduled job. Only written - * by the scheduler thread, can be accessed locklessly from + * by drm_sched_entity_pop_job(). Can be accessed locklessly from * drm_sched_job_arm() if the queue is empty. */ struct dma_fence __rcu *last_scheduled; -- GitLab From e33c3f4d935454a6f8a18a5913189f060b9140ef Mon Sep 17 00:00:00 2001 From: Philipp Stanner Date: Fri, 14 Mar 2025 11:10:24 +0100 Subject: [PATCH 0044/1479] drm/sched: Remove kthread header The kthread header doesn't need to be included anymore. It's a relict from commit a6149f039369 ("drm/sched: Convert drm scheduler to use a work queue rather than kthread"). Remove the unneeded includes. Reviewed-by: Tvrtko Ursulin Signed-off-by: Philipp Stanner Link: https://lore.kernel.org/r/20250314101023.111248-3-phasta@kernel.org --- drivers/gpu/drm/scheduler/sched_entity.c | 1 - drivers/gpu/drm/scheduler/sched_fence.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index a9ec77a10d931..ff553d8dc5f46 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -21,7 +21,6 @@ * */ -#include #include #include diff --git a/drivers/gpu/drm/scheduler/sched_fence.c b/drivers/gpu/drm/scheduler/sched_fence.c index e971528504a53..d6239e015b66c 100644 --- a/drivers/gpu/drm/scheduler/sched_fence.c +++ b/drivers/gpu/drm/scheduler/sched_fence.c @@ -21,7 +21,6 @@ * */ -#include #include #include #include -- GitLab From 64a8d0aa55e98bf2c9b7e1a3df3e8acbfecba619 Mon Sep 17 00:00:00 2001 From: Asahi Lina Date: Tue, 18 Mar 2025 16:22:35 -0300 Subject: [PATCH 0045/1479] drm/shmem-helper: Add lockdep asserts to vmap/vunmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 21aa27ddc582 ("drm/shmem-helper: Switch to reservation lock"), the drm_gem_shmem_vmap and drm_gem_shmem_vunmap functions require that the caller holds the DMA reservation lock for the object. Add lockdep assertions to help validate this. Signed-off-by: Asahi Lina Signed-off-by: Daniel Almeida Reviewed-by: Christian König Signed-off-by: Lyude Paul Link: https://lore.kernel.org/r/20250318-drm-gem-shmem-v1-1-64b96511a84f@collabora.com --- drivers/gpu/drm/drm_gem_shmem_helper.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c index aa43265f4f4f6..0b41f0346bad1 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -348,6 +348,8 @@ int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, struct drm_gem_object *obj = &shmem->base; int ret = 0; + dma_resv_assert_held(obj->resv); + if (drm_gem_is_imported(obj)) { ret = dma_buf_vmap(obj->dma_buf, map); } else { @@ -408,6 +410,8 @@ void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem, { struct drm_gem_object *obj = &shmem->base; + dma_resv_assert_held(obj->resv); + if (drm_gem_is_imported(obj)) { dma_buf_vunmap(obj->dma_buf, map); } else { -- GitLab From 1f372c1fc6cff841e85913ad2b3b3680e94eabac Mon Sep 17 00:00:00 2001 From: hienhuynh Date: Thu, 8 May 2025 10:50:35 +0100 Subject: [PATCH 0046/1479] drm: rz-du: Support panels connected directly to the DPAD output This patch is based on the commit 73eb5476df72 ("drm: rcar-du: Support panels connected directly to the DPAD outputs"). The RZ DU driver assumes that a bridge is always connected to the DU output. This is valid for the HDMI output, but the DPAD output can be connected directly to a panel, in which case no bridge is available. To support this use case, detect whether the entities connected to the DU DPAD output is encoders or panels based on the number of ports of their DT node, and retrieve the corresponding type of DRM objects. For panels, additionally create panel bridge instances. Signed-off-by: hienhuynh Signed-off-by: Biju Das Reviewed-by: Tommaso Merciai Tested-by: Tommaso Merciai Link: https://lore.kernel.org/r/20250508095042.25164-1-biju.das.jz@bp.renesas.com --- .../gpu/drm/renesas/rz-du/rzg2l_du_encoder.c | 44 +++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_encoder.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_encoder.c index 564ab4cb3d37d..5e6dd16705e60 100644 --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_encoder.c +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_encoder.c @@ -22,6 +22,26 @@ * Encoder */ +static unsigned int rzg2l_du_encoder_count_ports(struct device_node *node) +{ + struct device_node *ports; + struct device_node *port; + unsigned int num_ports = 0; + + ports = of_get_child_by_name(node, "ports"); + if (!ports) + ports = of_node_get(node); + + for_each_child_of_node(ports, port) { + if (of_node_name_eq(port, "port")) + num_ports++; + } + + of_node_put(ports); + + return num_ports; +} + static const struct drm_encoder_funcs rzg2l_du_encoder_funcs = { }; @@ -50,10 +70,26 @@ int rzg2l_du_encoder_init(struct rzg2l_du_device *rcdu, struct drm_bridge *bridge; int ret; - /* Locate the DRM bridge from the DT node. */ - bridge = of_drm_find_bridge(enc_node); - if (!bridge) - return -EPROBE_DEFER; + /* + * Locate the DRM bridge from the DT node. For the DPAD outputs, if the + * DT node has a single port, assume that it describes a panel and + * create a panel bridge. + */ + if (output == RZG2L_DU_OUTPUT_DPAD0 && rzg2l_du_encoder_count_ports(enc_node) == 1) { + struct drm_panel *panel = of_drm_find_panel(enc_node); + + if (IS_ERR(panel)) + return PTR_ERR(panel); + + bridge = devm_drm_panel_bridge_add_typed(rcdu->dev, panel, + DRM_MODE_CONNECTOR_DPI); + if (IS_ERR(bridge)) + return PTR_ERR(bridge); + } else { + bridge = of_drm_find_bridge(enc_node); + if (!bridge) + return -EPROBE_DEFER; + } dev_dbg(rcdu->dev, "initializing encoder %pOF for output %s\n", enc_node, rzg2l_du_output_name(output)); -- GitLab From 1c0ff333f2fe69d571798c11f0277985ce146358 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 14 Apr 2025 11:50:10 +0800 Subject: [PATCH 0047/1479] dt-bindings: display: imx: Add i.MX8qxp Display Controller processing units Freescale i.MX8qxp Display Controller is implemented as construction set of building blocks with unified concept and standardized interfaces. Document all existing processing units. Signed-off-by: Liu Ying Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250414035028.1561475-2-victor.liu@nxp.com --- .../display/imx/fsl,imx8qxp-dc-blitblend.yaml | 41 +++++ .../display/imx/fsl,imx8qxp-dc-clut.yaml | 44 ++++++ .../imx/fsl,imx8qxp-dc-constframe.yaml | 44 ++++++ .../display/imx/fsl,imx8qxp-dc-dither.yaml | 45 ++++++ .../display/imx/fsl,imx8qxp-dc-extdst.yaml | 72 +++++++++ .../display/imx/fsl,imx8qxp-dc-fetchunit.yaml | 141 ++++++++++++++++++ .../display/imx/fsl,imx8qxp-dc-filter.yaml | 43 ++++++ .../display/imx/fsl,imx8qxp-dc-framegen.yaml | 64 ++++++++ .../display/imx/fsl,imx8qxp-dc-gammacor.yaml | 32 ++++ .../imx/fsl,imx8qxp-dc-layerblend.yaml | 39 +++++ .../display/imx/fsl,imx8qxp-dc-matrix.yaml | 44 ++++++ .../display/imx/fsl,imx8qxp-dc-rop.yaml | 43 ++++++ .../display/imx/fsl,imx8qxp-dc-safety.yaml | 34 +++++ .../imx/fsl,imx8qxp-dc-scaling-engine.yaml | 83 +++++++++++ .../display/imx/fsl,imx8qxp-dc-signature.yaml | 53 +++++++ .../display/imx/fsl,imx8qxp-dc-store.yaml | 96 ++++++++++++ .../display/imx/fsl,imx8qxp-dc-tcon.yaml | 45 ++++++ 17 files changed, 963 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-blitblend.yaml create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-clut.yaml create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-constframe.yaml create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-dither.yaml create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-extdst.yaml create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-fetchunit.yaml create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-filter.yaml create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-framegen.yaml create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-gammacor.yaml create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-layerblend.yaml create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-matrix.yaml create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-rop.yaml create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-safety.yaml create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-scaling-engine.yaml create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-signature.yaml create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-store.yaml create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-tcon.yaml diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-blitblend.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-blitblend.yaml new file mode 100644 index 0000000000000..095e65939fba7 --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-blitblend.yaml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-blitblend.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Blit Blend Unit + +description: + Combines two input frames to a single output frame, all frames having the + same dimension. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-blitblend + + reg: + maxItems: 2 + + reg-names: + items: + - const: pec + - const: cfg + +required: + - compatible + - reg + - reg-names + +additionalProperties: false + +examples: + - | + blitblend@56180920 { + compatible = "fsl,imx8qxp-dc-blitblend"; + reg = <0x56180920 0x10>, <0x56183c00 0x3c>; + reg-names = "pec", "cfg"; + }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-clut.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-clut.yaml new file mode 100644 index 0000000000000..21d42aa11b52b --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-clut.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-clut.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Color Lookup Table + +description: | + The unit implements 3 look-up tables with 256 x 10 bit entries each. These + can be used for different kinds of applications. From 10-bit input values + only upper 8 bits are used. + + The unit supports color lookup, index lookup, dithering and alpha masking. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-clut + + reg: + maxItems: 2 + + reg-names: + items: + - const: pec + - const: cfg + +required: + - compatible + - reg + - reg-names + +additionalProperties: false + +examples: + - | + clut@56180880 { + compatible = "fsl,imx8qxp-dc-clut"; + reg = <0x56180880 0x10>, <0x56182400 0x404>; + reg-names = "pec", "cfg"; + }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-constframe.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-constframe.yaml new file mode 100644 index 0000000000000..94f6785636085 --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-constframe.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-constframe.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Constant Frame + +description: | + The Constant Frame unit is used instead of a Fetch unit where generation of + constant color frames only is sufficient. This is the case for the background + planes of content and safety streams in a Display Controller. + + The color can be setup to any RGBA value. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-constframe + + reg: + maxItems: 2 + + reg-names: + items: + - const: pec + - const: cfg + +required: + - compatible + - reg + - reg-names + +additionalProperties: false + +examples: + - | + constframe@56180960 { + compatible = "fsl,imx8qxp-dc-constframe"; + reg = <0x56180960 0xc>, <0x56184400 0x20>; + reg-names = "pec", "cfg"; + }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-dither.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-dither.yaml new file mode 100644 index 0000000000000..8e4468d918366 --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-dither.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-dither.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Dither Unit + +description: | + The unit can increase the physical color resolution of a display from 5, 6, 7 + or 8 bits per RGB channel to a virtual resolution of 10 bits. The physical + resolution can be set individually for each channel. + + The resolution is increased by mixing the two physical colors that are nearest + to the virtual color code in a variable ratio either by time (temporal + dithering) or by position (spatial dithering). + + An optimized algorithm for temporal dithering minimizes noise artifacts on the + output image. + + The dither operation can be individually enabled or disabled for each pixel + using the alpha input bit. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-dither + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + dither@5618c400 { + compatible = "fsl,imx8qxp-dc-dither"; + reg = <0x5618c400 0x14>; + }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-extdst.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-extdst.yaml new file mode 100644 index 0000000000000..dfc2d4f94f8eb --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-extdst.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-extdst.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller External Destination Interface + +description: | + The External Destination unit is the interface between the internal pixel + processing pipeline of the Pixel Engine, which is 30-bit RGB plus 8-bit Alpha, + and a Display Engine. + + It comprises the following built-in Gamma apply function. + + +------X-----------------------+ + | | ExtDst Unit | + | V | + | +-------+ | + | | Gamma | | + | +-------+ | + | | | + | V + + +------X-----------------------+ + + The output format is 24-bit RGB plus 1-bit Alpha. Conversion from 10 to 8 + bits is done by LSBit truncation. Alpha output bit is 1 for input 255, 0 + otherwise. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-extdst + + reg: + maxItems: 2 + + reg-names: + items: + - const: pec + - const: cfg + + interrupts: + maxItems: 3 + + interrupt-names: + items: + - const: shdload + - const: framecomplete + - const: seqcomplete + +required: + - compatible + - reg + - reg-names + - interrupts + - interrupt-names + +additionalProperties: false + +examples: + - | + extdst@56180980 { + compatible = "fsl,imx8qxp-dc-extdst"; + reg = <0x56180980 0x1c>, <0x56184800 0x28>; + reg-names = "pec", "cfg"; + interrupt-parent = <&dc0_intc>; + interrupts = <3>, <4>, <5>; + interrupt-names = "shdload", "framecomplete", "seqcomplete"; + }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-fetchunit.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-fetchunit.yaml new file mode 100644 index 0000000000000..97fb6a4598d96 --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-fetchunit.yaml @@ -0,0 +1,141 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-fetchunit.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Fetch Unit + +description: | + The Fetch Unit is the interface between the AXI bus for source buffer access + and the internal pixel processing pipeline, which is 30-bit RGB plus 8-bit + Alpha. + + It is used to generate foreground planes in Display Controllers and source + planes in Blit Engines, and comprises the following built-in functions to + convert a wide range of frame buffer types. + + +---------X-----------------------------------------+ + | | Fetch Unit | + | V | + | +---------+ | + | | | | + | | Decode | Decompression [Decode] | + | | | | + | +---------+ | + | | | + | V | + | +---------+ | + | | Clip & | Clip Window [All] | + | | Overlay | Plane composition [Layer, Warp] | + | | | | + | +---------+ | + | | | + | V | + | +---------+ | + | | Re- | Flip/Rotate/Repl./Drop [All] | + X--> | sample | Perspective/Affine warping [Persp] | + | | | | Arbitrary warping [Warp, Persp] | + | | +---------+ | + | | | | + | | V | + | | +---------+ | + | | | | | + | | | Palette | Color Palette [Layer, Decode] | + | | | | | + | | +---------+ | + | | | | + | | V | + | | +---------+ | + | | | Extract | Raw to RGBA/YUV [All] | + | | | & | Bit width expansion [All] | + | | | Expand | | + | | +---------+ | + | | | | + | | V | + | | +---------+ | + | | | | Planar to packed | + | |->| Combine | [Decode, Warp, Persp] | + | | | | | + | | +---------+ | + | | | | + | | V | + | | +---------+ | + | | | | YUV422 to YUV444 | + | | | Chroma | [Decode, Persp] | + | | | | | + | | +---------+ | + | | | | + | | V | + | | +---------+ | + | | | | YUV to RGB | + | | | Color | [Warp, Persp, Decode, Layer] | + | | | | | + | | +---------+ | + | | | | + | | V | + | | +---------+ | + | | | | Gamma removal | + | | | Gamma | [Warp, Persp, Decode, Layer] | + | | | | | + | | +---------+ | + | | | | + | | V | + | | +---------+ | + | | | | Alpla multiply, RGB pre-multiply | + | ->| Multiply| [Warp, Persp, Decode, Layer] | + | | | | + | --------- | + | | | + | V | + | +---------+ | + | | | Bilinear filter | + | | Filter | [Warp, Persp] | + | | | | + | +---------+ | + | | | + | V | + +---------X-----------------------------------------+ + + Note that different derivatives of the Fetch Unit exist. Each implements a + specific subset only of the pipeline stages shown above. Restrictions for the + units are specified in [square brackets]. + +maintainers: + - Liu Ying + +properties: + compatible: + enum: + - fsl,imx8qxp-dc-fetchdecode + - fsl,imx8qxp-dc-fetcheco + - fsl,imx8qxp-dc-fetchlayer + - fsl,imx8qxp-dc-fetchwarp + + reg: + maxItems: 2 + + reg-names: + items: + - const: pec + - const: cfg + + fsl,prg: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Optional Prefetch Resolve Gasket associated with the Fetch Unit. + +required: + - compatible + - reg + - reg-names + +additionalProperties: false + +examples: + - | + fetchlayer@56180ac0 { + compatible = "fsl,imx8qxp-dc-fetchlayer"; + reg = <0x56180ac0 0xc>, <0x56188400 0x404>; + reg-names = "pec", "cfg"; + }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-filter.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-filter.yaml new file mode 100644 index 0000000000000..5c54d5179ee38 --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-filter.yaml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-filter.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Filter Unit + +description: | + 5x5 FIR filter with 25 programmable coefficients. + + Typical applications are image blurring, sharpening or support for edge + detection algorithms. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-filter + + reg: + maxItems: 2 + + reg-names: + items: + - const: pec + - const: cfg + +required: + - compatible + - reg + - reg-names + +additionalProperties: false + +examples: + - | + filter@56180900 { + compatible = "fsl,imx8qxp-dc-filter"; + reg = <0x56180900 0x10>, <0x56183800 0x30>; + reg-names = "pec", "cfg"; + }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-framegen.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-framegen.yaml new file mode 100644 index 0000000000000..9d1dc3a9de90e --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-framegen.yaml @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-framegen.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Frame Generator + +description: + The Frame Generator (FrameGen) module generates a programmable video timing + and optionally allows to synchronize the generated video timing to external + synchronization signals. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-framegen + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + interrupts: + maxItems: 8 + + interrupt-names: + items: + - const: int0 + - const: int1 + - const: int2 + - const: int3 + - const: primsync_on + - const: primsync_off + - const: secsync_on + - const: secsync_off + +required: + - compatible + - reg + - clocks + - interrupts + - interrupt-names + +additionalProperties: false + +examples: + - | + #include + #include + + framegen@5618b800 { + compatible = "fsl,imx8qxp-dc-framegen"; + reg = <0x5618b800 0x98>; + clocks = <&dc0_disp_lpcg IMX_LPCG_CLK_0>; + interrupt-parent = <&dc0_intc>; + interrupts = <18>, <19>, <20>, <21>, <41>, <42>, <43>, <44>; + interrupt-names = "int0", "int1", "int2", "int3", + "primsync_on", "primsync_off", + "secsync_on", "secsync_off"; + }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-gammacor.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-gammacor.yaml new file mode 100644 index 0000000000000..25ad857429129 --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-gammacor.yaml @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-gammacor.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Gamma Correction Unit + +description: The unit supports non-linear color transformation. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-gammacor + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + gammacor@5618c000 { + compatible = "fsl,imx8qxp-dc-gammacor"; + reg = <0x5618c000 0x20>; + }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-layerblend.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-layerblend.yaml new file mode 100644 index 0000000000000..2a6ab8a0ed7fc --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-layerblend.yaml @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-layerblend.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Layer Blend Unit + +description: Combines two input frames to a single output frame. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-layerblend + + reg: + maxItems: 2 + + reg-names: + items: + - const: pec + - const: cfg + +required: + - compatible + - reg + - reg-names + +additionalProperties: false + +examples: + - | + layerblend@56180ba0 { + compatible = "fsl,imx8qxp-dc-layerblend"; + reg = <0x56180ba0 0x10>, <0x5618a400 0x20>; + reg-names = "pec", "cfg"; + }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-matrix.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-matrix.yaml new file mode 100644 index 0000000000000..d773389dd0dc1 --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-matrix.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-matrix.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Color Matrix + +description: + The unit supports linear color transformation, alpha pre-multiply and + alpha masking. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-matrix + + reg: + minItems: 1 + maxItems: 2 + + reg-names: + oneOf: + - const: cfg # matrix in display engine + - items: # matrix in pixel engine + - const: pec + - const: cfg + +required: + - compatible + - reg + - reg-names + +additionalProperties: false + +examples: + - | + matrix@5618bc00 { + compatible = "fsl,imx8qxp-dc-matrix"; + reg = <0x5618bc00 0x3c>; + reg-names = "cfg"; + }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-rop.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-rop.yaml new file mode 100644 index 0000000000000..7115950ecae0a --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-rop.yaml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-rop.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Raster Operation Unit + +description: | + The unit can combine up to three input frames to a single output frame, all + having the same dimension. + + The unit supports logic operations, arithmetic operations and packing. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-rop + + reg: + maxItems: 2 + + reg-names: + items: + - const: pec + - const: cfg + +required: + - compatible + - reg + - reg-names + +additionalProperties: false + +examples: + - | + rop@56180860 { + compatible = "fsl,imx8qxp-dc-rop"; + reg = <0x56180860 0x10>, <0x56182000 0x20>; + reg-names = "pec", "cfg"; + }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-safety.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-safety.yaml new file mode 100644 index 0000000000000..66c12948ab092 --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-safety.yaml @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-safety.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Safety Unit + +description: + The unit allows corresponding processing units to be configured in a path + leading to multiple endpoints. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-safety + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + safety@56180800 { + compatible = "fsl,imx8qxp-dc-safety"; + reg = <0x56180800 0x1c>; + }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-scaling-engine.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-scaling-engine.yaml new file mode 100644 index 0000000000000..76cbe11a63643 --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-scaling-engine.yaml @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-scaling-engine.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Scaling Engine + +description: | + The unit can change the dimension of the input frame by nearest or linear + re-sampling with 1/32 sub pixel precision. + + Internally it consist of two independent blocks for horizontal and vertical + scaling. The sequence of both operations is arbitrary. + + Any frame dimensions between 1 and 16384 pixels in width and height are + supported, except that the vertical scaler has a frame width maximum + depending of the system's functional limitations. + + In general all scale factors are supported inside the supported frame + dimensions. In range of scale factors 1/16..16 the filtered output colors + are LSBit precise (e.g. DC ripple free). + + +-----------+ + | Line | + | Buffer | + +-----------+ + ^ + | + V + |\ +-----------+ + ------+ | | | + | | +-->| Vertical |---- + | ----+ | | Scaler | | + | | |/ +-----------+ | + | | | + | | | + | | | |\ + | ------------- -------------+-----+ | + Input --+ X | +--> Output + | ------------- -------------+-----+ | + | | | |/ + | | | + | | |\ +-----------+ | + | ----+ | | | | + | | +-->| Horizontal|---- + ------+ | | Scaler | + |/ +-----------+ + + The unit supports downscaling, upscaling, sub pixel translation and bob + de-interlacing. + +maintainers: + - Liu Ying + +properties: + compatible: + enum: + - fsl,imx8qxp-dc-hscaler + - fsl,imx8qxp-dc-vscaler + + reg: + maxItems: 2 + + reg-names: + items: + - const: pec + - const: cfg + +required: + - compatible + - reg + - reg-names + +additionalProperties: false + +examples: + - | + hscaler@561808c0 { + compatible = "fsl,imx8qxp-dc-hscaler"; + reg = <0x561808c0 0x10>, <0x56183000 0x18>; + reg-names = "pec", "cfg"; + }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-signature.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-signature.yaml new file mode 100644 index 0000000000000..c495822fdc80e --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-signature.yaml @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-signature.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Signature Unit + +description: | + In order to control the correctness of display output, signature values can + be computed for each frame and compared against reference values. In case of + a mismatch (signature violation) a HW event can be triggered, for example a + SW interrupt. + + This unit supports signature computation, reference check, evaluation windows, + alpha masking and panic modes. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-signature + + reg: + maxItems: 1 + + interrupts: + maxItems: 3 + + interrupt-names: + items: + - const: shdload + - const: valid + - const: error + +required: + - compatible + - reg + - interrupts + - interrupt-names + +additionalProperties: false + +examples: + - | + signature@5618d000 { + compatible = "fsl,imx8qxp-dc-signature"; + reg = <0x5618d000 0x140>; + interrupt-parent = <&dc0_intc>; + interrupts = <22>, <23>, <24>; + interrupt-names = "shdload", "valid", "error"; + }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-store.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-store.yaml new file mode 100644 index 0000000000000..42d1b10906beb --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-store.yaml @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-store.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Store Unit + +description: | + The Store unit is the interface between the internal pixel processing + pipeline, which is 30-bit RGB plus 8-bit Alpha, and the AXI bus for + destination buffer access. It is used for the destination of Blit Engines. + It comprises a set of built-in functions to generate a wide range of buffer + formats. Note, that these are exactly inverse to corresponding functions in + the Fetch Unit. + + +------X-------------------------+ + | | Store Unit | + | V | + | +-------+ | + | | Gamma | Gamma apply | + | +-------+ | + | | | + | V | + | +-------+ | + | | Color | RGB to YUV | + | +-------+ | + | | | + | V | + | +-------+ | + | | Chroma| YUV444 to 422 | + | +-------+ | + | | | + | V | + | +-------+ | + | | Reduce| Bit width reduction | + | | | dithering | + | +-------+ | + | | | + | V | + | +-------+ | + | | Pack | RGBA/YUV to RAW | + | | Encode| or Compression | + | +-------+ | + | | | + | V | + +------X-------------------------+ + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-store + + reg: + maxItems: 2 + + reg-names: + items: + - const: pec + - const: cfg + + interrupts: + maxItems: 3 + + interrupt-names: + items: + - const: shdload + - const: framecomplete + - const: seqcomplete + + fsl,lts: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Optional Linear Tile Store associated with the Store Unit. + +required: + - compatible + - reg + - reg-names + - interrupts + - interrupt-names + +additionalProperties: false + +examples: + - | + store@56180940 { + compatible = "fsl,imx8qxp-dc-store"; + reg = <0x56180940 0x1c>, <0x56184000 0x5c>; + reg-names = "pec", "cfg"; + interrupt-parent = <&dc0_intc>; + interrupts = <0>, <1>, <2>; + interrupt-names = "shdload", "framecomplete", "seqcomplete"; + }; diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-tcon.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-tcon.yaml new file mode 100644 index 0000000000000..7a3b77ea92c73 --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-tcon.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-tcon.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Timing Controller + +description: + The TCon can generate a wide range of customized synchronization signals and + does the mapping of the color bits to the output. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-tcon + + reg: + maxItems: 1 + + port: + $ref: /schemas/graph.yaml#/properties/port + description: video output + +required: + - compatible + - reg + - port + +additionalProperties: false + +examples: + - | + tcon@5618c800 { + compatible = "fsl,imx8qxp-dc-tcon"; + reg = <0x5618c800 0x588>; + + port { + dc0_disp0_dc0_pixel_combiner_ch0: endpoint { + remote-endpoint = <&dc0_pixel_combiner_ch0_dc0_disp0>; + }; + }; + }; -- GitLab From b71d3ace779f3e8d6790dbe40c37883ed8be4106 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 14 Apr 2025 11:50:11 +0800 Subject: [PATCH 0048/1479] dt-bindings: display: imx: Add i.MX8qxp Display Controller blit engine i.MX8qxp Display Controller contains a blit engine for raster graphics. It may read up to 3 source images from memory and computes one destination image from it, which is written back to memory. Signed-off-by: Liu Ying Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250414035028.1561475-3-victor.liu@nxp.com --- .../imx/fsl,imx8qxp-dc-blit-engine.yaml | 204 ++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-blit-engine.yaml diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-blit-engine.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-blit-engine.yaml new file mode 100644 index 0000000000000..45db6da39e20e --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-blit-engine.yaml @@ -0,0 +1,204 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-blit-engine.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Blit Engine + +description: | + A blit operation (block based image transfer) reads up to 3 source images + from memory and computes one destination image from it, which is written + back to memory. The following basic operations are supported: + + * Buffer Fill + Fills a buffer with constant color + + * Buffer Copy + Copies one source to a destination buffer. + + * Image Blend + Combines two source images by a blending equation and writes result to + destination (which can be one of the sources). + + * Image Rop2/3 + Combines up to three source images by a logical equation (raster operation) + and writes result to destination (which can be one of the sources). + + * Image Flip + Mirrors the source image in horizontal and/or vertical direction. + + * Format Convert + Convert between the supported color and buffer formats. + + * Color Transform + Modify colors by linear or non-linear transformations. + + * Image Scale + Changes size of the source image. + + * Image Rotate + Rotates the source image by any angle. + + * Image Filter + Performs an FIR filter operation on the source image. + + * Image Warp + Performs a re-sampling of the source image with any pattern. The sample + point positions are read from a compressed coordinate buffer. + + * Buffer Pack + Writes an image with color components stored in up to three different + buffers (planar formats) into a single buffer (packed format). + + * Chroma Resample + Converts between different YUV formats that differ in chroma sampling rate + (4:4:4, 4:2:2, 4:2:0). + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-blit-engine + + reg: + maxItems: 2 + + reg-names: + items: + - const: pec + - const: cfg + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + + ranges: true + +patternProperties: + "^blitblend@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-blitblend + + "^clut@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-clut + + "^fetchdecode@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-fetchdecode + + "^fetcheco@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-fetcheco + + "^fetchwarp@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-fetchwarp + + "^filter@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-filter + + "^hscaler@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-hscaler + + "^matrix@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-matrix + + "^rop@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-rop + + "^store@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-store + + "^vscaler@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-vscaler + +required: + - compatible + - reg + - reg-names + - "#address-cells" + - "#size-cells" + - ranges + +additionalProperties: false + +examples: + - | + blit-engine@56180820 { + compatible = "fsl,imx8qxp-dc-blit-engine"; + reg = <0x56180820 0x13c>, <0x56181000 0x3400>; + reg-names = "pec", "cfg"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + fetchdecode@56180820 { + compatible = "fsl,imx8qxp-dc-fetchdecode"; + reg = <0x56180820 0x10>, <0x56181000 0x404>; + reg-names = "pec", "cfg"; + }; + + store@56180940 { + compatible = "fsl,imx8qxp-dc-store"; + reg = <0x56180940 0x1c>, <0x56184000 0x5c>; + reg-names = "pec", "cfg"; + interrupt-parent = <&dc0_intc>; + interrupts = <0>, <1>, <2>; + interrupt-names = "shdload", "framecomplete", "seqcomplete"; + }; + }; -- GitLab From 33ce3179110db1e83fb7e99d102dd7c3a0e7d55d Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 14 Apr 2025 11:50:12 +0800 Subject: [PATCH 0049/1479] dt-bindings: display: imx: Add i.MX8qxp Display Controller display engine i.MX8qxp Display Controller display engine consists of all processing units that operate in a display clock domain. Signed-off-by: Liu Ying Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250414035028.1561475-4-victor.liu@nxp.com --- .../imx/fsl,imx8qxp-dc-display-engine.yaml | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-display-engine.yaml diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-display-engine.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-display-engine.yaml new file mode 100644 index 0000000000000..91f3bb77d8d0d --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-display-engine.yaml @@ -0,0 +1,152 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-display-engine.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Display Engine + +description: + All Processing Units that operate in a display clock domain. Pixel pipeline + is driven by a video timing and cannot be stalled. Implements all display + specific processing. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-display-engine + + reg: + maxItems: 2 + + reg-names: + items: + - const: top + - const: cfg + + resets: + maxItems: 1 + + interrupts: + maxItems: 3 + + interrupt-names: + items: + - const: shdload + - const: framecomplete + - const: seqcomplete + + power-domains: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + + ranges: true + +patternProperties: + "^dither@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-dither + + "^framegen@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-framegen + + "^gammacor@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-gammacor + + "^matrix@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-matrix + + "^signature@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-signature + + "^tcon@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-tcon + +required: + - compatible + - reg + - reg-names + - interrupts + - interrupt-names + - power-domains + - "#address-cells" + - "#size-cells" + - ranges + +additionalProperties: false + +examples: + - | + #include + #include + + display-engine@5618b400 { + compatible = "fsl,imx8qxp-dc-display-engine"; + reg = <0x5618b400 0x14>, <0x5618b800 0x1c00>; + reg-names = "top", "cfg"; + interrupt-parent = <&dc0_intc>; + interrupts = <15>, <16>, <17>; + interrupt-names = "shdload", "framecomplete", "seqcomplete"; + power-domains = <&pd IMX_SC_R_DC_0_PLL_0>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + framegen@5618b800 { + compatible = "fsl,imx8qxp-dc-framegen"; + reg = <0x5618b800 0x98>; + clocks = <&dc0_disp_lpcg IMX_LPCG_CLK_0>; + interrupt-parent = <&dc0_intc>; + interrupts = <18>, <19>, <20>, <21>, <41>, <42>, <43>, <44>; + interrupt-names = "int0", "int1", "int2", "int3", + "primsync_on", "primsync_off", + "secsync_on", "secsync_off"; + }; + + tcon@5618c800 { + compatible = "fsl,imx8qxp-dc-tcon"; + reg = <0x5618c800 0x588>; + + port { + dc0_disp0_dc0_pixel_combiner_ch0: endpoint { + remote-endpoint = <&dc0_pixel_combiner_ch0_dc0_disp0>; + }; + }; + }; + }; -- GitLab From 69c78e7e8c2a65a007ba92d8c780365fed0aff5d Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 14 Apr 2025 11:50:13 +0800 Subject: [PATCH 0050/1479] dt-bindings: display: imx: Add i.MX8qxp Display Controller pixel engine i.MX8qxp Display Controller pixel engine consists of all processing units that operate in the AXI bus clock domain. Command sequencer and interrupt controller of the Display Controller work with AXI bus clock, but they are not in pixel engine. Signed-off-by: Liu Ying Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250414035028.1561475-5-victor.liu@nxp.com --- .../imx/fsl,imx8qxp-dc-pixel-engine.yaml | 250 ++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-pixel-engine.yaml diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-pixel-engine.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-pixel-engine.yaml new file mode 100644 index 0000000000000..633443a6cc380 --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-pixel-engine.yaml @@ -0,0 +1,250 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-pixel-engine.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Pixel Engine + +description: + All Processing Units that operate in the AXI bus clock domain. Pixel + pipelines have the ability to stall when a destination is busy. Implements + all communication to memory resources and most of the image processing + functions. Interconnection of Processing Units is re-configurable. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-pixel-engine + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + + ranges: true + +patternProperties: + "^blit-engine@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-blit-engine + + "^constframe@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-constframe + + "^extdst@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-extdst + + "^fetchdecode@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-fetchdecode + + "^fetcheco@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-fetcheco + + "^fetchlayer@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-fetchlayer + + "^fetchwarp@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-fetchwarp + + "^hscaler@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-hscaler + + "^layerblend@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-layerblend + + "^matrix@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-matrix + + "^safety@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-safety + + "^vscaler@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-vscaler + +required: + - compatible + - reg + - clocks + - "#address-cells" + - "#size-cells" + - ranges + +additionalProperties: false + +examples: + - | + #include + + pixel-engine@56180800 { + compatible = "fsl,imx8qxp-dc-pixel-engine"; + reg = <0x56180800 0xac00>; + clocks = <&dc0_lpcg IMX_LPCG_CLK_5>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + constframe@56180960 { + compatible = "fsl,imx8qxp-dc-constframe"; + reg = <0x56180960 0xc>, <0x56184400 0x20>; + reg-names = "pec", "cfg"; + }; + + extdst@56180980 { + compatible = "fsl,imx8qxp-dc-extdst"; + reg = <0x56180980 0x1c>, <0x56184800 0x28>; + reg-names = "pec", "cfg"; + interrupt-parent = <&dc0_intc>; + interrupts = <3>, <4>, <5>; + interrupt-names = "shdload", "framecomplete", "seqcomplete"; + }; + + constframe@561809a0 { + compatible = "fsl,imx8qxp-dc-constframe"; + reg = <0x561809a0 0xc>, <0x56184c00 0x20>; + reg-names = "pec", "cfg"; + }; + + extdst@561809c0 { + compatible = "fsl,imx8qxp-dc-extdst"; + reg = <0x561809c0 0x1c>, <0x56185000 0x28>; + reg-names = "pec", "cfg"; + interrupt-parent = <&dc0_intc>; + interrupts = <6>, <7>, <8>; + interrupt-names = "shdload", "framecomplete", "seqcomplete"; + }; + + constframe@561809e0 { + compatible = "fsl,imx8qxp-dc-constframe"; + reg = <0x561809e0 0xc>, <0x56185400 0x20>; + reg-names = "pec", "cfg"; + }; + + extdst@56180a00 { + compatible = "fsl,imx8qxp-dc-extdst"; + reg = <0x56180a00 0x1c>, <0x56185800 0x28>; + reg-names = "pec", "cfg"; + interrupt-parent = <&dc0_intc>; + interrupts = <9>, <10>, <11>; + interrupt-names = "shdload", "framecomplete", "seqcomplete"; + }; + + constframe@56180a20 { + compatible = "fsl,imx8qxp-dc-constframe"; + reg = <0x56180a20 0xc>, <0x56185c00 0x20>; + reg-names = "pec", "cfg"; + }; + + extdst@56180a40 { + compatible = "fsl,imx8qxp-dc-extdst"; + reg = <0x56180a40 0x1c>, <0x56186000 0x28>; + reg-names = "pec", "cfg"; + interrupt-parent = <&dc0_intc>; + interrupts = <12>, <13>, <14>; + interrupt-names = "shdload", "framecomplete", "seqcomplete"; + }; + + fetchwarp@56180a60 { + compatible = "fsl,imx8qxp-dc-fetchwarp"; + reg = <0x56180a60 0x10>, <0x56186400 0x190>; + reg-names = "pec", "cfg"; + }; + + fetchlayer@56180ac0 { + compatible = "fsl,imx8qxp-dc-fetchlayer"; + reg = <0x56180ac0 0xc>, <0x56188400 0x404>; + reg-names = "pec", "cfg"; + }; + + layerblend@56180ba0 { + compatible = "fsl,imx8qxp-dc-layerblend"; + reg = <0x56180ba0 0x10>, <0x5618a400 0x20>; + reg-names = "pec", "cfg"; + }; + + layerblend@56180bc0 { + compatible = "fsl,imx8qxp-dc-layerblend"; + reg = <0x56180bc0 0x10>, <0x5618a800 0x20>; + reg-names = "pec", "cfg"; + }; + + layerblend@56180be0 { + compatible = "fsl,imx8qxp-dc-layerblend"; + reg = <0x56180be0 0x10>, <0x5618ac00 0x20>; + reg-names = "pec", "cfg"; + }; + + layerblend@56180c00 { + compatible = "fsl,imx8qxp-dc-layerblend"; + reg = <0x56180c00 0x10>, <0x5618b000 0x20>; + reg-names = "pec", "cfg"; + }; + }; -- GitLab From e0390da391b9c240a309790fd226caa3d906cf8c Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 14 Apr 2025 11:50:14 +0800 Subject: [PATCH 0051/1479] dt-bindings: display: imx: Add i.MX8qxp Display Controller AXI performance counter i.MX8qxp Display Controller contains a AXI performance counter which allows measurement of average bandwidth and latency during operation. Signed-off-by: Liu Ying Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250414035028.1561475-6-victor.liu@nxp.com --- ...sl,imx8qxp-dc-axi-performance-counter.yaml | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-axi-performance-counter.yaml diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-axi-performance-counter.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-axi-performance-counter.yaml new file mode 100644 index 0000000000000..1d6501afc7f2e --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-axi-performance-counter.yaml @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-axi-performance-counter.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller AXI Performance Counter + +description: | + Performance counters are provided to allow measurement of average bandwidth + and latency during operation. The following features are supported: + + * Manual and timer controlled measurement mode. + + * Measurement counters: + - GLOBAL_COUNTER for overall measurement time + - BUSY_COUNTER for number of data bus busy cycles + - DATA_COUNTER for number of data transfer cycles + - TRANSFER_COUNTER for number of transfers + - ADDRBUSY_COUNTER for number of address bus busy cycles + - LATENCY_COUNTER for average latency + + * Counter overflow detection. + + * Outstanding Transfer Counters (OTC) which are used for latency measurement + have to run immediately after reset, but can be disabled by software when + there is no need for latency measurement. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-axi-performance-counter + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + +required: + - compatible + - reg + - clocks + +additionalProperties: false + +examples: + - | + #include + + pmu@5618f000 { + compatible = "fsl,imx8qxp-dc-axi-performance-counter"; + reg = <0x5618f000 0x90>; + clocks = <&dc0_lpcg IMX_LPCG_CLK_5>; + }; -- GitLab From c809469f25fde307190a38c99982f91e5df53ac7 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 14 Apr 2025 11:50:15 +0800 Subject: [PATCH 0052/1479] dt-bindings: display: imx: Add i.MX8qxp Display Controller command sequencer i.MX8qxp Display Controller contains a command sequencer is designed to autonomously process command lists. Signed-off-by: Liu Ying Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250414035028.1561475-7-victor.liu@nxp.com --- .../imx/fsl,imx8qxp-dc-command-sequencer.yaml | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-command-sequencer.yaml diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-command-sequencer.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-command-sequencer.yaml new file mode 100644 index 0000000000000..27118f4c0d281 --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-command-sequencer.yaml @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc-command-sequencer.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller Command Sequencer + +description: | + The Command Sequencer is designed to autonomously process command lists. + By that it can load setups into the DC configuration and synchronize to + hardware events. This releases a system's CPU from workload, because it + does not need to wait for certain events. Also it simplifies SW architecture, + because no interrupt handlers are required. Setups are read via AXI bus, + while write access to configuration registers occurs directly via an internal + bus. This saves bandwidth for the AXI interconnect and improves the system + architecture in terms of safety aspects. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-command-sequencer + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + interrupts: + maxItems: 5 + + interrupt-names: + items: + - const: error + - const: sw0 + - const: sw1 + - const: sw2 + - const: sw3 + + sram: + $ref: /schemas/types.yaml#/definitions/phandle + description: phandle pointing to the mmio-sram device node + +required: + - compatible + - reg + - clocks + - interrupts + - interrupt-names + +additionalProperties: false + +examples: + - | + #include + + command-sequencer@56180400 { + compatible = "fsl,imx8qxp-dc-command-sequencer"; + reg = <0x56180400 0x1a4>; + clocks = <&dc0_lpcg IMX_LPCG_CLK_5>; + interrupt-parent = <&dc0_intc>; + interrupts = <36>, <37>, <38>, <39>, <40>; + interrupt-names = "error", "sw0", "sw1", "sw2", "sw3"; + }; -- GitLab From 57e464a30d335c2fd8f64449ac2170ce7c2f3662 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 14 Apr 2025 11:50:16 +0800 Subject: [PATCH 0053/1479] dt-bindings: interrupt-controller: Add i.MX8qxp Display Controller interrupt controller i.MX8qxp Display Controller has a built-in interrupt controller to support Enable/Status/Preset/Clear interrupt bit. Signed-off-by: Liu Ying Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250414035028.1561475-8-victor.liu@nxp.com --- .../fsl,imx8qxp-dc-intc.yaml | 318 ++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/fsl,imx8qxp-dc-intc.yaml diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,imx8qxp-dc-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/fsl,imx8qxp-dc-intc.yaml new file mode 100644 index 0000000000000..6985ee644a255 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,imx8qxp-dc-intc.yaml @@ -0,0 +1,318 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/fsl,imx8qxp-dc-intc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller interrupt controller + +description: | + The Display Controller has a built-in interrupt controller with the following + features for all relevant HW events: + + * Enable bit (mask) + * Status bit (set by an HW event) + * Preset bit (can be used by SW to set status) + * Clear bit (used by SW to reset the status) + + Each interrupt can be connected as IRQ (maskable) and/or NMI (non-maskable). + Alternatively the un-masked trigger signals for all HW events are provided, + allowing it to use a global interrupt controller instead. + + Each interrupt can be protected against SW running in user mode. In that case, + only privileged AHB access can control the interrupt status. + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc-intc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + interrupt-controller: true + + "#interrupt-cells": + const: 1 + + interrupts: + items: + - description: store9 shadow load interrupt(blit engine) + - description: store9 frame complete interrupt(blit engine) + - description: store9 sequence complete interrupt(blit engine) + - description: + extdst0 shadow load interrupt + (display controller, content stream 0) + - description: + extdst0 frame complete interrupt + (display controller, content stream 0) + - description: + extdst0 sequence complete interrupt + (display controller, content stream 0) + - description: + extdst4 shadow load interrupt + (display controller, safety stream 0) + - description: + extdst4 frame complete interrupt + (display controller, safety stream 0) + - description: + extdst4 sequence complete interrupt + (display controller, safety stream 0) + - description: + extdst1 shadow load interrupt + (display controller, content stream 1) + - description: + extdst1 frame complete interrupt + (display controller, content stream 1) + - description: + extdst1 sequence complete interrupt + (display controller, content stream 1) + - description: + extdst5 shadow load interrupt + (display controller, safety stream 1) + - description: + extdst5 frame complete interrupt + (display controller, safety stream 1) + - description: + extdst5 sequence complete interrupt + (display controller, safety stream 1) + - description: + disengcfg0 shadow load interrupt + (display controller, display stream 0) + - description: + disengcfg0 frame complete interrupt + (display controller, display stream 0) + - description: + disengcfg0 sequence complete interrupt + (display controller, display stream 0) + - description: + framegen0 programmable interrupt0 + (display controller, display stream 0) + - description: + framegen0 programmable interrupt1 + (display controller, display stream 0) + - description: + framegen0 programmable interrupt2 + (display controller, display stream 0) + - description: + framegen0 programmable interrupt3 + (display controller, display stream 0) + - description: + signature0 shadow load interrupt + (display controller, display stream 0) + - description: + signature0 measurement valid interrupt + (display controller, display stream 0) + - description: + signature0 error condition interrupt + (display controller, display stream 0) + - description: + disengcfg1 shadow load interrupt + (display controller, display stream 1) + - description: + disengcfg1 frame complete interrupt + (display controller, display stream 1) + - description: + disengcfg1 sequence complete interrupt + (display controller, display stream 1) + - description: + framegen1 programmable interrupt0 + (display controller, display stream 1) + - description: + framegen1 programmable interrupt1 + (display controller, display stream 1) + - description: + framegen1 programmable interrupt2 + (display controller, display stream 1) + - description: + framegen1 programmable interrupt3 + (display controller, display stream 1) + - description: + signature1 shadow load interrupt + (display controller, display stream 1) + - description: + signature1 measurement valid interrupt + (display controller, display stream 1) + - description: + signature1 error condition interrupt + (display controller, display stream 1) + - description: reserved + - description: + command sequencer error condition interrupt(command sequencer) + - description: + common control software interrupt0(common control) + - description: + common control software interrupt1(common control) + - description: + common control software interrupt2(common control) + - description: + common control software interrupt3(common control) + - description: + framegen0 synchronization status activated interrupt + (display controller, safety stream 0) + - description: + framegen0 synchronization status deactivated interrupt + (display controller, safety stream 0) + - description: + framegen0 synchronization status activated interrupt + (display controller, content stream 0) + - description: + framegen0 synchronization status deactivated interrupt + (display controller, content stream 0) + - description: + framegen1 synchronization status activated interrupt + (display controller, safety stream 1) + - description: + framegen1 synchronization status deactivated interrupt + (display controller, safety stream 1) + - description: + framegen1 synchronization status activated interrupt + (display controller, content stream 1) + - description: + framegen1 synchronization status deactivated interrupt + (display controller, content stream 1) + minItems: 49 + + interrupt-names: + items: + - const: store9_shdload + - const: store9_framecomplete + - const: store9_seqcomplete + - const: extdst0_shdload + - const: extdst0_framecomplete + - const: extdst0_seqcomplete + - const: extdst4_shdload + - const: extdst4_framecomplete + - const: extdst4_seqcomplete + - const: extdst1_shdload + - const: extdst1_framecomplete + - const: extdst1_seqcomplete + - const: extdst5_shdload + - const: extdst5_framecomplete + - const: extdst5_seqcomplete + - const: disengcfg_shdload0 + - const: disengcfg_framecomplete0 + - const: disengcfg_seqcomplete0 + - const: framegen0_int0 + - const: framegen0_int1 + - const: framegen0_int2 + - const: framegen0_int3 + - const: sig0_shdload + - const: sig0_valid + - const: sig0_error + - const: disengcfg_shdload1 + - const: disengcfg_framecomplete1 + - const: disengcfg_seqcomplete1 + - const: framegen1_int0 + - const: framegen1_int1 + - const: framegen1_int2 + - const: framegen1_int3 + - const: sig1_shdload + - const: sig1_valid + - const: sig1_error + - const: reserved + - const: cmdseq_error + - const: comctrl_sw0 + - const: comctrl_sw1 + - const: comctrl_sw2 + - const: comctrl_sw3 + - const: framegen0_primsync_on + - const: framegen0_primsync_off + - const: framegen0_secsync_on + - const: framegen0_secsync_off + - const: framegen1_primsync_on + - const: framegen1_primsync_off + - const: framegen1_secsync_on + - const: framegen1_secsync_off + minItems: 49 + +required: + - compatible + - reg + - clocks + - interrupt-controller + - "#interrupt-cells" + - interrupts + - interrupt-names + +additionalProperties: false + +examples: + - | + #include + + interrupt-controller@56180040 { + compatible = "fsl,imx8qxp-dc-intc"; + reg = <0x56180040 0x60>; + clocks = <&dc0_lpcg IMX_LPCG_CLK_5>; + interrupt-controller; + interrupt-parent = <&dc0_irqsteer>; + #interrupt-cells = <1>; + interrupts = <448>, <449>, <450>, <64>, + <65>, <66>, <67>, <68>, + <69>, <70>, <193>, <194>, + <195>, <196>, <197>, <72>, + <73>, <74>, <75>, <76>, + <77>, <78>, <79>, <80>, + <81>, <199>, <200>, <201>, + <202>, <203>, <204>, <205>, + <206>, <207>, <208>, <5>, + <0>, <1>, <2>, <3>, + <4>, <82>, <83>, <84>, + <85>, <209>, <210>, <211>, + <212>; + interrupt-names = "store9_shdload", + "store9_framecomplete", + "store9_seqcomplete", + "extdst0_shdload", + "extdst0_framecomplete", + "extdst0_seqcomplete", + "extdst4_shdload", + "extdst4_framecomplete", + "extdst4_seqcomplete", + "extdst1_shdload", + "extdst1_framecomplete", + "extdst1_seqcomplete", + "extdst5_shdload", + "extdst5_framecomplete", + "extdst5_seqcomplete", + "disengcfg_shdload0", + "disengcfg_framecomplete0", + "disengcfg_seqcomplete0", + "framegen0_int0", + "framegen0_int1", + "framegen0_int2", + "framegen0_int3", + "sig0_shdload", + "sig0_valid", + "sig0_error", + "disengcfg_shdload1", + "disengcfg_framecomplete1", + "disengcfg_seqcomplete1", + "framegen1_int0", + "framegen1_int1", + "framegen1_int2", + "framegen1_int3", + "sig1_shdload", + "sig1_valid", + "sig1_error", + "reserved", + "cmdseq_error", + "comctrl_sw0", + "comctrl_sw1", + "comctrl_sw2", + "comctrl_sw3", + "framegen0_primsync_on", + "framegen0_primsync_off", + "framegen0_secsync_on", + "framegen0_secsync_off", + "framegen1_primsync_on", + "framegen1_primsync_off", + "framegen1_secsync_on", + "framegen1_secsync_off"; + }; -- GitLab From 813f71ac2541d12e146cdb9ac3a81432e6687625 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 14 Apr 2025 11:50:17 +0800 Subject: [PATCH 0054/1479] dt-bindings: display: imx: Add i.MX8qxp Display Controller i.MX8qxp Display Controller(DC) is comprised of three main components that include a blit engine for 2D graphics accelerations, display controller for display output processing, as well as a command sequencer. Signed-off-by: Liu Ying Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250414035028.1561475-9-victor.liu@nxp.com --- .../bindings/display/imx/fsl,imx8qxp-dc.yaml | 236 ++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc.yaml diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc.yaml new file mode 100644 index 0000000000000..0a72f9f0b5fda --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc.yaml @@ -0,0 +1,236 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/imx/fsl,imx8qxp-dc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX8qxp Display Controller + +description: | + The Freescale i.MX8qxp Display Controller(DC) is comprised of three main + components that include a blit engine for 2D graphics accelerations, display + controller for display output processing, as well as a command sequencer. + + Display buffers Source buffers + (AXI read master) (AXI read master) + | .......... | | | | + +---------------------------+------------+------------------+-+-+------+ + | Display Controller (DC) | .......... | | | | | + | | | | | | | + | @@@@@@@@@@@ +----------+------------+------------+ | | | | + A | | Command | | V V | | | | | + X <-+->| Sequencer | | @@@@@@@@@@@@@@@@@@@@@@@@@@@@ | V V V | + I | | (AXI CLK) | | | | | @@@@@@@@@@ | + | @@@@@@@@@@@ | | Pixel Engine | | | | | + | | | | (AXI CLK) | | | | | + | V | @@@@@@@@@@@@@@@@@@@@@@@@@@@@ | | | | + A | *********** | | | | | | | Blit | | + H <-+->| Configure | | V V V V | | Engine | | + B | | (CFG CLK) | | 00000000000 11111111111 | | (AXI CLK)| | + | *********** | | Display | | Display | | | | | + | | | Engine | | Engine | | | | | + | | | (Disp CLK)| | (Disp CLK)| | | | | + | @@@@@@@@@@@ | 00000000000 11111111111 | @@@@@@@@@@ | + I | | Common | | | | | | | + R <-+--| Control | | | Display | | | | + Q | | (AXI CLK) | | | Controller | | | | + | @@@@@@@@@@@ +------------------------------------+ | | + | | | ^ | | + +--------------------------+----------------+-------+---------+--------+ + ^ | | | | + | V V | V + Clocks & Resets Display Display Panic Destination + Output0 Output1 Control buffer + (AXI write master) + +maintainers: + - Liu Ying + +properties: + compatible: + const: fsl,imx8qxp-dc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + resets: + maxItems: 2 + + reset-names: + items: + - const: axi + - const: cfg + + power-domains: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + + ranges: true + +patternProperties: + "^command-sequencer@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-command-sequencer + + "^display-engine@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-display-engine + + "^interrupt-controller@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-intc + + "^pixel-engine@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-pixel-engine + + "^pmu@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + const: fsl,imx8qxp-dc-axi-performance-counter + +required: + - compatible + - reg + - clocks + - power-domains + - "#address-cells" + - "#size-cells" + - ranges + +additionalProperties: false + +examples: + - | + #include + #include + + display-controller@56180000 { + compatible = "fsl,imx8qxp-dc"; + reg = <0x56180000 0x40000>; + clocks = <&dc0_lpcg IMX_LPCG_CLK_4>; + power-domains = <&pd IMX_SC_R_DC_0>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + interrupt-controller@56180040 { + compatible = "fsl,imx8qxp-dc-intc"; + reg = <0x56180040 0x60>; + clocks = <&dc0_lpcg IMX_LPCG_CLK_5>; + interrupt-controller; + interrupt-parent = <&dc0_irqsteer>; + #interrupt-cells = <1>; + interrupts = <448>, <449>, <450>, <64>, + <65>, <66>, <67>, <68>, + <69>, <70>, <193>, <194>, + <195>, <196>, <197>, <72>, + <73>, <74>, <75>, <76>, + <77>, <78>, <79>, <80>, + <81>, <199>, <200>, <201>, + <202>, <203>, <204>, <205>, + <206>, <207>, <208>, <5>, + <0>, <1>, <2>, <3>, + <4>, <82>, <83>, <84>, + <85>, <209>, <210>, <211>, + <212>; + interrupt-names = "store9_shdload", + "store9_framecomplete", + "store9_seqcomplete", + "extdst0_shdload", + "extdst0_framecomplete", + "extdst0_seqcomplete", + "extdst4_shdload", + "extdst4_framecomplete", + "extdst4_seqcomplete", + "extdst1_shdload", + "extdst1_framecomplete", + "extdst1_seqcomplete", + "extdst5_shdload", + "extdst5_framecomplete", + "extdst5_seqcomplete", + "disengcfg_shdload0", + "disengcfg_framecomplete0", + "disengcfg_seqcomplete0", + "framegen0_int0", + "framegen0_int1", + "framegen0_int2", + "framegen0_int3", + "sig0_shdload", + "sig0_valid", + "sig0_error", + "disengcfg_shdload1", + "disengcfg_framecomplete1", + "disengcfg_seqcomplete1", + "framegen1_int0", + "framegen1_int1", + "framegen1_int2", + "framegen1_int3", + "sig1_shdload", + "sig1_valid", + "sig1_error", + "reserved", + "cmdseq_error", + "comctrl_sw0", + "comctrl_sw1", + "comctrl_sw2", + "comctrl_sw3", + "framegen0_primsync_on", + "framegen0_primsync_off", + "framegen0_secsync_on", + "framegen0_secsync_off", + "framegen1_primsync_on", + "framegen1_primsync_off", + "framegen1_secsync_on", + "framegen1_secsync_off"; + }; + + pixel-engine@56180800 { + compatible = "fsl,imx8qxp-dc-pixel-engine"; + reg = <0x56180800 0xac00>; + clocks = <&dc0_lpcg IMX_LPCG_CLK_5>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + }; + + display-engine@5618b400 { + compatible = "fsl,imx8qxp-dc-display-engine"; + reg = <0x5618b400 0x14>, <0x5618b800 0x1c00>; + reg-names = "top", "cfg"; + interrupt-parent = <&dc0_intc>; + interrupts = <15>, <16>, <17>; + interrupt-names = "shdload", "framecomplete", "seqcomplete"; + power-domains = <&pd IMX_SC_R_DC_0_PLL_0>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + }; + }; -- GitLab From 9f09e3173776b9da4fde0c0641d1d1e9d08fcf46 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 14 Apr 2025 11:50:18 +0800 Subject: [PATCH 0055/1479] drm/imx: Add i.MX8qxp Display Controller display engine i.MX8qxp Display Controller display engine consists of all processing units that operate in a display clock domain. Add minimal feature support with FrameGen and TCon so that the engine can output display timings. The FrameGen driver, TCon driver and display engine driver are components to be aggregated by a master registered in the upcoming DRM driver. Reviewed-by: Maxime Ripard Signed-off-by: Liu Ying Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250414035028.1561475-10-victor.liu@nxp.com --- drivers/gpu/drm/imx/Kconfig | 1 + drivers/gpu/drm/imx/Makefile | 1 + drivers/gpu/drm/imx/dc/Kconfig | 7 + drivers/gpu/drm/imx/dc/Makefile | 5 + drivers/gpu/drm/imx/dc/dc-de.c | 177 +++++++++++++++ drivers/gpu/drm/imx/dc/dc-de.h | 56 +++++ drivers/gpu/drm/imx/dc/dc-drv.c | 32 +++ drivers/gpu/drm/imx/dc/dc-drv.h | 57 +++++ drivers/gpu/drm/imx/dc/dc-fg.c | 376 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/imx/dc/dc-tc.c | 141 ++++++++++++ 10 files changed, 853 insertions(+) create mode 100644 drivers/gpu/drm/imx/dc/Kconfig create mode 100644 drivers/gpu/drm/imx/dc/Makefile create mode 100644 drivers/gpu/drm/imx/dc/dc-de.c create mode 100644 drivers/gpu/drm/imx/dc/dc-de.h create mode 100644 drivers/gpu/drm/imx/dc/dc-drv.c create mode 100644 drivers/gpu/drm/imx/dc/dc-drv.h create mode 100644 drivers/gpu/drm/imx/dc/dc-fg.c create mode 100644 drivers/gpu/drm/imx/dc/dc-tc.c diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig index 03535a15dd8f3..3e8c6edbc17c2 100644 --- a/drivers/gpu/drm/imx/Kconfig +++ b/drivers/gpu/drm/imx/Kconfig @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only +source "drivers/gpu/drm/imx/dc/Kconfig" source "drivers/gpu/drm/imx/dcss/Kconfig" source "drivers/gpu/drm/imx/ipuv3/Kconfig" source "drivers/gpu/drm/imx/lcdc/Kconfig" diff --git a/drivers/gpu/drm/imx/Makefile b/drivers/gpu/drm/imx/Makefile index 86f38e7c74222..c7b317640d71d 100644 --- a/drivers/gpu/drm/imx/Makefile +++ b/drivers/gpu/drm/imx/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_DRM_IMX8_DC) += dc/ obj-$(CONFIG_DRM_IMX_DCSS) += dcss/ obj-$(CONFIG_DRM_IMX) += ipuv3/ obj-$(CONFIG_DRM_IMX_LCDC) += lcdc/ diff --git a/drivers/gpu/drm/imx/dc/Kconfig b/drivers/gpu/drm/imx/dc/Kconfig new file mode 100644 index 0000000000000..e1ef76d828307 --- /dev/null +++ b/drivers/gpu/drm/imx/dc/Kconfig @@ -0,0 +1,7 @@ +config DRM_IMX8_DC + tristate "Freescale i.MX8 Display Controller Graphics" + depends on DRM && COMMON_CLK && OF && (ARCH_MXC || COMPILE_TEST) + select REGMAP + select REGMAP_MMIO + help + enable Freescale i.MX8 Display Controller(DC) graphics support diff --git a/drivers/gpu/drm/imx/dc/Makefile b/drivers/gpu/drm/imx/dc/Makefile new file mode 100644 index 0000000000000..56de82d53d4d4 --- /dev/null +++ b/drivers/gpu/drm/imx/dc/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +imx8-dc-drm-objs := dc-de.o dc-drv.o dc-fg.o dc-tc.o + +obj-$(CONFIG_DRM_IMX8_DC) += imx8-dc-drm.o diff --git a/drivers/gpu/drm/imx/dc/dc-de.c b/drivers/gpu/drm/imx/dc/dc-de.c new file mode 100644 index 0000000000000..5a3125596fdf4 --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-de.c @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dc-de.h" +#include "dc-drv.h" + +#define POLARITYCTRL 0xc +#define POLEN_HIGH BIT(2) + +static const struct dc_subdev_info dc_de_info[] = { + { .reg_start = 0x5618b400, .id = 0, }, + { .reg_start = 0x5618b420, .id = 1, }, +}; + +static const struct regmap_range dc_de_regmap_ranges[] = { + regmap_reg_range(POLARITYCTRL, POLARITYCTRL), +}; + +static const struct regmap_access_table dc_de_regmap_access_table = { + .yes_ranges = dc_de_regmap_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_de_regmap_ranges), +}; + +static const struct regmap_config dc_de_top_regmap_config = { + .name = "top", + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .wr_table = &dc_de_regmap_access_table, + .rd_table = &dc_de_regmap_access_table, + .max_register = POLARITYCTRL, +}; + +static inline void dc_dec_init(struct dc_de *de) +{ + regmap_write_bits(de->reg_top, POLARITYCTRL, POLARITYCTRL, POLEN_HIGH); +} + +static int dc_de_bind(struct device *dev, struct device *master, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + struct dc_drm_device *dc_drm = data; + struct resource *res_top; + void __iomem *base_top; + struct dc_de *de; + int ret, id; + + de = devm_kzalloc(dev, sizeof(*de), GFP_KERNEL); + if (!de) + return -ENOMEM; + + base_top = devm_platform_get_and_ioremap_resource(pdev, 0, &res_top); + if (IS_ERR(base_top)) + return PTR_ERR(base_top); + + de->reg_top = devm_regmap_init_mmio(dev, base_top, + &dc_de_top_regmap_config); + if (IS_ERR(de->reg_top)) + return PTR_ERR(de->reg_top); + + de->irq_shdload = platform_get_irq_byname(pdev, "shdload"); + if (de->irq_shdload < 0) + return de->irq_shdload; + + de->irq_framecomplete = platform_get_irq_byname(pdev, "framecomplete"); + if (de->irq_framecomplete < 0) + return de->irq_framecomplete; + + de->irq_seqcomplete = platform_get_irq_byname(pdev, "seqcomplete"); + if (de->irq_seqcomplete < 0) + return de->irq_seqcomplete; + + de->dev = dev; + + dev_set_drvdata(dev, de); + + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; + + id = dc_subdev_get_id(dc_de_info, ARRAY_SIZE(dc_de_info), res_top); + if (id < 0) { + dev_err(dev, "failed to get instance number: %d\n", id); + return id; + } + + dc_drm->de[id] = de; + + return 0; +} + +/* + * It's possible to get the child device pointers from the child component + * bind callbacks, but it depends on the component helper behavior to bind + * the display engine component first. To avoid the dependency, post bind + * to get the pointers from dc_drm in a safe manner. + */ +void dc_de_post_bind(struct dc_drm_device *dc_drm) +{ + struct dc_de *de; + int i; + + for (i = 0; i < DC_DISPLAYS; i++) { + de = dc_drm->de[i]; + de->fg = dc_drm->fg[i]; + de->tc = dc_drm->tc[i]; + } +} + +static const struct component_ops dc_de_ops = { + .bind = dc_de_bind, +}; + +static int dc_de_probe(struct platform_device *pdev) +{ + int ret; + + ret = devm_of_platform_populate(&pdev->dev); + if (ret < 0) + return ret; + + ret = component_add(&pdev->dev, &dc_de_ops); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to add component\n"); + + return 0; +} + +static void dc_de_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &dc_de_ops); +} + +static int dc_de_runtime_resume(struct device *dev) +{ + struct dc_de *de = dev_get_drvdata(dev); + + dc_dec_init(de); + dc_fg_init(de->fg); + dc_tc_init(de->tc); + + return 0; +} + +static const struct dev_pm_ops dc_de_pm_ops = { + RUNTIME_PM_OPS(NULL, dc_de_runtime_resume, NULL) +}; + +static const struct of_device_id dc_de_dt_ids[] = { + { .compatible = "fsl,imx8qxp-dc-display-engine" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dc_de_dt_ids); + +struct platform_driver dc_de_driver = { + .probe = dc_de_probe, + .remove = dc_de_remove, + .driver = { + .name = "imx8-dc-display-engine", + .suppress_bind_attrs = true, + .of_match_table = dc_de_dt_ids, + .pm = pm_sleep_ptr(&dc_de_pm_ops), + }, +}; diff --git a/drivers/gpu/drm/imx/dc/dc-de.h b/drivers/gpu/drm/imx/dc/dc-de.h new file mode 100644 index 0000000000000..5dd311cde0768 --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-de.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2024 NXP + */ + +#ifndef __DC_DISPLAY_ENGINE_H__ +#define __DC_DISPLAY_ENGINE_H__ + +#include +#include +#include +#include + +#define DC_DISPLAYS 2 + +struct dc_fg { + struct device *dev; + struct regmap *reg; + struct clk *clk_disp; +}; + +struct dc_tc { + struct device *dev; + struct regmap *reg; +}; + +struct dc_de { + struct device *dev; + struct regmap *reg_top; + struct dc_fg *fg; + struct dc_tc *tc; + int irq_shdload; + int irq_framecomplete; + int irq_seqcomplete; +}; + +/* Frame Generator Unit */ +void dc_fg_cfg_videomode(struct dc_fg *fg, struct drm_display_mode *m); +void dc_fg_enable(struct dc_fg *fg); +void dc_fg_disable(struct dc_fg *fg); +void dc_fg_shdtokgen(struct dc_fg *fg); +u32 dc_fg_get_frame_index(struct dc_fg *fg); +u32 dc_fg_get_line_index(struct dc_fg *fg); +bool dc_fg_wait_for_frame_index_moving(struct dc_fg *fg); +bool dc_fg_secondary_requests_to_read_empty_fifo(struct dc_fg *fg); +void dc_fg_secondary_clear_channel_status(struct dc_fg *fg); +int dc_fg_wait_for_secondary_syncup(struct dc_fg *fg); +void dc_fg_enable_clock(struct dc_fg *fg); +void dc_fg_disable_clock(struct dc_fg *fg); +enum drm_mode_status dc_fg_check_clock(struct dc_fg *fg, int clk_khz); +void dc_fg_init(struct dc_fg *fg); + +/* Timing Controller Unit */ +void dc_tc_init(struct dc_tc *tc); + +#endif /* __DC_DISPLAY_ENGINE_H__ */ diff --git a/drivers/gpu/drm/imx/dc/dc-drv.c b/drivers/gpu/drm/imx/dc/dc-drv.c new file mode 100644 index 0000000000000..e5910a82dd4df --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-drv.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include +#include + +#include "dc-drv.h" + +static struct platform_driver * const dc_drivers[] = { + &dc_de_driver, + &dc_fg_driver, + &dc_tc_driver, +}; + +static int __init dc_drm_init(void) +{ + return platform_register_drivers(dc_drivers, ARRAY_SIZE(dc_drivers)); +} + +static void __exit dc_drm_exit(void) +{ + platform_unregister_drivers(dc_drivers, ARRAY_SIZE(dc_drivers)); +} + +module_init(dc_drm_init); +module_exit(dc_drm_exit); + +MODULE_DESCRIPTION("i.MX8 Display Controller DRM Driver"); +MODULE_AUTHOR("Liu Ying "); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/imx/dc/dc-drv.h b/drivers/gpu/drm/imx/dc/dc-drv.h new file mode 100644 index 0000000000000..65ae9c7c36941 --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-drv.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2024 NXP + */ + +#ifndef __DC_DRV_H__ +#define __DC_DRV_H__ + +#include +#include +#include + +#include + +#include "dc-de.h" + +/** + * struct dc_drm_device - DC specific drm_device + */ +struct dc_drm_device { + /** @base: base drm_device structure */ + struct drm_device base; + /** @de: display engine list */ + struct dc_de *de[DC_DISPLAYS]; + /** @fg: framegen list */ + struct dc_fg *fg[DC_DISPLAYS]; + /** @tc: tcon list */ + struct dc_tc *tc[DC_DISPLAYS]; +}; + +struct dc_subdev_info { + resource_size_t reg_start; + int id; +}; + +extern struct platform_driver dc_de_driver; +extern struct platform_driver dc_fg_driver; +extern struct platform_driver dc_tc_driver; + +static inline int dc_subdev_get_id(const struct dc_subdev_info *info, + int info_cnt, struct resource *res) +{ + int i; + + if (!res) + return -EINVAL; + + for (i = 0; i < info_cnt; i++) + if (info[i].reg_start == res->start) + return info[i].id; + + return -EINVAL; +} + +void dc_de_post_bind(struct dc_drm_device *dc_drm); + +#endif /* __DC_DRV_H__ */ diff --git a/drivers/gpu/drm/imx/dc/dc-fg.c b/drivers/gpu/drm/imx/dc/dc-fg.c new file mode 100644 index 0000000000000..7f6c1852bf724 --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-fg.c @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dc-de.h" +#include "dc-drv.h" + +#define FGSTCTRL 0x8 +#define FGSYNCMODE_MASK GENMASK(2, 1) +#define FGSYNCMODE(x) FIELD_PREP(FGSYNCMODE_MASK, (x)) +#define SHDEN BIT(0) + +#define HTCFG1 0xc +#define HTOTAL(x) FIELD_PREP(GENMASK(29, 16), ((x) - 1)) +#define HACT(x) FIELD_PREP(GENMASK(13, 0), (x)) + +#define HTCFG2 0x10 +#define HSEN BIT(31) +#define HSBP(x) FIELD_PREP(GENMASK(29, 16), ((x) - 1)) +#define HSYNC(x) FIELD_PREP(GENMASK(13, 0), ((x) - 1)) + +#define VTCFG1 0x14 +#define VTOTAL(x) FIELD_PREP(GENMASK(29, 16), ((x) - 1)) +#define VACT(x) FIELD_PREP(GENMASK(13, 0), (x)) + +#define VTCFG2 0x18 +#define VSEN BIT(31) +#define VSBP(x) FIELD_PREP(GENMASK(29, 16), ((x) - 1)) +#define VSYNC(x) FIELD_PREP(GENMASK(13, 0), ((x) - 1)) + +#define PKICKCONFIG 0x2c +#define SKICKCONFIG 0x30 +#define EN BIT(31) +#define ROW(x) FIELD_PREP(GENMASK(29, 16), (x)) +#define COL(x) FIELD_PREP(GENMASK(13, 0), (x)) + +#define PACFG 0x54 +#define SACFG 0x58 +#define STARTY(x) FIELD_PREP(GENMASK(29, 16), ((x) + 1)) +#define STARTX(x) FIELD_PREP(GENMASK(13, 0), ((x) + 1)) + +#define FGINCTRL 0x5c +#define FGINCTRLPANIC 0x60 +#define FGDM_MASK GENMASK(2, 0) +#define ENPRIMALPHA BIT(3) +#define ENSECALPHA BIT(4) + +#define FGCCR 0x64 +#define CCGREEN(x) FIELD_PREP(GENMASK(19, 10), (x)) + +#define FGENABLE 0x68 +#define FGEN BIT(0) + +#define FGSLR 0x6c +#define SHDTOKGEN BIT(0) + +#define FGTIMESTAMP 0x74 +#define FRAMEINDEX(x) FIELD_GET(GENMASK(31, 14), (x)) +#define LINEINDEX(x) FIELD_GET(GENMASK(13, 0), (x)) + +#define FGCHSTAT 0x78 +#define SECSYNCSTAT BIT(24) +#define SFIFOEMPTY BIT(16) + +#define FGCHSTATCLR 0x7c +#define CLRSECSTAT BIT(16) + +enum dc_fg_syncmode { + FG_SYNCMODE_OFF, /* No side-by-side synchronization. */ +}; + +enum dc_fg_dm { + FG_DM_CONSTCOL = 0x1, /* Constant Color Background is shown. */ + FG_DM_SEC_ON_TOP = 0x5, /* Both inputs overlaid with secondary on top. */ +}; + +static const struct dc_subdev_info dc_fg_info[] = { + { .reg_start = 0x5618b800, .id = 0, }, + { .reg_start = 0x5618d400, .id = 1, }, +}; + +static const struct regmap_range dc_fg_regmap_write_ranges[] = { + regmap_reg_range(FGSTCTRL, VTCFG2), + regmap_reg_range(PKICKCONFIG, SKICKCONFIG), + regmap_reg_range(PACFG, FGSLR), + regmap_reg_range(FGCHSTATCLR, FGCHSTATCLR), +}; + +static const struct regmap_range dc_fg_regmap_read_ranges[] = { + regmap_reg_range(FGSTCTRL, VTCFG2), + regmap_reg_range(PKICKCONFIG, SKICKCONFIG), + regmap_reg_range(PACFG, FGENABLE), + regmap_reg_range(FGTIMESTAMP, FGCHSTAT), +}; + +static const struct regmap_access_table dc_fg_regmap_write_table = { + .yes_ranges = dc_fg_regmap_write_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_fg_regmap_write_ranges), +}; + +static const struct regmap_access_table dc_fg_regmap_read_table = { + .yes_ranges = dc_fg_regmap_read_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_fg_regmap_read_ranges), +}; + +static const struct regmap_config dc_fg_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .wr_table = &dc_fg_regmap_write_table, + .rd_table = &dc_fg_regmap_read_table, + .max_register = FGCHSTATCLR, +}; + +static inline void dc_fg_enable_shden(struct dc_fg *fg) +{ + regmap_write_bits(fg->reg, FGSTCTRL, SHDEN, SHDEN); +} + +static inline void dc_fg_syncmode(struct dc_fg *fg, enum dc_fg_syncmode mode) +{ + regmap_write_bits(fg->reg, FGSTCTRL, FGSYNCMODE_MASK, FGSYNCMODE(mode)); +} + +void dc_fg_cfg_videomode(struct dc_fg *fg, struct drm_display_mode *m) +{ + u32 hact, htotal, hsync, hsbp; + u32 vact, vtotal, vsync, vsbp; + u32 kick_row, kick_col; + int ret; + + hact = m->crtc_hdisplay; + htotal = m->crtc_htotal; + hsync = m->crtc_hsync_end - m->crtc_hsync_start; + hsbp = m->crtc_htotal - m->crtc_hsync_start; + + vact = m->crtc_vdisplay; + vtotal = m->crtc_vtotal; + vsync = m->crtc_vsync_end - m->crtc_vsync_start; + vsbp = m->crtc_vtotal - m->crtc_vsync_start; + + /* video mode */ + regmap_write(fg->reg, HTCFG1, HACT(hact) | HTOTAL(htotal)); + regmap_write(fg->reg, HTCFG2, HSYNC(hsync) | HSBP(hsbp) | HSEN); + regmap_write(fg->reg, VTCFG1, VACT(vact) | VTOTAL(vtotal)); + regmap_write(fg->reg, VTCFG2, VSYNC(vsync) | VSBP(vsbp) | VSEN); + + kick_col = hact + 1; + kick_row = vact; + + /* pkickconfig */ + regmap_write(fg->reg, PKICKCONFIG, COL(kick_col) | ROW(kick_row) | EN); + + /* skikconfig */ + regmap_write(fg->reg, SKICKCONFIG, COL(kick_col) | ROW(kick_row) | EN); + + /* primary and secondary area position configuration */ + regmap_write(fg->reg, PACFG, STARTX(0) | STARTY(0)); + regmap_write(fg->reg, SACFG, STARTX(0) | STARTY(0)); + + /* alpha */ + regmap_write_bits(fg->reg, FGINCTRL, ENPRIMALPHA | ENSECALPHA, 0); + regmap_write_bits(fg->reg, FGINCTRLPANIC, ENPRIMALPHA | ENSECALPHA, 0); + + /* constant color is green(used in panic mode) */ + regmap_write(fg->reg, FGCCR, CCGREEN(0x3ff)); + + ret = clk_set_rate(fg->clk_disp, m->clock * HZ_PER_KHZ); + if (ret < 0) + dev_err(fg->dev, "failed to set display clock rate: %d\n", ret); +} + +static inline void dc_fg_displaymode(struct dc_fg *fg, enum dc_fg_dm mode) +{ + regmap_write_bits(fg->reg, FGINCTRL, FGDM_MASK, mode); +} + +static inline void dc_fg_panic_displaymode(struct dc_fg *fg, enum dc_fg_dm mode) +{ + regmap_write_bits(fg->reg, FGINCTRLPANIC, FGDM_MASK, mode); +} + +void dc_fg_enable(struct dc_fg *fg) +{ + regmap_write(fg->reg, FGENABLE, FGEN); +} + +void dc_fg_disable(struct dc_fg *fg) +{ + regmap_write(fg->reg, FGENABLE, 0); +} + +void dc_fg_shdtokgen(struct dc_fg *fg) +{ + regmap_write(fg->reg, FGSLR, SHDTOKGEN); +} + +u32 dc_fg_get_frame_index(struct dc_fg *fg) +{ + u32 val; + + regmap_read(fg->reg, FGTIMESTAMP, &val); + + return FRAMEINDEX(val); +} + +u32 dc_fg_get_line_index(struct dc_fg *fg) +{ + u32 val; + + regmap_read(fg->reg, FGTIMESTAMP, &val); + + return LINEINDEX(val); +} + +bool dc_fg_wait_for_frame_index_moving(struct dc_fg *fg) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(100); + u32 frame_index, last_frame_index; + + frame_index = dc_fg_get_frame_index(fg); + do { + last_frame_index = frame_index; + frame_index = dc_fg_get_frame_index(fg); + } while (last_frame_index == frame_index && + time_before(jiffies, timeout)); + + return last_frame_index != frame_index; +} + +bool dc_fg_secondary_requests_to_read_empty_fifo(struct dc_fg *fg) +{ + u32 val; + + regmap_read(fg->reg, FGCHSTAT, &val); + + return !!(val & SFIFOEMPTY); +} + +void dc_fg_secondary_clear_channel_status(struct dc_fg *fg) +{ + regmap_write(fg->reg, FGCHSTATCLR, CLRSECSTAT); +} + +int dc_fg_wait_for_secondary_syncup(struct dc_fg *fg) +{ + unsigned int val; + + return regmap_read_poll_timeout(fg->reg, FGCHSTAT, val, + val & SECSYNCSTAT, 5, 100000); +} + +void dc_fg_enable_clock(struct dc_fg *fg) +{ + int ret; + + ret = clk_prepare_enable(fg->clk_disp); + if (ret) + dev_err(fg->dev, "failed to enable display clock: %d\n", ret); +} + +void dc_fg_disable_clock(struct dc_fg *fg) +{ + clk_disable_unprepare(fg->clk_disp); +} + +enum drm_mode_status dc_fg_check_clock(struct dc_fg *fg, int clk_khz) +{ + unsigned long rounded_rate; + + rounded_rate = clk_round_rate(fg->clk_disp, clk_khz * HZ_PER_KHZ); + + if (rounded_rate != clk_khz * HZ_PER_KHZ) + return MODE_NOCLOCK; + + return MODE_OK; +} + +void dc_fg_init(struct dc_fg *fg) +{ + dc_fg_enable_shden(fg); + dc_fg_syncmode(fg, FG_SYNCMODE_OFF); + dc_fg_displaymode(fg, FG_DM_SEC_ON_TOP); + dc_fg_panic_displaymode(fg, FG_DM_CONSTCOL); +} + +static int dc_fg_bind(struct device *dev, struct device *master, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + struct dc_drm_device *dc_drm = data; + struct resource *res; + void __iomem *base; + struct dc_fg *fg; + int id; + + fg = devm_kzalloc(dev, sizeof(*fg), GFP_KERNEL); + if (!fg) + return -ENOMEM; + + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(base)) + return PTR_ERR(base); + + fg->reg = devm_regmap_init_mmio(dev, base, &dc_fg_regmap_config); + if (IS_ERR(fg->reg)) + return PTR_ERR(fg->reg); + + fg->clk_disp = devm_clk_get(dev, NULL); + if (IS_ERR(fg->clk_disp)) + return dev_err_probe(dev, PTR_ERR(fg->clk_disp), + "failed to get display clock\n"); + + id = dc_subdev_get_id(dc_fg_info, ARRAY_SIZE(dc_fg_info), res); + if (id < 0) { + dev_err(dev, "failed to get instance number: %d\n", id); + return id; + } + + fg->dev = dev; + dc_drm->fg[id] = fg; + + return 0; +} + +static const struct component_ops dc_fg_ops = { + .bind = dc_fg_bind, +}; + +static int dc_fg_probe(struct platform_device *pdev) +{ + int ret; + + ret = component_add(&pdev->dev, &dc_fg_ops); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to add component\n"); + + return 0; +} + +static void dc_fg_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &dc_fg_ops); +} + +static const struct of_device_id dc_fg_dt_ids[] = { + { .compatible = "fsl,imx8qxp-dc-framegen" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dc_fg_dt_ids); + +struct platform_driver dc_fg_driver = { + .probe = dc_fg_probe, + .remove = dc_fg_remove, + .driver = { + .name = "imx8-dc-framegen", + .suppress_bind_attrs = true, + .of_match_table = dc_fg_dt_ids, + }, +}; diff --git a/drivers/gpu/drm/imx/dc/dc-tc.c b/drivers/gpu/drm/imx/dc/dc-tc.c new file mode 100644 index 0000000000000..0bfd381b2cea1 --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-tc.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include +#include +#include +#include +#include + +#include "dc-drv.h" +#include "dc-de.h" + +#define TCON_CTRL 0x410 +#define CTRL_RST_VAL 0x01401408 + +/* red: MAPBIT 29-20, green: MAPBIT 19-10, blue: MAPBIT 9-0 */ +#define MAPBIT3_0 0x418 +#define MAPBIT7_4 0x41c +#define MAPBIT11_8 0x420 +#define MAPBIT15_12 0x424 +#define MAPBIT19_16 0x428 +#define MAPBIT23_20 0x42c +#define MAPBIT27_24 0x430 +#define MAPBIT31_28 0x434 + +static const struct dc_subdev_info dc_tc_info[] = { + { .reg_start = 0x5618c800, .id = 0, }, + { .reg_start = 0x5618e400, .id = 1, }, +}; + +static const struct regmap_range dc_tc_regmap_ranges[] = { + regmap_reg_range(TCON_CTRL, TCON_CTRL), + regmap_reg_range(MAPBIT3_0, MAPBIT31_28), +}; + +static const struct regmap_access_table dc_tc_regmap_access_table = { + .yes_ranges = dc_tc_regmap_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_tc_regmap_ranges), +}; + +static const struct regmap_config dc_tc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .wr_table = &dc_tc_regmap_access_table, + .rd_table = &dc_tc_regmap_access_table, + .max_register = MAPBIT31_28, +}; + +/* + * The pixels reach TCON are always in 30-bit BGR format. + * The first bridge always receives pixels in 30-bit RGB format. + * So, map the format to MEDIA_BUS_FMT_RGB101010_1X30. + */ +static const u32 dc_tc_mapbit[] = { + 0x17161514, 0x1b1a1918, 0x0b0a1d1c, 0x0f0e0d0c, + 0x13121110, 0x03020100, 0x07060504, 0x00000908, +}; + +void dc_tc_init(struct dc_tc *tc) +{ + /* reset TCON_CTRL to POR default so that TCON works in bypass mode */ + regmap_write(tc->reg, TCON_CTRL, CTRL_RST_VAL); + + /* set format */ + regmap_bulk_write(tc->reg, MAPBIT3_0, dc_tc_mapbit, + ARRAY_SIZE(dc_tc_mapbit)); +} + +static int dc_tc_bind(struct device *dev, struct device *master, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + struct dc_drm_device *dc_drm = data; + struct resource *res; + void __iomem *base; + struct dc_tc *tc; + int id; + + tc = devm_kzalloc(dev, sizeof(*tc), GFP_KERNEL); + if (!tc) + return -ENOMEM; + + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(base)) + return PTR_ERR(base); + + tc->reg = devm_regmap_init_mmio(dev, base, &dc_tc_regmap_config); + if (IS_ERR(tc->reg)) + return PTR_ERR(tc->reg); + + id = dc_subdev_get_id(dc_tc_info, ARRAY_SIZE(dc_tc_info), res); + if (id < 0) { + dev_err(dev, "failed to get instance number: %d\n", id); + return id; + } + + tc->dev = dev; + dc_drm->tc[id] = tc; + + return 0; +} + +static const struct component_ops dc_tc_ops = { + .bind = dc_tc_bind, +}; + +static int dc_tc_probe(struct platform_device *pdev) +{ + int ret; + + ret = component_add(&pdev->dev, &dc_tc_ops); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to add component\n"); + + return 0; +} + +static void dc_tc_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &dc_tc_ops); +} + +static const struct of_device_id dc_tc_dt_ids[] = { + { .compatible = "fsl,imx8qxp-dc-tcon" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dc_tc_dt_ids); + +struct platform_driver dc_tc_driver = { + .probe = dc_tc_probe, + .remove = dc_tc_remove, + .driver = { + .name = "imx8-dc-tcon", + .suppress_bind_attrs = true, + .of_match_table = dc_tc_dt_ids, + }, +}; -- GitLab From 0e177d5ce01ca52c5c754afbe8773d4ed5626cd6 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 14 Apr 2025 11:50:19 +0800 Subject: [PATCH 0056/1479] drm/imx: Add i.MX8qxp Display Controller pixel engine i.MX8qxp Display Controller pixel engine consists of all processing units that operate in the AXI bus clock domain. Add drivers for ConstFrame, ExtDst, FetchLayer, FetchWarp and LayerBlend units, as well as a pixel engine driver, so that two displays with primary planes can be supported. The pixel engine driver and those unit drivers are components to be aggregated by a master registered in the upcoming DRM driver. Reviewed-by: Maxime Ripard Signed-off-by: Liu Ying Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250414035028.1561475-11-victor.liu@nxp.com --- drivers/gpu/drm/imx/dc/Makefile | 3 +- drivers/gpu/drm/imx/dc/dc-cf.c | 172 +++++++++++++++++ drivers/gpu/drm/imx/dc/dc-drv.c | 6 + drivers/gpu/drm/imx/dc/dc-drv.h | 22 +++ drivers/gpu/drm/imx/dc/dc-ed.c | 288 ++++++++++++++++++++++++++++ drivers/gpu/drm/imx/dc/dc-fl.c | 185 ++++++++++++++++++ drivers/gpu/drm/imx/dc/dc-fu.c | 258 +++++++++++++++++++++++++ drivers/gpu/drm/imx/dc/dc-fu.h | 129 +++++++++++++ drivers/gpu/drm/imx/dc/dc-fw.c | 222 ++++++++++++++++++++++ drivers/gpu/drm/imx/dc/dc-lb.c | 325 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/imx/dc/dc-pe.c | 158 ++++++++++++++++ drivers/gpu/drm/imx/dc/dc-pe.h | 101 ++++++++++ 12 files changed, 1868 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/imx/dc/dc-cf.c create mode 100644 drivers/gpu/drm/imx/dc/dc-ed.c create mode 100644 drivers/gpu/drm/imx/dc/dc-fl.c create mode 100644 drivers/gpu/drm/imx/dc/dc-fu.c create mode 100644 drivers/gpu/drm/imx/dc/dc-fu.h create mode 100644 drivers/gpu/drm/imx/dc/dc-fw.c create mode 100644 drivers/gpu/drm/imx/dc/dc-lb.c create mode 100644 drivers/gpu/drm/imx/dc/dc-pe.c create mode 100644 drivers/gpu/drm/imx/dc/dc-pe.h diff --git a/drivers/gpu/drm/imx/dc/Makefile b/drivers/gpu/drm/imx/dc/Makefile index 56de82d53d4d4..2942ae6fd5bd7 100644 --- a/drivers/gpu/drm/imx/dc/Makefile +++ b/drivers/gpu/drm/imx/dc/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -imx8-dc-drm-objs := dc-de.o dc-drv.o dc-fg.o dc-tc.o +imx8-dc-drm-objs := dc-cf.o dc-de.o dc-drv.o dc-ed.o dc-fg.o dc-fl.o dc-fu.o \ + dc-fw.o dc-lb.o dc-pe.o dc-tc.o obj-$(CONFIG_DRM_IMX8_DC) += imx8-dc-drm.o diff --git a/drivers/gpu/drm/imx/dc/dc-cf.c b/drivers/gpu/drm/imx/dc/dc-cf.c new file mode 100644 index 0000000000000..2f077161e9126 --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-cf.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dc-drv.h" +#include "dc-pe.h" + +#define STATICCONTROL 0x8 + +#define FRAMEDIMENSIONS 0xc +#define HEIGHT(x) FIELD_PREP(GENMASK(29, 16), ((x) - 1)) +#define WIDTH(x) FIELD_PREP(GENMASK(13, 0), ((x) - 1)) + +#define CONSTANTCOLOR 0x10 +#define BLUE(x) FIELD_PREP(GENMASK(15, 8), (x)) + +static const struct dc_subdev_info dc_cf_info[] = { + { .reg_start = 0x56180960, .id = 0, }, + { .reg_start = 0x561809e0, .id = 1, }, + { .reg_start = 0x561809a0, .id = 4, }, + { .reg_start = 0x56180a20, .id = 5, }, +}; + +static const struct regmap_range dc_cf_regmap_ranges[] = { + regmap_reg_range(STATICCONTROL, CONSTANTCOLOR), +}; + +static const struct regmap_access_table dc_cf_regmap_access_table = { + .yes_ranges = dc_cf_regmap_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_cf_regmap_ranges), +}; + +static const struct regmap_config dc_cf_cfg_regmap_config = { + .name = "cfg", + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .wr_table = &dc_cf_regmap_access_table, + .rd_table = &dc_cf_regmap_access_table, + .max_register = CONSTANTCOLOR, +}; + +static inline void dc_cf_enable_shden(struct dc_cf *cf) +{ + regmap_write(cf->reg_cfg, STATICCONTROL, SHDEN); +} + +enum dc_link_id dc_cf_get_link_id(struct dc_cf *cf) +{ + return cf->link; +} + +void dc_cf_framedimensions(struct dc_cf *cf, unsigned int w, + unsigned int h) +{ + regmap_write(cf->reg_cfg, FRAMEDIMENSIONS, WIDTH(w) | HEIGHT(h)); +} + +void dc_cf_constantcolor_black(struct dc_cf *cf) +{ + regmap_write(cf->reg_cfg, CONSTANTCOLOR, 0); +} + +void dc_cf_constantcolor_blue(struct dc_cf *cf) +{ + regmap_write(cf->reg_cfg, CONSTANTCOLOR, BLUE(0xff)); +} + +void dc_cf_init(struct dc_cf *cf) +{ + dc_cf_enable_shden(cf); +} + +static int dc_cf_bind(struct device *dev, struct device *master, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + struct dc_drm_device *dc_drm = data; + struct resource *res_pec; + void __iomem *base_cfg; + struct dc_cf *cf; + int id; + + cf = devm_kzalloc(dev, sizeof(*cf), GFP_KERNEL); + if (!cf) + return -ENOMEM; + + res_pec = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + base_cfg = devm_platform_ioremap_resource_byname(pdev, "cfg"); + if (IS_ERR(base_cfg)) + return PTR_ERR(base_cfg); + + cf->reg_cfg = devm_regmap_init_mmio(dev, base_cfg, + &dc_cf_cfg_regmap_config); + if (IS_ERR(cf->reg_cfg)) + return PTR_ERR(cf->reg_cfg); + + id = dc_subdev_get_id(dc_cf_info, ARRAY_SIZE(dc_cf_info), res_pec); + if (id < 0) { + dev_err(dev, "failed to get instance number: %d\n", id); + return id; + } + + switch (id) { + case 0: + cf->link = LINK_ID_CONSTFRAME0; + dc_drm->cf_cont[0] = cf; + break; + case 1: + cf->link = LINK_ID_CONSTFRAME1; + dc_drm->cf_cont[1] = cf; + break; + case 4: + cf->link = LINK_ID_CONSTFRAME4; + dc_drm->cf_safe[0] = cf; + break; + case 5: + cf->link = LINK_ID_CONSTFRAME5; + dc_drm->cf_safe[1] = cf; + break; + } + + return 0; +} + +static const struct component_ops dc_cf_ops = { + .bind = dc_cf_bind, +}; + +static int dc_cf_probe(struct platform_device *pdev) +{ + int ret; + + ret = component_add(&pdev->dev, &dc_cf_ops); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to add component\n"); + + return 0; +} + +static void dc_cf_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &dc_cf_ops); +} + +static const struct of_device_id dc_cf_dt_ids[] = { + { .compatible = "fsl,imx8qxp-dc-constframe" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dc_cf_dt_ids); + +struct platform_driver dc_cf_driver = { + .probe = dc_cf_probe, + .remove = dc_cf_remove, + .driver = { + .name = "imx8-dc-constframe", + .suppress_bind_attrs = true, + .of_match_table = dc_cf_dt_ids, + }, +}; diff --git a/drivers/gpu/drm/imx/dc/dc-drv.c b/drivers/gpu/drm/imx/dc/dc-drv.c index e5910a82dd4df..7c64acc863ad9 100644 --- a/drivers/gpu/drm/imx/dc/dc-drv.c +++ b/drivers/gpu/drm/imx/dc/dc-drv.c @@ -9,8 +9,14 @@ #include "dc-drv.h" static struct platform_driver * const dc_drivers[] = { + &dc_cf_driver, &dc_de_driver, + &dc_ed_driver, &dc_fg_driver, + &dc_fl_driver, + &dc_fw_driver, + &dc_lb_driver, + &dc_pe_driver, &dc_tc_driver, }; diff --git a/drivers/gpu/drm/imx/dc/dc-drv.h b/drivers/gpu/drm/imx/dc/dc-drv.h index 65ae9c7c36941..b9fe12577a195 100644 --- a/drivers/gpu/drm/imx/dc/dc-drv.h +++ b/drivers/gpu/drm/imx/dc/dc-drv.h @@ -13,6 +13,7 @@ #include #include "dc-de.h" +#include "dc-pe.h" /** * struct dc_drm_device - DC specific drm_device @@ -20,10 +21,24 @@ struct dc_drm_device { /** @base: base drm_device structure */ struct drm_device base; + /** @cf_safe: constframe list(safety stream) */ + struct dc_cf *cf_safe[DC_DISPLAYS]; + /** @cf_cont: constframe list(content stream) */ + struct dc_cf *cf_cont[DC_DISPLAYS]; /** @de: display engine list */ struct dc_de *de[DC_DISPLAYS]; + /** @ed_safe: extdst list(safety stream) */ + struct dc_ed *ed_safe[DC_DISPLAYS]; + /** @ed_cont: extdst list(content stream) */ + struct dc_ed *ed_cont[DC_DISPLAYS]; /** @fg: framegen list */ struct dc_fg *fg[DC_DISPLAYS]; + /** @fu_disp: fetchunit list(used by display engine) */ + struct dc_fu *fu_disp[DC_DISP_FU_CNT]; + /** @lb: layerblend list */ + struct dc_lb *lb[DC_LB_CNT]; + /** @pe: pixel engine */ + struct dc_pe *pe; /** @tc: tcon list */ struct dc_tc *tc[DC_DISPLAYS]; }; @@ -33,8 +48,14 @@ struct dc_subdev_info { int id; }; +extern struct platform_driver dc_cf_driver; extern struct platform_driver dc_de_driver; +extern struct platform_driver dc_ed_driver; extern struct platform_driver dc_fg_driver; +extern struct platform_driver dc_fl_driver; +extern struct platform_driver dc_fw_driver; +extern struct platform_driver dc_lb_driver; +extern struct platform_driver dc_pe_driver; extern struct platform_driver dc_tc_driver; static inline int dc_subdev_get_id(const struct dc_subdev_info *info, @@ -53,5 +74,6 @@ static inline int dc_subdev_get_id(const struct dc_subdev_info *info, } void dc_de_post_bind(struct dc_drm_device *dc_drm); +void dc_pe_post_bind(struct dc_drm_device *dc_drm); #endif /* __DC_DRV_H__ */ diff --git a/drivers/gpu/drm/imx/dc/dc-ed.c b/drivers/gpu/drm/imx/dc/dc-ed.c new file mode 100644 index 0000000000000..86ecc22d0a554 --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-ed.c @@ -0,0 +1,288 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "dc-drv.h" +#include "dc-pe.h" + +#define PIXENGCFG_STATIC 0x8 +#define POWERDOWN BIT(4) +#define SYNC_MODE BIT(8) +#define SINGLE 0 +#define DIV_MASK GENMASK(23, 16) +#define DIV(x) FIELD_PREP(DIV_MASK, (x)) +#define DIV_RESET 0x80 + +#define PIXENGCFG_DYNAMIC 0xc + +#define PIXENGCFG_TRIGGER 0x14 +#define SYNC_TRIGGER BIT(0) + +#define STATICCONTROL 0x8 +#define KICK_MODE BIT(8) +#define EXTERNAL BIT(8) +#define PERFCOUNTMODE BIT(12) + +#define CONTROL 0xc +#define GAMMAAPPLYENABLE BIT(0) + +static const struct dc_subdev_info dc_ed_info[] = { + { .reg_start = 0x56180980, .id = 0, }, + { .reg_start = 0x56180a00, .id = 1, }, + { .reg_start = 0x561809c0, .id = 4, }, + { .reg_start = 0x56180a40, .id = 5, }, +}; + +static const struct regmap_range dc_ed_pec_regmap_write_ranges[] = { + regmap_reg_range(PIXENGCFG_STATIC, PIXENGCFG_STATIC), + regmap_reg_range(PIXENGCFG_DYNAMIC, PIXENGCFG_DYNAMIC), + regmap_reg_range(PIXENGCFG_TRIGGER, PIXENGCFG_TRIGGER), +}; + +static const struct regmap_access_table dc_ed_pec_regmap_write_table = { + .yes_ranges = dc_ed_pec_regmap_write_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_ed_pec_regmap_write_ranges), +}; + +static const struct regmap_range dc_ed_pec_regmap_read_ranges[] = { + regmap_reg_range(PIXENGCFG_STATIC, PIXENGCFG_STATIC), + regmap_reg_range(PIXENGCFG_DYNAMIC, PIXENGCFG_DYNAMIC), +}; + +static const struct regmap_access_table dc_ed_pec_regmap_read_table = { + .yes_ranges = dc_ed_pec_regmap_read_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_ed_pec_regmap_read_ranges), +}; + +static const struct regmap_range dc_ed_pec_regmap_volatile_ranges[] = { + regmap_reg_range(PIXENGCFG_TRIGGER, PIXENGCFG_TRIGGER), +}; + +static const struct regmap_access_table dc_ed_pec_regmap_volatile_table = { + .yes_ranges = dc_ed_pec_regmap_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_ed_pec_regmap_volatile_ranges), +}; + +static const struct regmap_config dc_ed_pec_regmap_config = { + .name = "pec", + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .wr_table = &dc_ed_pec_regmap_write_table, + .rd_table = &dc_ed_pec_regmap_read_table, + .volatile_table = &dc_ed_pec_regmap_volatile_table, + .max_register = PIXENGCFG_TRIGGER, +}; + +static const struct regmap_range dc_ed_regmap_ranges[] = { + regmap_reg_range(STATICCONTROL, STATICCONTROL), + regmap_reg_range(CONTROL, CONTROL), +}; + +static const struct regmap_access_table dc_ed_regmap_access_table = { + .yes_ranges = dc_ed_regmap_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_ed_regmap_ranges), +}; + +static const struct regmap_config dc_ed_cfg_regmap_config = { + .name = "cfg", + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .wr_table = &dc_ed_regmap_access_table, + .rd_table = &dc_ed_regmap_access_table, + .max_register = CONTROL, +}; + +static const enum dc_link_id src_sels[] = { + LINK_ID_NONE, + LINK_ID_CONSTFRAME0, + LINK_ID_CONSTFRAME1, + LINK_ID_CONSTFRAME4, + LINK_ID_CONSTFRAME5, + LINK_ID_LAYERBLEND3, + LINK_ID_LAYERBLEND2, + LINK_ID_LAYERBLEND1, + LINK_ID_LAYERBLEND0, +}; + +static inline void dc_ed_pec_enable_shden(struct dc_ed *ed) +{ + regmap_write_bits(ed->reg_pec, PIXENGCFG_STATIC, SHDEN, SHDEN); +} + +static inline void dc_ed_pec_poweron(struct dc_ed *ed) +{ + regmap_write_bits(ed->reg_pec, PIXENGCFG_STATIC, POWERDOWN, 0); +} + +static inline void dc_ed_pec_sync_mode_single(struct dc_ed *ed) +{ + regmap_write_bits(ed->reg_pec, PIXENGCFG_STATIC, SYNC_MODE, SINGLE); +} + +static inline void dc_ed_pec_div_reset(struct dc_ed *ed) +{ + regmap_write_bits(ed->reg_pec, PIXENGCFG_STATIC, DIV_MASK, + DIV(DIV_RESET)); +} + +void dc_ed_pec_src_sel(struct dc_ed *ed, enum dc_link_id src) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(src_sels); i++) { + if (src_sels[i] == src) { + regmap_write(ed->reg_pec, PIXENGCFG_DYNAMIC, src); + return; + } + } +} + +void dc_ed_pec_sync_trigger(struct dc_ed *ed) +{ + regmap_write(ed->reg_pec, PIXENGCFG_TRIGGER, SYNC_TRIGGER); +} + +static inline void dc_ed_enable_shden(struct dc_ed *ed) +{ + regmap_write_bits(ed->reg_cfg, STATICCONTROL, SHDEN, SHDEN); +} + +static inline void dc_ed_kick_mode_external(struct dc_ed *ed) +{ + regmap_write_bits(ed->reg_cfg, STATICCONTROL, KICK_MODE, EXTERNAL); +} + +static inline void dc_ed_disable_perfcountmode(struct dc_ed *ed) +{ + regmap_write_bits(ed->reg_cfg, STATICCONTROL, PERFCOUNTMODE, 0); +} + +static inline void dc_ed_disable_gamma_apply(struct dc_ed *ed) +{ + regmap_write_bits(ed->reg_cfg, CONTROL, GAMMAAPPLYENABLE, 0); +} + +void dc_ed_init(struct dc_ed *ed) +{ + dc_ed_pec_src_sel(ed, LINK_ID_NONE); + dc_ed_pec_enable_shden(ed); + dc_ed_pec_poweron(ed); + dc_ed_pec_sync_mode_single(ed); + dc_ed_pec_div_reset(ed); + dc_ed_enable_shden(ed); + dc_ed_disable_perfcountmode(ed); + dc_ed_kick_mode_external(ed); + dc_ed_disable_gamma_apply(ed); +} + +static int dc_ed_bind(struct device *dev, struct device *master, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + struct dc_drm_device *dc_drm = data; + struct resource *res_pec; + void __iomem *base_pec; + void __iomem *base_cfg; + struct dc_ed *ed; + int id; + + ed = devm_kzalloc(dev, sizeof(*ed), GFP_KERNEL); + if (!ed) + return -ENOMEM; + + base_pec = devm_platform_get_and_ioremap_resource(pdev, 0, &res_pec); + if (IS_ERR(base_pec)) + return PTR_ERR(base_pec); + + base_cfg = devm_platform_ioremap_resource_byname(pdev, "cfg"); + if (IS_ERR(base_cfg)) + return PTR_ERR(base_cfg); + + ed->reg_pec = devm_regmap_init_mmio(dev, base_pec, + &dc_ed_pec_regmap_config); + if (IS_ERR(ed->reg_pec)) + return PTR_ERR(ed->reg_pec); + + ed->reg_cfg = devm_regmap_init_mmio(dev, base_cfg, + &dc_ed_cfg_regmap_config); + if (IS_ERR(ed->reg_cfg)) + return PTR_ERR(ed->reg_cfg); + + ed->irq_shdload = platform_get_irq_byname(pdev, "shdload"); + if (ed->irq_shdload < 0) + return ed->irq_shdload; + + ed->dev = dev; + + id = dc_subdev_get_id(dc_ed_info, ARRAY_SIZE(dc_ed_info), res_pec); + if (id < 0) { + dev_err(dev, "failed to get instance number: %d\n", id); + return id; + } + + switch (id) { + case 0: + dc_drm->ed_cont[0] = ed; + break; + case 1: + dc_drm->ed_cont[1] = ed; + break; + case 4: + dc_drm->ed_safe[0] = ed; + break; + case 5: + dc_drm->ed_safe[1] = ed; + break; + } + + return 0; +} + +static const struct component_ops dc_ed_ops = { + .bind = dc_ed_bind, +}; + +static int dc_ed_probe(struct platform_device *pdev) +{ + int ret; + + ret = component_add(&pdev->dev, &dc_ed_ops); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to add component\n"); + + return 0; +} + +static void dc_ed_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &dc_ed_ops); +} + +static const struct of_device_id dc_ed_dt_ids[] = { + { .compatible = "fsl,imx8qxp-dc-extdst" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dc_ed_dt_ids); + +struct platform_driver dc_ed_driver = { + .probe = dc_ed_probe, + .remove = dc_ed_remove, + .driver = { + .name = "imx8-dc-extdst", + .suppress_bind_attrs = true, + .of_match_table = dc_ed_dt_ids, + }, +}; diff --git a/drivers/gpu/drm/imx/dc/dc-fl.c b/drivers/gpu/drm/imx/dc/dc-fl.c new file mode 100644 index 0000000000000..3ce24c72aa13e --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-fl.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "dc-drv.h" +#include "dc-fu.h" + +#define BASEADDRESS(x) (0x10 + FRAC_OFFSET * (x)) +#define SOURCEBUFFERATTRIBUTES(x) (0x14 + FRAC_OFFSET * (x)) +#define SOURCEBUFFERDIMENSION(x) (0x18 + FRAC_OFFSET * (x)) +#define COLORCOMPONENTBITS(x) (0x1c + FRAC_OFFSET * (x)) +#define COLORCOMPONENTSHIFT(x) (0x20 + FRAC_OFFSET * (x)) +#define LAYEROFFSET(x) (0x24 + FRAC_OFFSET * (x)) +#define CLIPWINDOWOFFSET(x) (0x28 + FRAC_OFFSET * (x)) +#define CLIPWINDOWDIMENSIONS(x) (0x2c + FRAC_OFFSET * (x)) +#define CONSTANTCOLOR(x) (0x30 + FRAC_OFFSET * (x)) +#define LAYERPROPERTY(x) (0x34 + FRAC_OFFSET * (x)) +#define FRAMEDIMENSIONS 0x150 + +struct dc_fl { + struct dc_fu fu; +}; + +static const struct dc_subdev_info dc_fl_info[] = { + { .reg_start = 0x56180ac0, .id = 0, }, +}; + +static const struct regmap_range dc_fl_regmap_ranges[] = { + regmap_reg_range(STATICCONTROL, FRAMEDIMENSIONS), +}; + +static const struct regmap_access_table dc_fl_regmap_access_table = { + .yes_ranges = dc_fl_regmap_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_fl_regmap_ranges), +}; + +static const struct regmap_config dc_fl_cfg_regmap_config = { + .name = "cfg", + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .wr_table = &dc_fl_regmap_access_table, + .rd_table = &dc_fl_regmap_access_table, + .max_register = FRAMEDIMENSIONS, +}; + +static void dc_fl_set_fmt(struct dc_fu *fu, enum dc_fu_frac frac, + const struct drm_format_info *format) +{ + u32 bits = 0, shifts = 0; + + dc_fu_set_src_bpp(fu, frac, format->cpp[0] * 8); + + regmap_write_bits(fu->reg_cfg, LAYERPROPERTY(frac), + YUVCONVERSIONMODE_MASK, + YUVCONVERSIONMODE(YUVCONVERSIONMODE_OFF)); + + dc_fu_get_pixel_format_bits(fu, format->format, &bits); + dc_fu_get_pixel_format_shifts(fu, format->format, &shifts); + + regmap_write(fu->reg_cfg, COLORCOMPONENTBITS(frac), bits); + regmap_write(fu->reg_cfg, COLORCOMPONENTSHIFT(frac), shifts); +} + +static void dc_fl_set_framedimensions(struct dc_fu *fu, int w, int h) +{ + regmap_write(fu->reg_cfg, FRAMEDIMENSIONS, + FRAMEWIDTH(w) | FRAMEHEIGHT(h)); +} + +static void dc_fl_init(struct dc_fu *fu) +{ + dc_fu_common_hw_init(fu); + dc_fu_shdldreq_sticky(fu, 0xff); +} + +static void dc_fl_set_ops(struct dc_fu *fu) +{ + memcpy(&fu->ops, &dc_fu_common_ops, sizeof(dc_fu_common_ops)); + fu->ops.init = dc_fl_init; + fu->ops.set_fmt = dc_fl_set_fmt; + fu->ops.set_framedimensions = dc_fl_set_framedimensions; +} + +static int dc_fl_bind(struct device *dev, struct device *master, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + struct dc_drm_device *dc_drm = data; + struct resource *res_pec; + void __iomem *base_cfg; + struct dc_fl *fl; + struct dc_fu *fu; + int i, id; + + fl = devm_kzalloc(dev, sizeof(*fl), GFP_KERNEL); + if (!fl) + return -ENOMEM; + + fu = &fl->fu; + + res_pec = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + base_cfg = devm_platform_ioremap_resource_byname(pdev, "cfg"); + if (IS_ERR(base_cfg)) + return PTR_ERR(base_cfg); + + fu->reg_cfg = devm_regmap_init_mmio(dev, base_cfg, + &dc_fl_cfg_regmap_config); + if (IS_ERR(fu->reg_cfg)) + return PTR_ERR(fu->reg_cfg); + + id = dc_subdev_get_id(dc_fl_info, ARRAY_SIZE(dc_fl_info), res_pec); + if (id < 0) { + dev_err(dev, "failed to get instance number: %d\n", id); + return id; + } + + fu->link_id = LINK_ID_FETCHLAYER0; + fu->id = DC_FETCHUNIT_FL0; + for (i = 0; i < DC_FETCHUNIT_FRAC_NUM; i++) { + fu->reg_baseaddr[i] = BASEADDRESS(i); + fu->reg_sourcebufferattributes[i] = SOURCEBUFFERATTRIBUTES(i); + fu->reg_sourcebufferdimension[i] = SOURCEBUFFERDIMENSION(i); + fu->reg_layeroffset[i] = LAYEROFFSET(i); + fu->reg_clipwindowoffset[i] = CLIPWINDOWOFFSET(i); + fu->reg_clipwindowdimensions[i] = CLIPWINDOWDIMENSIONS(i); + fu->reg_constantcolor[i] = CONSTANTCOLOR(i); + fu->reg_layerproperty[i] = LAYERPROPERTY(i); + } + snprintf(fu->name, sizeof(fu->name), "FetchLayer%d", id); + + dc_fl_set_ops(fu); + + dc_drm->fu_disp[fu->id] = fu; + + return 0; +} + +static const struct component_ops dc_fl_ops = { + .bind = dc_fl_bind, +}; + +static int dc_fl_probe(struct platform_device *pdev) +{ + int ret; + + ret = component_add(&pdev->dev, &dc_fl_ops); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to add component\n"); + + return 0; +} + +static void dc_fl_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &dc_fl_ops); +} + +static const struct of_device_id dc_fl_dt_ids[] = { + { .compatible = "fsl,imx8qxp-dc-fetchlayer" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dc_fl_dt_ids); + +struct platform_driver dc_fl_driver = { + .probe = dc_fl_probe, + .remove = dc_fl_remove, + .driver = { + .name = "imx8-dc-fetchlayer", + .suppress_bind_attrs = true, + .of_match_table = dc_fl_dt_ids, + }, +}; diff --git a/drivers/gpu/drm/imx/dc/dc-fu.c b/drivers/gpu/drm/imx/dc/dc-fu.c new file mode 100644 index 0000000000000..f94c591c81589 --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-fu.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include +#include +#include +#include + +#include "dc-fu.h" +#include "dc-pe.h" + +/* STATICCONTROL */ +#define SHDLDREQSTICKY_MASK GENMASK(31, 24) +#define SHDLDREQSTICKY(x) FIELD_PREP(SHDLDREQSTICKY_MASK, (x)) +#define BASEADDRESSAUTOUPDATE_MASK GENMASK(23, 16) +#define BASEADDRESSAUTOUPDATE(x) FIELD_PREP(BASEADDRESSAUTOUPDATE_MASK, (x)) + +/* BURSTBUFFERMANAGEMENT */ +#define SETBURSTLENGTH_MASK GENMASK(12, 8) +#define SETBURSTLENGTH(x) FIELD_PREP(SETBURSTLENGTH_MASK, (x)) +#define SETNUMBUFFERS_MASK GENMASK(7, 0) +#define SETNUMBUFFERS(x) FIELD_PREP(SETNUMBUFFERS_MASK, (x)) +#define LINEMODE_MASK BIT(31) + +/* SOURCEBUFFERATTRIBUTES */ +#define BITSPERPIXEL_MASK GENMASK(21, 16) +#define BITSPERPIXEL(x) FIELD_PREP(BITSPERPIXEL_MASK, (x)) +#define STRIDE_MASK GENMASK(15, 0) +#define STRIDE(x) FIELD_PREP(STRIDE_MASK, (x) - 1) + +/* SOURCEBUFFERDIMENSION */ +#define LINEWIDTH(x) FIELD_PREP(GENMASK(13, 0), (x)) +#define LINECOUNT(x) FIELD_PREP(GENMASK(29, 16), (x)) + +/* LAYEROFFSET */ +#define LAYERXOFFSET(x) FIELD_PREP(GENMASK(14, 0), (x)) +#define LAYERYOFFSET(x) FIELD_PREP(GENMASK(30, 16), (x)) + +/* CLIPWINDOWOFFSET */ +#define CLIPWINDOWXOFFSET(x) FIELD_PREP(GENMASK(14, 0), (x)) +#define CLIPWINDOWYOFFSET(x) FIELD_PREP(GENMASK(30, 16), (x)) + +/* CLIPWINDOWDIMENSIONS */ +#define CLIPWINDOWWIDTH(x) FIELD_PREP(GENMASK(13, 0), (x) - 1) +#define CLIPWINDOWHEIGHT(x) FIELD_PREP(GENMASK(29, 16), (x) - 1) + +enum dc_linemode { + /* + * Mandatory setting for operation in the Display Controller. + * Works also for Blit Engine with marginal performance impact. + */ + LINEMODE_DISPLAY = 0, +}; + +struct dc_fu_pixel_format { + u32 pixel_format; + u32 bits; + u32 shifts; +}; + +static const struct dc_fu_pixel_format pixel_formats[] = { + { + DRM_FORMAT_XRGB8888, + R_BITS(8) | G_BITS(8) | B_BITS(8) | A_BITS(0), + R_SHIFT(16) | G_SHIFT(8) | B_SHIFT(0) | A_SHIFT(0), + }, +}; + +void dc_fu_get_pixel_format_bits(struct dc_fu *fu, u32 format, u32 *bits) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pixel_formats); i++) { + if (pixel_formats[i].pixel_format == format) { + *bits = pixel_formats[i].bits; + return; + } + } +} + +void +dc_fu_get_pixel_format_shifts(struct dc_fu *fu, u32 format, u32 *shifts) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pixel_formats); i++) { + if (pixel_formats[i].pixel_format == format) { + *shifts = pixel_formats[i].shifts; + return; + } + } +} + +static inline void dc_fu_enable_shden(struct dc_fu *fu) +{ + regmap_write_bits(fu->reg_cfg, STATICCONTROL, SHDEN, SHDEN); +} + +static inline void dc_fu_baddr_autoupdate(struct dc_fu *fu, u8 layer_mask) +{ + regmap_write_bits(fu->reg_cfg, STATICCONTROL, + BASEADDRESSAUTOUPDATE_MASK, + BASEADDRESSAUTOUPDATE(layer_mask)); +} + +void dc_fu_shdldreq_sticky(struct dc_fu *fu, u8 layer_mask) +{ + regmap_write_bits(fu->reg_cfg, STATICCONTROL, SHDLDREQSTICKY_MASK, + SHDLDREQSTICKY(layer_mask)); +} + +static inline void dc_fu_set_linemode(struct dc_fu *fu, enum dc_linemode mode) +{ + regmap_write_bits(fu->reg_cfg, BURSTBUFFERMANAGEMENT, LINEMODE_MASK, + mode); +} + +static inline void dc_fu_set_numbuffers(struct dc_fu *fu, unsigned int num) +{ + regmap_write_bits(fu->reg_cfg, BURSTBUFFERMANAGEMENT, + SETNUMBUFFERS_MASK, SETNUMBUFFERS(num)); +} + +static void dc_fu_set_burstlength(struct dc_fu *fu, dma_addr_t baddr) +{ + unsigned int burst_size, burst_length; + + burst_size = 1 << __ffs(baddr); + burst_size = round_up(burst_size, 8); + burst_size = min(burst_size, 128U); + burst_length = burst_size / 8; + + regmap_write_bits(fu->reg_cfg, BURSTBUFFERMANAGEMENT, + SETBURSTLENGTH_MASK, SETBURSTLENGTH(burst_length)); +} + +static void dc_fu_set_baseaddress(struct dc_fu *fu, enum dc_fu_frac frac, + dma_addr_t baddr) +{ + regmap_write(fu->reg_cfg, fu->reg_baseaddr[frac], baddr); +} + +void dc_fu_set_src_bpp(struct dc_fu *fu, enum dc_fu_frac frac, unsigned int bpp) +{ + regmap_write_bits(fu->reg_cfg, fu->reg_sourcebufferattributes[frac], + BITSPERPIXEL_MASK, BITSPERPIXEL(bpp)); +} + +static void dc_fu_set_src_stride(struct dc_fu *fu, enum dc_fu_frac frac, + unsigned int stride) +{ + regmap_write_bits(fu->reg_cfg, fu->reg_sourcebufferattributes[frac], + STRIDE_MASK, STRIDE(stride)); +} + +static void dc_fu_set_src_buf_dimensions(struct dc_fu *fu, enum dc_fu_frac frac, + int w, int h) +{ + regmap_write(fu->reg_cfg, fu->reg_sourcebufferdimension[frac], + LINEWIDTH(w) | LINECOUNT(h)); +} + +static inline void dc_fu_layeroffset(struct dc_fu *fu, enum dc_fu_frac frac, + unsigned int x, unsigned int y) +{ + regmap_write(fu->reg_cfg, fu->reg_layeroffset[frac], + LAYERXOFFSET(x) | LAYERYOFFSET(y)); +} + +static inline void dc_fu_clipoffset(struct dc_fu *fu, enum dc_fu_frac frac, + unsigned int x, unsigned int y) +{ + regmap_write(fu->reg_cfg, fu->reg_clipwindowoffset[frac], + CLIPWINDOWXOFFSET(x) | CLIPWINDOWYOFFSET(y)); +} + +static inline void dc_fu_clipdimensions(struct dc_fu *fu, enum dc_fu_frac frac, + unsigned int w, unsigned int h) +{ + regmap_write(fu->reg_cfg, fu->reg_clipwindowdimensions[frac], + CLIPWINDOWWIDTH(w) | CLIPWINDOWHEIGHT(h)); +} + +static inline void +dc_fu_set_pixel_blend_mode(struct dc_fu *fu, enum dc_fu_frac frac) +{ + regmap_write(fu->reg_cfg, fu->reg_layerproperty[frac], 0); + regmap_write(fu->reg_cfg, fu->reg_constantcolor[frac], 0); +} + +static void dc_fu_enable_src_buf(struct dc_fu *fu, enum dc_fu_frac frac) +{ + regmap_write_bits(fu->reg_cfg, fu->reg_layerproperty[frac], + SOURCEBUFFERENABLE, SOURCEBUFFERENABLE); +} + +static void dc_fu_disable_src_buf(struct dc_fu *fu, enum dc_fu_frac frac) +{ + regmap_write_bits(fu->reg_cfg, fu->reg_layerproperty[frac], + SOURCEBUFFERENABLE, 0); + + if (fu->lb) { + dc_lb_pec_clken(fu->lb, CLKEN_DISABLE); + dc_lb_mode(fu->lb, LB_NEUTRAL); + } +} + +static void dc_fu_set_layerblend(struct dc_fu *fu, struct dc_lb *lb) +{ + fu->lb = lb; +} + +static enum dc_link_id dc_fu_get_link_id(struct dc_fu *fu) +{ + return fu->link_id; +} + +static const char *dc_fu_get_name(struct dc_fu *fu) +{ + return fu->name; +} + +const struct dc_fu_ops dc_fu_common_ops = { + .set_burstlength = dc_fu_set_burstlength, + .set_baseaddress = dc_fu_set_baseaddress, + .set_src_stride = dc_fu_set_src_stride, + .set_src_buf_dimensions = dc_fu_set_src_buf_dimensions, + .enable_src_buf = dc_fu_enable_src_buf, + .disable_src_buf = dc_fu_disable_src_buf, + .set_layerblend = dc_fu_set_layerblend, + .get_link_id = dc_fu_get_link_id, + .get_name = dc_fu_get_name, +}; + +const struct dc_fu_ops *dc_fu_get_ops(struct dc_fu *fu) +{ + return &fu->ops; +} + +void dc_fu_common_hw_init(struct dc_fu *fu) +{ + enum dc_fu_frac i; + + dc_fu_baddr_autoupdate(fu, 0x0); + dc_fu_enable_shden(fu); + dc_fu_set_linemode(fu, LINEMODE_DISPLAY); + dc_fu_set_numbuffers(fu, 16); + + for (i = DC_FETCHUNIT_FRAC0; i < DC_FETCHUNIT_FRAC_NUM; i++) { + dc_fu_layeroffset(fu, i, 0, 0); + dc_fu_clipoffset(fu, i, 0, 0); + dc_fu_clipdimensions(fu, i, 1, 1); + dc_fu_disable_src_buf(fu, i); + dc_fu_set_pixel_blend_mode(fu, i); + } +} diff --git a/drivers/gpu/drm/imx/dc/dc-fu.h b/drivers/gpu/drm/imx/dc/dc-fu.h new file mode 100644 index 0000000000000..e016e1ea5b4e0 --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-fu.h @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2024 NXP + */ + +#ifndef __DC_FETCHUNIT_H__ +#define __DC_FETCHUNIT_H__ + +#include +#include +#include +#include + +#include + +#include "dc-pe.h" + +#define FRAC_OFFSET 0x28 + +#define STATICCONTROL 0x8 +#define BURSTBUFFERMANAGEMENT 0xc + +/* COLORCOMPONENTBITS */ +#define R_BITS(x) FIELD_PREP_CONST(GENMASK(27, 24), (x)) +#define G_BITS(x) FIELD_PREP_CONST(GENMASK(19, 16), (x)) +#define B_BITS(x) FIELD_PREP_CONST(GENMASK(11, 8), (x)) +#define A_BITS(x) FIELD_PREP_CONST(GENMASK(3, 0), (x)) + +/* COLORCOMPONENTSHIFT */ +#define R_SHIFT(x) FIELD_PREP_CONST(GENMASK(28, 24), (x)) +#define G_SHIFT(x) FIELD_PREP_CONST(GENMASK(20, 16), (x)) +#define B_SHIFT(x) FIELD_PREP_CONST(GENMASK(12, 8), (x)) +#define A_SHIFT(x) FIELD_PREP_CONST(GENMASK(4, 0), (x)) + +/* LAYERPROPERTY */ +#define YUVCONVERSIONMODE_MASK GENMASK(18, 17) +#define YUVCONVERSIONMODE(x) FIELD_PREP(YUVCONVERSIONMODE_MASK, (x)) +#define SOURCEBUFFERENABLE BIT(31) + +/* FRAMEDIMENSIONS */ +#define FRAMEWIDTH(x) FIELD_PREP(GENMASK(13, 0), (x)) +#define FRAMEHEIGHT(x) FIELD_PREP(GENMASK(29, 16), (x)) + +/* CONTROL */ +#define INPUTSELECT_MASK GENMASK(4, 3) +#define INPUTSELECT(x) FIELD_PREP(INPUTSELECT_MASK, (x)) +#define RASTERMODE_MASK GENMASK(2, 0) +#define RASTERMODE(x) FIELD_PREP(RASTERMODE_MASK, (x)) + +enum dc_yuvconversionmode { + YUVCONVERSIONMODE_OFF, +}; + +enum dc_inputselect { + INPUTSELECT_INACTIVE, +}; + +enum dc_rastermode { + RASTERMODE_NORMAL, +}; + +enum { + DC_FETCHUNIT_FL0, + DC_FETCHUNIT_FW2, +}; + +enum dc_fu_frac { + DC_FETCHUNIT_FRAC0, + DC_FETCHUNIT_FRAC1, + DC_FETCHUNIT_FRAC2, + DC_FETCHUNIT_FRAC3, + DC_FETCHUNIT_FRAC4, + DC_FETCHUNIT_FRAC5, + DC_FETCHUNIT_FRAC6, + DC_FETCHUNIT_FRAC7, + DC_FETCHUNIT_FRAC_NUM +}; + +struct dc_fu; +struct dc_lb; + +struct dc_fu_ops { + void (*init)(struct dc_fu *fu); + void (*set_burstlength)(struct dc_fu *fu, dma_addr_t baddr); + void (*set_baseaddress)(struct dc_fu *fu, enum dc_fu_frac frac, + dma_addr_t baddr); + void (*set_src_stride)(struct dc_fu *fu, enum dc_fu_frac frac, + unsigned int stride); + void (*set_src_buf_dimensions)(struct dc_fu *fu, enum dc_fu_frac frac, + int w, int h); + void (*set_fmt)(struct dc_fu *fu, enum dc_fu_frac frac, + const struct drm_format_info *format); + void (*enable_src_buf)(struct dc_fu *fu, enum dc_fu_frac frac); + void (*disable_src_buf)(struct dc_fu *fu, enum dc_fu_frac frac); + void (*set_framedimensions)(struct dc_fu *fu, int w, int h); + void (*set_layerblend)(struct dc_fu *fu, struct dc_lb *lb); + enum dc_link_id (*get_link_id)(struct dc_fu *fu); + const char *(*get_name)(struct dc_fu *fu); +}; + +struct dc_fu { + struct regmap *reg_pec; + struct regmap *reg_cfg; + char name[21]; + u32 reg_baseaddr[DC_FETCHUNIT_FRAC_NUM]; + u32 reg_sourcebufferattributes[DC_FETCHUNIT_FRAC_NUM]; + u32 reg_sourcebufferdimension[DC_FETCHUNIT_FRAC_NUM]; + u32 reg_layeroffset[DC_FETCHUNIT_FRAC_NUM]; + u32 reg_clipwindowoffset[DC_FETCHUNIT_FRAC_NUM]; + u32 reg_clipwindowdimensions[DC_FETCHUNIT_FRAC_NUM]; + u32 reg_constantcolor[DC_FETCHUNIT_FRAC_NUM]; + u32 reg_layerproperty[DC_FETCHUNIT_FRAC_NUM]; + unsigned int id; + enum dc_link_id link_id; + struct dc_fu_ops ops; + struct dc_lb *lb; +}; + +extern const struct dc_fu_ops dc_fu_common_ops; + +void dc_fu_get_pixel_format_bits(struct dc_fu *fu, u32 format, u32 *bits); +void dc_fu_get_pixel_format_shifts(struct dc_fu *fu, u32 format, u32 *shifts); +void dc_fu_shdldreq_sticky(struct dc_fu *fu, u8 layer_mask); +void dc_fu_set_src_bpp(struct dc_fu *fu, enum dc_fu_frac frac, unsigned int bpp); +void dc_fu_common_hw_init(struct dc_fu *fu); + +const struct dc_fu_ops *dc_fu_get_ops(struct dc_fu *fu); + +#endif /* __DC_FETCHUNIT_H__ */ diff --git a/drivers/gpu/drm/imx/dc/dc-fw.c b/drivers/gpu/drm/imx/dc/dc-fw.c new file mode 100644 index 0000000000000..acb2d4d9e2ecd --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-fw.c @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include +#include +#include +#include +#include + +#include + +#include "dc-drv.h" +#include "dc-fu.h" + +#define PIXENGCFG_DYNAMIC 0x8 + +#define BASEADDRESS(x) (0x10 + FRAC_OFFSET * (x)) +#define SOURCEBUFFERATTRIBUTES(x) (0x14 + FRAC_OFFSET * (x)) +#define SOURCEBUFFERDIMENSION(x) (0x18 + FRAC_OFFSET * (x)) +#define COLORCOMPONENTBITS(x) (0x1c + FRAC_OFFSET * (x)) +#define COLORCOMPONENTSHIFT(x) (0x20 + FRAC_OFFSET * (x)) +#define LAYEROFFSET(x) (0x24 + FRAC_OFFSET * (x)) +#define CLIPWINDOWOFFSET(x) (0x28 + FRAC_OFFSET * (x)) +#define CLIPWINDOWDIMENSIONS(x) (0x2c + FRAC_OFFSET * (x)) +#define CONSTANTCOLOR(x) (0x30 + FRAC_OFFSET * (x)) +#define LAYERPROPERTY(x) (0x34 + FRAC_OFFSET * (x)) +#define FRAMEDIMENSIONS 0x150 +#define CONTROL 0x170 + +struct dc_fw { + struct dc_fu fu; +}; + +static const struct dc_subdev_info dc_fw_info[] = { + { .reg_start = 0x56180a60, .id = 2, }, +}; + +static const struct regmap_range dc_fw_pec_regmap_access_ranges[] = { + regmap_reg_range(PIXENGCFG_DYNAMIC, PIXENGCFG_DYNAMIC), +}; + +static const struct regmap_access_table dc_fw_pec_regmap_access_table = { + .yes_ranges = dc_fw_pec_regmap_access_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_fw_pec_regmap_access_ranges), +}; + +static const struct regmap_config dc_fw_pec_regmap_config = { + .name = "pec", + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .wr_table = &dc_fw_pec_regmap_access_table, + .rd_table = &dc_fw_pec_regmap_access_table, + .max_register = PIXENGCFG_DYNAMIC, +}; + +static const struct regmap_range dc_fw_regmap_ranges[] = { + regmap_reg_range(STATICCONTROL, FRAMEDIMENSIONS), + regmap_reg_range(CONTROL, CONTROL), +}; + +static const struct regmap_access_table dc_fw_regmap_access_table = { + .yes_ranges = dc_fw_regmap_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_fw_regmap_ranges), +}; + +static const struct regmap_config dc_fw_cfg_regmap_config = { + .name = "cfg", + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .wr_table = &dc_fw_regmap_access_table, + .rd_table = &dc_fw_regmap_access_table, + .max_register = CONTROL, +}; + +static void dc_fw_set_fmt(struct dc_fu *fu, enum dc_fu_frac frac, + const struct drm_format_info *format) +{ + u32 bits = 0, shifts = 0; + + dc_fu_set_src_bpp(fu, frac, format->cpp[0] * 8); + + regmap_write_bits(fu->reg_cfg, CONTROL, INPUTSELECT_MASK, + INPUTSELECT(INPUTSELECT_INACTIVE)); + regmap_write_bits(fu->reg_cfg, CONTROL, RASTERMODE_MASK, + RASTERMODE(RASTERMODE_NORMAL)); + + regmap_write_bits(fu->reg_cfg, LAYERPROPERTY(frac), + YUVCONVERSIONMODE_MASK, + YUVCONVERSIONMODE(YUVCONVERSIONMODE_OFF)); + + dc_fu_get_pixel_format_bits(fu, format->format, &bits); + dc_fu_get_pixel_format_shifts(fu, format->format, &shifts); + + regmap_write(fu->reg_cfg, COLORCOMPONENTBITS(frac), bits); + regmap_write(fu->reg_cfg, COLORCOMPONENTSHIFT(frac), shifts); +} + +static void dc_fw_set_framedimensions(struct dc_fu *fu, int w, int h) +{ + regmap_write(fu->reg_cfg, FRAMEDIMENSIONS, + FRAMEWIDTH(w) | FRAMEHEIGHT(h)); +} + +static void dc_fw_init(struct dc_fu *fu) +{ + regmap_write(fu->reg_pec, PIXENGCFG_DYNAMIC, LINK_ID_NONE); + dc_fu_common_hw_init(fu); + dc_fu_shdldreq_sticky(fu, 0xff); +} + +static void dc_fw_set_ops(struct dc_fu *fu) +{ + memcpy(&fu->ops, &dc_fu_common_ops, sizeof(dc_fu_common_ops)); + fu->ops.init = dc_fw_init; + fu->ops.set_fmt = dc_fw_set_fmt; + fu->ops.set_framedimensions = dc_fw_set_framedimensions; +} + +static int dc_fw_bind(struct device *dev, struct device *master, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + struct dc_drm_device *dc_drm = data; + struct resource *res_pec; + void __iomem *base_pec; + void __iomem *base_cfg; + struct dc_fw *fw; + struct dc_fu *fu; + int i, id; + + fw = devm_kzalloc(dev, sizeof(*fw), GFP_KERNEL); + if (!fw) + return -ENOMEM; + + fu = &fw->fu; + + base_pec = devm_platform_get_and_ioremap_resource(pdev, 0, &res_pec); + if (IS_ERR(base_pec)) + return PTR_ERR(base_pec); + + base_cfg = devm_platform_ioremap_resource_byname(pdev, "cfg"); + if (IS_ERR(base_cfg)) + return PTR_ERR(base_cfg); + + fu->reg_pec = devm_regmap_init_mmio(dev, base_pec, + &dc_fw_pec_regmap_config); + if (IS_ERR(fu->reg_pec)) + return PTR_ERR(fu->reg_pec); + + fu->reg_cfg = devm_regmap_init_mmio(dev, base_cfg, + &dc_fw_cfg_regmap_config); + if (IS_ERR(fu->reg_cfg)) + return PTR_ERR(fu->reg_cfg); + + id = dc_subdev_get_id(dc_fw_info, ARRAY_SIZE(dc_fw_info), res_pec); + if (id < 0) { + dev_err(dev, "failed to get instance number: %d\n", id); + return id; + } + + fu->link_id = LINK_ID_FETCHWARP2; + fu->id = DC_FETCHUNIT_FW2; + for (i = 0; i < DC_FETCHUNIT_FRAC_NUM; i++) { + fu->reg_baseaddr[i] = BASEADDRESS(i); + fu->reg_sourcebufferattributes[i] = SOURCEBUFFERATTRIBUTES(i); + fu->reg_sourcebufferdimension[i] = SOURCEBUFFERDIMENSION(i); + fu->reg_layeroffset[i] = LAYEROFFSET(i); + fu->reg_clipwindowoffset[i] = CLIPWINDOWOFFSET(i); + fu->reg_clipwindowdimensions[i] = CLIPWINDOWDIMENSIONS(i); + fu->reg_constantcolor[i] = CONSTANTCOLOR(i); + fu->reg_layerproperty[i] = LAYERPROPERTY(i); + } + snprintf(fu->name, sizeof(fu->name), "FetchWarp%d", id); + + dc_fw_set_ops(fu); + + dc_drm->fu_disp[fu->id] = fu; + + return 0; +} + +static const struct component_ops dc_fw_ops = { + .bind = dc_fw_bind, +}; + +static int dc_fw_probe(struct platform_device *pdev) +{ + int ret; + + ret = component_add(&pdev->dev, &dc_fw_ops); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to add component\n"); + + return 0; +} + +static void dc_fw_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &dc_fw_ops); +} + +static const struct of_device_id dc_fw_dt_ids[] = { + { .compatible = "fsl,imx8qxp-dc-fetchwarp" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dc_fw_dt_ids); + +struct platform_driver dc_fw_driver = { + .probe = dc_fw_probe, + .remove = dc_fw_remove, + .driver = { + .name = "imx8-dc-fetchwarp", + .suppress_bind_attrs = true, + .of_match_table = dc_fw_dt_ids, + }, +}; diff --git a/drivers/gpu/drm/imx/dc/dc-lb.c b/drivers/gpu/drm/imx/dc/dc-lb.c new file mode 100644 index 0000000000000..38f966625d382 --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-lb.c @@ -0,0 +1,325 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dc-drv.h" +#include "dc-pe.h" + +#define PIXENGCFG_DYNAMIC 0x8 +#define PIXENGCFG_DYNAMIC_PRIM_SEL_MASK GENMASK(5, 0) +#define PIXENGCFG_DYNAMIC_PRIM_SEL(x) \ + FIELD_PREP(PIXENGCFG_DYNAMIC_PRIM_SEL_MASK, (x)) +#define PIXENGCFG_DYNAMIC_SEC_SEL_MASK GENMASK(13, 8) +#define PIXENGCFG_DYNAMIC_SEC_SEL(x) \ + FIELD_PREP(PIXENGCFG_DYNAMIC_SEC_SEL_MASK, (x)) + +#define STATICCONTROL 0x8 +#define SHDTOKSEL_MASK GENMASK(4, 3) +#define SHDTOKSEL(x) FIELD_PREP(SHDTOKSEL_MASK, (x)) +#define SHDLDSEL_MASK GENMASK(2, 1) +#define SHDLDSEL(x) FIELD_PREP(SHDLDSEL_MASK, (x)) + +#define CONTROL 0xc +#define CTRL_MODE_MASK BIT(0) +#define CTRL_MODE(x) FIELD_PREP(CTRL_MODE_MASK, (x)) + +#define BLENDCONTROL 0x10 +#define ALPHA_MASK GENMASK(23, 16) +#define ALPHA(x) FIELD_PREP(ALPHA_MASK, (x)) +#define PRIM_C_BLD_FUNC_MASK GENMASK(2, 0) +#define PRIM_C_BLD_FUNC(x) \ + FIELD_PREP(PRIM_C_BLD_FUNC_MASK, (x)) +#define SEC_C_BLD_FUNC_MASK GENMASK(6, 4) +#define SEC_C_BLD_FUNC(x) \ + FIELD_PREP(SEC_C_BLD_FUNC_MASK, (x)) +#define PRIM_A_BLD_FUNC_MASK GENMASK(10, 8) +#define PRIM_A_BLD_FUNC(x) \ + FIELD_PREP(PRIM_A_BLD_FUNC_MASK, (x)) +#define SEC_A_BLD_FUNC_MASK GENMASK(14, 12) +#define SEC_A_BLD_FUNC(x) \ + FIELD_PREP(SEC_A_BLD_FUNC_MASK, (x)) + +#define POSITION 0x14 +#define XPOS_MASK GENMASK(15, 0) +#define XPOS(x) FIELD_PREP(XPOS_MASK, (x)) +#define YPOS_MASK GENMASK(31, 16) +#define YPOS(x) FIELD_PREP(YPOS_MASK, (x)) + +enum dc_lb_blend_func { + DC_LAYERBLEND_BLEND_ZERO, + DC_LAYERBLEND_BLEND_ONE, + DC_LAYERBLEND_BLEND_PRIM_ALPHA, + DC_LAYERBLEND_BLEND_ONE_MINUS_PRIM_ALPHA, + DC_LAYERBLEND_BLEND_SEC_ALPHA, + DC_LAYERBLEND_BLEND_ONE_MINUS_SEC_ALPHA, + DC_LAYERBLEND_BLEND_CONST_ALPHA, + DC_LAYERBLEND_BLEND_ONE_MINUS_CONST_ALPHA, +}; + +enum dc_lb_shadow_sel { + BOTH = 0x2, +}; + +static const struct dc_subdev_info dc_lb_info[] = { + { .reg_start = 0x56180ba0, .id = 0, }, + { .reg_start = 0x56180bc0, .id = 1, }, + { .reg_start = 0x56180be0, .id = 2, }, + { .reg_start = 0x56180c00, .id = 3, }, +}; + +static const struct regmap_range dc_lb_pec_regmap_access_ranges[] = { + regmap_reg_range(PIXENGCFG_DYNAMIC, PIXENGCFG_DYNAMIC), +}; + +static const struct regmap_access_table dc_lb_pec_regmap_access_table = { + .yes_ranges = dc_lb_pec_regmap_access_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_lb_pec_regmap_access_ranges), +}; + +static const struct regmap_config dc_lb_pec_regmap_config = { + .name = "pec", + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .wr_table = &dc_lb_pec_regmap_access_table, + .rd_table = &dc_lb_pec_regmap_access_table, + .max_register = PIXENGCFG_DYNAMIC, +}; + +static const struct regmap_range dc_lb_regmap_ranges[] = { + regmap_reg_range(STATICCONTROL, POSITION), +}; + +static const struct regmap_access_table dc_lb_regmap_access_table = { + .yes_ranges = dc_lb_regmap_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_lb_regmap_ranges), +}; + +static const struct regmap_config dc_lb_cfg_regmap_config = { + .name = "cfg", + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .wr_table = &dc_lb_regmap_access_table, + .rd_table = &dc_lb_regmap_access_table, + .max_register = POSITION, +}; + +static const enum dc_link_id prim_sels[] = { + /* common options */ + LINK_ID_NONE, + LINK_ID_CONSTFRAME0, + LINK_ID_CONSTFRAME1, + LINK_ID_CONSTFRAME4, + LINK_ID_CONSTFRAME5, + /* + * special options: + * layerblend(n) has n special options, + * from layerblend0 to layerblend(n - 1), e.g., + * layerblend3 has 3 special options - + * layerblend0/1/2. + */ + LINK_ID_LAYERBLEND0, + LINK_ID_LAYERBLEND1, + LINK_ID_LAYERBLEND2, + LINK_ID_LAYERBLEND3, +}; + +static const enum dc_link_id sec_sels[] = { + LINK_ID_NONE, + LINK_ID_FETCHWARP2, + LINK_ID_FETCHLAYER0, +}; + +enum dc_link_id dc_lb_get_link_id(struct dc_lb *lb) +{ + return lb->link; +} + +void dc_lb_pec_dynamic_prim_sel(struct dc_lb *lb, enum dc_link_id prim) +{ + int fixed_sels_num = ARRAY_SIZE(prim_sels) - 4; + int i; + + for (i = 0; i < fixed_sels_num + lb->id; i++) { + if (prim_sels[i] == prim) { + regmap_write_bits(lb->reg_pec, PIXENGCFG_DYNAMIC, + PIXENGCFG_DYNAMIC_PRIM_SEL_MASK, + PIXENGCFG_DYNAMIC_PRIM_SEL(prim)); + return; + } + } + + dev_warn(lb->dev, "invalid primary input selection:%d\n", prim); +} + +void dc_lb_pec_dynamic_sec_sel(struct dc_lb *lb, enum dc_link_id sec) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(sec_sels); i++) { + if (sec_sels[i] == sec) { + regmap_write_bits(lb->reg_pec, PIXENGCFG_DYNAMIC, + PIXENGCFG_DYNAMIC_SEC_SEL_MASK, + PIXENGCFG_DYNAMIC_SEC_SEL(sec)); + return; + } + } + + dev_warn(lb->dev, "invalid secondary input selection:%d\n", sec); +} + +void dc_lb_pec_clken(struct dc_lb *lb, enum dc_pec_clken clken) +{ + regmap_write_bits(lb->reg_pec, PIXENGCFG_DYNAMIC, CLKEN_MASK, + CLKEN(clken)); +} + +static inline void dc_lb_enable_shden(struct dc_lb *lb) +{ + regmap_write_bits(lb->reg_cfg, STATICCONTROL, SHDEN, SHDEN); +} + +static inline void dc_lb_shdtoksel(struct dc_lb *lb, enum dc_lb_shadow_sel sel) +{ + regmap_write_bits(lb->reg_cfg, STATICCONTROL, SHDTOKSEL_MASK, + SHDTOKSEL(sel)); +} + +static inline void dc_lb_shdldsel(struct dc_lb *lb, enum dc_lb_shadow_sel sel) +{ + regmap_write_bits(lb->reg_cfg, STATICCONTROL, SHDLDSEL_MASK, + SHDLDSEL(sel)); +} + +void dc_lb_mode(struct dc_lb *lb, enum dc_lb_mode mode) +{ + regmap_write_bits(lb->reg_cfg, CONTROL, CTRL_MODE_MASK, mode); +} + +static inline void dc_lb_blendcontrol(struct dc_lb *lb) +{ + u32 val = PRIM_A_BLD_FUNC(DC_LAYERBLEND_BLEND_ZERO) | + SEC_A_BLD_FUNC(DC_LAYERBLEND_BLEND_ZERO) | + PRIM_C_BLD_FUNC(DC_LAYERBLEND_BLEND_ZERO) | + SEC_C_BLD_FUNC(DC_LAYERBLEND_BLEND_CONST_ALPHA) | + ALPHA(DRM_BLEND_ALPHA_OPAQUE >> 8); + + regmap_write(lb->reg_cfg, BLENDCONTROL, val); +} + +void dc_lb_position(struct dc_lb *lb, int x, int y) +{ + regmap_write(lb->reg_cfg, POSITION, XPOS(x) | YPOS(y)); +} + +int dc_lb_get_id(struct dc_lb *lb) +{ + return lb->id; +} + +void dc_lb_init(struct dc_lb *lb) +{ + dc_lb_pec_dynamic_prim_sel(lb, LINK_ID_NONE); + dc_lb_pec_dynamic_sec_sel(lb, LINK_ID_NONE); + dc_lb_pec_clken(lb, CLKEN_DISABLE); + dc_lb_shdldsel(lb, BOTH); + dc_lb_shdtoksel(lb, BOTH); + dc_lb_blendcontrol(lb); + dc_lb_enable_shden(lb); +} + +static int dc_lb_bind(struct device *dev, struct device *master, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + struct dc_drm_device *dc_drm = data; + struct resource *res_pec; + void __iomem *base_pec; + void __iomem *base_cfg; + struct dc_lb *lb; + + lb = devm_kzalloc(dev, sizeof(*lb), GFP_KERNEL); + if (!lb) + return -ENOMEM; + + base_pec = devm_platform_get_and_ioremap_resource(pdev, 0, &res_pec); + if (IS_ERR(base_pec)) + return PTR_ERR(base_pec); + + base_cfg = devm_platform_ioremap_resource_byname(pdev, "cfg"); + if (IS_ERR(base_cfg)) + return PTR_ERR(base_cfg); + + lb->reg_pec = devm_regmap_init_mmio(dev, base_pec, + &dc_lb_pec_regmap_config); + if (IS_ERR(lb->reg_pec)) + return PTR_ERR(lb->reg_pec); + + lb->reg_cfg = devm_regmap_init_mmio(dev, base_cfg, + &dc_lb_cfg_regmap_config); + if (IS_ERR(lb->reg_cfg)) + return PTR_ERR(lb->reg_cfg); + + lb->id = dc_subdev_get_id(dc_lb_info, ARRAY_SIZE(dc_lb_info), res_pec); + if (lb->id < 0) { + dev_err(dev, "failed to get instance number: %d\n", lb->id); + return lb->id; + } + + lb->dev = dev; + lb->link = LINK_ID_LAYERBLEND0 + lb->id; + + dc_drm->lb[lb->id] = lb; + + return 0; +} + +static const struct component_ops dc_lb_ops = { + .bind = dc_lb_bind, +}; + +static int dc_lb_probe(struct platform_device *pdev) +{ + int ret; + + ret = component_add(&pdev->dev, &dc_lb_ops); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to add component\n"); + + return 0; +} + +static void dc_lb_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &dc_lb_ops); +} + +static const struct of_device_id dc_lb_dt_ids[] = { + { .compatible = "fsl,imx8qxp-dc-layerblend" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dc_lb_dt_ids); + +struct platform_driver dc_lb_driver = { + .probe = dc_lb_probe, + .remove = dc_lb_remove, + .driver = { + .name = "imx8-dc-layerblend", + .suppress_bind_attrs = true, + .of_match_table = dc_lb_dt_ids, + }, +}; diff --git a/drivers/gpu/drm/imx/dc/dc-pe.c b/drivers/gpu/drm/imx/dc/dc-pe.c new file mode 100644 index 0000000000000..6676c22f3f458 --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-pe.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dc-drv.h" +#include "dc-fu.h" +#include "dc-pe.h" + +static int dc_pe_bind(struct device *dev, struct device *master, void *data) +{ + struct dc_drm_device *dc_drm = data; + struct dc_pe *pe; + int ret; + + pe = devm_kzalloc(dev, sizeof(*pe), GFP_KERNEL); + if (!pe) + return -ENOMEM; + + pe->clk_axi = devm_clk_get(dev, NULL); + if (IS_ERR(pe->clk_axi)) + return dev_err_probe(dev, PTR_ERR(pe->clk_axi), + "failed to get AXI clock\n"); + + pe->dev = dev; + + dev_set_drvdata(dev, pe); + + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; + + dc_drm->pe = pe; + + return 0; +} + +/* + * It's possible to get the child device pointers from the child component + * bind callbacks, but it depends on the component helper behavior to bind + * the pixel engine component first. To avoid the dependency, post bind to + * get the pointers from dc_drm in a safe manner. + */ +void dc_pe_post_bind(struct dc_drm_device *dc_drm) +{ + struct dc_pe *pe = dc_drm->pe; + int i; + + for (i = 0; i < DC_DISPLAYS; i++) { + pe->cf_safe[i] = dc_drm->cf_safe[i]; + pe->cf_cont[i] = dc_drm->cf_cont[i]; + pe->ed_safe[i] = dc_drm->ed_safe[i]; + pe->ed_cont[i] = dc_drm->ed_cont[i]; + } + + for (i = 0; i < DC_DISP_FU_CNT; i++) + pe->fu_disp[i] = dc_drm->fu_disp[i]; + + for (i = 0; i < DC_LB_CNT; i++) + pe->lb[i] = dc_drm->lb[i]; +} + +static const struct component_ops dc_pe_ops = { + .bind = dc_pe_bind, +}; + +static int dc_pe_probe(struct platform_device *pdev) +{ + int ret; + + ret = devm_of_platform_populate(&pdev->dev); + if (ret < 0) + return ret; + + ret = component_add(&pdev->dev, &dc_pe_ops); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to add component\n"); + + return 0; +} + +static void dc_pe_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &dc_pe_ops); +} + +static int dc_pe_runtime_suspend(struct device *dev) +{ + struct dc_pe *pe = dev_get_drvdata(dev); + + clk_disable_unprepare(pe->clk_axi); + + return 0; +} + +static int dc_pe_runtime_resume(struct device *dev) +{ + struct dc_pe *pe = dev_get_drvdata(dev); + int i, ret; + + ret = clk_prepare_enable(pe->clk_axi); + if (ret) { + dev_err(dev, "failed to enable AXI clock: %d\n", ret); + return ret; + } + + for (i = 0; i < ARRAY_SIZE(pe->cf_safe); i++) + dc_cf_init(pe->cf_safe[i]); + + for (i = 0; i < ARRAY_SIZE(pe->cf_cont); i++) + dc_cf_init(pe->cf_cont[i]); + + for (i = 0; i < ARRAY_SIZE(pe->ed_safe); i++) + dc_ed_init(pe->ed_safe[i]); + + for (i = 0; i < ARRAY_SIZE(pe->ed_cont); i++) + dc_ed_init(pe->ed_cont[i]); + + for (i = 0; i < ARRAY_SIZE(pe->fu_disp); i++) + pe->fu_disp[i]->ops.init(pe->fu_disp[i]); + + for (i = 0; i < ARRAY_SIZE(pe->lb); i++) + dc_lb_init(pe->lb[i]); + + return 0; +} + +static const struct dev_pm_ops dc_pe_pm_ops = { + RUNTIME_PM_OPS(dc_pe_runtime_suspend, dc_pe_runtime_resume, NULL) +}; + +static const struct of_device_id dc_pe_dt_ids[] = { + { .compatible = "fsl,imx8qxp-dc-pixel-engine", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dc_pe_dt_ids); + +struct platform_driver dc_pe_driver = { + .probe = dc_pe_probe, + .remove = dc_pe_remove, + .driver = { + .name = "imx8-dc-pixel-engine", + .suppress_bind_attrs = true, + .of_match_table = dc_pe_dt_ids, + .pm = pm_sleep_ptr(&dc_pe_pm_ops), + }, +}; diff --git a/drivers/gpu/drm/imx/dc/dc-pe.h b/drivers/gpu/drm/imx/dc/dc-pe.h new file mode 100644 index 0000000000000..f5e01a6eb9e91 --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-pe.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2024 NXP + */ + +#ifndef __DC_PIXEL_ENGINE_H__ +#define __DC_PIXEL_ENGINE_H__ + +#include +#include +#include + +#include "dc-de.h" + +#define SHDEN BIT(0) + +#define CLKEN_MASK_SHIFT 24 +#define CLKEN_MASK (0x3 << CLKEN_MASK_SHIFT) +#define CLKEN(n) ((n) << CLKEN_MASK_SHIFT) + +#define DC_DISP_FU_CNT 2 +#define DC_LB_CNT 4 + +enum dc_link_id { + LINK_ID_NONE = 0x00, + LINK_ID_CONSTFRAME0 = 0x0c, + LINK_ID_CONSTFRAME4 = 0x0e, + LINK_ID_CONSTFRAME1 = 0x10, + LINK_ID_CONSTFRAME5 = 0x12, + LINK_ID_FETCHWARP2 = 0x14, + LINK_ID_FETCHLAYER0 = 0x1a, + LINK_ID_LAYERBLEND0 = 0x21, + LINK_ID_LAYERBLEND1 = 0x22, + LINK_ID_LAYERBLEND2 = 0x23, + LINK_ID_LAYERBLEND3 = 0x24, +}; + +enum dc_lb_mode { + LB_NEUTRAL, /* Output is same as primary input. */ + LB_BLEND, +}; + +enum dc_pec_clken { + CLKEN_DISABLE, + CLKEN_AUTOMATIC, +}; + +struct dc_cf { + struct regmap *reg_cfg; + enum dc_link_id link; +}; + +struct dc_ed { + struct device *dev; + struct regmap *reg_pec; + struct regmap *reg_cfg; + int irq_shdload; +}; + +struct dc_lb { + struct device *dev; + struct regmap *reg_pec; + struct regmap *reg_cfg; + int id; + enum dc_link_id link; +}; + +struct dc_pe { + struct device *dev; + struct clk *clk_axi; + struct dc_cf *cf_safe[DC_DISPLAYS]; + struct dc_cf *cf_cont[DC_DISPLAYS]; + struct dc_ed *ed_safe[DC_DISPLAYS]; + struct dc_ed *ed_cont[DC_DISPLAYS]; + struct dc_fu *fu_disp[DC_DISP_FU_CNT]; + struct dc_lb *lb[DC_LB_CNT]; +}; + +/* Constant Frame Unit */ +enum dc_link_id dc_cf_get_link_id(struct dc_cf *cf); +void dc_cf_framedimensions(struct dc_cf *cf, unsigned int w, unsigned int h); +void dc_cf_constantcolor_black(struct dc_cf *cf); +void dc_cf_constantcolor_blue(struct dc_cf *cf); +void dc_cf_init(struct dc_cf *cf); + +/* External Destination Unit */ +void dc_ed_pec_src_sel(struct dc_ed *ed, enum dc_link_id src); +void dc_ed_pec_sync_trigger(struct dc_ed *ed); +void dc_ed_init(struct dc_ed *ed); + +/* Layer Blend Unit */ +enum dc_link_id dc_lb_get_link_id(struct dc_lb *lb); +void dc_lb_pec_dynamic_prim_sel(struct dc_lb *lb, enum dc_link_id prim); +void dc_lb_pec_dynamic_sec_sel(struct dc_lb *lb, enum dc_link_id sec); +void dc_lb_pec_clken(struct dc_lb *lb, enum dc_pec_clken clken); +void dc_lb_mode(struct dc_lb *lb, enum dc_lb_mode mode); +void dc_lb_position(struct dc_lb *lb, int x, int y); +int dc_lb_get_id(struct dc_lb *lb); +void dc_lb_init(struct dc_lb *lb); + +#endif /* __DC_PIXEL_ENGINE_H__ */ -- GitLab From 37571feb6c08dab97f0a8a37e3c486aa8aead5f7 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 14 Apr 2025 11:50:20 +0800 Subject: [PATCH 0057/1479] drm/imx: Add i.MX8qxp Display Controller interrupt controller i.MX8qxp Display Controller has a built-in interrupt controller to support Enable/Status/Preset/Clear interrupt bit. Add driver for it. Reviewed-by: Maxime Ripard Reviewed-by: Dmitry Baryshkov Signed-off-by: Liu Ying Link: https://lore.kernel.org/r/20250414035028.1561475-12-victor.liu@nxp.com --- drivers/gpu/drm/imx/dc/Kconfig | 1 + drivers/gpu/drm/imx/dc/Makefile | 2 +- drivers/gpu/drm/imx/dc/dc-drv.c | 1 + drivers/gpu/drm/imx/dc/dc-drv.h | 1 + drivers/gpu/drm/imx/dc/dc-ic.c | 282 ++++++++++++++++++++++++++++++++ 5 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/imx/dc/dc-ic.c diff --git a/drivers/gpu/drm/imx/dc/Kconfig b/drivers/gpu/drm/imx/dc/Kconfig index e1ef76d828307..1fc84c7475de1 100644 --- a/drivers/gpu/drm/imx/dc/Kconfig +++ b/drivers/gpu/drm/imx/dc/Kconfig @@ -1,6 +1,7 @@ config DRM_IMX8_DC tristate "Freescale i.MX8 Display Controller Graphics" depends on DRM && COMMON_CLK && OF && (ARCH_MXC || COMPILE_TEST) + select GENERIC_IRQ_CHIP select REGMAP select REGMAP_MMIO help diff --git a/drivers/gpu/drm/imx/dc/Makefile b/drivers/gpu/drm/imx/dc/Makefile index 2942ae6fd5bd7..1ce3e8a8db22f 100644 --- a/drivers/gpu/drm/imx/dc/Makefile +++ b/drivers/gpu/drm/imx/dc/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 imx8-dc-drm-objs := dc-cf.o dc-de.o dc-drv.o dc-ed.o dc-fg.o dc-fl.o dc-fu.o \ - dc-fw.o dc-lb.o dc-pe.o dc-tc.o + dc-fw.o dc-ic.o dc-lb.o dc-pe.o dc-tc.o obj-$(CONFIG_DRM_IMX8_DC) += imx8-dc-drm.o diff --git a/drivers/gpu/drm/imx/dc/dc-drv.c b/drivers/gpu/drm/imx/dc/dc-drv.c index 7c64acc863ad9..fd68861f770a5 100644 --- a/drivers/gpu/drm/imx/dc/dc-drv.c +++ b/drivers/gpu/drm/imx/dc/dc-drv.c @@ -15,6 +15,7 @@ static struct platform_driver * const dc_drivers[] = { &dc_fg_driver, &dc_fl_driver, &dc_fw_driver, + &dc_ic_driver, &dc_lb_driver, &dc_pe_driver, &dc_tc_driver, diff --git a/drivers/gpu/drm/imx/dc/dc-drv.h b/drivers/gpu/drm/imx/dc/dc-drv.h index b9fe12577a195..e4c2d564ab5d8 100644 --- a/drivers/gpu/drm/imx/dc/dc-drv.h +++ b/drivers/gpu/drm/imx/dc/dc-drv.h @@ -54,6 +54,7 @@ extern struct platform_driver dc_ed_driver; extern struct platform_driver dc_fg_driver; extern struct platform_driver dc_fl_driver; extern struct platform_driver dc_fw_driver; +extern struct platform_driver dc_ic_driver; extern struct platform_driver dc_lb_driver; extern struct platform_driver dc_pe_driver; extern struct platform_driver dc_tc_driver; diff --git a/drivers/gpu/drm/imx/dc/dc-ic.c b/drivers/gpu/drm/imx/dc/dc-ic.c new file mode 100644 index 0000000000000..a270ae4030cdc --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-ic.c @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USERINTERRUPTMASK(n) (0x8 + 4 * (n)) +#define INTERRUPTENABLE(n) (0x10 + 4 * (n)) +#define INTERRUPTPRESET(n) (0x18 + 4 * (n)) +#define INTERRUPTCLEAR(n) (0x20 + 4 * (n)) +#define INTERRUPTSTATUS(n) (0x28 + 4 * (n)) +#define USERINTERRUPTENABLE(n) (0x40 + 4 * (n)) +#define USERINTERRUPTPRESET(n) (0x48 + 4 * (n)) +#define USERINTERRUPTCLEAR(n) (0x50 + 4 * (n)) +#define USERINTERRUPTSTATUS(n) (0x58 + 4 * (n)) + +#define IRQ_COUNT 49 +#define IRQ_RESERVED 35 +#define REG_NUM 2 + +struct dc_ic_data { + struct regmap *regs; + struct clk *clk_axi; + int irq[IRQ_COUNT]; + struct irq_domain *domain; +}; + +struct dc_ic_entry { + struct dc_ic_data *data; + int irq; +}; + +static const struct regmap_range dc_ic_regmap_write_ranges[] = { + regmap_reg_range(USERINTERRUPTMASK(0), INTERRUPTCLEAR(1)), + regmap_reg_range(USERINTERRUPTENABLE(0), USERINTERRUPTCLEAR(1)), +}; + +static const struct regmap_access_table dc_ic_regmap_write_table = { + .yes_ranges = dc_ic_regmap_write_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_ic_regmap_write_ranges), +}; + +static const struct regmap_range dc_ic_regmap_read_ranges[] = { + regmap_reg_range(USERINTERRUPTMASK(0), INTERRUPTENABLE(1)), + regmap_reg_range(INTERRUPTSTATUS(0), INTERRUPTSTATUS(1)), + regmap_reg_range(USERINTERRUPTENABLE(0), USERINTERRUPTENABLE(1)), + regmap_reg_range(USERINTERRUPTSTATUS(0), USERINTERRUPTSTATUS(1)), +}; + +static const struct regmap_access_table dc_ic_regmap_read_table = { + .yes_ranges = dc_ic_regmap_read_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_ic_regmap_read_ranges), +}; + +static const struct regmap_range dc_ic_regmap_volatile_ranges[] = { + regmap_reg_range(INTERRUPTPRESET(0), INTERRUPTCLEAR(1)), + regmap_reg_range(USERINTERRUPTPRESET(0), USERINTERRUPTCLEAR(1)), +}; + +static const struct regmap_access_table dc_ic_regmap_volatile_table = { + .yes_ranges = dc_ic_regmap_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(dc_ic_regmap_volatile_ranges), +}; + +static const struct regmap_config dc_ic_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, + .wr_table = &dc_ic_regmap_write_table, + .rd_table = &dc_ic_regmap_read_table, + .volatile_table = &dc_ic_regmap_volatile_table, + .max_register = USERINTERRUPTSTATUS(1), +}; + +static void dc_ic_irq_handler(struct irq_desc *desc) +{ + struct dc_ic_entry *entry = irq_desc_get_handler_data(desc); + struct dc_ic_data *data = entry->data; + unsigned int status, enable; + unsigned int virq; + + chained_irq_enter(irq_desc_get_chip(desc), desc); + + regmap_read(data->regs, USERINTERRUPTSTATUS(entry->irq / 32), &status); + regmap_read(data->regs, USERINTERRUPTENABLE(entry->irq / 32), &enable); + + status &= enable; + + if (status & BIT(entry->irq % 32)) { + virq = irq_find_mapping(data->domain, entry->irq); + if (virq) + generic_handle_irq(virq); + } + + chained_irq_exit(irq_desc_get_chip(desc), desc); +} + +static const unsigned long unused_irq[REG_NUM] = {0x00000000, 0xfffe0008}; + +static int dc_ic_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct irq_chip_generic *gc; + struct dc_ic_entry *entry; + struct irq_chip_type *ct; + struct dc_ic_data *data; + void __iomem *base; + int i, ret; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + entry = devm_kcalloc(dev, IRQ_COUNT, sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) { + dev_err(dev, "failed to initialize reg\n"); + return PTR_ERR(base); + } + + data->regs = devm_regmap_init_mmio(dev, base, &dc_ic_regmap_config); + if (IS_ERR(data->regs)) + return PTR_ERR(data->regs); + + data->clk_axi = devm_clk_get(dev, NULL); + if (IS_ERR(data->clk_axi)) + return dev_err_probe(dev, PTR_ERR(data->clk_axi), + "failed to get AXI clock\n"); + + for (i = 0; i < IRQ_COUNT; i++) { + /* skip the reserved IRQ */ + if (i == IRQ_RESERVED) + continue; + + ret = platform_get_irq(pdev, i); + if (ret < 0) + return ret; + } + + dev_set_drvdata(dev, data); + + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; + + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) { + dev_err(dev, "failed to get runtime PM sync: %d\n", ret); + return ret; + } + + for (i = 0; i < REG_NUM; i++) { + /* mask and clear all interrupts */ + regmap_write(data->regs, USERINTERRUPTENABLE(i), 0x0); + regmap_write(data->regs, INTERRUPTENABLE(i), 0x0); + regmap_write(data->regs, USERINTERRUPTCLEAR(i), 0xffffffff); + regmap_write(data->regs, INTERRUPTCLEAR(i), 0xffffffff); + + /* set all interrupts to user mode */ + regmap_write(data->regs, USERINTERRUPTMASK(i), 0xffffffff); + } + + data->domain = irq_domain_add_linear(dev->of_node, IRQ_COUNT, + &irq_generic_chip_ops, data); + if (!data->domain) { + dev_err(dev, "failed to create IRQ domain\n"); + pm_runtime_put(dev); + return -ENOMEM; + } + irq_domain_set_pm_device(data->domain, dev); + + ret = irq_alloc_domain_generic_chips(data->domain, 32, 1, "DC", + handle_level_irq, 0, 0, 0); + if (ret) { + dev_err(dev, "failed to alloc generic IRQ chips: %d\n", ret); + irq_domain_remove(data->domain); + pm_runtime_put(dev); + return ret; + } + + for (i = 0; i < IRQ_COUNT; i += 32) { + gc = irq_get_domain_generic_chip(data->domain, i); + gc->reg_base = base; + gc->unused = unused_irq[i / 32]; + ct = gc->chip_types; + ct->chip.irq_ack = irq_gc_ack_set_bit; + ct->chip.irq_mask = irq_gc_mask_clr_bit; + ct->chip.irq_unmask = irq_gc_mask_set_bit; + ct->regs.ack = USERINTERRUPTCLEAR(i / 32); + ct->regs.mask = USERINTERRUPTENABLE(i / 32); + } + + for (i = 0; i < IRQ_COUNT; i++) { + /* skip the reserved IRQ */ + if (i == IRQ_RESERVED) + continue; + + data->irq[i] = irq_of_parse_and_map(dev->of_node, i); + + entry[i].data = data; + entry[i].irq = i; + + irq_set_chained_handler_and_data(data->irq[i], + dc_ic_irq_handler, &entry[i]); + } + + return 0; +} + +static void dc_ic_remove(struct platform_device *pdev) +{ + struct dc_ic_data *data = dev_get_drvdata(&pdev->dev); + int i; + + for (i = 0; i < IRQ_COUNT; i++) { + if (i == IRQ_RESERVED) + continue; + + irq_set_chained_handler_and_data(data->irq[i], NULL, NULL); + } + + irq_domain_remove(data->domain); + + pm_runtime_put_sync(&pdev->dev); +} + +static int dc_ic_runtime_suspend(struct device *dev) +{ + struct dc_ic_data *data = dev_get_drvdata(dev); + + clk_disable_unprepare(data->clk_axi); + + return 0; +} + +static int dc_ic_runtime_resume(struct device *dev) +{ + struct dc_ic_data *data = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(data->clk_axi); + if (ret) + dev_err(dev, "failed to enable AXI clock: %d\n", ret); + + return ret; +} + +static const struct dev_pm_ops dc_ic_pm_ops = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + RUNTIME_PM_OPS(dc_ic_runtime_suspend, dc_ic_runtime_resume, NULL) +}; + +static const struct of_device_id dc_ic_dt_ids[] = { + { .compatible = "fsl,imx8qxp-dc-intc", }, + { /* sentinel */ } +}; + +struct platform_driver dc_ic_driver = { + .probe = dc_ic_probe, + .remove = dc_ic_remove, + .driver = { + .name = "imx8-dc-intc", + .suppress_bind_attrs = true, + .of_match_table = dc_ic_dt_ids, + .pm = pm_sleep_ptr(&dc_ic_pm_ops), + }, +}; -- GitLab From 711a3b8783666ffd24ca99ae1c0fde76315b27a9 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 14 Apr 2025 11:50:21 +0800 Subject: [PATCH 0058/1479] drm/imx: Add i.MX8qxp Display Controller KMS i.MX8qxp Display Controller(DC) is comprised of three main components that include a blit engine for 2D graphics accelerations, display controller for display output processing, as well as a command sequencer. Add kernel mode setting support for the display controller part with two CRTCs and two primary planes(backed by FetchLayer and FetchWarp respectively). The registers of the display controller are accessed without command sequencer involved, instead just by using CPU. The command sequencer is supposed to be used by the blit engine. Reviewed-by: Maxime Ripard Reviewed-by: Dmitry Baryshkov Signed-off-by: Liu Ying Link: https://lore.kernel.org/r/20250414035028.1561475-13-victor.liu@nxp.com --- drivers/gpu/drm/imx/dc/Kconfig | 5 + drivers/gpu/drm/imx/dc/Makefile | 5 +- drivers/gpu/drm/imx/dc/dc-crtc.c | 555 ++++++++++++++++++++++++++++++ drivers/gpu/drm/imx/dc/dc-de.h | 3 + drivers/gpu/drm/imx/dc/dc-drv.c | 254 ++++++++++++++ drivers/gpu/drm/imx/dc/dc-drv.h | 22 ++ drivers/gpu/drm/imx/dc/dc-kms.c | 143 ++++++++ drivers/gpu/drm/imx/dc/dc-kms.h | 131 +++++++ drivers/gpu/drm/imx/dc/dc-plane.c | 224 ++++++++++++ 9 files changed, 1340 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/imx/dc/dc-crtc.c create mode 100644 drivers/gpu/drm/imx/dc/dc-kms.c create mode 100644 drivers/gpu/drm/imx/dc/dc-kms.h create mode 100644 drivers/gpu/drm/imx/dc/dc-plane.c diff --git a/drivers/gpu/drm/imx/dc/Kconfig b/drivers/gpu/drm/imx/dc/Kconfig index 1fc84c7475de1..415993207f2e3 100644 --- a/drivers/gpu/drm/imx/dc/Kconfig +++ b/drivers/gpu/drm/imx/dc/Kconfig @@ -1,6 +1,11 @@ config DRM_IMX8_DC tristate "Freescale i.MX8 Display Controller Graphics" depends on DRM && COMMON_CLK && OF && (ARCH_MXC || COMPILE_TEST) + select DRM_CLIENT_SELECTION + select DRM_GEM_DMA_HELPER + select DRM_KMS_HELPER + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR select GENERIC_IRQ_CHIP select REGMAP select REGMAP_MMIO diff --git a/drivers/gpu/drm/imx/dc/Makefile b/drivers/gpu/drm/imx/dc/Makefile index 1ce3e8a8db22f..b9d33c074984a 100644 --- a/drivers/gpu/drm/imx/dc/Makefile +++ b/drivers/gpu/drm/imx/dc/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 -imx8-dc-drm-objs := dc-cf.o dc-de.o dc-drv.o dc-ed.o dc-fg.o dc-fl.o dc-fu.o \ - dc-fw.o dc-ic.o dc-lb.o dc-pe.o dc-tc.o +imx8-dc-drm-objs := dc-cf.o dc-crtc.o dc-de.o dc-drv.o dc-ed.o dc-fg.o dc-fl.o \ + dc-fu.o dc-fw.o dc-ic.o dc-kms.o dc-lb.o dc-pe.o \ + dc-plane.o dc-tc.o obj-$(CONFIG_DRM_IMX8_DC) += imx8-dc-drm.o diff --git a/drivers/gpu/drm/imx/dc/dc-crtc.c b/drivers/gpu/drm/imx/dc/dc-crtc.c new file mode 100644 index 0000000000000..31d3a982deaf7 --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-crtc.c @@ -0,0 +1,555 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dc-de.h" +#include "dc-drv.h" +#include "dc-kms.h" +#include "dc-pe.h" + +#define dc_crtc_dbg(crtc, fmt, ...) \ +do { \ + struct drm_crtc *_crtc = (crtc); \ + drm_dbg_kms(_crtc->dev, "[CRTC:%d:%s] " fmt, \ + _crtc->base.id, _crtc->name, ##__VA_ARGS__); \ +} while (0) + +#define dc_crtc_err(crtc, fmt, ...) \ +do { \ + struct drm_crtc *_crtc = (crtc); \ + drm_err(_crtc->dev, "[CRTC:%d:%s] " fmt, \ + _crtc->base.id, _crtc->name, ##__VA_ARGS__); \ +} while (0) + +#define DC_CRTC_WAIT_FOR_COMPLETION_TIMEOUT(c) \ +do { \ + unsigned long ret; \ + ret = wait_for_completion_timeout(&dc_crtc->c, HZ); \ + if (ret == 0) \ + dc_crtc_err(crtc, "%s: wait for " #c " timeout\n", \ + __func__); \ +} while (0) + +#define DC_CRTC_CHECK_FRAMEGEN_FIFO(fg) \ +do { \ + struct dc_fg *_fg = (fg); \ + if (dc_fg_secondary_requests_to_read_empty_fifo(_fg)) { \ + dc_fg_secondary_clear_channel_status(_fg); \ + dc_crtc_err(crtc, "%s: FrameGen FIFO empty\n", \ + __func__); \ + } \ +} while (0) + +#define DC_CRTC_WAIT_FOR_FRAMEGEN_SECONDARY_SYNCUP(fg) \ +do { \ + if (dc_fg_wait_for_secondary_syncup(fg)) \ + dc_crtc_err(crtc, \ + "%s: FrameGen secondary channel isn't syncup\n",\ + __func__); \ +} while (0) + +static inline struct dc_crtc *to_dc_crtc(struct drm_crtc *crtc) +{ + return container_of(crtc, struct dc_crtc, base); +} + +static u32 dc_crtc_get_vblank_counter(struct drm_crtc *crtc) +{ + struct dc_crtc *dc_crtc = to_dc_crtc(crtc); + + return dc_fg_get_frame_index(dc_crtc->fg); +} + +static int dc_crtc_enable_vblank(struct drm_crtc *crtc) +{ + struct dc_crtc *dc_crtc = to_dc_crtc(crtc); + + enable_irq(dc_crtc->irq_dec_framecomplete); + + return 0; +} + +static void dc_crtc_disable_vblank(struct drm_crtc *crtc) +{ + struct dc_crtc *dc_crtc = to_dc_crtc(crtc); + + /* nosync due to atomic context */ + disable_irq_nosync(dc_crtc->irq_dec_framecomplete); +} + +static const struct drm_crtc_funcs dc_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .get_vblank_counter = dc_crtc_get_vblank_counter, + .enable_vblank = dc_crtc_enable_vblank, + .disable_vblank = dc_crtc_disable_vblank, + .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, +}; + +static void dc_crtc_queue_state_event(struct drm_crtc_state *crtc_state) +{ + struct drm_crtc *crtc = crtc_state->crtc; + struct dc_crtc *dc_crtc = to_dc_crtc(crtc); + + spin_lock_irq(&crtc->dev->event_lock); + if (crtc_state->event) { + WARN_ON(drm_crtc_vblank_get(crtc)); + WARN_ON(dc_crtc->event); + dc_crtc->event = crtc_state->event; + crtc_state->event = NULL; + } + spin_unlock_irq(&crtc->dev->event_lock); +} + +static inline enum drm_mode_status +dc_crtc_check_clock(struct dc_crtc *dc_crtc, int clk_khz) +{ + return dc_fg_check_clock(dc_crtc->fg, clk_khz); +} + +static enum drm_mode_status +dc_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode) +{ + struct dc_crtc *dc_crtc = to_dc_crtc(crtc); + enum drm_mode_status status; + + status = dc_crtc_check_clock(dc_crtc, mode->clock); + if (status != MODE_OK) + return status; + + if (mode->crtc_clock > DC_FRAMEGEN_MAX_CLOCK_KHZ) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static int +dc_crtc_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) +{ + struct drm_crtc_state *new_crtc_state = + drm_atomic_get_new_crtc_state(state, crtc); + struct drm_display_mode *adj = &new_crtc_state->adjusted_mode; + struct dc_crtc *dc_crtc = to_dc_crtc(crtc); + enum drm_mode_status status; + + status = dc_crtc_check_clock(dc_crtc, adj->clock); + if (status != MODE_OK) + return -EINVAL; + + return 0; +} + +static void +dc_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state) +{ + struct drm_crtc_state *new_crtc_state = + drm_atomic_get_new_crtc_state(state, crtc); + struct dc_drm_device *dc_drm = to_dc_drm_device(crtc->dev); + int idx, ret; + + if (!drm_atomic_crtc_needs_modeset(new_crtc_state) || + !new_crtc_state->active) + return; + + if (!drm_dev_enter(crtc->dev, &idx)) + return; + + /* request pixel engine power-on when CRTC starts to be active */ + ret = pm_runtime_resume_and_get(dc_drm->pe->dev); + if (ret) + dc_crtc_err(crtc, "failed to get DC pixel engine RPM: %d\n", + ret); + + drm_dev_exit(idx); +} + +static void +dc_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state) +{ + struct drm_crtc_state *old_crtc_state = + drm_atomic_get_old_crtc_state(state, crtc); + struct drm_crtc_state *new_crtc_state = + drm_atomic_get_new_crtc_state(state, crtc); + struct dc_crtc *dc_crtc = to_dc_crtc(crtc); + int idx; + + if (drm_atomic_crtc_needs_modeset(new_crtc_state) || + (!old_crtc_state->active && !new_crtc_state->active)) + return; + + if (!drm_dev_enter(crtc->dev, &idx)) + goto out; + + enable_irq(dc_crtc->irq_ed_cont_shdload); + + /* flush plane update out to display */ + dc_ed_pec_sync_trigger(dc_crtc->ed_cont); + + DC_CRTC_WAIT_FOR_COMPLETION_TIMEOUT(ed_cont_shdload_done); + + disable_irq(dc_crtc->irq_ed_cont_shdload); + + DC_CRTC_CHECK_FRAMEGEN_FIFO(dc_crtc->fg); + + drm_dev_exit(idx); + +out: + dc_crtc_queue_state_event(new_crtc_state); +} + +static void +dc_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) +{ + struct drm_crtc_state *new_crtc_state = + drm_atomic_get_new_crtc_state(state, crtc); + struct drm_display_mode *adj = &new_crtc_state->adjusted_mode; + struct dc_crtc *dc_crtc = to_dc_crtc(crtc); + enum dc_link_id cf_link; + int idx, ret; + + dc_crtc_dbg(crtc, "mode " DRM_MODE_FMT "\n", DRM_MODE_ARG(adj)); + + drm_crtc_vblank_on(crtc); + + if (!drm_dev_enter(crtc->dev, &idx)) + goto out; + + /* request display engine power-on when CRTC is enabled */ + ret = pm_runtime_resume_and_get(dc_crtc->de->dev); + if (ret < 0) + dc_crtc_err(crtc, "failed to get DC display engine RPM: %d\n", + ret); + + enable_irq(dc_crtc->irq_dec_shdload); + enable_irq(dc_crtc->irq_ed_cont_shdload); + enable_irq(dc_crtc->irq_ed_safe_shdload); + + dc_fg_cfg_videomode(dc_crtc->fg, adj); + + dc_cf_framedimensions(dc_crtc->cf_cont, + adj->crtc_hdisplay, adj->crtc_vdisplay); + dc_cf_framedimensions(dc_crtc->cf_safe, + adj->crtc_hdisplay, adj->crtc_vdisplay); + + /* constframe in safety stream shows blue frame */ + dc_cf_constantcolor_blue(dc_crtc->cf_safe); + cf_link = dc_cf_get_link_id(dc_crtc->cf_safe); + dc_ed_pec_src_sel(dc_crtc->ed_safe, cf_link); + + /* show CRTC background if no plane is enabled */ + if (new_crtc_state->plane_mask == 0) { + /* constframe in content stream shows black frame */ + dc_cf_constantcolor_black(dc_crtc->cf_cont); + + cf_link = dc_cf_get_link_id(dc_crtc->cf_cont); + dc_ed_pec_src_sel(dc_crtc->ed_cont, cf_link); + } + + dc_fg_enable_clock(dc_crtc->fg); + dc_ed_pec_sync_trigger(dc_crtc->ed_cont); + dc_ed_pec_sync_trigger(dc_crtc->ed_safe); + dc_fg_shdtokgen(dc_crtc->fg); + dc_fg_enable(dc_crtc->fg); + + DC_CRTC_WAIT_FOR_COMPLETION_TIMEOUT(ed_safe_shdload_done); + DC_CRTC_WAIT_FOR_COMPLETION_TIMEOUT(ed_cont_shdload_done); + DC_CRTC_WAIT_FOR_COMPLETION_TIMEOUT(dec_shdload_done); + + disable_irq(dc_crtc->irq_ed_safe_shdload); + disable_irq(dc_crtc->irq_ed_cont_shdload); + disable_irq(dc_crtc->irq_dec_shdload); + + DC_CRTC_WAIT_FOR_FRAMEGEN_SECONDARY_SYNCUP(dc_crtc->fg); + + DC_CRTC_CHECK_FRAMEGEN_FIFO(dc_crtc->fg); + + drm_dev_exit(idx); + +out: + dc_crtc_queue_state_event(new_crtc_state); +} + +static void +dc_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state) +{ + struct drm_crtc_state *new_crtc_state = + drm_atomic_get_new_crtc_state(state, crtc); + struct dc_drm_device *dc_drm = to_dc_drm_device(crtc->dev); + struct dc_crtc *dc_crtc = to_dc_crtc(crtc); + int idx, ret; + + if (!drm_dev_enter(crtc->dev, &idx)) + goto out; + + enable_irq(dc_crtc->irq_dec_seqcomplete); + dc_fg_disable(dc_crtc->fg); + DC_CRTC_WAIT_FOR_COMPLETION_TIMEOUT(dec_seqcomplete_done); + disable_irq(dc_crtc->irq_dec_seqcomplete); + + dc_fg_disable_clock(dc_crtc->fg); + + /* request pixel engine power-off as plane is off too */ + ret = pm_runtime_put(dc_drm->pe->dev); + if (ret) + dc_crtc_err(crtc, "failed to put DC pixel engine RPM: %d\n", + ret); + + /* request display engine power-off when CRTC is disabled */ + ret = pm_runtime_put(dc_crtc->de->dev); + if (ret < 0) + dc_crtc_err(crtc, "failed to put DC display engine RPM: %d\n", + ret); + + drm_dev_exit(idx); + +out: + drm_crtc_vblank_off(crtc); + + spin_lock_irq(&crtc->dev->event_lock); + if (new_crtc_state->event && !new_crtc_state->active) { + drm_crtc_send_vblank_event(crtc, new_crtc_state->event); + new_crtc_state->event = NULL; + } + spin_unlock_irq(&crtc->dev->event_lock); +} + +static bool dc_crtc_get_scanout_position(struct drm_crtc *crtc, + bool in_vblank_irq, + int *vpos, int *hpos, + ktime_t *stime, ktime_t *etime, + const struct drm_display_mode *mode) +{ + struct dc_crtc *dc_crtc = to_dc_crtc(crtc); + int vdisplay = mode->crtc_vdisplay; + int vtotal = mode->crtc_vtotal; + bool reliable; + int line; + int idx; + + if (stime) + *stime = ktime_get(); + + if (!drm_dev_enter(crtc->dev, &idx)) { + reliable = false; + *vpos = 0; + *hpos = 0; + goto out; + } + + /* line index starts with 0 for the first active output line */ + line = dc_fg_get_line_index(dc_crtc->fg); + + if (line < vdisplay) + /* active scanout area - positive */ + *vpos = line + 1; + else + /* inside vblank - negative */ + *vpos = line - (vtotal - 1); + + *hpos = 0; + + reliable = true; + + drm_dev_exit(idx); +out: + if (etime) + *etime = ktime_get(); + + return reliable; +} + +static const struct drm_crtc_helper_funcs dc_helper_funcs = { + .mode_valid = dc_crtc_mode_valid, + .atomic_check = dc_crtc_atomic_check, + .atomic_begin = dc_crtc_atomic_begin, + .atomic_flush = dc_crtc_atomic_flush, + .atomic_enable = dc_crtc_atomic_enable, + .atomic_disable = dc_crtc_atomic_disable, + .get_scanout_position = dc_crtc_get_scanout_position, +}; + +static irqreturn_t dc_crtc_irq_handler_dec_framecomplete(int irq, void *dev_id) +{ + struct dc_crtc *dc_crtc = dev_id; + struct drm_crtc *crtc = &dc_crtc->base; + unsigned long flags; + + drm_crtc_handle_vblank(crtc); + + spin_lock_irqsave(&crtc->dev->event_lock, flags); + if (dc_crtc->event) { + drm_crtc_send_vblank_event(crtc, dc_crtc->event); + dc_crtc->event = NULL; + drm_crtc_vblank_put(crtc); + } + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + + return IRQ_HANDLED; +} + +static irqreturn_t +dc_crtc_irq_handler_dec_seqcomplete_done(int irq, void *dev_id) +{ + struct dc_crtc *dc_crtc = dev_id; + + complete(&dc_crtc->dec_seqcomplete_done); + + return IRQ_HANDLED; +} + +static irqreturn_t dc_crtc_irq_handler_dec_shdload_done(int irq, void *dev_id) +{ + struct dc_crtc *dc_crtc = dev_id; + + complete(&dc_crtc->dec_shdload_done); + + return IRQ_HANDLED; +} + +static irqreturn_t +dc_crtc_irq_handler_ed_cont_shdload_done(int irq, void *dev_id) +{ + struct dc_crtc *dc_crtc = dev_id; + + complete(&dc_crtc->ed_cont_shdload_done); + + return IRQ_HANDLED; +} + +static irqreturn_t +dc_crtc_irq_handler_ed_safe_shdload_done(int irq, void *dev_id) +{ + struct dc_crtc *dc_crtc = dev_id; + + complete(&dc_crtc->ed_safe_shdload_done); + + return IRQ_HANDLED; +} + +static int dc_crtc_request_irqs(struct drm_device *drm, struct dc_crtc *dc_crtc) +{ + struct { + struct device *dev; + unsigned int irq; + irqreturn_t (*irq_handler)(int irq, void *dev_id); + } irqs[DC_CRTC_IRQS] = { + { + dc_crtc->de->dev, + dc_crtc->irq_dec_framecomplete, + dc_crtc_irq_handler_dec_framecomplete, + }, { + dc_crtc->de->dev, + dc_crtc->irq_dec_seqcomplete, + dc_crtc_irq_handler_dec_seqcomplete_done, + }, { + dc_crtc->de->dev, + dc_crtc->irq_dec_shdload, + dc_crtc_irq_handler_dec_shdload_done, + }, { + dc_crtc->ed_cont->dev, + dc_crtc->irq_ed_cont_shdload, + dc_crtc_irq_handler_ed_cont_shdload_done, + }, { + dc_crtc->ed_safe->dev, + dc_crtc->irq_ed_safe_shdload, + dc_crtc_irq_handler_ed_safe_shdload_done, + }, + }; + int i, ret; + + for (i = 0; i < DC_CRTC_IRQS; i++) { + struct dc_crtc_irq *irq = &dc_crtc->irqs[i]; + + ret = devm_request_irq(irqs[i].dev, irqs[i].irq, + irqs[i].irq_handler, IRQF_NO_AUTOEN, + dev_name(irqs[i].dev), dc_crtc); + if (ret) { + dev_err(irqs[i].dev, "failed to request irq(%u): %d\n", + irqs[i].irq, ret); + return ret; + } + + irq->dc_crtc = dc_crtc; + irq->irq = irqs[i].irq; + } + + return 0; +} + +int dc_crtc_init(struct dc_drm_device *dc_drm, int crtc_index) +{ + struct dc_crtc *dc_crtc = &dc_drm->dc_crtc[crtc_index]; + struct drm_device *drm = &dc_drm->base; + struct dc_de *de = dc_drm->de[crtc_index]; + struct dc_pe *pe = dc_drm->pe; + struct dc_plane *dc_primary; + int ret; + + dc_crtc->de = de; + + init_completion(&dc_crtc->dec_seqcomplete_done); + init_completion(&dc_crtc->dec_shdload_done); + init_completion(&dc_crtc->ed_cont_shdload_done); + init_completion(&dc_crtc->ed_safe_shdload_done); + + dc_crtc->cf_cont = pe->cf_cont[crtc_index]; + dc_crtc->cf_safe = pe->cf_safe[crtc_index]; + dc_crtc->ed_cont = pe->ed_cont[crtc_index]; + dc_crtc->ed_safe = pe->ed_safe[crtc_index]; + dc_crtc->fg = de->fg; + + dc_crtc->irq_dec_framecomplete = de->irq_framecomplete; + dc_crtc->irq_dec_seqcomplete = de->irq_seqcomplete; + dc_crtc->irq_dec_shdload = de->irq_shdload; + dc_crtc->irq_ed_safe_shdload = dc_crtc->ed_safe->irq_shdload; + dc_crtc->irq_ed_cont_shdload = dc_crtc->ed_cont->irq_shdload; + + dc_primary = &dc_drm->dc_primary[crtc_index]; + ret = dc_plane_init(dc_drm, dc_primary); + if (ret) { + dev_err(de->dev, "failed to initialize primary plane: %d\n", + ret); + return ret; + } + + drm_crtc_helper_add(&dc_crtc->base, &dc_helper_funcs); + + ret = drm_crtc_init_with_planes(drm, &dc_crtc->base, &dc_primary->base, + NULL, &dc_crtc_funcs, NULL); + if (ret) + dev_err(de->dev, "failed to add CRTC: %d\n", ret); + + return ret; +} + +int dc_crtc_post_init(struct dc_drm_device *dc_drm, int crtc_index) +{ + struct dc_crtc *dc_crtc = &dc_drm->dc_crtc[crtc_index]; + struct drm_device *drm = &dc_drm->base; + + return dc_crtc_request_irqs(drm, dc_crtc); +} diff --git a/drivers/gpu/drm/imx/dc/dc-de.h b/drivers/gpu/drm/imx/dc/dc-de.h index 5dd311cde0768..211f3fcc1a9ad 100644 --- a/drivers/gpu/drm/imx/dc/dc-de.h +++ b/drivers/gpu/drm/imx/dc/dc-de.h @@ -13,6 +13,9 @@ #define DC_DISPLAYS 2 +#define DC_FRAMEGEN_MAX_FRAME_INDEX 0x3ffff +#define DC_FRAMEGEN_MAX_CLOCK_KHZ 300000 + struct dc_fg { struct device *dev; struct regmap *reg; diff --git a/drivers/gpu/drm/imx/dc/dc-drv.c b/drivers/gpu/drm/imx/dc/dc-drv.c index fd68861f770a5..04f021d2d6cfc 100644 --- a/drivers/gpu/drm/imx/dc/dc-drv.c +++ b/drivers/gpu/drm/imx/dc/dc-drv.c @@ -3,10 +3,263 @@ * Copyright 2024 NXP */ +#include +#include +#include +#include +#include #include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dc-de.h" #include "dc-drv.h" +#include "dc-pe.h" + +struct dc_priv { + struct drm_device *drm; + struct clk *clk_cfg; +}; + +DEFINE_DRM_GEM_DMA_FOPS(dc_drm_driver_fops); + +static struct drm_driver dc_drm_driver = { + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, + DRM_GEM_DMA_DRIVER_OPS, + DRM_FBDEV_DMA_DRIVER_OPS, + .fops = &dc_drm_driver_fops, + .name = "imx8-dc", + .desc = "i.MX8 DC DRM graphics", + .major = 1, + .minor = 0, + .patchlevel = 0, +}; + +static void +dc_add_components(struct device *dev, struct component_match **matchptr) +{ + struct device_node *child, *grandchild; + + for_each_available_child_of_node(dev->of_node, child) { + /* The interrupt controller is not a component. */ + if (of_device_is_compatible(child, "fsl,imx8qxp-dc-intc")) + continue; + + drm_of_component_match_add(dev, matchptr, component_compare_of, + child); + + for_each_available_child_of_node(child, grandchild) + drm_of_component_match_add(dev, matchptr, + component_compare_of, + grandchild); + } +} + +static int dc_drm_component_bind_all(struct dc_drm_device *dc_drm) +{ + struct drm_device *drm = &dc_drm->base; + int ret; + + ret = component_bind_all(drm->dev, dc_drm); + if (ret) + return ret; + + dc_de_post_bind(dc_drm); + dc_pe_post_bind(dc_drm); + + return 0; +} + +static void dc_drm_component_unbind_all(void *ptr) +{ + struct dc_drm_device *dc_drm = ptr; + struct drm_device *drm = &dc_drm->base; + + component_unbind_all(drm->dev, dc_drm); +} + +static int dc_drm_bind(struct device *dev) +{ + struct dc_priv *priv = dev_get_drvdata(dev); + struct dc_drm_device *dc_drm; + struct drm_device *drm; + int ret; + + dc_drm = devm_drm_dev_alloc(dev, &dc_drm_driver, struct dc_drm_device, + base); + if (IS_ERR(dc_drm)) + return PTR_ERR(dc_drm); + + drm = &dc_drm->base; + + ret = dc_drm_component_bind_all(dc_drm); + if (ret) + return ret; + + ret = devm_add_action_or_reset(dev, dc_drm_component_unbind_all, + dc_drm); + if (ret) + return ret; + + ret = dc_kms_init(dc_drm); + if (ret) + return ret; + + ret = drm_dev_register(drm, 0); + if (ret) { + dev_err(dev, "failed to register drm device: %d\n", ret); + goto err; + } + + drm_client_setup_with_fourcc(drm, DRM_FORMAT_XRGB8888); + + priv->drm = drm; + + return 0; + +err: + dc_kms_uninit(dc_drm); + + return ret; +} + +static void dc_drm_unbind(struct device *dev) +{ + struct dc_priv *priv = dev_get_drvdata(dev); + struct dc_drm_device *dc_drm = to_dc_drm_device(priv->drm); + struct drm_device *drm = &dc_drm->base; + + priv->drm = NULL; + drm_dev_unplug(drm); + dc_kms_uninit(dc_drm); + drm_atomic_helper_shutdown(drm); +} + +static const struct component_master_ops dc_drm_ops = { + .bind = dc_drm_bind, + .unbind = dc_drm_unbind, +}; + +static int dc_probe(struct platform_device *pdev) +{ + struct component_match *match = NULL; + struct dc_priv *priv; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->clk_cfg = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(priv->clk_cfg)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->clk_cfg), + "failed to get cfg clock\n"); + + dev_set_drvdata(&pdev->dev, priv); + + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + + ret = devm_of_platform_populate(&pdev->dev); + if (ret) + return ret; + + dc_add_components(&pdev->dev, &match); + + ret = component_master_add_with_match(&pdev->dev, &dc_drm_ops, match); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to add component master\n"); + + return 0; +} + +static void dc_remove(struct platform_device *pdev) +{ + component_master_del(&pdev->dev, &dc_drm_ops); +} + +static int dc_runtime_suspend(struct device *dev) +{ + struct dc_priv *priv = dev_get_drvdata(dev); + + clk_disable_unprepare(priv->clk_cfg); + + return 0; +} + +static int dc_runtime_resume(struct device *dev) +{ + struct dc_priv *priv = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(priv->clk_cfg); + if (ret) + dev_err(dev, "failed to enable cfg clock: %d\n", ret); + + return ret; +} + +static int dc_suspend(struct device *dev) +{ + struct dc_priv *priv = dev_get_drvdata(dev); + + return drm_mode_config_helper_suspend(priv->drm); +} + +static int dc_resume(struct device *dev) +{ + struct dc_priv *priv = dev_get_drvdata(dev); + + return drm_mode_config_helper_resume(priv->drm); +} + +static void dc_shutdown(struct platform_device *pdev) +{ + struct dc_priv *priv = dev_get_drvdata(&pdev->dev); + + drm_atomic_helper_shutdown(priv->drm); +} + +static const struct dev_pm_ops dc_pm_ops = { + RUNTIME_PM_OPS(dc_runtime_suspend, dc_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(dc_suspend, dc_resume) +}; + +static const struct of_device_id dc_dt_ids[] = { + { .compatible = "fsl,imx8qxp-dc", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dc_dt_ids); + +static struct platform_driver dc_driver = { + .probe = dc_probe, + .remove = dc_remove, + .shutdown = dc_shutdown, + .driver = { + .name = "imx8-dc", + .of_match_table = dc_dt_ids, + .pm = pm_sleep_ptr(&dc_pm_ops), + }, +}; static struct platform_driver * const dc_drivers[] = { &dc_cf_driver, @@ -19,6 +272,7 @@ static struct platform_driver * const dc_drivers[] = { &dc_lb_driver, &dc_pe_driver, &dc_tc_driver, + &dc_driver, }; static int __init dc_drm_init(void) diff --git a/drivers/gpu/drm/imx/dc/dc-drv.h b/drivers/gpu/drm/imx/dc/dc-drv.h index e4c2d564ab5d8..eb61b8c762693 100644 --- a/drivers/gpu/drm/imx/dc/dc-drv.h +++ b/drivers/gpu/drm/imx/dc/dc-drv.h @@ -6,13 +6,16 @@ #ifndef __DC_DRV_H__ #define __DC_DRV_H__ +#include #include #include #include #include +#include #include "dc-de.h" +#include "dc-kms.h" #include "dc-pe.h" /** @@ -21,6 +24,12 @@ struct dc_drm_device { /** @base: base drm_device structure */ struct drm_device base; + /** @dc_crtc: DC specific CRTC list */ + struct dc_crtc dc_crtc[DC_DISPLAYS]; + /** @dc_primary: DC specific primary plane list */ + struct dc_plane dc_primary[DC_DISPLAYS]; + /** @encoder: encoder list */ + struct drm_encoder encoder[DC_DISPLAYS]; /** @cf_safe: constframe list(safety stream) */ struct dc_cf *cf_safe[DC_DISPLAYS]; /** @cf_cont: constframe list(content stream) */ @@ -48,6 +57,19 @@ struct dc_subdev_info { int id; }; +static inline struct dc_drm_device *to_dc_drm_device(struct drm_device *drm) +{ + return container_of(drm, struct dc_drm_device, base); +} + +int dc_crtc_init(struct dc_drm_device *dc_drm, int crtc_index); +int dc_crtc_post_init(struct dc_drm_device *dc_drm, int crtc_index); + +int dc_kms_init(struct dc_drm_device *dc_drm); +void dc_kms_uninit(struct dc_drm_device *dc_drm); + +int dc_plane_init(struct dc_drm_device *dc_drm, struct dc_plane *dc_plane); + extern struct platform_driver dc_cf_driver; extern struct platform_driver dc_de_driver; extern struct platform_driver dc_ed_driver; diff --git a/drivers/gpu/drm/imx/dc/dc-kms.c b/drivers/gpu/drm/imx/dc/dc-kms.c new file mode 100644 index 0000000000000..2b18aa37a4a8b --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-kms.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dc-de.h" +#include "dc-drv.h" +#include "dc-kms.h" + +static const struct drm_mode_config_funcs dc_drm_mode_config_funcs = { + .fb_create = drm_gem_fb_create, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static int dc_kms_init_encoder_per_crtc(struct dc_drm_device *dc_drm, + int crtc_index) +{ + struct dc_crtc *dc_crtc = &dc_drm->dc_crtc[crtc_index]; + struct drm_device *drm = &dc_drm->base; + struct drm_crtc *crtc = &dc_crtc->base; + struct drm_connector *connector; + struct device *dev = drm->dev; + struct drm_encoder *encoder; + struct drm_bridge *bridge; + int ret; + + bridge = devm_drm_of_get_bridge(dev, dc_crtc->de->tc->dev->of_node, + 0, 0); + if (IS_ERR(bridge)) { + ret = PTR_ERR(bridge); + if (ret == -ENODEV) + return 0; + + return dev_err_probe(dev, ret, + "failed to find bridge for CRTC%u\n", + crtc->index); + } + + encoder = &dc_drm->encoder[crtc_index]; + ret = drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_NONE); + if (ret) { + dev_err(dev, "failed to initialize encoder for CRTC%u: %d\n", + crtc->index, ret); + return ret; + } + + encoder->possible_crtcs = drm_crtc_mask(crtc); + + ret = drm_bridge_attach(encoder, bridge, NULL, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); + if (ret) { + dev_err(dev, + "failed to attach bridge to encoder for CRTC%u: %d\n", + crtc->index, ret); + return ret; + } + + connector = drm_bridge_connector_init(drm, encoder); + if (IS_ERR(connector)) { + ret = PTR_ERR(connector); + dev_err(dev, "failed to init bridge connector for CRTC%u: %d\n", + crtc->index, ret); + return ret; + } + + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) + dev_err(dev, + "failed to attach encoder to connector for CRTC%u: %d\n", + crtc->index, ret); + + return ret; +} + +int dc_kms_init(struct dc_drm_device *dc_drm) +{ + struct drm_device *drm = &dc_drm->base; + int ret, i; + + ret = drmm_mode_config_init(drm); + if (ret) + return ret; + + drm->mode_config.min_width = 60; + drm->mode_config.min_height = 60; + drm->mode_config.max_width = 8192; + drm->mode_config.max_height = 8192; + drm->mode_config.funcs = &dc_drm_mode_config_funcs; + + drm->vblank_disable_immediate = true; + drm->max_vblank_count = DC_FRAMEGEN_MAX_FRAME_INDEX; + + for (i = 0; i < DC_DISPLAYS; i++) { + ret = dc_crtc_init(dc_drm, i); + if (ret) + return ret; + + ret = dc_kms_init_encoder_per_crtc(dc_drm, i); + if (ret) + return ret; + } + + for (i = 0; i < DC_DISPLAYS; i++) { + ret = dc_crtc_post_init(dc_drm, i); + if (ret) + return ret; + } + + ret = drm_vblank_init(drm, DC_DISPLAYS); + if (ret) { + dev_err(drm->dev, "failed to init vblank support: %d\n", ret); + return ret; + } + + drm_mode_config_reset(drm); + + drm_kms_helper_poll_init(drm); + + return 0; +} + +void dc_kms_uninit(struct dc_drm_device *dc_drm) +{ + drm_kms_helper_poll_fini(&dc_drm->base); +} diff --git a/drivers/gpu/drm/imx/dc/dc-kms.h b/drivers/gpu/drm/imx/dc/dc-kms.h new file mode 100644 index 0000000000000..cd7860eff986a --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-kms.h @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2024 NXP + */ + +#ifndef __DC_KMS_H__ +#define __DC_KMS_H__ + +#include + +#include +#include +#include + +#include "dc-de.h" +#include "dc-fu.h" +#include "dc-pe.h" + +#define DC_CRTC_IRQS 5 + +struct dc_crtc_irq { + struct dc_crtc *dc_crtc; + unsigned int irq; +}; + +/** + * struct dc_crtc - DC specific drm_crtc + * + * Each display controller contains one content stream and one safety stream. + * In general, the two streams have the same functionality. One stream is + * overlaid on the other by @fg. This driver chooses to generate black constant + * color from the content stream as background color, build plane(s) on the + * content stream by using layerblend(s) and always generate a constant color + * from the safety stream. Note that due to the decoupled timing, the safety + * stream still works to show the constant color properly even when the content + * stream has completely hung up due to mal-function of this driver. + */ +struct dc_crtc { + /** @base: base drm_crtc structure */ + struct drm_crtc base; + /** @de: display engine */ + struct dc_de *de; + /** @cf_cont: content stream constframe */ + struct dc_cf *cf_cont; + /** @cf_safe: safety stream constframe */ + struct dc_cf *cf_safe; + /** @ed_cont: content stream extdst */ + struct dc_ed *ed_cont; + /** @ed_safe: safety stream extdst */ + struct dc_ed *ed_safe; + /** @fg: framegen */ + struct dc_fg *fg; + /** + * @irq_dec_framecomplete: + * + * display engine configuration frame complete interrupt + */ + unsigned int irq_dec_framecomplete; + /** + * @irq_dec_seqcomplete: + * + * display engine configuration sequence complete interrupt + */ + unsigned int irq_dec_seqcomplete; + /** + * @irq_dec_shdload: + * + * display engine configuration shadow load interrupt + */ + unsigned int irq_dec_shdload; + /** + * @irq_ed_cont_shdload: + * + * content stream extdst shadow load interrupt + */ + unsigned int irq_ed_cont_shdload; + /** + * @irq_ed_safe_shdload: + * + * safety stream extdst shadow load interrupt + */ + unsigned int irq_ed_safe_shdload; + /** + * @dec_seqcomplete_done: + * + * display engine configuration sequence completion + */ + struct completion dec_seqcomplete_done; + /** + * @dec_shdload_done: + * + * display engine configuration shadow load completion + */ + struct completion dec_shdload_done; + /** + * @ed_cont_shdload_done: + * + * content stream extdst shadow load completion + */ + struct completion ed_cont_shdload_done; + /** + * @ed_safe_shdload_done: + * + * safety stream extdst shadow load completion + */ + struct completion ed_safe_shdload_done; + /** @event: cached pending vblank event */ + struct drm_pending_vblank_event *event; + /** @irqs: interrupt list */ + struct dc_crtc_irq irqs[DC_CRTC_IRQS]; +}; + +/** + * struct dc_plane - DC specific drm_plane + * + * Build a plane on content stream with a fetchunit and a layerblend. + */ +struct dc_plane { + /** @base: base drm_plane structure */ + struct drm_plane base; + /** @fu: fetchunit */ + struct dc_fu *fu; + /** @cf: content stream constframe */ + struct dc_cf *cf; + /** @lb: layerblend */ + struct dc_lb *lb; + /** @ed: content stream extdst */ + struct dc_ed *ed; +}; + +#endif /* __DC_KMS_H__ */ diff --git a/drivers/gpu/drm/imx/dc/dc-plane.c b/drivers/gpu/drm/imx/dc/dc-plane.c new file mode 100644 index 0000000000000..d8b946fb90de6 --- /dev/null +++ b/drivers/gpu/drm/imx/dc/dc-plane.c @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dc-drv.h" +#include "dc-fu.h" +#include "dc-kms.h" + +#define DC_PLANE_MAX_PITCH 0x10000 +#define DC_PLANE_MAX_PIX_CNT 8192 + +#define dc_plane_dbg(plane, fmt, ...) \ +do { \ + struct drm_plane *_plane = (plane); \ + drm_dbg_kms(_plane->dev, "[PLANE:%d:%s] " fmt, \ + _plane->base.id, _plane->name, ##__VA_ARGS__); \ +} while (0) + +static const uint32_t dc_plane_formats[] = { + DRM_FORMAT_XRGB8888, +}; + +static const struct drm_plane_funcs dc_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static inline struct dc_plane *to_dc_plane(struct drm_plane *plane) +{ + return container_of(plane, struct dc_plane, base); +} + +static int dc_plane_check_max_source_resolution(struct drm_plane_state *state) +{ + int src_h = drm_rect_height(&state->src) >> 16; + int src_w = drm_rect_width(&state->src) >> 16; + + if (src_w > DC_PLANE_MAX_PIX_CNT || src_h > DC_PLANE_MAX_PIX_CNT) { + dc_plane_dbg(state->plane, "invalid source resolution\n"); + return -EINVAL; + } + + return 0; +} + +static int dc_plane_check_fb(struct drm_plane_state *state) +{ + struct drm_framebuffer *fb = state->fb; + dma_addr_t baseaddr = drm_fb_dma_get_gem_addr(fb, state, 0); + + /* base address alignment */ + if (baseaddr & 0x3) { + dc_plane_dbg(state->plane, "fb bad baddr alignment\n"); + return -EINVAL; + } + + /* pitches[0] range */ + if (fb->pitches[0] > DC_PLANE_MAX_PITCH) { + dc_plane_dbg(state->plane, "fb pitches[0] is out of range\n"); + return -EINVAL; + } + + /* pitches[0] alignment */ + if (fb->pitches[0] & 0x3) { + dc_plane_dbg(state->plane, "fb bad pitches[0] alignment\n"); + return -EINVAL; + } + + return 0; +} + +static int +dc_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state) +{ + struct drm_plane_state *plane_state = + drm_atomic_get_new_plane_state(state, plane); + struct drm_crtc_state *crtc_state; + int ret; + + /* ok to disable */ + if (!plane_state->fb) + return 0; + + if (!plane_state->crtc) { + dc_plane_dbg(plane, "no CRTC in plane state\n"); + return -EINVAL; + } + + crtc_state = + drm_atomic_get_existing_crtc_state(state, plane_state->crtc); + if (WARN_ON(!crtc_state)) + return -EINVAL; + + ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + true, false); + if (ret) { + dc_plane_dbg(plane, "failed to check plane state: %d\n", ret); + return ret; + } + + ret = dc_plane_check_max_source_resolution(plane_state); + if (ret) + return ret; + + return dc_plane_check_fb(plane_state); +} + +static void +dc_plane_atomic_update(struct drm_plane *plane, struct drm_atomic_state *state) +{ + struct drm_plane_state *new_state = + drm_atomic_get_new_plane_state(state, plane); + struct dc_plane *dplane = to_dc_plane(plane); + struct drm_framebuffer *fb = new_state->fb; + const struct dc_fu_ops *fu_ops; + struct dc_lb *lb = dplane->lb; + struct dc_fu *fu = dplane->fu; + dma_addr_t baseaddr; + int src_w, src_h; + int idx; + + if (!drm_dev_enter(plane->dev, &idx)) + return; + + src_w = drm_rect_width(&new_state->src) >> 16; + src_h = drm_rect_height(&new_state->src) >> 16; + + baseaddr = drm_fb_dma_get_gem_addr(fb, new_state, 0); + + fu_ops = dc_fu_get_ops(dplane->fu); + + fu_ops->set_layerblend(fu, lb); + fu_ops->set_burstlength(fu, baseaddr); + fu_ops->set_src_stride(fu, DC_FETCHUNIT_FRAC0, fb->pitches[0]); + fu_ops->set_src_buf_dimensions(fu, DC_FETCHUNIT_FRAC0, src_w, src_h); + fu_ops->set_fmt(fu, DC_FETCHUNIT_FRAC0, fb->format); + fu_ops->set_framedimensions(fu, src_w, src_h); + fu_ops->set_baseaddress(fu, DC_FETCHUNIT_FRAC0, baseaddr); + fu_ops->enable_src_buf(fu, DC_FETCHUNIT_FRAC0); + + dc_plane_dbg(plane, "uses %s\n", fu_ops->get_name(fu)); + + dc_lb_pec_dynamic_prim_sel(lb, dc_cf_get_link_id(dplane->cf)); + dc_lb_pec_dynamic_sec_sel(lb, fu_ops->get_link_id(fu)); + dc_lb_mode(lb, LB_BLEND); + dc_lb_position(lb, new_state->dst.x1, new_state->dst.y1); + dc_lb_pec_clken(lb, CLKEN_AUTOMATIC); + + dc_plane_dbg(plane, "uses LayerBlend%d\n", dc_lb_get_id(lb)); + + /* set ExtDst's source to LayerBlend */ + dc_ed_pec_src_sel(dplane->ed, dc_lb_get_link_id(lb)); + + drm_dev_exit(idx); +} + +static void dc_plane_atomic_disable(struct drm_plane *plane, + struct drm_atomic_state *state) +{ + struct dc_plane *dplane = to_dc_plane(plane); + const struct dc_fu_ops *fu_ops; + int idx; + + if (!drm_dev_enter(plane->dev, &idx)) + return; + + /* disable fetchunit in shadow */ + fu_ops = dc_fu_get_ops(dplane->fu); + fu_ops->disable_src_buf(dplane->fu, DC_FETCHUNIT_FRAC0); + + /* set ExtDst's source to ConstFrame */ + dc_ed_pec_src_sel(dplane->ed, dc_cf_get_link_id(dplane->cf)); + + drm_dev_exit(idx); +} + +static const struct drm_plane_helper_funcs dc_plane_helper_funcs = { + .atomic_check = dc_plane_atomic_check, + .atomic_update = dc_plane_atomic_update, + .atomic_disable = dc_plane_atomic_disable, +}; + +int dc_plane_init(struct dc_drm_device *dc_drm, struct dc_plane *dc_plane) +{ + struct drm_plane *plane = &dc_plane->base; + int ret; + + ret = drm_universal_plane_init(&dc_drm->base, plane, 0, &dc_plane_funcs, + dc_plane_formats, + ARRAY_SIZE(dc_plane_formats), + NULL, DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + return ret; + + drm_plane_helper_add(plane, &dc_plane_helper_funcs); + + dc_plane->fu = dc_drm->pe->fu_disp[plane->index]; + dc_plane->cf = dc_drm->pe->cf_cont[plane->index]; + dc_plane->lb = dc_drm->pe->lb[plane->index]; + dc_plane->ed = dc_drm->pe->ed_cont[plane->index]; + + return 0; +} -- GitLab From 217f80acfcf126b7d7d7b818c9bfea3c96fa85ec Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 14 Apr 2025 11:50:22 +0800 Subject: [PATCH 0059/1479] MAINTAINERS: Add maintainer for i.MX8qxp Display Controller Add myself as the maintainer of i.MX8qxp Display Controller. Signed-off-by: Liu Ying Reviewed-by: Maxime Ripard Link: https://lore.kernel.org/r/20250414035028.1561475-14-victor.liu@nxp.com --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index ef7f0d002a092..88b17f23ed4f5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7929,6 +7929,14 @@ F: Documentation/devicetree/bindings/display/imx/ F: drivers/gpu/drm/imx/ipuv3/ F: drivers/gpu/ipu-v3/ +DRM DRIVERS FOR FREESCALE IMX8 DISPLAY CONTROLLER +M: Liu Ying +L: dri-devel@lists.freedesktop.org +S: Maintained +T: git https://gitlab.freedesktop.org/drm/misc/kernel.git +F: Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc*.yaml +F: drivers/gpu/drm/imx/dc/ + DRM DRIVERS FOR FREESCALE IMX BRIDGE M: Liu Ying L: dri-devel@lists.freedesktop.org -- GitLab From 2d278488761f0b5be651a3db41e615a964123d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Tue, 13 May 2025 08:48:13 +0300 Subject: [PATCH 0060/1479] drm/i915/alpm: Make intel_alpm_enable_sink available for PSR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to enable sink ALPM from PSR code. Make intel_alpm_enable_sink available for PSR. v2: do not add kerneldoc comments Reviewed-by: Suraj Kandpal Signed-off-by: Jouni Högander Link: https://lore.kernel.org/r/20250513054814.3702977-2-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_alpm.c | 4 ++-- drivers/gpu/drm/i915/display/intel_alpm.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index 1bf08b80c23f9..da70a98a1292e 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -426,8 +426,8 @@ void intel_alpm_pre_plane_update(struct intel_atomic_state *state, } } -static void intel_alpm_enable_sink(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) +void intel_alpm_enable_sink(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) { u8 val; diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h b/drivers/gpu/drm/i915/display/intel_alpm.h index d7126d65b60fb..c9fe21e3e72ce 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.h +++ b/drivers/gpu/drm/i915/display/intel_alpm.h @@ -23,6 +23,8 @@ void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp, struct drm_connector_state *conn_state); void intel_alpm_configure(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); +void intel_alpm_enable_sink(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); void intel_alpm_pre_plane_update(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_alpm_post_plane_update(struct intel_atomic_state *state, -- GitLab From a8eb102ce0944a9de2a62aa9d195861b7f26668a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Tue, 13 May 2025 08:48:14 +0300 Subject: [PATCH 0061/1479] drm/i915/alpm: Stop writing ALPM registers when PSR is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we are seeing these on PTL: xe 0000:00:02.0: [drm] *ERROR* Timeout waiting for DDI BUF A to get active These seem to be caused by writing ALPM registers while Panel Replay is enabled. Fix this by writing ALPM registers only when Panel Replay is about to be enabled. v4: improve comment on intel_psr_panel_replay_enable_sink call v3: enable/disable ALPM from PSR code Fixes: 172757acd6f6 ("drm/i915/lobf: Add lobf enablement in post plane update") Signed-off-by: Jouni Högander Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20250513054814.3702977-3-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_alpm.c | 4 ++-- drivers/gpu/drm/i915/display/intel_psr.c | 13 ++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index da70a98a1292e..c176bdbc19a34 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -453,8 +453,8 @@ void intel_alpm_post_plane_update(struct intel_atomic_state *state, intel_atomic_get_old_crtc_state(state, crtc); struct intel_encoder *encoder; - if ((!crtc_state->has_lobf || - crtc_state->has_lobf == old_crtc_state->has_lobf) && !crtc_state->has_psr) + if (crtc_state->has_psr || !crtc_state->has_lobf || + crtc_state->has_lobf == old_crtc_state->has_lobf) return; for_each_intel_encoder_mask(display->drm, encoder, diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index ccd66bbc72f79..430ad4ef71466 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -800,6 +800,8 @@ static void _psr_enable_sink(struct intel_dp *intel_dp, static void intel_psr_enable_sink(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { + intel_alpm_enable_sink(intel_dp, crtc_state); + crtc_state->has_panel_replay ? _panel_replay_enable_sink(intel_dp, crtc_state) : _psr_enable_sink(intel_dp, crtc_state); @@ -1962,6 +1964,8 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0)) && !intel_dp->psr.panel_replay_enabled) intel_dmc_block_pkgc(display, intel_dp->psr.pipe, true); + + intel_alpm_configure(intel_dp, crtc_state); } static bool psr_interrupt_error_check(struct intel_dp *intel_dp) @@ -2029,8 +2033,9 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp, intel_dp->psr.sel_update_enabled ? "2" : "1"); /* - * Enabling here only for PSR. Panel Replay enable bit is already - * written at this point. See + * Enabling sink PSR/Panel Replay here only for PSR. Panel Replay enable + * bit is already written at this point. Sink ALPM is enabled here for + * PSR and Panel Replay. See * intel_psr_panel_replay_enable_sink. Modifiers/options: * - Selective Update * - Region Early Transport @@ -2172,6 +2177,9 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) if (intel_dp_is_edp(intel_dp)) intel_snps_phy_update_psr_power_state(&dp_to_dig_port(intel_dp)->base, false); + if (intel_dp->psr.panel_replay_enabled && intel_dp_is_edp(intel_dp)) + intel_alpm_disable(intel_dp); + /* Disable PSR on Sink */ if (!intel_dp->psr.panel_replay_enabled) { drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0); @@ -3498,7 +3506,6 @@ static void psr_alpm_check(struct intel_dp *intel_dp) if (intel_alpm_get_error(intel_dp)) { intel_psr_disable_locked(intel_dp); psr->sink_not_reliable = true; - intel_alpm_disable(intel_dp); } } -- GitLab From 59cbff3a8f766adede869a955fb92924bb3707a9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 13 May 2025 12:28:41 +0300 Subject: [PATCH 0062/1479] drm/i915/pps: drop dependency on intel_display_conversion.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the PPS register users have been converted to struct intel_display. The backward compat conversion to struct drm_i915_private is no longer needed. Drop it, along with the include, and convert the dev_priv macro parameter names to display while at it. Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/4c23fd8dfcadefeeb52189045421084bcfd50d57.1747128495.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_pps_regs.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_pps_regs.h b/drivers/gpu/drm/i915/display/intel_pps_regs.h index 8f9dbfab95233..2f014d929d327 100644 --- a/drivers/gpu/drm/i915/display/intel_pps_regs.h +++ b/drivers/gpu/drm/i915/display/intel_pps_regs.h @@ -6,7 +6,6 @@ #ifndef __INTEL_PPS_REGS_H__ #define __INTEL_PPS_REGS_H__ -#include "intel_display_conversion.h" #include "intel_display_reg_defs.h" /* Panel power sequencing */ @@ -14,11 +13,11 @@ #define VLV_PPS_BASE (VLV_DISPLAY_BASE + PPS_BASE) #define PCH_PPS_BASE 0xC7200 -#define _MMIO_PPS(dev_priv, pps_idx, reg) \ - _MMIO(__to_intel_display(dev_priv)->pps.mmio_base - PPS_BASE + (reg) + (pps_idx) * 0x100) +#define _MMIO_PPS(display, pps_idx, reg) \ + _MMIO((display)->pps.mmio_base - PPS_BASE + (reg) + (pps_idx) * 0x100) #define _PP_STATUS 0x61200 -#define PP_STATUS(dev_priv, pps_idx) _MMIO_PPS(dev_priv, pps_idx, _PP_STATUS) +#define PP_STATUS(display, pps_idx) _MMIO_PPS((display), (pps_idx), _PP_STATUS) #define PP_ON REG_BIT(31) /* * Indicates that all dependencies of the panel are on: @@ -45,7 +44,7 @@ #define PP_SEQUENCE_STATE_RESET REG_FIELD_PREP(PP_SEQUENCE_STATE_MASK, 0xf) #define _PP_CONTROL 0x61204 -#define PP_CONTROL(dev_priv, pps_idx) _MMIO_PPS(dev_priv, pps_idx, _PP_CONTROL) +#define PP_CONTROL(display, pps_idx) _MMIO_PPS((display), (pps_idx), _PP_CONTROL) #define PANEL_UNLOCK_MASK REG_GENMASK(31, 16) #define PANEL_UNLOCK_REGS REG_FIELD_PREP(PANEL_UNLOCK_MASK, 0xabcd) #define BXT_POWER_CYCLE_DELAY_MASK REG_GENMASK(8, 4) @@ -55,7 +54,7 @@ #define PANEL_POWER_ON REG_BIT(0) #define _PP_ON_DELAYS 0x61208 -#define PP_ON_DELAYS(dev_priv, pps_idx) _MMIO_PPS(dev_priv, pps_idx, _PP_ON_DELAYS) +#define PP_ON_DELAYS(display, pps_idx) _MMIO_PPS((display), (pps_idx), _PP_ON_DELAYS) #define PANEL_PORT_SELECT_MASK REG_GENMASK(31, 30) #define PANEL_PORT_SELECT_LVDS REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, 0) #define PANEL_PORT_SELECT_DPA REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, 1) @@ -66,12 +65,12 @@ #define PANEL_LIGHT_ON_DELAY_MASK REG_GENMASK(12, 0) #define _PP_OFF_DELAYS 0x6120C -#define PP_OFF_DELAYS(dev_priv, pps_idx) _MMIO_PPS(dev_priv, pps_idx, _PP_OFF_DELAYS) +#define PP_OFF_DELAYS(display, pps_idx) _MMIO_PPS((display), (pps_idx), _PP_OFF_DELAYS) #define PANEL_POWER_DOWN_DELAY_MASK REG_GENMASK(28, 16) #define PANEL_LIGHT_OFF_DELAY_MASK REG_GENMASK(12, 0) #define _PP_DIVISOR 0x61210 -#define PP_DIVISOR(dev_priv, pps_idx) _MMIO_PPS(dev_priv, pps_idx, _PP_DIVISOR) +#define PP_DIVISOR(display, pps_idx) _MMIO_PPS((display), (pps_idx), _PP_DIVISOR) #define PP_REFERENCE_DIVIDER_MASK REG_GENMASK(31, 8) #define PANEL_POWER_CYCLE_DELAY_MASK REG_GENMASK(4, 0) -- GitLab From c00d3615969e9bba610c83050f308aee75341156 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 13 May 2025 12:28:42 +0300 Subject: [PATCH 0063/1479] drm/i915/rps: pass struct intel_display to DISPLAY_VER() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid passing drm_i915_private to DISPLAY_VER(). Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/5e97ee7675b32397163eb4fba17184fc1c5a04cd.1747128495.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_rps.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_rps.c b/drivers/gpu/drm/i915/display/intel_display_rps.c index 678b241159512..0f1c95d70843b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_rps.c +++ b/drivers/gpu/drm/i915/display/intel_display_rps.c @@ -45,12 +45,13 @@ static int do_rps_boost(struct wait_queue_entry *_wait, void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc, struct dma_fence *fence) { + struct intel_display *display = to_intel_display(crtc->dev); struct wait_rps_boost *wait; if (!dma_fence_is_i915(fence)) return; - if (DISPLAY_VER(to_i915(crtc->dev)) < 6) + if (DISPLAY_VER(display) < 6) return; if (drm_crtc_vblank_get(crtc)) -- GitLab From 1882dc90dfb13450f3c1ca5e529fa6a4f80c6e44 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 13 May 2025 12:28:43 +0300 Subject: [PATCH 0064/1479] drm/i915/display: drop unused declarations from intel_display.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We've accumulated lots of forward declarations in intel_display.h that are no longer necessary. Clean them up. Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/5ad046b74040e84fab51786c346ff9a445e351bc.1747128495.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.h | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index fa857c0e03c70..37e2ab301a80e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -30,37 +30,21 @@ #include "i915_reg_defs.h" #include "intel_display_limits.h" -enum drm_scaling_filter; -struct dpll; struct drm_atomic_state; -struct drm_connector; struct drm_device; struct drm_display_mode; struct drm_encoder; -struct drm_file; -struct drm_format_info; -struct drm_framebuffer; -struct drm_mode_fb_cmd2; struct drm_modeset_acquire_ctx; -struct drm_plane; -struct drm_plane_state; -struct i915_address_space; -struct i915_gtt_view; struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; struct intel_digital_port; struct intel_display; -struct intel_dp; struct intel_encoder; -struct intel_initial_plane_config; struct intel_link_m_n; struct intel_plane; struct intel_plane_state; struct intel_power_domain_mask; -struct pci_dev; -struct work_struct; - #define pipe_name(p) ((p) + 'A') -- GitLab From a1216d84f13ca53c107cba99311a90177eeaa508 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 13 May 2025 12:28:44 +0300 Subject: [PATCH 0065/1479] drm/i915/gem: drop intel_display.h include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The include is not needed since commit 44a34dec43e8 ("drm/i915: Calculate the VT-d guard size in the display code"). Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/80ea203e004b7378c14f2367258b5785e40bf126.1747128495.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index 75a143d996e0e..50f5ec84574e0 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -4,7 +4,6 @@ * Copyright © 2014-2016 Intel Corporation */ -#include "display/intel_display.h" #include "gt/intel_gt.h" #include "i915_drv.h" -- GitLab From e2e02eb978c590e7278413eecd93142218609419 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 13 May 2025 12:28:45 +0300 Subject: [PATCH 0066/1479] drm/i915/display: drop unnecessary includes on i915 core headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These includes have become unnecessary. Drop them. Reviewed-by: Ville Syrjälä Link: https://lore.kernel.org/r/6ca3be3e3fbbd99c169345c3add4b76315390e77.1747128495.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 1 - drivers/gpu/drm/i915/display/intel_crt.c | 1 - drivers/gpu/drm/i915/display/intel_display.c | 1 - drivers/gpu/drm/i915/display/intel_display_debugfs.c | 1 - drivers/gpu/drm/i915/display/intel_dp.c | 1 - drivers/gpu/drm/i915/display/intel_dsb.c | 1 - 6 files changed, 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 7276179df8786..d41f2bd5bdfa5 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -42,7 +42,6 @@ #include #include "gem/i915_gem_object.h" -#include "i915_config.h" #include "i915_scheduler_types.h" #include "i915_vma.h" #include "i9xx_plane_regs.h" diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 38b50a779b6bb..04ef729dae0ba 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -34,7 +34,6 @@ #include #include -#include "i915_irq.h" #include "i915_reg.h" #include "intel_connector.h" #include "intel_crt.h" diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e0928f28d7116..91ca467b069b2 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -105,7 +105,6 @@ #include "intel_panel.h" #include "intel_pch_display.h" #include "intel_pch_refclk.h" -#include "intel_pcode.h" #include "intel_pfit.h" #include "intel_pipe_crc.h" #include "intel_plane_initial.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index a9b1ec4cf0f75..9df8995e5bac6 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -13,7 +13,6 @@ #include #include "hsw_ips.h" -#include "i915_irq.h" #include "i915_reg.h" #include "i9xx_wm_regs.h" #include "intel_alpm.h" diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 91a34d474463a..21297bc4cc00d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -51,7 +51,6 @@ #include #include "g4x_dp.h" -#include "i915_irq.h" #include "i915_reg.h" #include "i915_utils.h" #include "intel_alpm.h" diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 481488d1fe677..393ea07947b41 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -7,7 +7,6 @@ #include #include -#include "i915_irq.h" #include "i915_reg.h" #include "i915_utils.h" #include "intel_crtc.h" -- GitLab From 9934ab18051118385c7ea44d8e14175edbe6dc9c Mon Sep 17 00:00:00 2001 From: Philipp Stanner Date: Wed, 14 May 2025 09:31:27 +0200 Subject: [PATCH 0067/1479] drm/vmwgfx: Use non-hybrid PCI devres API vmwgfx enables its PCI device with pcim_enable_device(). This, implicitly, switches the function pci_request_regions() into managed mode, where it becomes a devres function. The PCI subsystem wants to remove this hybrid nature from its interfaces. To do so, users of the aforementioned combination of functions must be ported to non-hybrid functions. Moreover, since both functions are already managed in this driver, the calls to pci_release_regions() are unnecessary. Remove the calls to pci_release_regions(). Replace the call to sometimes-managed pci_request_regions() with one to always-managed pcim_request_all_regions(). Signed-off-by: Philipp Stanner Reviewed-by: Zack Rusin Signed-off-by: Zack Rusin Link: https://lore.kernel.org/r/20250514073126.85443-2-phasta@kernel.org --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 0695a342b1ef2..37b832e552a40 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -713,7 +713,7 @@ static int vmw_setup_pci_resources(struct vmw_private *dev, pci_set_master(pdev); - ret = pci_request_regions(pdev, "vmwgfx probe"); + ret = pcim_request_all_regions(pdev, "vmwgfx probe"); if (ret) return ret; @@ -733,7 +733,6 @@ static int vmw_setup_pci_resources(struct vmw_private *dev, if (!dev->rmmio) { drm_err(&dev->drm, "Failed mapping registers mmio memory.\n"); - pci_release_regions(pdev); return -ENOMEM; } } else if (pci_id == VMWGFX_PCI_ID_SVGA2) { @@ -754,11 +753,9 @@ static int vmw_setup_pci_resources(struct vmw_private *dev, if (IS_ERR(dev->fifo_mem)) { drm_err(&dev->drm, "Failed mapping FIFO memory.\n"); - pci_release_regions(pdev); return PTR_ERR(dev->fifo_mem); } } else { - pci_release_regions(pdev); return -EINVAL; } @@ -836,7 +833,6 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) int ret; enum vmw_res_type i; bool refuse_dma = false; - struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); vmw_sw_context_init(dev_priv); @@ -852,7 +848,7 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) return ret; ret = vmw_detect_version(dev_priv); if (ret) - goto out_no_pci_or_version; + return ret; for (i = vmw_res_context; i < vmw_res_max; ++i) { @@ -1152,15 +1148,13 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) if (dev_priv->ctx.staged_bindings) vmw_binding_state_free(dev_priv->ctx.staged_bindings); -out_no_pci_or_version: - pci_release_regions(pdev); + return ret; } static void vmw_driver_unload(struct drm_device *dev) { struct vmw_private *dev_priv = vmw_priv(dev); - struct pci_dev *pdev = to_pci_dev(dev->dev); enum vmw_res_type i; unregister_pm_notifier(&dev_priv->pm_nb); @@ -1196,8 +1190,6 @@ static void vmw_driver_unload(struct drm_device *dev) idr_destroy(&dev_priv->res_idr[i]); vmw_mksstat_remove_all(dev_priv); - - pci_release_regions(pdev); } static void vmw_postclose(struct drm_device *dev, -- GitLab From d0bf684bd42db22e7d131a038f8f78927fa6a72a Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 12 May 2025 17:26:00 +0300 Subject: [PATCH 0068/1479] drm/i915/ptl: Use everywhere the correct DDI port clock select mask The PTL XELPDP_PORT_CLOCK_CTL register XELPDP_DDI_CLOCK_SELECT field's size is 5 bits vs. the earlier platforms where its size is 4 bits. Make sure the field is read-out/programmed everywhere correctly, according to the above. Cc: Mika Kahola Cc: stable@vger.kernel.org # v6.13+ Tested-by: Mika Kahola Reviewed-by: Mika Kahola Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250512142600.824347-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 27 +++++++------------ .../gpu/drm/i915/display/intel_cx0_phy_regs.h | 15 ++++++++--- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index b09f724c3046b..a82b93cbc81d2 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2763,9 +2763,9 @@ static void intel_program_port_clock_ctl(struct intel_encoder *encoder, val |= XELPDP_FORWARD_CLOCK_UNGATE; if (!is_dp && is_hdmi_frl(port_clock)) - val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_DIV18CLK); + val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, XELPDP_DDI_CLOCK_SELECT_DIV18CLK); else - val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_MAXPCLK); + val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, XELPDP_DDI_CLOCK_SELECT_MAXPCLK); /* TODO: HDMI FRL */ /* DP2.0 10G and 20G rates enable MPLLA*/ @@ -2776,7 +2776,7 @@ static void intel_program_port_clock_ctl(struct intel_encoder *encoder, intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE | - XELPDP_DDI_CLOCK_SELECT_MASK | XELPDP_SSC_ENABLE_PLLA | + XELPDP_DDI_CLOCK_SELECT_MASK(display) | XELPDP_SSC_ENABLE_PLLA | XELPDP_SSC_ENABLE_PLLB, val); } @@ -3099,10 +3099,7 @@ int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder) val = intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port)); - if (DISPLAY_VER(display) >= 30) - clock = REG_FIELD_GET(XE3_DDI_CLOCK_SELECT_MASK, val); - else - clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val); + clock = XELPDP_DDI_CLOCK_SELECT_GET(display, val); drm_WARN_ON(display->drm, !(val & XELPDP_FORWARD_CLOCK_UNGATE)); drm_WARN_ON(display->drm, !(val & XELPDP_TBT_CLOCK_REQUEST)); @@ -3170,13 +3167,9 @@ static void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder, * clock muxes, gating and SSC */ - if (DISPLAY_VER(display) >= 30) { - mask = XE3_DDI_CLOCK_SELECT_MASK; - val |= XE3_DDI_CLOCK_SELECT(intel_mtl_tbt_clock_select(display, crtc_state->port_clock)); - } else { - mask = XELPDP_DDI_CLOCK_SELECT_MASK; - val |= XELPDP_DDI_CLOCK_SELECT(intel_mtl_tbt_clock_select(display, crtc_state->port_clock)); - } + mask = XELPDP_DDI_CLOCK_SELECT_MASK(display); + val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, + intel_mtl_tbt_clock_select(display, crtc_state->port_clock)); mask |= XELPDP_FORWARD_CLOCK_UNGATE; val |= XELPDP_FORWARD_CLOCK_UNGATE; @@ -3289,7 +3282,7 @@ static void intel_cx0pll_disable(struct intel_encoder *encoder) /* 7. Program PORT_CLOCK_CTL register to disable and gate clocks. */ intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), - XELPDP_DDI_CLOCK_SELECT_MASK, 0); + XELPDP_DDI_CLOCK_SELECT_MASK(display), 0); intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), XELPDP_FORWARD_CLOCK_UNGATE, 0); @@ -3338,7 +3331,7 @@ static void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder) * 5. Program PORT CLOCK CTRL register to disable and gate clocks */ intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), - XELPDP_DDI_CLOCK_SELECT_MASK | + XELPDP_DDI_CLOCK_SELECT_MASK(display) | XELPDP_FORWARD_CLOCK_UNGATE, 0); /* 6. Program DDI_CLK_VALFREQ to 0. */ @@ -3367,7 +3360,7 @@ intel_mtl_port_pll_type(struct intel_encoder *encoder, * handling is done via the standard shared DPLL framework. */ val = intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port)); - clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val); + clock = XELPDP_DDI_CLOCK_SELECT_GET(display, val); if (clock == XELPDP_DDI_CLOCK_SELECT_MAXPCLK || clock == XELPDP_DDI_CLOCK_SELECT_DIV18CLK) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h index 960f7f778fb81..59c22beaf1de5 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h @@ -192,10 +192,17 @@ #define XELPDP_TBT_CLOCK_REQUEST REG_BIT(19) #define XELPDP_TBT_CLOCK_ACK REG_BIT(18) -#define XELPDP_DDI_CLOCK_SELECT_MASK REG_GENMASK(15, 12) -#define XE3_DDI_CLOCK_SELECT_MASK REG_GENMASK(16, 12) -#define XELPDP_DDI_CLOCK_SELECT(val) REG_FIELD_PREP(XELPDP_DDI_CLOCK_SELECT_MASK, val) -#define XE3_DDI_CLOCK_SELECT(val) REG_FIELD_PREP(XE3_DDI_CLOCK_SELECT_MASK, val) +#define _XELPDP_DDI_CLOCK_SELECT_MASK REG_GENMASK(15, 12) +#define _XE3_DDI_CLOCK_SELECT_MASK REG_GENMASK(16, 12) +#define XELPDP_DDI_CLOCK_SELECT_MASK(display) (DISPLAY_VER(display) >= 30 ? \ + _XE3_DDI_CLOCK_SELECT_MASK : _XELPDP_DDI_CLOCK_SELECT_MASK) +#define XELPDP_DDI_CLOCK_SELECT_PREP(display, val) (DISPLAY_VER(display) >= 30 ? \ + REG_FIELD_PREP(_XE3_DDI_CLOCK_SELECT_MASK, (val)) : \ + REG_FIELD_PREP(_XELPDP_DDI_CLOCK_SELECT_MASK, (val))) +#define XELPDP_DDI_CLOCK_SELECT_GET(display, val) (DISPLAY_VER(display) >= 30 ? \ + REG_FIELD_GET(_XE3_DDI_CLOCK_SELECT_MASK, (val)) : \ + REG_FIELD_GET(_XELPDP_DDI_CLOCK_SELECT_MASK, (val))) + #define XELPDP_DDI_CLOCK_SELECT_NONE 0x0 #define XELPDP_DDI_CLOCK_SELECT_MAXPCLK 0x8 #define XELPDP_DDI_CLOCK_SELECT_DIV18CLK 0x9 -- GitLab From 745df157e4f2d695a9149ff964abe77490b1e96c Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:14 +0530 Subject: [PATCH 0069/1479] drm/xe: Introduce xe_vma_op_prefetch_range struct for prefetch of ranges MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add xe_vma_op_prefetch_range struct for svm ranges prefetching, including an xarray of SVM range pointers, range count, and target memory region. -v2: Fix doc Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-2-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_vm_types.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h index 1662604c4486d..0afd0296a57e9 100644 --- a/drivers/gpu/drm/xe/xe_vm_types.h +++ b/drivers/gpu/drm/xe/xe_vm_types.h @@ -374,6 +374,16 @@ struct xe_vma_op_unmap_range { struct xe_svm_range *range; }; +/** struct xe_vma_op_prefetch_range - VMA prefetch range operation */ +struct xe_vma_op_prefetch_range { + /** @range: xarray for SVM ranges data */ + struct xarray range; + /** @ranges_count: number of svm ranges to map */ + u32 ranges_count; + /** @region: memory region to prefetch to */ + u32 region; +}; + /** enum xe_vma_op_flags - flags for VMA operation */ enum xe_vma_op_flags { /** @XE_VMA_OP_COMMITTED: VMA operation committed */ @@ -416,6 +426,8 @@ struct xe_vma_op { struct xe_vma_op_map_range map_range; /** @unmap_range: VMA unmap range operation specific data */ struct xe_vma_op_unmap_range unmap_range; + /** @prefetch_range: VMA prefetch range operation specific data */ + struct xe_vma_op_prefetch_range prefetch_range; }; }; -- GitLab From 686a526dad183e1ca7fc2f38df34b1dd3c7c387e Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:15 +0530 Subject: [PATCH 0070/1479] drm/xe: Make xe_svm_alloc_vram public MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function will be used in prefetch too, hence make it public. v2: - Add kernel-doc (Matthew Brost) - Rebase v3: - Move CONFIG_DRM_XE_DEVMEM_MIRROR stub out to xe_svm.c (Matthew Brost) Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-3-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_svm.c | 30 ++++++++++++++++++++---------- drivers/gpu/drm/xe/xe_svm.h | 12 ++++++++++++ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index ab88b4194e574..875376bddc886 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -677,9 +677,19 @@ static struct xe_vram_region *tile_to_vr(struct xe_tile *tile) return &tile->mem.vram; } -static int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, - struct xe_svm_range *range, - const struct drm_gpusvm_ctx *ctx) +/** + * xe_svm_alloc_vram()- Allocate device memory pages for range, + * migrating existing data. + * @vm: The VM. + * @tile: tile to allocate vram from + * @range: SVM range + * @ctx: DRM GPU SVM context + * + * Return: 0 on success, error code on failure. + */ +int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, + struct xe_svm_range *range, + const struct drm_gpusvm_ctx *ctx) { struct mm_struct *mm = vm->svm.gpusvm.mm; struct xe_vram_region *vr = tile_to_vr(tile); @@ -733,13 +743,6 @@ static int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, return err; } -#else -static int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, - struct xe_svm_range *range, - const struct drm_gpusvm_ctx *ctx) -{ - return -EOPNOTSUPP; -} #endif static bool supports_4K_migration(struct xe_device *xe) @@ -1025,6 +1028,13 @@ int xe_devm_add(struct xe_tile *tile, struct xe_vram_region *vr) return 0; } #else +int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, + struct xe_svm_range *range, + const struct drm_gpusvm_ctx *ctx) +{ + return -EOPNOTSUPP; +} + int xe_devm_add(struct xe_tile *tile, struct xe_vram_region *vr) { return 0; diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 30fc78b85b30f..36e245ec64225 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -70,6 +70,9 @@ int xe_svm_bo_evict(struct xe_bo *bo); void xe_svm_range_debug(struct xe_svm_range *range, const char *operation); +int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, + struct xe_svm_range *range, + const struct drm_gpusvm_ctx *ctx); /** * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping * @range: SVM range @@ -97,6 +100,7 @@ void xe_svm_flush(struct xe_vm *vm); #include struct drm_pagemap_device_addr; +struct drm_gpusvm_ctx; struct xe_bo; struct xe_gt; struct xe_vm; @@ -167,6 +171,14 @@ void xe_svm_range_debug(struct xe_svm_range *range, const char *operation) { } +static inline +int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, + struct xe_svm_range *range, + const struct drm_gpusvm_ctx *ctx) +{ + return -EOPNOTSUPP; +} + #define xe_svm_assert_in_notifier(...) do {} while (0) #define xe_svm_range_has_dma_mapping(...) false -- GitLab From eb07c2fc10bf9b98fb5df8a78ce707e3a20b5443 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:16 +0530 Subject: [PATCH 0071/1479] drm/xe/svm: Helper to add tile masks to svm ranges Introduce a helper to add tile mask of binding present and invalidated for the range. Add a lockdep_assert to ensure it is protected by GPU SVM notifier lock. -v7 rebased Suggested-by: Matthew Brost Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250513040228.470682-4-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_pt.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index b04756a97cdcf..4d248d06bfa57 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -2216,6 +2216,18 @@ static void unbind_op_commit(struct xe_vm *vm, struct xe_tile *tile, } } +static void range_present_and_invalidated_tile(struct xe_vm *vm, + struct xe_svm_range *range, + u8 tile_id) +{ + /* WRITE_ONCE pairs with READ_ONCE in xe_svm.c */ + + lockdep_assert_held(&vm->svm.gpusvm.notifier_lock); + + WRITE_ONCE(range->tile_present, range->tile_present | BIT(tile_id)); + WRITE_ONCE(range->tile_invalidated, range->tile_invalidated & ~BIT(tile_id)); +} + static void op_commit(struct xe_vm *vm, struct xe_tile *tile, struct xe_vm_pgtable_update_ops *pt_update_ops, @@ -2271,19 +2283,13 @@ static void op_commit(struct xe_vm *vm, case DRM_GPUVA_OP_DRIVER: { /* WRITE_ONCE pairs with READ_ONCE in xe_svm.c */ - - if (op->subop == XE_VMA_SUBOP_MAP_RANGE) { - WRITE_ONCE(op->map_range.range->tile_present, - op->map_range.range->tile_present | - BIT(tile->id)); - WRITE_ONCE(op->map_range.range->tile_invalidated, - op->map_range.range->tile_invalidated & - ~BIT(tile->id)); - } else if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE) { + if (op->subop == XE_VMA_SUBOP_MAP_RANGE) + range_present_and_invalidated_tile(vm, op->map_range.range, tile->id); + else if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE) WRITE_ONCE(op->unmap_range.range->tile_present, op->unmap_range.range->tile_present & ~BIT(tile->id)); - } + break; } default: -- GitLab From 18211ff4d57381476cf34bc6a8883eccee9a893a Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:17 +0530 Subject: [PATCH 0072/1479] drm/xe/svm: Make to_xe_range a public function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The to_xe_range function will be used in other files. Therefore, make it public and add kernel-doc documentation Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-5-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_svm.c | 5 ----- drivers/gpu/drm/xe/xe_svm.h | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 875376bddc886..77740730e8215 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -103,11 +103,6 @@ static void xe_svm_range_free(struct drm_gpusvm_range *range) kfree(range); } -static struct xe_svm_range *to_xe_range(struct drm_gpusvm_range *r) -{ - return container_of(r, struct xe_svm_range, base); -} - static void xe_svm_garbage_collector_add_range(struct xe_vm *vm, struct xe_svm_range *range, const struct mmu_notifier_range *mmu_range) diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 36e245ec64225..e9257f0b3ffcc 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -85,6 +85,20 @@ static inline bool xe_svm_range_has_dma_mapping(struct xe_svm_range *range) return range->base.flags.has_dma_mapping; } +/** + * to_xe_range - Convert a drm_gpusvm_range pointer to a xe_svm_range + * @r: Pointer to the drm_gpusvm_range structure + * + * This function takes a pointer to a drm_gpusvm_range structure and + * converts it to a pointer to the containing xe_svm_range structure. + * + * Return: Pointer to the xe_svm_range structure + */ +static inline struct xe_svm_range *to_xe_range(struct drm_gpusvm_range *r) +{ + return container_of(r, struct xe_svm_range, base); +} + #define xe_svm_assert_in_notifier(vm__) \ lockdep_assert_held_write(&(vm__)->svm.gpusvm.notifier_lock) @@ -101,6 +115,7 @@ void xe_svm_flush(struct xe_vm *vm); struct drm_pagemap_device_addr; struct drm_gpusvm_ctx; +struct drm_gpusvm_range; struct xe_bo; struct xe_gt; struct xe_vm; @@ -179,6 +194,11 @@ int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, return -EOPNOTSUPP; } +static inline struct xe_svm_range *to_xe_range(struct drm_gpusvm_range *r) +{ + return NULL; +} + #define xe_svm_assert_in_notifier(...) do {} while (0) #define xe_svm_range_has_dma_mapping(...) false -- GitLab From da2eb41004e955293675a4049da94084ebd41241 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:18 +0530 Subject: [PATCH 0073/1479] drm/xe/svm: Make xe_svm_range_* end/start/size public MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These functions will be used in prefetch too, therefore make them public. v2 - Fix kernel doc Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-6-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_svm.c | 15 ------------ drivers/gpu/drm/xe/xe_svm.h | 48 +++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 77740730e8215..6cfe92b8adbe1 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -45,21 +45,6 @@ static struct xe_vm *range_to_vm(struct drm_gpusvm_range *r) return gpusvm_to_vm(r->gpusvm); } -static unsigned long xe_svm_range_start(struct xe_svm_range *range) -{ - return drm_gpusvm_range_start(&range->base); -} - -static unsigned long xe_svm_range_end(struct xe_svm_range *range) -{ - return drm_gpusvm_range_end(&range->base); -} - -static unsigned long xe_svm_range_size(struct xe_svm_range *range) -{ - return drm_gpusvm_range_size(&range->base); -} - #define range_debug(r__, operaton__) \ vm_dbg(&range_to_vm(&(r__)->base)->xe->drm, \ "%s: asid=%u, gpusvm=%p, vram=%d,%d, seqno=%lu, " \ diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index e9257f0b3ffcc..a69bbdc736082 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -99,6 +99,39 @@ static inline struct xe_svm_range *to_xe_range(struct drm_gpusvm_range *r) return container_of(r, struct xe_svm_range, base); } +/** + * xe_svm_range_start() - SVM range start address + * @range: SVM range + * + * Return: start address of range. + */ +static inline unsigned long xe_svm_range_start(struct xe_svm_range *range) +{ + return drm_gpusvm_range_start(&range->base); +} + +/** + * xe_svm_range_end() - SVM range end address + * @range: SVM range + * + * Return: end address of range. + */ +static inline unsigned long xe_svm_range_end(struct xe_svm_range *range) +{ + return drm_gpusvm_range_end(&range->base); +} + +/** + * xe_svm_range_size() - SVM range size + * @range: SVM range + * + * Return: Size of range. + */ +static inline unsigned long xe_svm_range_size(struct xe_svm_range *range) +{ + return drm_gpusvm_range_size(&range->base); +} + #define xe_svm_assert_in_notifier(vm__) \ lockdep_assert_held_write(&(vm__)->svm.gpusvm.notifier_lock) @@ -199,6 +232,21 @@ static inline struct xe_svm_range *to_xe_range(struct drm_gpusvm_range *r) return NULL; } +static inline unsigned long xe_svm_range_start(struct xe_svm_range *range) +{ + return 0; +} + +static inline unsigned long xe_svm_range_end(struct xe_svm_range *range) +{ + return 0; +} + +static inline unsigned long xe_svm_range_size(struct xe_svm_range *range) +{ + return 0; +} + #define xe_svm_assert_in_notifier(...) do {} while (0) #define xe_svm_range_has_dma_mapping(...) false -- GitLab From 34ebb62723aa766be85ea38fac7e651bfaca6a61 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:19 +0530 Subject: [PATCH 0074/1479] drm/xe/vm: Update xe_vma_ops_incr_pt_update_ops to take an increment value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefetch for SVM ranges can have more than one operation to increment, hence modify the function to accept an increment value as input. v2: - Call xe_vma_ops_incr_pt_update_ops only once for REMAP (Matthew Brost) - Add check for 0 ops v3: - s/u8/int for inc_val and num_remap_ops (Matthew Brost) Suggested-by: Matthew Brost Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-7-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_vm.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 79323c78130f3..f4382386b34c9 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -806,13 +806,16 @@ static void xe_vma_ops_fini(struct xe_vma_ops *vops) kfree(vops->pt_update_ops[i].ops); } -static void xe_vma_ops_incr_pt_update_ops(struct xe_vma_ops *vops, u8 tile_mask) +static void xe_vma_ops_incr_pt_update_ops(struct xe_vma_ops *vops, u8 tile_mask, int inc_val) { int i; + if (!inc_val) + return; + for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) if (BIT(i) & tile_mask) - ++vops->pt_update_ops[i].num_ops; + vops->pt_update_ops[i].num_ops += inc_val; } static void xe_vm_populate_rebind(struct xe_vma_op *op, struct xe_vma *vma, @@ -842,7 +845,7 @@ static int xe_vm_ops_add_rebind(struct xe_vma_ops *vops, struct xe_vma *vma, xe_vm_populate_rebind(op, vma, tile_mask); list_add_tail(&op->link, &vops->list); - xe_vma_ops_incr_pt_update_ops(vops, tile_mask); + xe_vma_ops_incr_pt_update_ops(vops, tile_mask, 1); return 0; } @@ -977,7 +980,7 @@ xe_vm_ops_add_range_rebind(struct xe_vma_ops *vops, xe_vm_populate_range_rebind(op, vma, range, tile_mask); list_add_tail(&op->link, &vops->list); - xe_vma_ops_incr_pt_update_ops(vops, tile_mask); + xe_vma_ops_incr_pt_update_ops(vops, tile_mask, 1); return 0; } @@ -1062,7 +1065,7 @@ xe_vm_ops_add_range_unbind(struct xe_vma_ops *vops, xe_vm_populate_range_unbind(op, range); list_add_tail(&op->link, &vops->list); - xe_vma_ops_incr_pt_update_ops(vops, range->tile_present); + xe_vma_ops_incr_pt_update_ops(vops, range->tile_present, 1); return 0; } @@ -2493,7 +2496,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, !op->map.is_cpu_addr_mirror) || op->map.invalidate_on_bind) xe_vma_ops_incr_pt_update_ops(vops, - op->tile_mask); + op->tile_mask, 1); break; } case DRM_GPUVA_OP_REMAP: @@ -2502,6 +2505,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, gpuva_to_vma(op->base.remap.unmap->va); bool skip = xe_vma_is_cpu_addr_mirror(old); u64 start = xe_vma_start(old), end = xe_vma_end(old); + int num_remap_ops = 0; if (op->base.remap.prev) start = op->base.remap.prev->va.addr + @@ -2554,7 +2558,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, (ULL)op->remap.start, (ULL)op->remap.range); } else { - xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); + num_remap_ops++; } } @@ -2583,11 +2587,13 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, (ULL)op->remap.start, (ULL)op->remap.range); } else { - xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); + num_remap_ops++; } } if (!skip) - xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); + num_remap_ops++; + + xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask, num_remap_ops); break; } case DRM_GPUVA_OP_UNMAP: @@ -2599,7 +2605,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, return -EBUSY; if (!xe_vma_is_cpu_addr_mirror(vma)) - xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); + xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask, 1); break; case DRM_GPUVA_OP_PREFETCH: vma = gpuva_to_vma(op->base.prefetch.va); @@ -2611,7 +2617,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, } if (!xe_vma_is_cpu_addr_mirror(vma)) - xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); + xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask, 1); break; default: drm_warn(&vm->xe->drm, "NOT POSSIBLE"); -- GitLab From bd1d1b46fe42a248916172cdf3cded07b7d93f8a Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:20 +0530 Subject: [PATCH 0075/1479] drm/xe/vm: Add an identifier in xe_vma_ops for svm prefetch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a flag in xe_vma_ops to determine whether it has svm prefetch ops or not. v2: - s/false/0 (Matthew Brost) v3: - s/XE_VMA_OPS_HAS_SVM_PREFETCH/XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH Suggested-by: Matthew Brost Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-8-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_vm.c | 1 + drivers/gpu/drm/xe/xe_vm_types.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index f4382386b34c9..21564ecf87657 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -3240,6 +3240,7 @@ static void xe_vma_ops_init(struct xe_vma_ops *vops, struct xe_vm *vm, vops->q = q; vops->syncs = syncs; vops->num_syncs = num_syncs; + vops->flags = 0; } static int xe_vm_bind_ioctl_validate_bo(struct xe_device *xe, struct xe_bo *bo, diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h index 0afd0296a57e9..bfc145baad496 100644 --- a/drivers/gpu/drm/xe/xe_vm_types.h +++ b/drivers/gpu/drm/xe/xe_vm_types.h @@ -445,6 +445,9 @@ struct xe_vma_ops { u32 num_syncs; /** @pt_update_ops: page table update operations */ struct xe_vm_pgtable_update_ops pt_update_ops[XE_MAX_TILES_PER_DEVICE]; + /** @flag: signify the properties within xe_vma_ops*/ +#define XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH BIT(0) + u32 flags; #ifdef TEST_VM_OPS_ERROR /** @inject_error: inject error to test error handling */ bool inject_error; -- GitLab From da05e5ddc652d1ab66efddc52e32a8770a89cbd9 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:21 +0530 Subject: [PATCH 0076/1479] drm/xe: Rename lookup_vma function to xe_find_vma_by_addr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This update renames the lookup_vma function to xe_vm_find_vma_by_addr and makes it accessible externally. The function, which looks up a VMA by its address within a specified VM, will be utilized in upcoming patches. v2 - Fix doc Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-9-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_gt_pagefault.c | 24 +---------------------- drivers/gpu/drm/xe/xe_vm.c | 29 ++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_vm.h | 2 ++ 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c index 10622ca471a28..7a8f87709e39c 100644 --- a/drivers/gpu/drm/xe/xe_gt_pagefault.c +++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c @@ -72,28 +72,6 @@ static bool vma_is_valid(struct xe_tile *tile, struct xe_vma *vma) !(BIT(tile->id) & vma->tile_invalidated); } -static bool vma_matches(struct xe_vma *vma, u64 page_addr) -{ - if (page_addr > xe_vma_end(vma) - 1 || - page_addr + SZ_4K - 1 < xe_vma_start(vma)) - return false; - - return true; -} - -static struct xe_vma *lookup_vma(struct xe_vm *vm, u64 page_addr) -{ - struct xe_vma *vma = NULL; - - if (vm->usm.last_fault_vma) { /* Fast lookup */ - if (vma_matches(vm->usm.last_fault_vma, page_addr)) - vma = vm->usm.last_fault_vma; - } - if (!vma) - vma = xe_vm_find_overlapping_vma(vm, page_addr, SZ_4K); - - return vma; -} static int xe_pf_begin(struct drm_exec *exec, struct xe_vma *vma, bool atomic, unsigned int id) @@ -231,7 +209,7 @@ static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf) goto unlock_vm; } - vma = lookup_vma(vm, pf->page_addr); + vma = xe_vm_find_vma_by_addr(vm, pf->page_addr); if (!vma) { err = -EINVAL; goto unlock_vm; diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 21564ecf87657..cb79a37d2132b 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -2139,6 +2139,35 @@ int xe_vm_destroy_ioctl(struct drm_device *dev, void *data, return err; } +static bool vma_matches(struct xe_vma *vma, u64 page_addr) +{ + if (page_addr > xe_vma_end(vma) - 1 || + page_addr + SZ_4K - 1 < xe_vma_start(vma)) + return false; + + return true; +} + +/** + * xe_vm_find_vma_by_addr() - Find a VMA by its address + * + * @vm: the xe_vm the vma belongs to + * @page_addr: address to look up + */ +struct xe_vma *xe_vm_find_vma_by_addr(struct xe_vm *vm, u64 page_addr) +{ + struct xe_vma *vma = NULL; + + if (vm->usm.last_fault_vma) { /* Fast lookup */ + if (vma_matches(vm->usm.last_fault_vma, page_addr)) + vma = vm->usm.last_fault_vma; + } + if (!vma) + vma = xe_vm_find_overlapping_vma(vm, page_addr, SZ_4K); + + return vma; +} + static const u32 region_to_mem_type[] = { XE_PL_TT, XE_PL_VRAM0, diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h index 0ef811fc2bdee..99e164852f637 100644 --- a/drivers/gpu/drm/xe/xe_vm.h +++ b/drivers/gpu/drm/xe/xe_vm.h @@ -169,6 +169,8 @@ static inline bool xe_vma_is_userptr(struct xe_vma *vma) !xe_vma_is_cpu_addr_mirror(vma); } +struct xe_vma *xe_vm_find_vma_by_addr(struct xe_vm *vm, u64 page_addr); + /** * to_userptr_vma() - Return a pointer to an embedding userptr vma * @vma: Pointer to the embedded struct xe_vma -- GitLab From e0ff0d7cf928fdd0e52565dd6285c46ccf3bce89 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:22 +0530 Subject: [PATCH 0077/1479] drm/xe/svm: Refactor usage of drm_gpusvm* function in xe_svm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define xe_svm_range_find_or_insert function wrapping drm_gpusvm_range_find_or_insert for reusing in prefetch. Define xe_svm_range_get_pages function wrapping drm_gpusvm_range_get_pages for reusing in prefetch. -v2 pass pagefault defined drm_gpu_svm context as parameter in xe_svm_range_find_or_insert(Matthew Brost) Cc: Matthew Brost Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-10-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_svm.c | 65 ++++++++++++++++++++++++++++++++----- drivers/gpu/drm/xe/xe_svm.h | 21 ++++++++++++ 2 files changed, 77 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 6cfe92b8adbe1..6e593733d473f 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -785,7 +785,6 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, vm->xe->atomic_svm_timeslice_ms : 0, }; struct xe_svm_range *range; - struct drm_gpusvm_range *r; struct drm_exec exec; struct dma_fence *fence; struct xe_tile *tile = gt_to_tile(gt); @@ -804,16 +803,14 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, if (err) return err; - r = drm_gpusvm_range_find_or_insert(&vm->svm.gpusvm, fault_addr, - xe_vma_start(vma), xe_vma_end(vma), - &ctx); - if (IS_ERR(r)) - return PTR_ERR(r); + range = xe_svm_range_find_or_insert(vm, fault_addr, vma, &ctx); - if (ctx.devmem_only && !r->flags.migrate_devmem) + if (IS_ERR(range)) + return PTR_ERR(range); + + if (ctx.devmem_only && !range->base.flags.migrate_devmem) return -EACCES; - range = to_xe_range(r); if (xe_svm_range_is_valid(range, tile, ctx.devmem_only)) return 0; @@ -839,7 +836,7 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, } range_debug(range, "GET PAGES"); - err = drm_gpusvm_range_get_pages(&vm->svm.gpusvm, r, &ctx); + err = xe_svm_range_get_pages(vm, range, &ctx); /* Corner where CPU mappings have changed */ if (err == -EOPNOTSUPP || err == -EFAULT || err == -EPERM) { ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ @@ -930,6 +927,56 @@ int xe_svm_bo_evict(struct xe_bo *bo) return drm_gpusvm_evict_to_ram(&bo->devmem_allocation); } +/** + * xe_svm_range_find_or_insert- Find or insert GPU SVM range + * @vm: xe_vm pointer + * @addr: address for which range needs to be found/inserted + * @vma: Pointer to struct xe_vma which mirrors CPU + * @ctx: GPU SVM context + * + * This function finds or inserts a newly allocated a SVM range based on the + * address. + * + * Return: Pointer to the SVM range on success, ERR_PTR() on failure. + */ +struct xe_svm_range *xe_svm_range_find_or_insert(struct xe_vm *vm, u64 addr, + struct xe_vma *vma, struct drm_gpusvm_ctx *ctx) +{ + struct drm_gpusvm_range *r; + + r = drm_gpusvm_range_find_or_insert(&vm->svm.gpusvm, max(addr, xe_vma_start(vma)), + xe_vma_start(vma), xe_vma_end(vma), ctx); + if (IS_ERR(r)) + return ERR_PTR(PTR_ERR(r)); + + return to_xe_range(r); +} + +/** + * xe_svm_range_get_pages() - Get pages for a SVM range + * @vm: Pointer to the struct xe_vm + * @range: Pointer to the xe SVM range structure + * @ctx: GPU SVM context + * + * This function gets pages for a SVM range and ensures they are mapped for + * DMA access. In case of failure with -EOPNOTSUPP, it evicts the range. + * + * Return: 0 on success, negative error code on failure. + */ +int xe_svm_range_get_pages(struct xe_vm *vm, struct xe_svm_range *range, + struct drm_gpusvm_ctx *ctx) +{ + int err = 0; + + err = drm_gpusvm_range_get_pages(&vm->svm.gpusvm, &range->base, ctx); + if (err == -EOPNOTSUPP) { + range_debug(range, "PAGE FAULT - EVICT PAGES"); + drm_gpusvm_range_evict(&vm->svm.gpusvm, &range->base); + } + + return err; +} + #if IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) static struct drm_pagemap_device_addr diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index a69bbdc736082..e304d147d309b 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -73,6 +73,13 @@ void xe_svm_range_debug(struct xe_svm_range *range, const char *operation); int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, struct xe_svm_range *range, const struct drm_gpusvm_ctx *ctx); + +struct xe_svm_range *xe_svm_range_find_or_insert(struct xe_vm *vm, u64 addr, + struct xe_vma *vma, struct drm_gpusvm_ctx *ctx); + +int xe_svm_range_get_pages(struct xe_vm *vm, struct xe_svm_range *range, + struct drm_gpusvm_ctx *ctx); + /** * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping * @range: SVM range @@ -227,6 +234,20 @@ int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile, return -EOPNOTSUPP; } +static inline +struct xe_svm_range *xe_svm_range_find_or_insert(struct xe_vm *vm, u64 addr, + struct xe_vma *vma, struct drm_gpusvm_ctx *ctx) +{ + return ERR_PTR(-EINVAL); +} + +static inline +int xe_svm_range_get_pages(struct xe_vm *vm, struct xe_svm_range *range, + struct drm_gpusvm_ctx *ctx) +{ + return -EINVAL; +} + static inline struct xe_svm_range *to_xe_range(struct drm_gpusvm_range *r) { return NULL; -- GitLab From cc795e0410342076a4ad65ca2b5450cda779f784 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:23 +0530 Subject: [PATCH 0078/1479] drm/xe/svm: Make xe_svm_range_needs_migrate_to_vram() public xe_svm_range_needs_migrate_to_vram() determines whether range needs migration to vram or not, modify it to accept region preference parameter too, so we can use it in prefetch too. v2 - add assert instead of warn (Matthew Brost) Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250513040228.470682-11-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_svm.c | 26 ++++++++++++++++++-------- drivers/gpu/drm/xe/xe_svm.h | 10 ++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 6e593733d473f..c6505350c8ffd 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -733,22 +733,32 @@ static bool supports_4K_migration(struct xe_device *xe) return true; } -static bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, - struct xe_vma *vma) +/** + * xe_svm_range_needs_migrate_to_vram() - SVM range needs migrate to VRAM or not + * @range: SVM range for which migration needs to be decided + * @vma: vma which has range + * @preferred_region_is_vram: preferred region for range is vram + * + * Return: True for range needing migration and migration is supported else false + */ +bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vma *vma, + bool preferred_region_is_vram) { struct xe_vm *vm = range_to_vm(&range->base); u64 range_size = xe_svm_range_size(range); - if (!range->base.flags.migrate_devmem) + if (!range->base.flags.migrate_devmem || !preferred_region_is_vram) return false; - if (xe_svm_range_in_vram(range)) { - drm_dbg(&vm->xe->drm, "Range is already in VRAM\n"); + xe_assert(vm->xe, IS_DGFX(vm->xe)); + + if (preferred_region_is_vram && xe_svm_range_in_vram(range)) { + drm_info(&vm->xe->drm, "Range is already in VRAM\n"); return false; } - if (range_size <= SZ_64K && !supports_4K_migration(vm->xe)) { - drm_dbg(&vm->xe->drm, "Platform doesn't support SZ_4K range migration\n"); + if (preferred_region_is_vram && range_size <= SZ_64K && !supports_4K_migration(vm->xe)) { + drm_warn(&vm->xe->drm, "Platform doesn't support SZ_4K range migration\n"); return false; } @@ -817,7 +827,7 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, range_debug(range, "PAGE FAULT"); if (--migrate_try_count >= 0 && - xe_svm_range_needs_migrate_to_vram(range, vma)) { + xe_svm_range_needs_migrate_to_vram(range, vma, IS_DGFX(vm->xe))) { err = xe_svm_alloc_vram(vm, tile, range, &ctx); ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ if (err) { diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index e304d147d309b..0ee845e35b3ee 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -80,6 +80,9 @@ struct xe_svm_range *xe_svm_range_find_or_insert(struct xe_vm *vm, u64 addr, int xe_svm_range_get_pages(struct xe_vm *vm, struct xe_svm_range *range, struct drm_gpusvm_ctx *ctx); +bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vma *vma, + bool preferred_region_is_vram); + /** * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping * @range: SVM range @@ -268,6 +271,13 @@ static inline unsigned long xe_svm_range_size(struct xe_svm_range *range) return 0; } +static inline +bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vma *vma, + u32 region) +{ + return false; +} + #define xe_svm_assert_in_notifier(...) do {} while (0) #define xe_svm_range_has_dma_mapping(...) false -- GitLab From 6275362f1837ba538956d05e1c6120db3a635631 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:24 +0530 Subject: [PATCH 0079/1479] drm/xe/svm: Add xe_svm_range_validate() and xe_svm_range_migrate_to_smem() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The xe_svm_range_validate() function checks if a range is valid and located in the desired memory region. xe_svm_range_migrate_to_smem() checks if range have pages in devmem and migrate them to smem. v2 - Fix function stub in xe_svm.h - Fix doc v3 (Matthew Brost) - Remove extra new line - s/range->base.flags.has_devmem_pages/xe_svm_range_in_vram v4 (Matthew Brost) - s/xe_svm_range_in_vram/range->base.flags.has_devmem_pages - Move eviction logic to separate function Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-12-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_svm.c | 41 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_svm.h | 19 +++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index c6505350c8ffd..248f615a343e6 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -651,6 +651,47 @@ static bool xe_svm_range_is_valid(struct xe_svm_range *range, (!devmem_only || xe_svm_range_in_vram(range)); } +/** xe_svm_range_migrate_to_smem() - Move range pages from VRAM to SMEM + * @vm: xe_vm pointer + * @range: Pointer to the SVM range structure + * + * The xe_svm_range_migrate_to_smem() checks range has pages in VRAM + * and migrates them to SMEM + */ +void xe_svm_range_migrate_to_smem(struct xe_vm *vm, struct xe_svm_range *range) +{ + if (xe_svm_range_in_vram(range)) + drm_gpusvm_range_evict(&vm->svm.gpusvm, &range->base); +} + +/** + * xe_svm_range_validate() - Check if the SVM range is valid + * @vm: xe_vm pointer + * @range: Pointer to the SVM range structure + * @tile_mask: Mask representing the tiles to be checked + * @devmem_preferred : if true range needs to be in devmem + * + * The xe_svm_range_validate() function checks if a range is + * valid and located in the desired memory region. + * + * Return: true if the range is valid, false otherwise + */ +bool xe_svm_range_validate(struct xe_vm *vm, + struct xe_svm_range *range, + u8 tile_mask, bool devmem_preferred) +{ + bool ret; + + xe_svm_notifier_lock(vm); + + ret = (range->tile_present & ~range->tile_invalidated & tile_mask) == tile_mask && + (devmem_preferred == range->base.flags.has_devmem_pages); + + xe_svm_notifier_unlock(vm); + + return ret; +} + #if IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) static struct xe_vram_region *tile_to_vr(struct xe_tile *tile) { diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 0ee845e35b3ee..42be9e5d04445 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -83,6 +83,12 @@ int xe_svm_range_get_pages(struct xe_vm *vm, struct xe_svm_range *range, bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vma *vma, bool preferred_region_is_vram); +void xe_svm_range_migrate_to_smem(struct xe_vm *vm, struct xe_svm_range *range); + +bool xe_svm_range_validate(struct xe_vm *vm, + struct xe_svm_range *range, + u8 tile_mask, bool devmem_preferred); + /** * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping * @range: SVM range @@ -278,6 +284,19 @@ bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vm return false; } +static inline +void xe_svm_range_migrate_to_smem(struct xe_vm *vm, struct xe_svm_range *range) +{ +} + +static inline +bool xe_svm_range_validate(struct xe_vm *vm, + struct xe_svm_range *range, + u8 tile_mask, bool devmem_preferred) +{ + return false; +} + #define xe_svm_assert_in_notifier(...) do {} while (0) #define xe_svm_range_has_dma_mapping(...) false -- GitLab From 72fa870957f53314bfa4b75bd3d402b72fab17ee Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:25 +0530 Subject: [PATCH 0080/1479] drm/gpusvm: Introduce drm_gpusvm_find_vma_start() function The drm_gpusvm_find_vma_start() function is used to determine the starting address of a CPU VMA within a specified user range. If the range does not contain any VMA, the function returns ULONG_MAX. v2 - Rename function as drm_gpusvm_find_vma_start() (Matthew Brost) - mmget/mmput v3 - s/mmget/mmget_not_zero/ Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250513040228.470682-13-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/drm_gpusvm.c | 34 ++++++++++++++++++++++++++++++++++ include/drm/drm_gpusvm.h | 5 +++++ 2 files changed, 39 insertions(+) diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index 4b2f32889f00f..7bb9eb71c9aa5 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -980,6 +980,40 @@ static void drm_gpusvm_driver_lock_held(struct drm_gpusvm *gpusvm) } #endif +/** + * drm_gpusvm_find_vma_start() - Find start address for first VMA in range + * @gpusvm: Pointer to the GPU SVM structure + * @start: The inclusive start user address. + * @end: The exclusive end user address. + * + * Returns: The start address of first VMA within the provided range, + * ULONG_MAX otherwise. Assumes start_addr < end_addr. + */ +unsigned long +drm_gpusvm_find_vma_start(struct drm_gpusvm *gpusvm, + unsigned long start, + unsigned long end) +{ + struct mm_struct *mm = gpusvm->mm; + struct vm_area_struct *vma; + unsigned long addr = ULONG_MAX; + + if (!mmget_not_zero(mm)) + return addr; + + mmap_read_lock(mm); + + vma = find_vma_intersection(mm, start, end); + if (vma) + addr = vma->vm_start; + + mmap_read_unlock(mm); + mmput(mm); + + return addr; +} +EXPORT_SYMBOL_GPL(drm_gpusvm_find_vma_start); + /** * drm_gpusvm_range_find_or_insert() - Find or insert GPU SVM range * @gpusvm: Pointer to the GPU SVM structure diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h index eaf704d3d05e8..6a5156476bf47 100644 --- a/include/drm/drm_gpusvm.h +++ b/include/drm/drm_gpusvm.h @@ -327,6 +327,11 @@ void drm_gpusvm_fini(struct drm_gpusvm *gpusvm); void drm_gpusvm_free(struct drm_gpusvm *gpusvm); +unsigned long +drm_gpusvm_find_vma_start(struct drm_gpusvm *gpusvm, + unsigned long start, + unsigned long end); + struct drm_gpusvm_range * drm_gpusvm_range_find_or_insert(struct drm_gpusvm *gpusvm, unsigned long fault_addr, -- GitLab From c904d4e2d73216c31487501b774afa9e3ed8be29 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:26 +0530 Subject: [PATCH 0081/1479] drm/xe/svm: Add xe_svm_find_vma_start() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add helper xe_svm_find_vma_start() function to determine start of cpu vma in input range. Reviewed-by: Matthew Brost Acked-by: Thomas Hellström Link: https://lore.kernel.org/r/20250513040228.470682-14-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_svm.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/xe/xe_svm.h | 8 ++++++++ 2 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 248f615a343e6..4432685936ed4 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -692,6 +692,28 @@ bool xe_svm_range_validate(struct xe_vm *vm, return ret; } +/** + * xe_svm_find_vma_start - Find start of CPU VMA + * @vm: xe_vm pointer + * @start: start address + * @end: end address + * @vma: Pointer to struct xe_vma + * + * + * This function searches for a cpu vma, within the specified + * range [start, end] in the given VM. It adjusts the range based on the + * xe_vma start and end addresses. If no cpu VMA is found, it returns ULONG_MAX. + * + * Return: The starting address of the VMA within the range, + * or ULONG_MAX if no VMA is found + */ +u64 xe_svm_find_vma_start(struct xe_vm *vm, u64 start, u64 end, struct xe_vma *vma) +{ + return drm_gpusvm_find_vma_start(&vm->svm.gpusvm, + max(start, xe_vma_start(vma)), + min(end, xe_vma_end(vma))); +} + #if IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) static struct xe_vram_region *tile_to_vr(struct xe_tile *tile) { diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 42be9e5d04445..19ce4f2754a78 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -89,6 +89,8 @@ bool xe_svm_range_validate(struct xe_vm *vm, struct xe_svm_range *range, u8 tile_mask, bool devmem_preferred); +u64 xe_svm_find_vma_start(struct xe_vm *vm, u64 addr, u64 end, struct xe_vma *vma); + /** * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping * @range: SVM range @@ -297,6 +299,12 @@ bool xe_svm_range_validate(struct xe_vm *vm, return false; } +static inline +u64 xe_svm_find_vma_start(struct xe_vm *vm, u64 addr, u64 end, struct xe_vma *vma) +{ + return ULONG_MAX; +} + #define xe_svm_assert_in_notifier(...) do {} while (0) #define xe_svm_range_has_dma_mapping(...) false -- GitLab From 09ba0a8f06cd69d93eef0dc3bee33546880e46f8 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:27 +0530 Subject: [PATCH 0082/1479] drm/xe/svm: Implement prefetch support for SVM ranges MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds prefetch support for SVM ranges, utilizing the existing ioctl vm_bind functionality to achieve this. v2: rebase v3: - use xa_for_each() instead of manual loop - check range is valid and in preferred location before adding to xarray - Fix naming conventions - Fix return condition as -ENODATA instead of -EAGAIN (Matthew Brost) - Handle sparsely populated cpu vma range (Matthew Brost) v4: - fix end address to find next cpu vma in case of -ENOENT v5: - Move find next vma logic to drm gpusvm layer - Avoid mixing declaration and logic v6: - Use new function names - Move eviction logic to prefetch_ranges v7: - devmem_only assigned 0 - nit address v8: - initialize ctx with 0 Cc: Matthew Brost Acked-by: Thomas Hellström Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250513040228.470682-15-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_pt.c | 58 ++++++++--- drivers/gpu/drm/xe/xe_vm.c | 196 +++++++++++++++++++++++++++++++++++-- 2 files changed, 233 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index 4d248d06bfa57..c9c41fbe125c6 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -1458,6 +1458,7 @@ static int xe_pt_svm_pre_commit(struct xe_migrate_pt_update *pt_update) struct xe_vm *vm = pt_update->vops->vm; struct xe_vma_ops *vops = pt_update->vops; struct xe_vma_op *op; + unsigned long i; int err; err = xe_pt_pre_commit(pt_update); @@ -1467,20 +1468,35 @@ static int xe_pt_svm_pre_commit(struct xe_migrate_pt_update *pt_update) xe_svm_notifier_lock(vm); list_for_each_entry(op, &vops->list, link) { - struct xe_svm_range *range = op->map_range.range; + struct xe_svm_range *range = NULL; if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE) continue; - xe_svm_range_debug(range, "PRE-COMMIT"); + if (op->base.op == DRM_GPUVA_OP_PREFETCH) { + xe_assert(vm->xe, + xe_vma_is_cpu_addr_mirror(gpuva_to_vma(op->base.prefetch.va))); + xa_for_each(&op->prefetch_range.range, i, range) { + xe_svm_range_debug(range, "PRE-COMMIT"); - xe_assert(vm->xe, xe_vma_is_cpu_addr_mirror(op->map_range.vma)); - xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE); + if (!xe_svm_range_pages_valid(range)) { + xe_svm_range_debug(range, "PRE-COMMIT - RETRY"); + xe_svm_notifier_unlock(vm); + return -ENODATA; + } + } + } else { + xe_assert(vm->xe, xe_vma_is_cpu_addr_mirror(op->map_range.vma)); + xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE); + range = op->map_range.range; - if (!xe_svm_range_pages_valid(range)) { - xe_svm_range_debug(range, "PRE-COMMIT - RETRY"); - xe_svm_notifier_unlock(vm); - return -EAGAIN; + xe_svm_range_debug(range, "PRE-COMMIT"); + + if (!xe_svm_range_pages_valid(range)) { + xe_svm_range_debug(range, "PRE-COMMIT - RETRY"); + xe_svm_notifier_unlock(vm); + return -EAGAIN; + } } } @@ -2065,11 +2081,20 @@ static int op_prepare(struct xe_vm *vm, { struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va); - if (xe_vma_is_cpu_addr_mirror(vma)) - break; + if (xe_vma_is_cpu_addr_mirror(vma)) { + struct xe_svm_range *range; + unsigned long i; - err = bind_op_prepare(vm, tile, pt_update_ops, vma, false); - pt_update_ops->wait_vm_kernel = true; + xa_for_each(&op->prefetch_range.range, i, range) { + err = bind_range_prepare(vm, tile, pt_update_ops, + vma, range); + if (err) + return err; + } + } else { + err = bind_op_prepare(vm, tile, pt_update_ops, vma, false); + pt_update_ops->wait_vm_kernel = true; + } break; } case DRM_GPUVA_OP_DRIVER: @@ -2275,9 +2300,16 @@ static void op_commit(struct xe_vm *vm, { struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va); - if (!xe_vma_is_cpu_addr_mirror(vma)) + if (xe_vma_is_cpu_addr_mirror(vma)) { + struct xe_svm_range *range = NULL; + unsigned long i; + + xa_for_each(&op->prefetch_range.range, i, range) + range_present_and_invalidated_tile(vm, range, tile->id); + } else { bind_op_commit(vm, tile, pt_update_ops, vma, fence, fence2, false); + } break; } case DRM_GPUVA_OP_DRIVER: diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index cb79a37d2132b..842af808c39b7 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -798,10 +798,33 @@ static int xe_vma_ops_alloc(struct xe_vma_ops *vops, bool array_of_binds) } ALLOW_ERROR_INJECTION(xe_vma_ops_alloc, ERRNO); +static void xe_vma_svm_prefetch_op_fini(struct xe_vma_op *op) +{ + struct xe_vma *vma; + + vma = gpuva_to_vma(op->base.prefetch.va); + + if (op->base.op == DRM_GPUVA_OP_PREFETCH && xe_vma_is_cpu_addr_mirror(vma)) + xa_destroy(&op->prefetch_range.range); +} + +static void xe_vma_svm_prefetch_ops_fini(struct xe_vma_ops *vops) +{ + struct xe_vma_op *op; + + if (!(vops->flags & XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH)) + return; + + list_for_each_entry(op, &vops->list, link) + xe_vma_svm_prefetch_op_fini(op); +} + static void xe_vma_ops_fini(struct xe_vma_ops *vops) { int i; + xe_vma_svm_prefetch_ops_fini(vops); + for (i = 0; i < XE_MAX_TILES_PER_DEVICE; ++i) kfree(vops->pt_update_ops[i].ops); } @@ -2248,13 +2271,25 @@ static bool __xe_vm_needs_clear_scratch_pages(struct xe_vm *vm, u32 bind_flags) return true; } +static void xe_svm_prefetch_gpuva_ops_fini(struct drm_gpuva_ops *ops) +{ + struct drm_gpuva_op *__op; + + drm_gpuva_for_each_op(__op, ops) { + struct xe_vma_op *op = gpuva_op_to_vma_op(__op); + + xe_vma_svm_prefetch_op_fini(op); + } +} + /* * Create operations list from IOCTL arguments, setup operations fields so parse * and commit steps are decoupled from IOCTL arguments. This step can fail. */ static struct drm_gpuva_ops * -vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_bo *bo, - u64 bo_offset_or_userptr, u64 addr, u64 range, +vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_vma_ops *vops, + struct xe_bo *bo, u64 bo_offset_or_userptr, + u64 addr, u64 range, u32 operation, u32 flags, u32 prefetch_region, u16 pat_index) { @@ -2262,6 +2297,7 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_bo *bo, struct drm_gpuva_ops *ops; struct drm_gpuva_op *__op; struct drm_gpuvm_bo *vm_bo; + u64 range_end = addr + range; int err; lockdep_assert_held_write(&vm->lock); @@ -2323,14 +2359,77 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_bo *bo, op->map.invalidate_on_bind = __xe_vm_needs_clear_scratch_pages(vm, flags); } else if (__op->op == DRM_GPUVA_OP_PREFETCH) { - op->prefetch.region = prefetch_region; - } + struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va); + struct xe_svm_range *svm_range; + struct drm_gpusvm_ctx ctx = {}; + struct xe_tile *tile; + u8 id, tile_mask = 0; + u32 i; + + if (!xe_vma_is_cpu_addr_mirror(vma)) { + op->prefetch.region = prefetch_region; + break; + } + + ctx.read_only = xe_vma_read_only(vma); + ctx.devmem_possible = IS_DGFX(vm->xe) && + IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR); + + for_each_tile(tile, vm->xe, id) + tile_mask |= 0x1 << id; + + xa_init_flags(&op->prefetch_range.range, XA_FLAGS_ALLOC); + op->prefetch_range.region = prefetch_region; + op->prefetch_range.ranges_count = 0; +alloc_next_range: + svm_range = xe_svm_range_find_or_insert(vm, addr, vma, &ctx); + + if (PTR_ERR(svm_range) == -ENOENT) { + u64 ret = xe_svm_find_vma_start(vm, addr, range_end, vma); + + addr = ret == ULONG_MAX ? 0 : ret; + if (addr) + goto alloc_next_range; + else + goto print_op_label; + } + + if (IS_ERR(svm_range)) { + err = PTR_ERR(svm_range); + goto unwind_prefetch_ops; + } + + if (xe_svm_range_validate(vm, svm_range, tile_mask, !!prefetch_region)) + goto check_next_range; + + err = xa_alloc(&op->prefetch_range.range, + &i, svm_range, xa_limit_32b, + GFP_KERNEL); + if (err) + goto unwind_prefetch_ops; + + op->prefetch_range.ranges_count++; + vops->flags |= XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH; +check_next_range: + if (range_end > xe_svm_range_end(svm_range) && + xe_svm_range_end(svm_range) < xe_vma_end(vma)) { + addr = xe_svm_range_end(svm_range); + goto alloc_next_range; + } + } +print_op_label: print_op(vm->xe, __op); } return ops; + +unwind_prefetch_ops: + xe_svm_prefetch_gpuva_ops_fini(ops); + drm_gpuva_ops_free(&vm->gpuvm, ops); + return ERR_PTR(err); } + ALLOW_ERROR_INJECTION(vm_bind_ioctl_ops_create, ERRNO); static struct xe_vma *new_vma(struct xe_vm *vm, struct drm_gpuva_op_map *op, @@ -2645,8 +2744,12 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, return err; } - if (!xe_vma_is_cpu_addr_mirror(vma)) + if (xe_vma_is_cpu_addr_mirror(vma)) + xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask, + op->prefetch_range.ranges_count); + else xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask, 1); + break; default: drm_warn(&vm->xe->drm, "NOT POSSIBLE"); @@ -2772,6 +2875,55 @@ static int check_ufence(struct xe_vma *vma) return 0; } +static int prefetch_ranges(struct xe_vm *vm, struct xe_vma_op *op) +{ + bool devmem_possible = IS_DGFX(vm->xe) && IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR); + struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va); + int err = 0; + + struct xe_svm_range *svm_range; + struct drm_gpusvm_ctx ctx = {}; + struct xe_tile *tile; + unsigned long i; + u32 region; + + if (!xe_vma_is_cpu_addr_mirror(vma)) + return 0; + + region = op->prefetch_range.region; + + ctx.read_only = xe_vma_read_only(vma); + ctx.devmem_possible = devmem_possible; + ctx.check_pages_threshold = devmem_possible ? SZ_64K : 0; + + /* TODO: Threading the migration */ + xa_for_each(&op->prefetch_range.range, i, svm_range) { + if (!region) + xe_svm_range_migrate_to_smem(vm, svm_range); + + if (xe_svm_range_needs_migrate_to_vram(svm_range, vma, region)) { + tile = &vm->xe->tiles[region_to_mem_type[region] - XE_PL_VRAM0]; + err = xe_svm_alloc_vram(vm, tile, svm_range, &ctx); + if (err) { + drm_dbg(&vm->xe->drm, "VRAM allocation failed, retry from userspace, asid=%u, gpusvm=%p, errno=%pe\n", + vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); + return -ENODATA; + } + } + + err = xe_svm_range_get_pages(vm, svm_range, &ctx); + if (err) { + if (err == -EOPNOTSUPP || err == -EFAULT || err == -EPERM) + err = -ENODATA; + drm_dbg(&vm->xe->drm, "Get pages failed, asid=%u, gpusvm=%p, errno=%pe\n", + vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); + return err; + } + } + + return err; +} + static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm, struct xe_vma_op *op) { @@ -2809,7 +2961,12 @@ static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm, case DRM_GPUVA_OP_PREFETCH: { struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va); - u32 region = op->prefetch.region; + u32 region; + + if (xe_vma_is_cpu_addr_mirror(vma)) + region = op->prefetch_range.region; + else + region = op->prefetch.region; xe_assert(vm->xe, region <= ARRAY_SIZE(region_to_mem_type)); @@ -2828,6 +2985,25 @@ static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm, return err; } +static int vm_bind_ioctl_ops_prefetch_ranges(struct xe_vm *vm, struct xe_vma_ops *vops) +{ + struct xe_vma_op *op; + int err; + + if (!(vops->flags & XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH)) + return 0; + + list_for_each_entry(op, &vops->list, link) { + if (op->base.op == DRM_GPUVA_OP_PREFETCH) { + err = prefetch_ranges(vm, op); + if (err) + return err; + } + } + + return 0; +} + static int vm_bind_ioctl_ops_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm, struct xe_vma_ops *vops) @@ -3477,7 +3653,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) u32 prefetch_region = bind_ops[i].prefetch_mem_region_instance; u16 pat_index = bind_ops[i].pat_index; - ops[i] = vm_bind_ioctl_ops_create(vm, bos[i], obj_offset, + ops[i] = vm_bind_ioctl_ops_create(vm, &vops, bos[i], obj_offset, addr, range, op, flags, prefetch_region, pat_index); if (IS_ERR(ops[i])) { @@ -3510,6 +3686,10 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) if (err) goto unwind_ops; + err = vm_bind_ioctl_ops_prefetch_ranges(vm, &vops); + if (err) + goto unwind_ops; + fence = vm_bind_ioctl_ops_execute(vm, &vops); if (IS_ERR(fence)) err = PTR_ERR(fence); @@ -3579,7 +3759,7 @@ struct dma_fence *xe_vm_bind_kernel_bo(struct xe_vm *vm, struct xe_bo *bo, xe_vma_ops_init(&vops, vm, q, NULL, 0); - ops = vm_bind_ioctl_ops_create(vm, bo, 0, addr, bo->size, + ops = vm_bind_ioctl_ops_create(vm, &vops, bo, 0, addr, bo->size, DRM_XE_VM_BIND_OP_MAP, 0, 0, vm->xe->pat.idx[cache_lvl]); if (IS_ERR(ops)) { -- GitLab From 5aee6e33e19593dafc42f9afb59fd2c53f75141f Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Tue, 13 May 2025 09:32:28 +0530 Subject: [PATCH 0083/1479] drm/xe/vm: Add debug prints for SVM range prefetch Introduce debug logs for the prefetch operation of SVM ranges. Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250513040228.470682-16-himal.prasad.ghimiray@intel.com Signed-off-by: Himal Prasad Ghimiray --- drivers/gpu/drm/xe/xe_vm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 842af808c39b7..5a978da411b03 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -2399,8 +2399,10 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_vma_ops *vops, goto unwind_prefetch_ops; } - if (xe_svm_range_validate(vm, svm_range, tile_mask, !!prefetch_region)) + if (xe_svm_range_validate(vm, svm_range, tile_mask, !!prefetch_region)) { + xe_svm_range_debug(svm_range, "PREFETCH - RANGE IS VALID"); goto check_next_range; + } err = xa_alloc(&op->prefetch_range.range, &i, svm_range, xa_limit_32b, @@ -2411,6 +2413,7 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_vma_ops *vops, op->prefetch_range.ranges_count++; vops->flags |= XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH; + xe_svm_range_debug(svm_range, "PREFETCH - RANGE CREATED"); check_next_range: if (range_end > xe_svm_range_end(svm_range) && xe_svm_range_end(svm_range) < xe_vma_end(vma)) { @@ -2909,6 +2912,7 @@ static int prefetch_ranges(struct xe_vm *vm, struct xe_vma_op *op) vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); return -ENODATA; } + xe_svm_range_debug(svm_range, "PREFETCH - RANGE MIGRATED TO VRAM"); } err = xe_svm_range_get_pages(vm, svm_range, &ctx); @@ -2919,6 +2923,7 @@ static int prefetch_ranges(struct xe_vm *vm, struct xe_vma_op *op) vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); return err; } + xe_svm_range_debug(svm_range, "PREFETCH - RANGE GET PAGES DONE"); } return err; -- GitLab From b86babc9d92f0a5fbbc7ab4c7d09bce688f94ebf Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 13 May 2025 00:00:17 +0200 Subject: [PATCH 0084/1479] drm/xe/guc: Unblock GuC buffer cache for all modes Today we were using GuC buffer cache only in the PF mode, but shortly we will want to use it also in native and VF mode. Signed-off-by: Michal Wajdeczko Cc: Daniele Ceraolo Spurio Reviewed-by: Matthew Brost Reviewed-by: Daniele Ceraolo Spurio Link: https://lore.kernel.org/r/20250512220018.172-2-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_guc.c | 4 ++++ drivers/gpu/drm/xe/xe_guc_buf.c | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c index bac5471a1a780..350434a8b9537 100644 --- a/drivers/gpu/drm/xe/xe_guc.c +++ b/drivers/gpu/drm/xe/xe_guc.c @@ -710,6 +710,10 @@ static int vf_guc_init_post_hwconfig(struct xe_guc *guc) if (err) return err; + err = xe_guc_buf_cache_init(&guc->buf); + if (err) + return err; + /* XXX xe_guc_db_mgr_init not needed for now */ return 0; diff --git a/drivers/gpu/drm/xe/xe_guc_buf.c b/drivers/gpu/drm/xe/xe_guc_buf.c index 0193c94dd6a00..14a07dca48e7b 100644 --- a/drivers/gpu/drm/xe/xe_guc_buf.c +++ b/drivers/gpu/drm/xe/xe_guc_buf.c @@ -37,10 +37,6 @@ int xe_guc_buf_cache_init(struct xe_guc_buf_cache *cache) struct xe_gt *gt = cache_to_gt(cache); struct xe_sa_manager *sam; - /* XXX: currently it's useful only for the PF actions */ - if (!IS_SRIOV_PF(gt_to_xe(gt))) - return 0; - sam = __xe_sa_bo_manager_init(gt_to_tile(gt), SZ_8K, 0, sizeof(u32)); if (IS_ERR(sam)) return PTR_ERR(sam); -- GitLab From 3dbab383e3afe999d9e9513cd9a67883b6750358 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 13 May 2025 00:00:18 +0200 Subject: [PATCH 0085/1479] drm/xe/guc: Don't allocate managed BO for each policy change We shouldn't use xe_managed_bo_create_from_data() to allocate temporary BO, as it will be released only on unload and every change in wedge_mode policy will consume resources (including precious GGTT). Instead just switchover to GuC buffer cache. Signed-off-by: Michal Wajdeczko Cc: John Harrison Cc: Rodrigo Vivi Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250512220018.172-3-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_guc_ads.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_ads.c b/drivers/gpu/drm/xe/xe_guc_ads.c index 44c1fa2fe7c85..07a0277556271 100644 --- a/drivers/gpu/drm/xe/xe_guc_ads.c +++ b/drivers/gpu/drm/xe/xe_guc_ads.c @@ -20,6 +20,7 @@ #include "xe_gt_ccs_mode.h" #include "xe_gt_printk.h" #include "xe_guc.h" +#include "xe_guc_buf.h" #include "xe_guc_capture.h" #include "xe_guc_ct.h" #include "xe_hw_engine.h" @@ -994,6 +995,16 @@ static int guc_ads_action_update_policies(struct xe_guc_ads *ads, u32 policy_off return xe_guc_ct_send(ct, action, ARRAY_SIZE(action), 0, 0); } +static int guc_ads_update_policies(struct xe_guc_ads *ads, const struct guc_policies *policies) +{ + CLASS(xe_guc_buf_from_data, buf)(&ads_to_guc(ads)->buf, policies, sizeof(*policies)); + + if (!xe_guc_buf_is_valid(buf)) + return -ENOBUFS; + + return guc_ads_action_update_policies(ads, xe_guc_buf_flush(buf)); +} + /** * xe_guc_ads_scheduler_policy_toggle_reset - Toggle reset policy * @ads: Additional data structures object @@ -1005,11 +1016,8 @@ static int guc_ads_action_update_policies(struct xe_guc_ads *ads, u32 policy_off int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads) { struct xe_device *xe = ads_to_xe(ads); - struct xe_gt *gt = ads_to_gt(ads); - struct xe_tile *tile = gt_to_tile(gt); struct guc_policies *policies; - struct xe_bo *bo; - int ret = 0; + int ret; policies = kmalloc(sizeof(*policies), GFP_KERNEL); if (!policies) @@ -1023,16 +1031,7 @@ int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads) else policies->global_flags &= ~GLOBAL_POLICY_DISABLE_ENGINE_RESET; - bo = xe_managed_bo_create_from_data(xe, tile, policies, sizeof(struct guc_policies), - XE_BO_FLAG_VRAM_IF_DGFX(tile) | - XE_BO_FLAG_GGTT); - if (IS_ERR(bo)) { - ret = PTR_ERR(bo); - goto out; - } - - ret = guc_ads_action_update_policies(ads, xe_bo_ggtt_addr(bo)); -out: + ret = guc_ads_update_policies(ads, policies); kfree(policies); return ret; } -- GitLab From 4963049ea1aed7b5aefe164867e0312185e878bc Mon Sep 17 00:00:00 2001 From: Ryosuke Yasuoka Date: Sun, 27 Apr 2025 19:18:23 +0900 Subject: [PATCH 0086/1479] drm/hyperv: Replace simple-KMS with regular atomic helpers Drop simple-KMS in favor of regular atomic helpers to make the code more modular. The simple-KMS helper mix up plane and CRTC state, so it is obsolete and should go away [1]. Since it just split the simple-pipe functions into per-plane and per-CRTC, no functional changes is expected. [1] https://lore.kernel.org/lkml/dae5089d-e214-4518-b927-5c4149babad8@suse.de/ Acked-by: Javier Martinez Canillas Signed-off-by: Ryosuke Yasuoka Link: https://lore.kernel.org/r/20250427101825.812766-1-ryasuoka@redhat.com Signed-off-by: Jocelyn Falempe --- drivers/gpu/drm/hyperv/hyperv_drm.h | 4 +- drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 172 +++++++++++++------- 2 files changed, 115 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/hyperv/hyperv_drm.h b/drivers/gpu/drm/hyperv/hyperv_drm.h index d2d8582b36df9..9e776112c03ec 100644 --- a/drivers/gpu/drm/hyperv/hyperv_drm.h +++ b/drivers/gpu/drm/hyperv/hyperv_drm.h @@ -11,7 +11,9 @@ struct hyperv_drm_device { /* drm */ struct drm_device dev; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; struct drm_connector connector; /* mode */ diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c index 6c6b572987973..f7d2e973f79ee 100644 --- a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c +++ b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c @@ -5,6 +5,8 @@ #include +#include +#include #include #include #include @@ -15,7 +17,7 @@ #include #include #include -#include +#include #include "hyperv_drm.h" @@ -38,18 +40,6 @@ static int hyperv_blit_to_vram_rect(struct drm_framebuffer *fb, return 0; } -static int hyperv_blit_to_vram_fullscreen(struct drm_framebuffer *fb, - const struct iosys_map *map) -{ - struct drm_rect fullscreen = { - .x1 = 0, - .x2 = fb->width, - .y1 = 0, - .y2 = fb->height, - }; - return hyperv_blit_to_vram_rect(fb, map, &fullscreen); -} - static int hyperv_connector_get_modes(struct drm_connector *connector) { struct hyperv_drm_device *hv = to_hv(connector->dev); @@ -98,30 +88,66 @@ static int hyperv_check_size(struct hyperv_drm_device *hv, int w, int h, return 0; } -static void hyperv_pipe_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) +static const uint32_t hyperv_formats[] = { + DRM_FORMAT_XRGB8888, +}; + +static const uint64_t hyperv_modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + +static void hyperv_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_state *state) { - struct hyperv_drm_device *hv = to_hv(pipe->crtc.dev); - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); + struct hyperv_drm_device *hv = to_hv(crtc->dev); + struct drm_plane *plane = &hv->plane; + struct drm_plane_state *plane_state = plane->state; + struct drm_crtc_state *crtc_state = crtc->state; hyperv_hide_hw_ptr(hv->hdev); hyperv_update_situation(hv->hdev, 1, hv->screen_depth, crtc_state->mode.hdisplay, crtc_state->mode.vdisplay, plane_state->fb->pitches[0]); - hyperv_blit_to_vram_fullscreen(plane_state->fb, &shadow_plane_state->data[0]); } -static int hyperv_pipe_check(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *plane_state, - struct drm_crtc_state *crtc_state) +static const struct drm_crtc_helper_funcs hyperv_crtc_helper_funcs = { + .atomic_check = drm_crtc_helper_atomic_check, + .atomic_enable = hyperv_crtc_helper_atomic_enable, +}; + +static const struct drm_crtc_funcs hyperv_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static int hyperv_plane_atomic_check(struct drm_plane *plane, + struct drm_atomic_state *state) { - struct hyperv_drm_device *hv = to_hv(pipe->crtc.dev); + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); + struct hyperv_drm_device *hv = to_hv(plane->dev); struct drm_framebuffer *fb = plane_state->fb; + struct drm_crtc *crtc = plane_state->crtc; + struct drm_crtc_state *crtc_state = NULL; + int ret; - if (fb->format->format != DRM_FORMAT_XRGB8888) - return -EINVAL; + if (crtc) + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + + ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + false, false); + if (ret) + return ret; + + if (!plane_state->visible) + return 0; if (fb->pitches[0] * fb->height > hv->fb_size) { drm_err(&hv->dev, "fb size requested by %s for %dX%d (pitch %d) greater than %ld\n", @@ -132,53 +158,85 @@ static int hyperv_pipe_check(struct drm_simple_display_pipe *pipe, return 0; } -static void hyperv_pipe_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_state) +static void hyperv_plane_atomic_update(struct drm_plane *plane, + struct drm_atomic_state *state) { - struct hyperv_drm_device *hv = to_hv(pipe->crtc.dev); - struct drm_plane_state *state = pipe->plane.state; - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state); - struct drm_rect rect; - - if (drm_atomic_helper_damage_merged(old_state, state, &rect)) { - hyperv_blit_to_vram_rect(state->fb, &shadow_plane_state->data[0], &rect); - hyperv_update_dirt(hv->hdev, &rect); + struct hyperv_drm_device *hv = to_hv(plane->dev); + struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane); + struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(new_state); + struct drm_rect damage; + struct drm_rect dst_clip; + struct drm_atomic_helper_damage_iter iter; + + drm_atomic_helper_damage_iter_init(&iter, old_state, new_state); + drm_atomic_for_each_plane_damage(&iter, &damage) { + dst_clip = new_state->dst; + + if (!drm_rect_intersect(&dst_clip, &damage)) + continue; + + hyperv_blit_to_vram_rect(new_state->fb, &shadow_plane_state->data[0], &damage); + hyperv_update_dirt(hv->hdev, &damage); } } -static const struct drm_simple_display_pipe_funcs hyperv_pipe_funcs = { - .enable = hyperv_pipe_enable, - .check = hyperv_pipe_check, - .update = hyperv_pipe_update, - DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS, +static const struct drm_plane_helper_funcs hyperv_plane_helper_funcs = { + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, + .atomic_check = hyperv_plane_atomic_check, + .atomic_update = hyperv_plane_atomic_update, }; -static const uint32_t hyperv_formats[] = { - DRM_FORMAT_XRGB8888, +static const struct drm_plane_funcs hyperv_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + DRM_GEM_SHADOW_PLANE_FUNCS, }; -static const uint64_t hyperv_modifiers[] = { - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_MOD_INVALID +static const struct drm_encoder_funcs hyperv_drm_simple_encoder_funcs_cleanup = { + .destroy = drm_encoder_cleanup, }; static inline int hyperv_pipe_init(struct hyperv_drm_device *hv) { + struct drm_device *dev = &hv->dev; + struct drm_encoder *encoder = &hv->encoder; + struct drm_plane *plane = &hv->plane; + struct drm_crtc *crtc = &hv->crtc; + struct drm_connector *connector = &hv->connector; int ret; - ret = drm_simple_display_pipe_init(&hv->dev, - &hv->pipe, - &hyperv_pipe_funcs, - hyperv_formats, - ARRAY_SIZE(hyperv_formats), - hyperv_modifiers, - &hv->connector); + ret = drm_universal_plane_init(dev, plane, 0, + &hyperv_plane_funcs, + hyperv_formats, ARRAY_SIZE(hyperv_formats), + hyperv_modifiers, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + return ret; + drm_plane_helper_add(plane, &hyperv_plane_helper_funcs); + drm_plane_enable_fb_damage_clips(plane); + + ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, + &hyperv_crtc_funcs, NULL); if (ret) return ret; + drm_crtc_helper_add(crtc, &hyperv_crtc_helper_funcs); - drm_plane_enable_fb_damage_clips(&hv->pipe.plane); + encoder->possible_crtcs = drm_crtc_mask(crtc); + ret = drm_encoder_init(dev, encoder, + &hyperv_drm_simple_encoder_funcs_cleanup, + DRM_MODE_ENCODER_NONE, NULL); + if (ret) + return ret; - return 0; + ret = hyperv_conn_init(hv); + if (ret) { + drm_err(dev, "Failed to initialized connector.\n"); + return ret; + } + + return drm_connector_attach_encoder(connector, encoder); } static enum drm_mode_status @@ -221,12 +279,6 @@ int hyperv_mode_config_init(struct hyperv_drm_device *hv) dev->mode_config.funcs = &hyperv_mode_config_funcs; - ret = hyperv_conn_init(hv); - if (ret) { - drm_err(dev, "Failed to initialized connector.\n"); - return ret; - } - ret = hyperv_pipe_init(hv); if (ret) { drm_err(dev, "Failed to initialized pipe.\n"); -- GitLab From 549810e918155cc00d65d44ed3e7d2bd0aa89df9 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 15 May 2025 10:49:56 +0100 Subject: [PATCH 0087/1479] dma-fence: Change signature of __dma_fence_is_later MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the goal of reducing the need for drivers to touch (and dereference) fence->ops, we change the prototype of __dma_fence_is_later() to take fence instead of fence->ops. Signed-off-by: Tvrtko Ursulin Reviewed-by: Christian König Link: https://lore.kernel.org/r/20250515095004.28318-2-tvrtko.ursulin@igalia.com Signed-off-by: Christian König --- drivers/dma-buf/dma-fence-chain.c | 2 +- drivers/dma-buf/sw_sync.c | 2 +- drivers/gpu/drm/xe/xe_hw_fence.c | 2 +- drivers/gpu/drm/xe/xe_sched_job.c | 14 ++++++++------ include/linux/dma-fence.h | 9 ++++----- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/dma-buf/dma-fence-chain.c b/drivers/dma-buf/dma-fence-chain.c index 9663ba1bb6ac3..90424f23fd733 100644 --- a/drivers/dma-buf/dma-fence-chain.c +++ b/drivers/dma-buf/dma-fence-chain.c @@ -252,7 +252,7 @@ void dma_fence_chain_init(struct dma_fence_chain *chain, chain->prev_seqno = 0; /* Try to reuse the context of the previous chain node. */ - if (prev_chain && __dma_fence_is_later(seqno, prev->seqno, prev->ops)) { + if (prev_chain && __dma_fence_is_later(prev, seqno, prev->seqno)) { context = prev->context; chain->prev_seqno = prev->seqno; } else { diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 4f27ee93a00c2..3c20f1d31cf54 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -170,7 +170,7 @@ static bool timeline_fence_signaled(struct dma_fence *fence) { struct sync_timeline *parent = dma_fence_parent(fence); - return !__dma_fence_is_later(fence->seqno, parent->value, fence->ops); + return !__dma_fence_is_later(fence, fence->seqno, parent->value); } static void timeline_fence_set_deadline(struct dma_fence *fence, ktime_t deadline) diff --git a/drivers/gpu/drm/xe/xe_hw_fence.c b/drivers/gpu/drm/xe/xe_hw_fence.c index 0b4f12be3692a..03eb8c6d16169 100644 --- a/drivers/gpu/drm/xe/xe_hw_fence.c +++ b/drivers/gpu/drm/xe/xe_hw_fence.c @@ -165,7 +165,7 @@ static bool xe_hw_fence_signaled(struct dma_fence *dma_fence) u32 seqno = xe_map_rd(xe, &fence->seqno_map, 0, u32); return dma_fence->error || - !__dma_fence_is_later(dma_fence->seqno, seqno, dma_fence->ops); + !__dma_fence_is_later(dma_fence, dma_fence->seqno, seqno); } static bool xe_hw_fence_enable_signaling(struct dma_fence *dma_fence) diff --git a/drivers/gpu/drm/xe/xe_sched_job.c b/drivers/gpu/drm/xe/xe_sched_job.c index 1905ca5909658..f0a6ce610948b 100644 --- a/drivers/gpu/drm/xe/xe_sched_job.c +++ b/drivers/gpu/drm/xe/xe_sched_job.c @@ -216,15 +216,17 @@ void xe_sched_job_set_error(struct xe_sched_job *job, int error) bool xe_sched_job_started(struct xe_sched_job *job) { + struct dma_fence *fence = dma_fence_chain_contained(job->fence); struct xe_lrc *lrc = job->q->lrc[0]; - return !__dma_fence_is_later(xe_sched_job_lrc_seqno(job), - xe_lrc_start_seqno(lrc), - dma_fence_chain_contained(job->fence)->ops); + return !__dma_fence_is_later(fence, + xe_sched_job_lrc_seqno(job), + xe_lrc_start_seqno(lrc)); } bool xe_sched_job_completed(struct xe_sched_job *job) { + struct dma_fence *fence = dma_fence_chain_contained(job->fence); struct xe_lrc *lrc = job->q->lrc[0]; /* @@ -232,9 +234,9 @@ bool xe_sched_job_completed(struct xe_sched_job *job) * parallel handshake is done. */ - return !__dma_fence_is_later(xe_sched_job_lrc_seqno(job), - xe_lrc_seqno(lrc), - dma_fence_chain_contained(job->fence)->ops); + return !__dma_fence_is_later(fence, + xe_sched_job_lrc_seqno(job), + xe_lrc_seqno(lrc)); } void xe_sched_job_arm(struct xe_sched_job *job) diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h index b12776883d143..48b5202c531d3 100644 --- a/include/linux/dma-fence.h +++ b/include/linux/dma-fence.h @@ -441,21 +441,20 @@ dma_fence_is_signaled(struct dma_fence *fence) /** * __dma_fence_is_later - return if f1 is chronologically later than f2 + * @fence: fence in whose context to do the comparison * @f1: the first fence's seqno * @f2: the second fence's seqno from the same context - * @ops: dma_fence_ops associated with the seqno * * Returns true if f1 is chronologically later than f2. Both fences must be * from the same context, since a seqno is not common across contexts. */ -static inline bool __dma_fence_is_later(u64 f1, u64 f2, - const struct dma_fence_ops *ops) +static inline bool __dma_fence_is_later(struct dma_fence *fence, u64 f1, u64 f2) { /* This is for backward compatibility with drivers which can only handle * 32bit sequence numbers. Use a 64bit compare when the driver says to * do so. */ - if (ops->use_64bit_seqno) + if (fence->ops->use_64bit_seqno) return f1 > f2; return (int)(lower_32_bits(f1) - lower_32_bits(f2)) > 0; @@ -475,7 +474,7 @@ static inline bool dma_fence_is_later(struct dma_fence *f1, if (WARN_ON(f1->context != f2->context)) return false; - return __dma_fence_is_later(f1->seqno, f2->seqno, f1->ops); + return __dma_fence_is_later(f1, f1->seqno, f2->seqno); } /** -- GitLab From eaa287069a70aa80e5e95d5162445962809d8158 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 13 May 2025 07:25:49 -0700 Subject: [PATCH 0088/1479] drm/xe/guc_submit: Simplify and fix diff calculation With a u32 type, there's no need to check which one is greater: the current is always the latest and if it's less than the previous, it's because it wrapped: just do the unsigned calculation that will lead to the same result, or better the correct one. It fixes an off-by-one in the wrapped calculation, however that doesn't really matter for the timeout calculation. Reviewed-by: Raag Jadav Reviewed-by: Umesh Nerlige Ramappa Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20250513-time-wrap-v1-1-fba9a69a65c8@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_guc_submit.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index fb125f940de8f..80f748baad3f3 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -976,10 +976,7 @@ static bool check_timeout(struct xe_exec_queue *q, struct xe_sched_job *job) */ xe_gt_assert(gt, timeout_ms < 100 * MSEC_PER_SEC); - if (ctx_timestamp < ctx_job_timestamp) - diff = ctx_timestamp + U32_MAX - ctx_job_timestamp; - else - diff = ctx_timestamp - ctx_job_timestamp; + diff = ctx_timestamp - ctx_job_timestamp; /* * Ensure timeout is within 5% to account for an GuC scheduling latency -- GitLab From d6e020819612a4a06207af858e0978be4d3e3140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 12 May 2025 21:22:15 +0200 Subject: [PATCH 0089/1479] drm/i915/gem: Allow EXEC_CAPTURE on recoverable contexts on DG1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The intel-media-driver is currently broken on DG1 because it uses EXEC_CAPTURE with recovarable contexts. Relax the check to allow that. I've also submitted a fix for the intel-media-driver: https://github.com/intel/media-driver/pull/1920 Cc: stable@vger.kernel.org # v6.0+ Cc: Matthew Auld Cc: Thomas Hellström Testcase: igt/gem_exec_capture/capture-invisible Fixes: 71b1669ea9bd ("drm/i915/uapi: tweak error capture on recoverable contexts") Reviewed-by: Andi Shyti Signed-off-by: Ville Syrjälä Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20250411144313.11660-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 02c59808cbe48..7d44aadcd5a5c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -2013,7 +2013,7 @@ static int eb_capture_stage(struct i915_execbuffer *eb) continue; if (i915_gem_context_is_recoverable(eb->gem_context) && - (IS_DGFX(eb->i915) || GRAPHICS_VER_FULL(eb->i915) > IP_VER(12, 0))) + GRAPHICS_VER_FULL(eb->i915) > IP_VER(12, 10)) return -EINVAL; for_each_batch_create_order(eb, j) { -- GitLab From 9b961744a83a3027b8d4b97fe1fc587334883ce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 12 May 2025 21:22:16 +0200 Subject: [PATCH 0090/1479] drm/i915/pci: Remove force_probe requirement for DG1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dunno why we still have .require_force_probe=1 on DG1 after all this time. I'm not aware of any real problems with DG1, so get rid of the force_probe requirement. Generally the difficulty with DG1 is that it requires a 4GiB BAR for the local memory, and that's not something that works on every system. Reviewed-by: Andi Shyti Signed-off-by: Ville Syrjälä Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20250411144313.11660-3-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_pci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 21006c7f615c2..b2e311f4791a0 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -663,7 +663,6 @@ static const struct intel_device_info dg1_info = { DGFX_FEATURES, .__runtime.graphics.ip.rel = 10, PLATFORM(INTEL_DG1), - .require_force_probe = 1, .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0) | BIT(VCS2), -- GitLab From fddf8cdd4b9b7373f32f77e7a89123394e630188 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 12 May 2025 14:53:21 -0700 Subject: [PATCH 0091/1479] drm/xe/guc: Remove double blank line An earlier patch moved a drm_print a few lines lower but accidentally left a double blank line behind. So fix that. Signed-off-by: John Harrison Reviewed-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250512215324.1457009-2-John.C.Harrison@Intel.com --- drivers/gpu/drm/xe/xe_guc_ct.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c index ff6edf1b14f49..b09dd5788a270 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.c +++ b/drivers/gpu/drm/xe/xe_guc_ct.c @@ -2013,7 +2013,6 @@ static void ct_dead_print(struct xe_dead_ct *dead) return; } - /* Can't generate a genuine core dump at this point, so just do the good bits */ drm_puts(&lp, "**** Xe Device Coredump ****\n"); drm_printf(&lp, "Reason: CTB is dead - 0x%X\n", dead->reason); -- GitLab From 12373b30e27cffd4244453ed3bceb52504d7563f Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 12 May 2025 14:53:22 -0700 Subject: [PATCH 0092/1479] drm/xe/guc: Add missing H2G error code definitions These error codes are not actually used in the driver but it is extremely useful to have them available to understand error messages. v2: Add a bunch more error codes and drop 'status' from names (review feedback by Michal W). v3: Drop 'SUCCESS' response as meaningless in current API (review feedback by Michal W). Signed-off-by: John Harrison Reviewed-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250512215324.1457009-3-John.C.Harrison@Intel.com --- drivers/gpu/drm/xe/abi/guc_errors_abi.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/abi/guc_errors_abi.h b/drivers/gpu/drm/xe/abi/guc_errors_abi.h index 2c627a21648f7..ecf748fd87df3 100644 --- a/drivers/gpu/drm/xe/abi/guc_errors_abi.h +++ b/drivers/gpu/drm/xe/abi/guc_errors_abi.h @@ -6,8 +6,7 @@ #ifndef _ABI_GUC_ERRORS_ABI_H #define _ABI_GUC_ERRORS_ABI_H -enum xe_guc_response_status { - XE_GUC_RESPONSE_STATUS_SUCCESS = 0x0, +enum xe_guc_response { XE_GUC_RESPONSE_ERROR_PROTOCOL = 0x04, XE_GUC_RESPONSE_INVALID_STATE = 0x0A, XE_GUC_RESPONSE_UNSUPPORTED_VERSION = 0x0B, @@ -21,12 +20,20 @@ enum xe_guc_response_status { XE_GUC_RESPONSE_CANNOT_COMPLETE_ACTION = 0x41, XE_GUC_RESPONSE_INVALID_KLV_DATA = 0x50, XE_GUC_RESPONSE_INVALID_PARAMS = 0x60, + XE_GUC_RESPONSE_INVALID_CONTEXT_INDEX = 0x61, + XE_GUC_RESPONSE_INVALID_CONTEXT_REGISTRATION = 0x62, + XE_GUC_RESPONSE_INVALID_DOORBELL_ID = 0x63, + XE_GUC_RESPONSE_INVALID_ENGINE_ID = 0x64, XE_GUC_RESPONSE_INVALID_BUFFER_RANGE = 0x70, XE_GUC_RESPONSE_INVALID_BUFFER = 0x71, + XE_GUC_RESPONSE_BUFFER_ALREADY_REGISTERED = 0x72, XE_GUC_RESPONSE_INVALID_GGTT_ADDRESS = 0x80, XE_GUC_RESPONSE_PENDING_ACTION = 0x90, + XE_GUC_RESPONSE_CONTEXT_NOT_REGISTERED = 0x100, + XE_GUC_RESPONSE_CONTEXT_ALREADY_REGISTERED = 0X101, XE_GUC_RESPONSE_INVALID_SIZE = 0x102, XE_GUC_RESPONSE_MALFORMED_KLV = 0x103, + XE_GUC_RESPONSE_INVALID_CONTEXT = 0x104, XE_GUC_RESPONSE_INVALID_KLV_KEY = 0x105, XE_GUC_RESPONSE_DATA_TOO_LARGE = 0x106, XE_GUC_RESPONSE_VF_MIGRATED = 0x107, @@ -40,10 +47,11 @@ enum xe_guc_response_status { XE_GUC_RESPONSE_CTB_NOT_REGISTERED = 0x304, XE_GUC_RESPONSE_CTB_IN_USE = 0x305, XE_GUC_RESPONSE_CTB_INVALID_DESC = 0x306, + XE_GUC_RESPONSE_HW_TIMEOUT = 0x30C, XE_GUC_RESPONSE_CTB_SOURCE_INVALID_DESCRIPTOR = 0x30D, XE_GUC_RESPONSE_CTB_DESTINATION_INVALID_DESCRIPTOR = 0x30E, XE_GUC_RESPONSE_INVALID_CONFIG_STATE = 0x30F, - XE_GUC_RESPONSE_STATUS_GENERIC_FAIL = 0xF000, + XE_GUC_RESPONSE_GENERIC_FAIL = 0xF000, }; enum xe_guc_load_status { -- GitLab From d7d97890e2a7e3e306494dcbfb0e468a5089380d Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 12 May 2025 14:53:23 -0700 Subject: [PATCH 0093/1479] drm/xe/guc: Rename CONFIG_XE_LARGE_GUC_BUFFER Rename XE_LARGE_GUC_BUFFER to XE_DEBUG_GUC to allow for more debug only code (in subsequent patch) without adding more config defines that each control only a single thing. Signed-off-by: John Harrison Reviewed-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250512215324.1457009-4-John.C.Harrison@Intel.com --- drivers/gpu/drm/xe/Kconfig.debug | 8 +++++--- drivers/gpu/drm/xe/xe_guc_log.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/Kconfig.debug b/drivers/gpu/drm/xe/Kconfig.debug index 0d749ed448786..db063a513b1e5 100644 --- a/drivers/gpu/drm/xe/Kconfig.debug +++ b/drivers/gpu/drm/xe/Kconfig.debug @@ -86,12 +86,14 @@ config DRM_XE_KUNIT_TEST If in doubt, say "N". -config DRM_XE_LARGE_GUC_BUFFER - bool "Enable larger guc log buffer" +config DRM_XE_DEBUG_GUC + bool "Enable extra GuC related debug options" + depends on DRM_XE_DEBUG default n help Choose this option when debugging guc issues. - Buffer should be large enough for complex issues. + The GuC log buffer is increased to the maximum allowed, which should + be large enough for complex issues. Recommended for driver developers only. diff --git a/drivers/gpu/drm/xe/xe_guc_log.h b/drivers/gpu/drm/xe/xe_guc_log.h index 5b896f5fafafa..f1e2b0be90a9f 100644 --- a/drivers/gpu/drm/xe/xe_guc_log.h +++ b/drivers/gpu/drm/xe/xe_guc_log.h @@ -12,7 +12,7 @@ struct drm_printer; struct xe_device; -#if IS_ENABLED(CONFIG_DRM_XE_LARGE_GUC_BUFFER) +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC) #define CRASH_BUFFER_SIZE SZ_1M #define DEBUG_BUFFER_SIZE SZ_8M #define CAPTURE_BUFFER_SIZE SZ_2M -- GitLab From 16b7e65d299d56442879405ac85800877fa51355 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 12 May 2025 14:53:24 -0700 Subject: [PATCH 0094/1479] drm/xe/guc: Track FAST_REQ H2Gs to report where errors came from Most H2G messages are FAST_REQ which means no synchronous response is expected. The messages are sent as fire-and-forget with no tracking. However, errors can still be returned when something goes unexpectedly wrong. That leads to confusion due to not being able to match up the error response to the originating H2G. So add support for tracking the FAST_REQ H2Gs and matching up an error response to its originator. This is only enabled in XE_DEBUG builds given that such errors should never happen in a working system and there is an overhead for the tracking. Further, if XE_DEBUG_GUC is enabled then even more memory and time is used to record the call stack of each H2G and report that with the error. That makes it much easier to work out where a specific H2G came from if there are multiple code paths that can send it. v2: Some re-wording of comments and prints, more consistent use of #if vs stub functions - review feedback from Daniele & Michal). v3: Split config change to separate patch, improve a debug print (review feedback from Michal). v4: Bunch of minor tweaks (review feedback from Michal). Original-i915-code: Michal Wajdeczko Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio Reviewed-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250512215324.1457009-5-John.C.Harrison@Intel.com --- drivers/gpu/drm/xe/Kconfig.debug | 5 +- drivers/gpu/drm/xe/xe_guc_ct.c | 115 ++++++++++++++++++++++----- drivers/gpu/drm/xe/xe_guc_ct_types.h | 15 ++++ 3 files changed, 115 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/xe/Kconfig.debug b/drivers/gpu/drm/xe/Kconfig.debug index db063a513b1e5..01735c6ece8ba 100644 --- a/drivers/gpu/drm/xe/Kconfig.debug +++ b/drivers/gpu/drm/xe/Kconfig.debug @@ -90,10 +90,13 @@ config DRM_XE_DEBUG_GUC bool "Enable extra GuC related debug options" depends on DRM_XE_DEBUG default n + select STACKDEPOT help Choose this option when debugging guc issues. The GuC log buffer is increased to the maximum allowed, which should - be large enough for complex issues. + be large enough for complex issues. The tracking of FAST_REQ messages + is extended to include a record of the calling stack, which is then + dumped on a FAST_REQ error notification. Recommended for driver developers only. diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c index b09dd5788a270..822f4c33f7305 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.c +++ b/drivers/gpu/drm/xe/xe_guc_ct.c @@ -628,6 +628,47 @@ static void g2h_release_space(struct xe_guc_ct *ct, u32 g2h_len) spin_unlock_irq(&ct->fast_lock); } +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG) +static void fast_req_track(struct xe_guc_ct *ct, u16 fence, u16 action) +{ + unsigned int slot = fence % ARRAY_SIZE(ct->fast_req); +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC) + unsigned long entries[SZ_32]; + unsigned int n; + + n = stack_trace_save(entries, ARRAY_SIZE(entries), 1); + + /* May be called under spinlock, so avoid sleeping */ + ct->fast_req[slot].stack = stack_depot_save(entries, n, GFP_NOWAIT); +#endif + ct->fast_req[slot].fence = fence; + ct->fast_req[slot].action = action; +} +#else +static void fast_req_track(struct xe_guc_ct *ct, u16 fence, u16 action) +{ +} +#endif + +/* + * The CT protocol accepts a 16 bits fence. This field is fully owned by the + * driver, the GuC will just copy it to the reply message. Since we need to + * be able to distinguish between replies to REQUEST and FAST_REQUEST messages, + * we use one bit of the seqno as an indicator for that and a rolling counter + * for the remaining 15 bits. + */ +#define CT_SEQNO_MASK GENMASK(14, 0) +#define CT_SEQNO_UNTRACKED BIT(15) +static u16 next_ct_seqno(struct xe_guc_ct *ct, bool is_g2h_fence) +{ + u32 seqno = ct->fence_seqno++ & CT_SEQNO_MASK; + + if (!is_g2h_fence) + seqno |= CT_SEQNO_UNTRACKED; + + return seqno; +} + #define H2G_CT_HEADERS (GUC_CTB_HDR_LEN + 1) /* one DW CTB header and one DW HxG header */ static int h2g_write(struct xe_guc_ct *ct, const u32 *action, u32 len, @@ -704,6 +745,9 @@ static int h2g_write(struct xe_guc_ct *ct, const u32 *action, u32 len, FIELD_PREP(GUC_HXG_EVENT_MSG_0_ACTION | GUC_HXG_EVENT_MSG_0_DATA0, action[0]); } else { + fast_req_track(ct, ct_fence_value, + FIELD_GET(GUC_HXG_EVENT_MSG_0_ACTION, action[0])); + cmd[1] = FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_FAST_REQUEST) | FIELD_PREP(GUC_HXG_EVENT_MSG_0_ACTION | @@ -736,25 +780,6 @@ static int h2g_write(struct xe_guc_ct *ct, const u32 *action, u32 len, return -EPIPE; } -/* - * The CT protocol accepts a 16 bits fence. This field is fully owned by the - * driver, the GuC will just copy it to the reply message. Since we need to - * be able to distinguish between replies to REQUEST and FAST_REQUEST messages, - * we use one bit of the seqno as an indicator for that and a rolling counter - * for the remaining 15 bits. - */ -#define CT_SEQNO_MASK GENMASK(14, 0) -#define CT_SEQNO_UNTRACKED BIT(15) -static u16 next_ct_seqno(struct xe_guc_ct *ct, bool is_g2h_fence) -{ - u32 seqno = ct->fence_seqno++ & CT_SEQNO_MASK; - - if (!is_g2h_fence) - seqno |= CT_SEQNO_UNTRACKED; - - return seqno; -} - static int __guc_ct_send_locked(struct xe_guc_ct *ct, const u32 *action, u32 len, u32 g2h_len, u32 num_g2h, struct g2h_fence *g2h_fence) @@ -1146,6 +1171,55 @@ static int guc_crash_process_msg(struct xe_guc_ct *ct, u32 action) return 0; } +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG) +static void fast_req_report(struct xe_guc_ct *ct, u16 fence) +{ + u16 fence_min = U16_MAX, fence_max = 0; + struct xe_gt *gt = ct_to_gt(ct); + bool found = false; + unsigned int n; +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC) + char *buf; +#endif + + lockdep_assert_held(&ct->lock); + + for (n = 0; n < ARRAY_SIZE(ct->fast_req); n++) { + if (ct->fast_req[n].fence < fence_min) + fence_min = ct->fast_req[n].fence; + if (ct->fast_req[n].fence > fence_max) + fence_max = ct->fast_req[n].fence; + + if (ct->fast_req[n].fence != fence) + continue; + found = true; + +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC) + buf = kmalloc(SZ_4K, GFP_NOWAIT); + if (buf && stack_depot_snprint(ct->fast_req[n].stack, buf, SZ_4K, 0)) + xe_gt_err(gt, "Fence 0x%x was used by action %#04x sent at:\n%s", + fence, ct->fast_req[n].action, buf); + else + xe_gt_err(gt, "Fence 0x%x was used by action %#04x [failed to retrieve stack]\n", + fence, ct->fast_req[n].action); + kfree(buf); +#else + xe_gt_err(gt, "Fence 0x%x was used by action %#04x\n", + fence, ct->fast_req[n].action); +#endif + break; + } + + if (!found) + xe_gt_warn(gt, "Fence 0x%x not found - tracking buffer wrapped? [range = 0x%x -> 0x%x, next = 0x%X]\n", + fence, fence_min, fence_max, ct->fence_seqno); +} +#else +static void fast_req_report(struct xe_guc_ct *ct, u16 fence) +{ +} +#endif + static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len) { struct xe_gt *gt = ct_to_gt(ct); @@ -1174,6 +1248,9 @@ static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len) else xe_gt_err(gt, "unexpected response %u for FAST_REQ H2G fence 0x%x!\n", type, fence); + + fast_req_report(ct, fence); + CT_DEAD(ct, NULL, PARSE_G2H_RESPONSE); return -EPROTO; diff --git a/drivers/gpu/drm/xe/xe_guc_ct_types.h b/drivers/gpu/drm/xe/xe_guc_ct_types.h index 8e1b9d981d61e..8b03b50313d9f 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct_types.h +++ b/drivers/gpu/drm/xe/xe_guc_ct_types.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -104,6 +105,18 @@ struct xe_dead_ct { /** snapshot_log: copy of GuC log at point of error */ struct xe_guc_log_snapshot *snapshot_log; }; + +/** struct xe_fast_req_fence - Used to track FAST_REQ messages by fence to match error responses */ +struct xe_fast_req_fence { + /** @fence: sequence number sent in H2G and return in G2H error */ + u16 fence; + /** @action: H2G action code */ + u16 action; +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC) + /** @stack: call stack from when the H2G was sent */ + depot_stack_handle_t stack; +#endif +}; #endif /** @@ -152,6 +165,8 @@ struct xe_guc_ct { #if IS_ENABLED(CONFIG_DRM_XE_DEBUG) /** @dead: information for debugging dead CTs */ struct xe_dead_ct dead; + /** @fast_req: history of FAST_REQ messages for matching with G2H error responses */ + struct xe_fast_req_fence fast_req[SZ_32]; #endif }; -- GitLab From ceb7b62eaaaacfcf87473bd2e99ac73a758620cb Mon Sep 17 00:00:00 2001 From: Huan Yang Date: Mon, 28 Apr 2025 15:38:29 +0800 Subject: [PATCH 0095/1479] Revert "udmabuf: fix vmap_udmabuf error page set" This reverts commit 18d7de823b7150344d242c3677e65d68c5271b04. We cannot use vmap_pfn() in vmap_udmabuf() as it would fail the pfn_valid() check in vmap_pfn_apply(). This is because vmap_pfn() is intended to be used for mapping non-struct-page memory such as PCIe BARs. Since, udmabuf mostly works with pages/folios backed by shmem/hugetlbfs/THP, vmap_pfn() is not the right tool or API to invoke for implementing vmap. Signed-off-by: Huan Yang Suggested-by: Vivek Kasireddy Reported-by: Bingbu Cao Closes: https://lore.kernel.org/dri-devel/eb7e0137-3508-4287-98c4-816c5fd98e10@vivo.com/T/#mbda4f64a3532b32e061f4e8763bc8e307bea3ca8 Acked-by: Vivek Kasireddy Signed-off-by: Vivek Kasireddy Link: https://lore.kernel.org/r/20250428073831.19942-2-link@vivo.com --- drivers/dma-buf/Kconfig | 1 - drivers/dma-buf/udmabuf.c | 22 +++++++--------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/dma-buf/Kconfig b/drivers/dma-buf/Kconfig index fee04fdb08220..b46eb8a552d7b 100644 --- a/drivers/dma-buf/Kconfig +++ b/drivers/dma-buf/Kconfig @@ -36,7 +36,6 @@ config UDMABUF depends on DMA_SHARED_BUFFER depends on MEMFD_CREATE || COMPILE_TEST depends on MMU - select VMAP_PFN help A driver to let userspace turn memfd regions into dma-bufs. Qemu can use this to create host dmabufs for guest framebuffers. diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index 7eee3eb47a8ee..79845565089da 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -109,29 +109,21 @@ static int mmap_udmabuf(struct dma_buf *buf, struct vm_area_struct *vma) static int vmap_udmabuf(struct dma_buf *buf, struct iosys_map *map) { struct udmabuf *ubuf = buf->priv; - unsigned long *pfns; + struct page **pages; void *vaddr; pgoff_t pg; dma_resv_assert_held(buf->resv); - /** - * HVO may free tail pages, so just use pfn to map each folio - * into vmalloc area. - */ - pfns = kvmalloc_array(ubuf->pagecount, sizeof(*pfns), GFP_KERNEL); - if (!pfns) + pages = kvmalloc_array(ubuf->pagecount, sizeof(*pages), GFP_KERNEL); + if (!pages) return -ENOMEM; - for (pg = 0; pg < ubuf->pagecount; pg++) { - unsigned long pfn = folio_pfn(ubuf->folios[pg]); - - pfn += ubuf->offsets[pg] >> PAGE_SHIFT; - pfns[pg] = pfn; - } + for (pg = 0; pg < ubuf->pagecount; pg++) + pages[pg] = &ubuf->folios[pg]->page; - vaddr = vmap_pfn(pfns, ubuf->pagecount, PAGE_KERNEL); - kvfree(pfns); + vaddr = vm_map_ram(pages, ubuf->pagecount, -1); + kvfree(pages); if (!vaddr) return -EINVAL; -- GitLab From a26fd92b7223160ad31c3e2971b63178faed9cf5 Mon Sep 17 00:00:00 2001 From: Huan Yang Date: Mon, 28 Apr 2025 15:38:30 +0800 Subject: [PATCH 0096/1479] udmabuf: fix vmap missed offset page Before invoke vmap, we need offer a pages pointer array which each page need to map in vmalloc area. But currently vmap_udmabuf only set each folio's head page into pages, missed each offset pages when iter. This patch set the correctly offset page in each folio into array. Signed-off-by: Huan Yang Fixes: 5e72b2b41a21 ("udmabuf: convert udmabuf driver to use folios") Acked-by: Vivek Kasireddy Signed-off-by: Vivek Kasireddy Link: https://lore.kernel.org/r/20250428073831.19942-3-link@vivo.com --- drivers/dma-buf/udmabuf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index 79845565089da..af5200e360a6a 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -120,7 +120,8 @@ static int vmap_udmabuf(struct dma_buf *buf, struct iosys_map *map) return -ENOMEM; for (pg = 0; pg < ubuf->pagecount; pg++) - pages[pg] = &ubuf->folios[pg]->page; + pages[pg] = folio_page(ubuf->folios[pg], + ubuf->offsets[pg] >> PAGE_SHIFT); vaddr = vm_map_ram(pages, ubuf->pagecount, -1); kvfree(pages); -- GitLab From 5779b26aafeebb177430f9b56832fcf716f32c53 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 May 2025 12:38:33 +0300 Subject: [PATCH 0097/1479] drm/xe/rpm: use to_xe_device() instead of container_of Drop the dependency on display being a sub-struct of xe_device. Reviewed-by: Gustavo Sousa Signed-off-by: Jani Nikula Link: https://lore.kernel.org/r/3528f2cd5965e97248c161b8aa25a9df69606a39.1746610601.git.jani.nikula@intel.com --- drivers/gpu/drm/xe/display/xe_display_rpm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/display/xe_display_rpm.c b/drivers/gpu/drm/xe/display/xe_display_rpm.c index 1955153aadba0..ef76efe42e9f8 100644 --- a/drivers/gpu/drm/xe/display/xe_display_rpm.c +++ b/drivers/gpu/drm/xe/display/xe_display_rpm.c @@ -2,12 +2,13 @@ /* Copyright © 2025 Intel Corporation */ #include "intel_display_rpm.h" +#include "xe_device.h" #include "xe_device_types.h" #include "xe_pm.h" static struct xe_device *display_to_xe(struct intel_display *display) { - return container_of(display, struct xe_device, display); + return to_xe_device(display->drm); } struct ref_tracker *intel_display_rpm_get_raw(struct intel_display *display) -- GitLab From bfd43f9d1e858667f34fd5d7e6dafa5ba97986be Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 May 2025 12:38:34 +0300 Subject: [PATCH 0098/1479] drm/xe/display: do not reference xe->display inline Always use a local variable for display instead of referencing xe->display inline. This makes it easier to convert xe->display into a pointer. Reviewed-by: Gustavo Sousa Signed-off-by: Jani Nikula Link: https://lore.kernel.org/r/c99483ad86022d02f780bac73445baaf27a6edce.1746610601.git.jani.nikula@intel.com --- drivers/gpu/drm/xe/display/xe_display.c | 15 ++++++++++----- drivers/gpu/drm/xe/display/xe_fb_pin.c | 5 +++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 68f064f33d4b8..b8030492fbd10 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -38,7 +38,9 @@ static bool has_display(struct xe_device *xe) { - return HAS_DISPLAY(&xe->display); + struct intel_display *display = &xe->display; + + return HAS_DISPLAY(display); } /** @@ -84,8 +86,9 @@ static void unset_display_features(struct xe_device *xe) static void display_destroy(struct drm_device *dev, void *dummy) { struct xe_device *xe = to_xe_device(dev); + struct intel_display *display = &xe->display; - destroy_workqueue(xe->display.hotplug.dp_wq); + destroy_workqueue(display->hotplug.dp_wq); } /** @@ -101,9 +104,11 @@ static void display_destroy(struct drm_device *dev, void *dummy) */ int xe_display_create(struct xe_device *xe) { - spin_lock_init(&xe->display.fb_tracking.lock); + struct intel_display *display = &xe->display; + + spin_lock_init(&display->fb_tracking.lock); - xe->display.hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0); + display->hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0); return drmm_add_action_or_reset(&xe->drm, display_destroy, NULL); } @@ -362,7 +367,7 @@ void xe_display_pm_suspend(struct xe_device *xe) if (has_display(xe)) { intel_display_driver_suspend_access(display); - intel_encoder_suspend_all(&xe->display); + intel_encoder_suspend_all(display); } intel_opregion_suspend(display, s2idle ? PCI_D1 : PCI_D3cold); diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index d918ae1c80618..e95ca979e1fe3 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -389,6 +389,7 @@ static bool reuse_vma(struct intel_plane_state *new_plane_state, { struct intel_framebuffer *fb = to_intel_framebuffer(new_plane_state->hw.fb); struct xe_device *xe = to_xe_device(fb->base.dev); + struct intel_display *display = &xe->display; struct i915_vma *vma; if (old_plane_state->hw.fb == new_plane_state->hw.fb && @@ -399,8 +400,8 @@ static bool reuse_vma(struct intel_plane_state *new_plane_state, goto found; } - if (fb == intel_fbdev_framebuffer(xe->display.fbdev.fbdev)) { - vma = intel_fbdev_vma_pointer(xe->display.fbdev.fbdev); + if (fb == intel_fbdev_framebuffer(display->fbdev.fbdev)) { + vma = intel_fbdev_vma_pointer(display->fbdev.fbdev); if (vma) goto found; } -- GitLab From 702f530a647f00cf5730cfc88e4cd0e699f22351 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 May 2025 12:38:35 +0300 Subject: [PATCH 0099/1479] drm/i915: do not reference i915->display inline Always use a local variable for display instead of referencing i915->display inline. This makes it easier to convert i915->display into a pointer. Reviewed-by: Gustavo Sousa Signed-off-by: Jani Nikula Link: https://lore.kernel.org/r/afcf305e8c4ea452cee37479530958f36a10c840.1746610601.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_driver.c | 20 ++++++++++++-------- drivers/gpu/drm/i915/intel_clock_gating.c | 3 ++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 2b0bcb9aa3c72..134a1c3d1f9d1 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -115,6 +115,8 @@ static const struct drm_driver i915_drm_driver; static int i915_workqueues_init(struct drm_i915_private *dev_priv) { + struct intel_display *display = &dev_priv->display; + /* * The i915 workqueue is primarily used for batched retirement of * requests (and thus managing bo) once the task has been completed @@ -133,8 +135,8 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv) if (dev_priv->wq == NULL) goto out_err; - dev_priv->display.hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0); - if (dev_priv->display.hotplug.dp_wq == NULL) + display->hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0); + if (!display->hotplug.dp_wq) goto out_free_wq; /* @@ -150,7 +152,7 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv) return 0; out_free_dp_wq: - destroy_workqueue(dev_priv->display.hotplug.dp_wq); + destroy_workqueue(display->hotplug.dp_wq); out_free_wq: destroy_workqueue(dev_priv->wq); out_err: @@ -161,8 +163,10 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv) static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv) { + struct intel_display *display = &dev_priv->display; + destroy_workqueue(dev_priv->unordered_wq); - destroy_workqueue(dev_priv->display.hotplug.dp_wq); + destroy_workqueue(display->hotplug.dp_wq); destroy_workqueue(dev_priv->wq); } @@ -991,10 +995,10 @@ void i915_driver_shutdown(struct drm_i915_private *i915) if (HAS_DISPLAY(i915)) intel_display_driver_suspend_access(display); - intel_encoder_suspend_all(&i915->display); - intel_encoder_shutdown_all(&i915->display); + intel_encoder_suspend_all(display); + intel_encoder_shutdown_all(display); - intel_dmc_suspend(&i915->display); + intel_dmc_suspend(display); i915_gem_suspend(i915); @@ -1074,7 +1078,7 @@ static int i915_drm_suspend(struct drm_device *dev) if (HAS_DISPLAY(dev_priv)) intel_display_driver_suspend_access(display); - intel_encoder_suspend_all(&dev_priv->display); + intel_encoder_suspend_all(display); /* Must be called before GGTT is suspended. */ intel_dpt_suspend(display); diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index 8aec8c638fd81..892b1e19d9461 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -201,6 +201,7 @@ static void ilk_init_clock_gating(struct drm_i915_private *i915) static void cpt_init_clock_gating(struct drm_i915_private *i915) { + struct intel_display *display = &i915->display; enum pipe pipe; u32 val; @@ -220,7 +221,7 @@ static void cpt_init_clock_gating(struct drm_i915_private *i915) val = intel_uncore_read(&i915->uncore, TRANS_CHICKEN2(pipe)); val |= TRANS_CHICKEN2_TIMING_OVERRIDE; val &= ~TRANS_CHICKEN2_FDI_POLARITY_REVERSED; - if (i915->display.vbt.fdi_rx_polarity_inverted) + if (display->vbt.fdi_rx_polarity_inverted) val |= TRANS_CHICKEN2_FDI_POLARITY_REVERSED; val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER; val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH; -- GitLab From 96b451d53ae9760858c547081532b01038f00912 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 7 May 2025 18:22:54 +0300 Subject: [PATCH 0100/1479] drm/{i915,xe}: convert i915 and xe display members into pointers As the first step towards making struct intel_display an opaque pointer in i915 and xe drivers, convert the struct drm_i915_private and struct xe_device display members into pointers. Initially, add temporary struct intel_display __display members, and point display at it to avoid dynamic allocation. In the future, we can drop this, and switch to dynamic allocation. The conversion is done simply with sed: sed -i 's/&\([a-zA-Z0-9_>.-]*\)\(dev_priv\|i915\|xe\)->display\([^.]\)/\1\2->display\3/g' \ $(git ls-files -- drivers/gpu/drm/i915 drivers/gpu/drm/xe) sed -i 's/\(dev_priv\|i915\|xe\)->display\./\1->display->/g' \ $(git ls-files -- drivers/gpu/drm/i915 drivers/gpu/drm/xe) With a couple of manual tweaks on top. v2: Initialize i915->display also in selftest mock_gem_device() Reviewed-by: Gustavo Sousa Signed-off-by: Jani Nikula Link: https://lore.kernel.org/r/20250507152254.2398934-1-jani.nikula@intel.com --- .../i915/display/intel_display_conversion.c | 2 +- drivers/gpu/drm/i915/display/intel_dpt.c | 2 +- drivers/gpu/drm/i915/display/intel_vbt_defs.h | 2 +- .../i915/gem/i915_gem_object_frontbuffer.h | 2 +- drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c | 2 +- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 4 +- drivers/gpu/drm/i915/gt/intel_reset.c | 4 +- drivers/gpu/drm/i915/gt/intel_rps.c | 4 +- drivers/gpu/drm/i915/gvt/cmd_parser.c | 6 +-- drivers/gpu/drm/i915/gvt/display.c | 10 ++-- drivers/gpu/drm/i915/gvt/fb_decoder.c | 6 +-- drivers/gpu/drm/i915/gvt/handlers.c | 8 +-- drivers/gpu/drm/i915/i915_driver.c | 41 ++++++++------- drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/i915_getparam.c | 2 +- drivers/gpu/drm/i915/i915_gpu_error.c | 2 +- drivers/gpu/drm/i915/i915_irq.c | 50 +++++++++--------- drivers/gpu/drm/i915/intel_clock_gating.c | 2 +- .../gpu/drm/i915/selftests/mock_gem_device.c | 3 ++ drivers/gpu/drm/xe/display/xe_display.c | 51 ++++++++++--------- drivers/gpu/drm/xe/display/xe_fb_pin.c | 2 +- drivers/gpu/drm/xe/xe_device_types.h | 3 +- 22 files changed, 111 insertions(+), 100 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_conversion.c b/drivers/gpu/drm/i915/display/intel_display_conversion.c index 0578b68404da7..151d83fdbe379 100644 --- a/drivers/gpu/drm/i915/display/intel_display_conversion.c +++ b/drivers/gpu/drm/i915/display/intel_display_conversion.c @@ -5,7 +5,7 @@ struct intel_display *__i915_to_display(struct drm_i915_private *i915) { - return &i915->display; + return i915->display; } struct intel_display *__drm_to_display(struct drm_device *drm) diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c index 43bd97e4f5898..8684cf8e4b7f0 100644 --- a/drivers/gpu/drm/i915/display/intel_dpt.c +++ b/drivers/gpu/drm/i915/display/intel_dpt.c @@ -126,7 +126,7 @@ struct i915_vma *intel_dpt_pin_to_ggtt(struct i915_address_space *vm, unsigned int alignment) { struct drm_i915_private *i915 = vm->i915; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; struct i915_dpt *dpt = i915_vm_to_dpt(vm); struct ref_tracker *wakeref; struct i915_vma *vma; diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h index e9b809568cd42..92c04811aa28e 100644 --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h @@ -446,7 +446,7 @@ enum vbt_gmbus_ddi { * basically any of the fields to ensure the correct interpretation for the BDB * version in question. * - * When we copy the child device configs to dev_priv->display.vbt.child_dev, we + * When we copy the child device configs to display->vbt.child_dev, we * reserve space for the full structure below, and initialize the tail not * actually present in VBT to zeros. Accessing those fields is fine, as long as * the default zero is taken into account, again according to the BDB version. diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_frontbuffer.h b/drivers/gpu/drm/i915/gem/i915_gem_object_frontbuffer.h index 9fbf14867a2a6..b6dc3d1b9bb13 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_frontbuffer.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_frontbuffer.h @@ -77,7 +77,7 @@ i915_gem_object_get_frontbuffer(const struct drm_i915_gem_object *obj) * Set object's frontbuffer pointer. If frontbuffer is already set for the * object keep it and return it's pointer to the caller. Please note that RCU * mechanism is used to handle e.g. ongoing removal of frontbuffer pointer. This - * function is protected by i915->display.fb_tracking.lock + * function is protected by i915->display->fb_tracking.lock * * Return: pointer to frontbuffer which was set. */ diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c index 0c723e7c71a2b..889e61843ff30 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c @@ -328,7 +328,7 @@ static bool fence_is_active(const struct i915_fence_reg *fence) static struct i915_fence_reg *fence_find(struct i915_ggtt *ggtt) { - struct intel_display *display = &ggtt->vm.i915->display; + struct intel_display *display = ggtt->vm.i915->display; struct i915_fence_reg *active = NULL; struct i915_fence_reg *fence, *fn; diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index 3182f19b98376..3b77b4bb88e33 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -70,7 +70,7 @@ static int __gt_unpark(struct intel_wakeref *wf) { struct intel_gt *gt = container_of(wf, typeof(*gt), wakeref); struct drm_i915_private *i915 = gt->i915; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; GT_TRACE(gt, "\n"); @@ -104,7 +104,7 @@ static int __gt_park(struct intel_wakeref *wf) struct intel_gt *gt = container_of(wf, typeof(*gt), wakeref); intel_wakeref_t wakeref = fetch_and_zero(>->awake); struct drm_i915_private *i915 = gt->i915; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; GT_TRACE(gt, "\n"); diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index dbdcfe130ad41..971fbff1211c3 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1205,7 +1205,7 @@ void intel_gt_reset(struct intel_gt *gt, intel_engine_mask_t stalled_mask, const char *reason) { - struct intel_display *display = >->i915->display; + struct intel_display *display = gt->i915->display; intel_engine_mask_t awake; int ret; @@ -1423,7 +1423,7 @@ static void intel_gt_reset_global(struct intel_gt *gt, /* Use a watchdog to ensure that our reset completes */ intel_wedge_on_timeout(&w, gt, 60 * HZ) { struct drm_i915_private *i915 = gt->i915; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; bool need_display_reset; bool reset_display; diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index c619c6e2a76f4..74658835de1ac 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -550,7 +550,7 @@ static unsigned int init_emon(struct intel_uncore *uncore) static bool gen5_rps_enable(struct intel_rps *rps) { struct drm_i915_private *i915 = rps_to_i915(rps); - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; struct intel_uncore *uncore = rps_to_uncore(rps); u8 fstart, vstart; u32 rgvmodectl; @@ -620,7 +620,7 @@ static bool gen5_rps_enable(struct intel_rps *rps) static void gen5_rps_disable(struct intel_rps *rps) { struct drm_i915_private *i915 = rps_to_i915(rps); - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; struct intel_uncore *uncore = rps_to_uncore(rps); u16 rgvswctl; diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index f25ee2953baf5..2b5094e8de5e3 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -1286,7 +1286,7 @@ static int gen8_decode_mi_display_flip(struct parser_exec_state *s, struct mi_display_flip_command_info *info) { struct drm_i915_private *dev_priv = s->engine->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct plane_code_mapping gen8_plane_code[] = { [0] = {PIPE_A, PLANE_A, PRIMARY_A_FLIP_DONE}, [1] = {PIPE_B, PLANE_A, PRIMARY_B_FLIP_DONE}, @@ -1333,7 +1333,7 @@ static int skl_decode_mi_display_flip(struct parser_exec_state *s, struct mi_display_flip_command_info *info) { struct drm_i915_private *dev_priv = s->engine->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_vgpu *vgpu = s->vgpu; u32 dword0 = cmd_val(s, 0); u32 dword1 = cmd_val(s, 1); @@ -1421,7 +1421,7 @@ static int gen8_update_plane_mmio_from_mi_display_flip( struct mi_display_flip_command_info *info) { struct drm_i915_private *dev_priv = s->engine->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_vgpu *vgpu = s->vgpu; set_mask_bits(&vgpu_vreg_t(vgpu, info->surf_reg), GENMASK(31, 12), diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index 1e1af5e545a41..b77e8f3ff75c8 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -69,7 +69,7 @@ static int get_edp_pipe(struct intel_vgpu *vgpu) static int edp_pipe_is_enabled(struct intel_vgpu *vgpu) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; if (!(vgpu_vreg_t(vgpu, TRANSCONF(display, TRANSCODER_EDP)) & TRANSCONF_ENABLE)) return 0; @@ -82,7 +82,7 @@ static int edp_pipe_is_enabled(struct intel_vgpu *vgpu) int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; if (drm_WARN_ON(&dev_priv->drm, pipe < PIPE_A || pipe >= I915_MAX_PIPES)) @@ -183,7 +183,7 @@ static u8 dpcd_fix_data[DPCD_HEADER_SIZE] = { static void emulate_monitor_status_change(struct intel_vgpu *vgpu) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; int pipe; if (IS_BROXTON(dev_priv)) { @@ -634,7 +634,7 @@ void vgpu_update_vblank_emulation(struct intel_vgpu *vgpu, bool turnon) static void emulate_vblank_on_pipe(struct intel_vgpu *vgpu, int pipe) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_vgpu_irq *irq = &vgpu->irq; int vblank_event[] = { [PIPE_A] = PIPE_A_VBLANK, @@ -664,7 +664,7 @@ static void emulate_vblank_on_pipe(struct intel_vgpu *vgpu, int pipe) void intel_vgpu_emulate_vblank(struct intel_vgpu *vgpu) { struct drm_i915_private *i915 = vgpu->gvt->gt->i915; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; int pipe; mutex_lock(&vgpu->vgpu_lock); diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.c b/drivers/gpu/drm/i915/gvt/fb_decoder.c index f9f7ef131371f..4cfe8d7f368d2 100644 --- a/drivers/gpu/drm/i915/gvt/fb_decoder.c +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.c @@ -154,7 +154,7 @@ static u32 intel_vgpu_get_stride(struct intel_vgpu *vgpu, int pipe, u32 tiled, int stride_mask, int bpp) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; u32 stride_reg = vgpu_vreg_t(vgpu, DSPSTRIDE(display, pipe)) & stride_mask; u32 stride = stride_reg; @@ -211,7 +211,7 @@ int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu, struct intel_vgpu_primary_plane_format *plane) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; u32 val, fmt; int pipe; @@ -342,7 +342,7 @@ int intel_vgpu_decode_cursor_plane(struct intel_vgpu *vgpu, struct intel_vgpu_cursor_plane_format *plane) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; u32 val, mode, index; u32 alpha_plane, alpha_force; int pipe; diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 1344e6d20a34f..11cb8bf1fa4aa 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -658,7 +658,7 @@ static u32 skl_vgpu_get_dp_bitrate(struct intel_vgpu *vgpu, enum port port) static void vgpu_update_refresh_rate(struct intel_vgpu *vgpu) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; enum port port; u32 dp_br, link_m, link_n, htotal, vtotal; @@ -1022,7 +1022,7 @@ static int pri_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; u32 pipe = DSPSURF_TO_PIPE(display, offset); int event = SKL_FLIP_EVENT(pipe, PLANE_PRIMARY); @@ -1064,7 +1064,7 @@ static int reg50080_mmio_write(struct intel_vgpu *vgpu, unsigned int bytes) { struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; enum pipe pipe = REG_50080_TO_PIPE(offset); enum plane_id plane = REG_50080_TO_PLANE(offset); int event = SKL_FLIP_EVENT(pipe, plane); @@ -2200,7 +2200,7 @@ static int csfe_chicken1_mmio_write(struct intel_vgpu *vgpu, static int init_generic_mmio_info(struct intel_gvt *gvt) { struct drm_i915_private *dev_priv = gvt->gt->i915; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; int ret; MMIO_RING_DFH(RING_IMR, D_ALL, 0, NULL, diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 134a1c3d1f9d1..5c69d14a7673e 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -115,7 +115,7 @@ static const struct drm_driver i915_drm_driver; static int i915_workqueues_init(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; /* * The i915 workqueue is primarily used for batched retirement of @@ -163,7 +163,7 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv) static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; destroy_workqueue(dev_priv->unordered_wq); destroy_workqueue(display->hotplug.dp_wq); @@ -226,7 +226,7 @@ static void sanitize_gpu(struct drm_i915_private *i915) */ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; int ret = 0; if (i915_inject_probe_failure(dev_priv)) @@ -289,7 +289,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) */ static void i915_driver_late_release(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; intel_irq_fini(dev_priv); intel_power_domains_cleanup(display); @@ -317,7 +317,7 @@ static void i915_driver_late_release(struct drm_i915_private *dev_priv) */ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_gt *gt; int ret, i; @@ -464,7 +464,7 @@ static int i915_pcode_init(struct drm_i915_private *i915) */ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); int ret; @@ -603,7 +603,7 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv) */ static void i915_driver_hw_remove(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); i915_perf_fini(dev_priv); @@ -623,7 +623,7 @@ static void i915_driver_hw_remove(struct drm_i915_private *dev_priv) */ static int i915_driver_register(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_gt *gt; unsigned int i; int ret; @@ -674,7 +674,7 @@ static int i915_driver_register(struct drm_i915_private *dev_priv) */ static void i915_driver_unregister(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_gt *gt; unsigned int i; @@ -760,6 +760,9 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent) /* Set up device info and initial runtime info. */ intel_device_info_driver_create(i915, pdev->device, match_info); + /* TODO: Allocate display dynamically. */ + i915->display = &i915->__display; + intel_display_device_probe(pdev); return i915; @@ -794,7 +797,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return PTR_ERR(i915); } - display = &i915->display; + display = i915->display; ret = i915_driver_early_probe(i915); if (ret < 0) @@ -886,7 +889,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent) void i915_driver_remove(struct drm_i915_private *i915) { - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; intel_wakeref_t wakeref; wakeref = intel_runtime_pm_get(&i915->runtime_pm); @@ -919,7 +922,7 @@ void i915_driver_remove(struct drm_i915_private *i915) static void i915_driver_release(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; intel_wakeref_t wakeref; @@ -973,7 +976,7 @@ static void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) void i915_driver_shutdown(struct drm_i915_private *i915) { - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; disable_rpm_wakeref_asserts(&i915->runtime_pm); intel_runtime_pm_disable(&i915->runtime_pm); @@ -1053,7 +1056,7 @@ static int i915_drm_prepare(struct drm_device *dev) static int i915_drm_suspend(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); pci_power_t opregion_target_state; @@ -1103,7 +1106,7 @@ static int i915_drm_suspend(struct drm_device *dev) static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) { struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; struct intel_gt *gt; @@ -1175,7 +1178,7 @@ int i915_driver_suspend_switcheroo(struct drm_i915_private *i915, static int i915_drm_resume(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_gt *gt; int ret, i; @@ -1260,7 +1263,7 @@ static int i915_drm_resume(struct drm_device *dev) static int i915_drm_resume_early(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); struct intel_gt *gt; int ret, i; @@ -1492,7 +1495,7 @@ static int i915_pm_restore(struct device *kdev) static int intel_runtime_suspend(struct device *kdev) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); struct pci_dev *root_pdev; @@ -1591,7 +1594,7 @@ static int intel_runtime_suspend(struct device *kdev) static int intel_runtime_resume(struct device *kdev) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); struct pci_dev *root_pdev; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 93b4c504b7100..0841988c4a671 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -177,7 +177,8 @@ struct i915_selftest_stash { struct drm_i915_private { struct drm_device drm; - struct intel_display display; + struct intel_display *display; + struct intel_display __display; /* Transitional. Do not use directly. */ /* FIXME: Device release actions should all be moved to drmm_ */ bool do_release; diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c index be8149e462817..6fcda6d7b5b73 100644 --- a/drivers/gpu/drm/i915/i915_getparam.c +++ b/drivers/gpu/drm/i915/i915_getparam.c @@ -16,7 +16,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_i915_private *i915 = to_i915(dev); - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; struct pci_dev *pdev = to_pci_dev(dev->dev); const struct sseu_dev_info *sseu = &to_gt(i915)->info.sseu; drm_i915_getparam_t *param = data; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 4f785cdbd1553..f434b6825fc28 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -2067,7 +2067,7 @@ static struct i915_gpu_coredump * __i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 dump_flags) { struct drm_i915_private *i915 = gt->i915; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; struct i915_gpu_coredump *error; /* Check if GPU capture has been disabled */ diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index cc05f347555ad..351928481cd9e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -230,7 +230,7 @@ static void ivb_parity_work(struct work_struct *work) static irqreturn_t valleyview_irq_handler(int irq, void *arg) { struct drm_i915_private *dev_priv = arg; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; irqreturn_t ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) @@ -324,7 +324,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) static irqreturn_t cherryview_irq_handler(int irq, void *arg) { struct drm_i915_private *dev_priv = arg; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; irqreturn_t ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) @@ -418,7 +418,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) static irqreturn_t ilk_irq_handler(int irq, void *arg) { struct drm_i915_private *i915 = arg; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; void __iomem * const regs = intel_uncore_regs(&i915->uncore); u32 de_iir, gt_iir, de_ier, sde_ier = 0; irqreturn_t ret = IRQ_NONE; @@ -507,7 +507,7 @@ static inline void gen8_master_intr_enable(void __iomem * const regs) static irqreturn_t gen8_irq_handler(int irq, void *arg) { struct drm_i915_private *dev_priv = arg; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; void __iomem * const regs = intel_uncore_regs(&dev_priv->uncore); u32 master_ctl; @@ -558,7 +558,7 @@ static inline void gen11_master_intr_enable(void __iomem * const regs) static irqreturn_t gen11_irq_handler(int irq, void *arg) { struct drm_i915_private *i915 = arg; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; void __iomem * const regs = intel_uncore_regs(&i915->uncore); struct intel_gt *gt = to_gt(i915); u32 master_ctl; @@ -616,7 +616,7 @@ static inline void dg1_master_intr_enable(void __iomem * const regs) static irqreturn_t dg1_irq_handler(int irq, void *arg) { struct drm_i915_private * const i915 = arg; - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; struct intel_gt *gt = to_gt(i915); void __iomem * const regs = intel_uncore_regs(gt->uncore); u32 master_tile_ctl, master_ctl; @@ -660,7 +660,7 @@ static irqreturn_t dg1_irq_handler(int irq, void *arg) static void ilk_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; gen2_irq_reset(uncore, DE_IRQ_REGS); @@ -681,7 +681,7 @@ static void ilk_irq_reset(struct drm_i915_private *dev_priv) static void valleyview_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0); intel_uncore_posting_read(&dev_priv->uncore, VLV_MASTER_IER); @@ -693,7 +693,7 @@ static void valleyview_irq_reset(struct drm_i915_private *dev_priv) static void gen8_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; gen8_master_intr_disable(intel_uncore_regs(uncore)); @@ -705,7 +705,7 @@ static void gen8_irq_reset(struct drm_i915_private *dev_priv) static void gen11_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_gt *gt = to_gt(dev_priv); struct intel_uncore *uncore = gt->uncore; @@ -720,7 +720,7 @@ static void gen11_irq_reset(struct drm_i915_private *dev_priv) static void dg1_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; struct intel_gt *gt; unsigned int i; @@ -740,7 +740,7 @@ static void dg1_irq_reset(struct drm_i915_private *dev_priv) static void cherryview_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; intel_uncore_write(uncore, GEN8_MASTER_IRQ, 0); @@ -755,7 +755,7 @@ static void cherryview_irq_reset(struct drm_i915_private *dev_priv) static void ilk_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; gen5_gt_irq_postinstall(to_gt(dev_priv)); @@ -764,7 +764,7 @@ static void ilk_irq_postinstall(struct drm_i915_private *dev_priv) static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; gen5_gt_irq_postinstall(to_gt(dev_priv)); @@ -776,7 +776,7 @@ static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv) static void gen8_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; gen8_gt_irq_postinstall(to_gt(dev_priv)); gen8_de_irq_postinstall(display); @@ -786,7 +786,7 @@ static void gen8_irq_postinstall(struct drm_i915_private *dev_priv) static void gen11_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_gt *gt = to_gt(dev_priv); struct intel_uncore *uncore = gt->uncore; u32 gu_misc_masked = GEN11_GU_MISC_GSE; @@ -802,7 +802,7 @@ static void gen11_irq_postinstall(struct drm_i915_private *dev_priv) static void dg1_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; u32 gu_misc_masked = GEN11_GU_MISC_GSE; struct intel_gt *gt; @@ -821,7 +821,7 @@ static void dg1_irq_postinstall(struct drm_i915_private *dev_priv) static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; gen8_gt_irq_postinstall(to_gt(dev_priv)); @@ -894,7 +894,7 @@ static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv, static void i915_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; i9xx_display_irq_reset(display); @@ -906,7 +906,7 @@ static void i915_irq_reset(struct drm_i915_private *dev_priv) static void i915_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; u32 enable_mask; @@ -941,7 +941,7 @@ static void i915_irq_postinstall(struct drm_i915_private *dev_priv) static irqreturn_t i915_irq_handler(int irq, void *arg) { struct drm_i915_private *dev_priv = arg; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; irqreturn_t ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) @@ -996,7 +996,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) static void i965_irq_reset(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; i9xx_display_irq_reset(display); @@ -1027,7 +1027,7 @@ static u32 i965_error_mask(struct drm_i915_private *i915) static void i965_irq_postinstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; struct intel_uncore *uncore = &dev_priv->uncore; u32 enable_mask; @@ -1059,7 +1059,7 @@ static void i965_irq_postinstall(struct drm_i915_private *dev_priv) static irqreturn_t i965_irq_handler(int irq, void *arg) { struct drm_i915_private *dev_priv = arg; - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; irqreturn_t ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) @@ -1256,7 +1256,7 @@ int intel_irq_install(struct drm_i915_private *dev_priv) */ void intel_irq_uninstall(struct drm_i915_private *dev_priv) { - struct intel_display *display = &dev_priv->display; + struct intel_display *display = dev_priv->display; int irq = to_pci_dev(dev_priv->drm.dev)->irq; if (drm_WARN_ON(&dev_priv->drm, !dev_priv->irqs_enabled)) diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index 892b1e19d9461..5bbf891ccc32c 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -201,7 +201,7 @@ static void ilk_init_clock_gating(struct drm_i915_private *i915) static void cpt_init_clock_gating(struct drm_i915_private *i915) { - struct intel_display *display = &i915->display; + struct intel_display *display = i915->display; enum pipe pipe; u32 val; diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index a77e5b26542ce..0ea12c68cedb2 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -180,6 +180,9 @@ struct drm_i915_private *mock_gem_device(void) /* Set up device info and initial runtime info. */ intel_device_info_driver_create(i915, pdev->device, &mock_info); + /* TODO: Allocate display dynamically. */ + i915->display = &i915->__display; + intel_display_device_probe(pdev); dev_pm_domain_set(&pdev->dev, &pm_domain); diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index b8030492fbd10..699f401eff101 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -38,7 +38,7 @@ static bool has_display(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; return HAS_DISPLAY(display); } @@ -86,7 +86,7 @@ static void unset_display_features(struct xe_device *xe) static void display_destroy(struct drm_device *dev, void *dummy) { struct xe_device *xe = to_xe_device(dev); - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; destroy_workqueue(display->hotplug.dp_wq); } @@ -104,7 +104,10 @@ static void display_destroy(struct drm_device *dev, void *dummy) */ int xe_display_create(struct xe_device *xe) { - struct intel_display *display = &xe->display; + /* TODO: Allocate display dynamically. */ + struct intel_display *display = &xe->__display; + + xe->display = &xe->__display; spin_lock_init(&display->fb_tracking.lock); @@ -116,7 +119,7 @@ int xe_display_create(struct xe_device *xe) static void xe_display_fini_early(void *arg) { struct xe_device *xe = arg; - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -129,7 +132,7 @@ static void xe_display_fini_early(void *arg) int xe_display_init_early(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; int err; if (!xe->info.probe_display) @@ -173,7 +176,7 @@ int xe_display_init_early(struct xe_device *xe) static void xe_display_fini(void *arg) { struct xe_device *xe = arg; - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; intel_hpd_poll_fini(display); intel_hdcp_component_fini(display); @@ -183,7 +186,7 @@ static void xe_display_fini(void *arg) int xe_display_init(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; int err; if (!xe->info.probe_display) @@ -198,7 +201,7 @@ int xe_display_init(struct xe_device *xe) void xe_display_register(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -209,7 +212,7 @@ void xe_display_register(struct xe_device *xe) void xe_display_unregister(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -222,7 +225,7 @@ void xe_display_unregister(struct xe_device *xe) void xe_display_irq_handler(struct xe_device *xe, u32 master_ctl) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -233,7 +236,7 @@ void xe_display_irq_handler(struct xe_device *xe, u32 master_ctl) void xe_display_irq_enable(struct xe_device *xe, u32 gu_misc_iir) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -244,7 +247,7 @@ void xe_display_irq_enable(struct xe_device *xe, u32 gu_misc_iir) void xe_display_irq_reset(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -254,7 +257,7 @@ void xe_display_irq_reset(struct xe_device *xe) void xe_display_irq_postinstall(struct xe_device *xe, struct xe_gt *gt) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -295,7 +298,7 @@ static void xe_display_flush_cleanup_work(struct xe_device *xe) static void xe_display_enable_d3cold(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -318,7 +321,7 @@ static void xe_display_enable_d3cold(struct xe_device *xe) static void xe_display_disable_d3cold(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -342,7 +345,7 @@ static void xe_display_disable_d3cold(struct xe_device *xe) void xe_display_pm_suspend(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; bool s2idle = suspend_to_idle(); if (!xe->info.probe_display) @@ -377,7 +380,7 @@ void xe_display_pm_suspend(struct xe_device *xe) void xe_display_pm_shutdown(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -408,7 +411,7 @@ void xe_display_pm_shutdown(struct xe_device *xe) void xe_display_pm_runtime_suspend(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -423,7 +426,7 @@ void xe_display_pm_runtime_suspend(struct xe_device *xe) void xe_display_pm_suspend_late(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; bool s2idle = suspend_to_idle(); if (!xe->info.probe_display) @@ -434,7 +437,7 @@ void xe_display_pm_suspend_late(struct xe_device *xe) void xe_display_pm_runtime_suspend_late(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -452,7 +455,7 @@ void xe_display_pm_runtime_suspend_late(struct xe_device *xe) void xe_display_pm_shutdown_late(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -467,7 +470,7 @@ void xe_display_pm_shutdown_late(struct xe_device *xe) void xe_display_pm_resume_early(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -477,7 +480,7 @@ void xe_display_pm_resume_early(struct xe_device *xe) void xe_display_pm_resume(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; @@ -512,7 +515,7 @@ void xe_display_pm_resume(struct xe_device *xe) void xe_display_pm_runtime_resume(struct xe_device *xe) { - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; if (!xe->info.probe_display) return; diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index e95ca979e1fe3..c2b4be72f7a00 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -389,7 +389,7 @@ static bool reuse_vma(struct intel_plane_state *new_plane_state, { struct intel_framebuffer *fb = to_intel_framebuffer(new_plane_state->hw.fb); struct xe_device *xe = to_xe_device(fb->base.dev); - struct intel_display *display = &xe->display; + struct intel_display *display = xe->display; struct i915_vma *vma; if (old_plane_state->hw.fb == new_plane_state->hw.fb && diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 06c65dace0264..634ac4aa7674b 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -587,7 +587,8 @@ struct xe_device { * drm_i915_private during build. After cleanup these should go away, * migrating to the right sub-structs */ - struct intel_display display; + struct intel_display *display; + struct intel_display __display; /* Transitional. Do not use directly. */ struct dram_info { bool wm_lv_0_adjust_needed; -- GitLab From 24560c53664881ed833ace50febc48366b0d56a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 12 May 2025 13:33:52 +0300 Subject: [PATCH 0101/1479] drm/i915/dmc: Drop PIPEDMC faults from the fault mask on LNL+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On LNL+ PIPEDMC faults are reported via PIPEDMC interrupts instead of the direct DE_PIPE_* reporting used on earlier platforms. Drop the relevant bits from the fault mask. The bits are tied to zero on LNL, so there is no danger of spurious fault interrupts even with an incorrect mask. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250512103358.15724-2-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/intel_display_irq.c | 10 +++++++++- drivers/gpu/drm/i915/i915_reg.h | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index 3e73832e5e813..a7130b14aacee 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -1016,7 +1016,15 @@ static u32 gen8_de_port_aux_mask(struct intel_display *display) static u32 gen8_de_pipe_fault_mask(struct intel_display *display) { - if (DISPLAY_VER(display) >= 14) + if (DISPLAY_VER(display) >= 20) + return MTL_PLANE_ATS_FAULT | + GEN9_PIPE_CURSOR_FAULT | + GEN11_PIPE_PLANE5_FAULT | + GEN9_PIPE_PLANE4_FAULT | + GEN9_PIPE_PLANE3_FAULT | + GEN9_PIPE_PLANE2_FAULT | + GEN9_PIPE_PLANE1_FAULT; + else if (DISPLAY_VER(display) >= 14) return MTL_PIPEDMC_ATS_FAULT | MTL_PLANE_ATS_FAULT | GEN12_PIPEDMC_FAULT | diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2e4190da3e0d8..2d0e04eae7630 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2126,8 +2126,8 @@ #define GEN8_PIPE_CDCLK_CRC_ERROR REG_BIT(29) #define GEN8_PIPE_CDCLK_CRC_DONE REG_BIT(28) #define GEN12_PIPEDMC_INTERRUPT REG_BIT(26) /* tgl+ */ -#define GEN12_PIPEDMC_FAULT REG_BIT(25) /* tgl+ */ -#define MTL_PIPEDMC_ATS_FAULT REG_BIT(24) /* mtl+ */ +#define GEN12_PIPEDMC_FAULT REG_BIT(25) /* tgl-mtl */ +#define MTL_PIPEDMC_ATS_FAULT REG_BIT(24) /* mtl */ #define GEN11_PIPE_PLANE7_FAULT REG_BIT(22) /* icl/tgl */ #define GEN11_PIPE_PLANE6_FAULT REG_BIT(21) /* icl/tgl */ #define GEN11_PIPE_PLANE5_FAULT REG_BIT(20) /* icl+ */ -- GitLab From f91ee1a21c3716fb853d5a0d83850a1906675a92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 14 May 2025 20:42:57 +0300 Subject: [PATCH 0102/1479] drm/i915/dmc: Hook up PIPEDMC interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hook up PIPEDMC interrupts. We'll need these for: - flip queue signalling - GTT/ATS faults on LNL+ - unclaimed register access errors (supposedly that is what the error interrupt indicated according to Windows code). On LNL+ we get a new level of interrupts registers PIPEDMC_INTERRUPT*. On earlier platforms we only have the INT_VECTOR field in the PIPEDMC_STATUS registers, whose values are defined by the firmware. For now we'll enable the interrupts on LNL+ only. For earlier platforms it's not clear that there is any use for these interrupts, and some ADL machines have exhibited spurious DE_PIPE interrupts with the PIPEDMC interrupts unmasked/enabled. We can revisit enabling these for earlier platforms in the future. For some unknown reason LNL pipe B triggers the error interrupt during the first DC state transition (subsequent transitions are maybe OK?). No clear idea what's going on here yet, so keep the error interrupt disabled for now. Similar to DSB interrupt registers, the unused bits in PIPEDMC_INTERRUPT* seem to act like randomg r/w bits (instead of being hardwired to 0 like one would expect), and so we'll try to avoid setting them so that we don't mistake them for real interrupts. v2: Only enable/unmask for LNL+ Keep the flip queue interrupt masked off for now since we don't have a use for it yet v3: Also keep the error interrupt masked off for now due to LNL pipe B triggering it Reviewed-by: Luca Coelho Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250514174257.8708-1-ville.syrjala@linux.intel.com --- .../drm/i915/display/intel_display_device.h | 1 + .../gpu/drm/i915/display/intel_display_irq.c | 8 +++ drivers/gpu/drm/i915/display/intel_dmc.c | 49 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dmc.h | 2 + drivers/gpu/drm/i915/display/intel_dmc_regs.h | 22 +++++++++ drivers/gpu/drm/i915/i915_reg.h | 2 + 6 files changed, 84 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h index fe14a92ae8c65..f0ea56cc5def5 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.h +++ b/drivers/gpu/drm/i915/display/intel_display_device.h @@ -182,6 +182,7 @@ struct intel_display_platforms { #define HAS_MBUS_JOINING(__display) ((__display)->platform.alderlake_p || DISPLAY_VER(__display) >= 14) #define HAS_MSO(__display) (DISPLAY_VER(__display) >= 12) #define HAS_OVERLAY(__display) (DISPLAY_INFO(__display)->has_overlay) +#define HAS_PIPEDMC(__display) (DISPLAY_VER(__display) >= 12) #define HAS_PSR(__display) (DISPLAY_INFO(__display)->has_psr) #define HAS_PSR_HW_TRACKING(__display) (DISPLAY_INFO(__display)->has_psr_hw_tracking) #define HAS_PSR2_SEL_FETCH(__display) (DISPLAY_VER(__display) >= 12) diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index a7130b14aacee..c24841f57aac4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -17,6 +17,7 @@ #include "intel_display_rps.h" #include "intel_display_trace.h" #include "intel_display_types.h" +#include "intel_dmc.h" #include "intel_dmc_wl.h" #include "intel_dp_aux.h" #include "intel_dsb.h" @@ -1449,6 +1450,9 @@ void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl) intel_dsb_irq_handler(display, pipe, INTEL_DSB_2); } + if (HAS_PIPEDMC(display) && iir & GEN12_PIPEDMC_INTERRUPT) + intel_pipedmc_irq_handler(display, pipe); + if (iir & GEN8_PIPE_CDCLK_CRC_DONE) hsw_pipe_crc_irq_handler(display, pipe); @@ -2266,6 +2270,10 @@ void gen8_de_irq_postinstall(struct intel_display *display) GEN12_DSB_INT(INTEL_DSB_1) | GEN12_DSB_INT(INTEL_DSB_2); + /* TODO figure PIPEDMC interrupts for pre-LNL */ + if (DISPLAY_VER(display) >= 20) + de_pipe_masked |= GEN12_PIPEDMC_INTERRUPT; + de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN | gen8_de_pipe_flip_done_mask(display); diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index b58189d24e7e4..16dc52a8302c8 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -27,9 +27,11 @@ #include "i915_drv.h" #include "i915_reg.h" +#include "intel_crtc.h" #include "intel_de.h" #include "intel_display_rpm.h" #include "intel_display_power_well.h" +#include "intel_display_types.h" #include "intel_dmc.h" #include "intel_dmc_regs.h" #include "intel_step.h" @@ -490,6 +492,17 @@ static void pipedmc_clock_gating_wa(struct intel_display *display, bool enable) adlp_pipedmc_clock_gating_wa(display, enable); } +static u32 pipedmc_interrupt_mask(struct intel_display *display) +{ + /* + * FIXME PIPEDMC_ERROR not enabled for now due to LNL pipe B + * triggering it during the first DC state transition. Figure + * out what is going on... + */ + return PIPEDMC_GTT_FAULT | + PIPEDMC_ATS_FAULT; +} + void intel_dmc_enable_pipe(struct intel_display *display, enum pipe pipe) { enum intel_dmc_id dmc_id = PIPE_TO_DMC_ID(pipe); @@ -497,6 +510,11 @@ void intel_dmc_enable_pipe(struct intel_display *display, enum pipe pipe) if (!is_valid_dmc_id(dmc_id) || !has_dmc_id_fw(display, dmc_id)) return; + if (DISPLAY_VER(display) >= 20) { + intel_de_write(display, PIPEDMC_INTERRUPT(pipe), pipedmc_interrupt_mask(display)); + intel_de_write(display, PIPEDMC_INTERRUPT_MASK(pipe), ~pipedmc_interrupt_mask(display)); + } + if (DISPLAY_VER(display) >= 14) intel_de_rmw(display, MTL_PIPEDMC_CONTROL, 0, PIPEDMC_ENABLE_MTL(pipe)); else @@ -514,6 +532,11 @@ void intel_dmc_disable_pipe(struct intel_display *display, enum pipe pipe) intel_de_rmw(display, MTL_PIPEDMC_CONTROL, PIPEDMC_ENABLE_MTL(pipe), 0); else intel_de_rmw(display, PIPEDMC_CONTROL(pipe), PIPEDMC_ENABLE, 0); + + if (DISPLAY_VER(display) >= 20) { + intel_de_write(display, PIPEDMC_INTERRUPT_MASK(pipe), ~0); + intel_de_write(display, PIPEDMC_INTERRUPT(pipe), pipedmc_interrupt_mask(display)); + } } /** @@ -1403,3 +1426,29 @@ void intel_dmc_debugfs_register(struct intel_display *display) debugfs_create_file("i915_dmc_info", 0444, minor->debugfs_root, display, &intel_dmc_debugfs_status_fops); } + +void intel_pipedmc_irq_handler(struct intel_display *display, enum pipe pipe) +{ + struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe); + u32 tmp; + + if (DISPLAY_VER(display) >= 20) { + tmp = intel_de_read(display, PIPEDMC_INTERRUPT(pipe)); + intel_de_write(display, PIPEDMC_INTERRUPT(pipe), tmp); + + if (tmp & PIPEDMC_ATS_FAULT) + drm_err_ratelimited(display->drm, "[CRTC:%d:%s] PIPEDMC ATS fault\n", + crtc->base.base.id, crtc->base.name); + if (tmp & PIPEDMC_GTT_FAULT) + drm_err_ratelimited(display->drm, "[CRTC:%d:%s] PIPEDMC GTT fault\n", + crtc->base.base.id, crtc->base.name); + if (tmp & PIPEDMC_ERROR) + drm_err(display->drm, "[CRTC:%d:%s]] PIPEDMC error\n", + crtc->base.base.id, crtc->base.name); + } + + tmp = intel_de_read(display, PIPEDMC_STATUS(pipe)) & PIPEDMC_INT_VECTOR_MASK; + if (tmp) + drm_err(display->drm, "[CRTC:%d:%s]] PIPEDMC interrupt vector 0x%x\n", + crtc->base.base.id, crtc->base.name, tmp); +} diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h index bd1c459b00757..a98e8deff13aa 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.h +++ b/drivers/gpu/drm/i915/display/intel_dmc.h @@ -34,4 +34,6 @@ void intel_dmc_update_dc6_allowed_count(struct intel_display *display, bool star void assert_dmc_loaded(struct intel_display *display); +void intel_pipedmc_irq_handler(struct intel_display *display, enum pipe pipe); + #endif /* __INTEL_DMC_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dmc_regs.h b/drivers/gpu/drm/i915/display/intel_dmc_regs.h index e16ea3f16ed88..e8ac0e1be7649 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_dmc_regs.h @@ -27,6 +27,28 @@ _MTL_PIPEDMC_EVT_CTL_4_A, \ _MTL_PIPEDMC_EVT_CTL_4_B) +#define _PIPEDMC_STATUS_A 0x5f06c +#define _PIPEDMC_STATUS_B 0x5f46c +#define PIPEDMC_STATUS(pipe) _MMIO_PIPE((pipe), _PIPEDMC_STATUS_A, _PIPEDMC_STATUS_B) +#define PIPEDMC_SSP REG_GENMASK(31, 16) +#define PIPEDMC_INT_VECTOR_MASK REG_GENMASK(15, 8) +/* PIPEDMC_INT_VECTOR values defined by firmware */ +#define PIPEDMC_INT_VECTOR_SCANLINE_COMP_ERROR REG_FIELD_PREP(PIPEDMC_INT_VECTOR_MASK, 0x1) +#define PIPEDMC_INT_VECTOR_DC6V_FLIPQ_OVERLAP_ERROR REG_FIELD_PREP(PIPEDMC_INT_VECTOR_MASK, 0x2) +#define PIPEDMC_INT_VECTOR_FLIPQ_PROG_DONE REG_FIELD_PREP(PIPEDMC_INT_VECTOR_MASK, 0xff) /* Wa_16018781658:lnl[a0] */ +#define PIPEDMC_EVT_PENDING REG_GENMASK(7, 0) + +#define _PIPEDMC_INTERRUPT_A 0x5f190 /* lnl+ */ +#define _PIPEDMC_INTERRUPT_B 0x5f590 /* lnl+ */ +#define PIPEDMC_INTERRUPT(pipe) _MMIO_PIPE((pipe), _PIPEDMC_INTERRUPT_A, _PIPEDMC_INTERRUPT_B) +#define _PIPEDMC_INTERRUPT_MASK_A 0x5f194 /* lnl+ */ +#define _PIPEDMC_INTERRUPT_MASK_B 0x5f594 /* lnl+ */ +#define PIPEDMC_INTERRUPT_MASK(pipe) _MMIO_PIPE((pipe), _PIPEDMC_INTERRUPT_MASK_A, _PIPEDMC_INTERRUPT_MASK_B) +#define PIPEDMC_FLIPQ_PROG_DONE REG_BIT(3) +#define PIPEDMC_ERROR REG_BIT(2) +#define PIPEDMC_GTT_FAULT REG_BIT(1) +#define PIPEDMC_ATS_FAULT REG_BIT(0) + #define PIPEDMC_BLOCK_PKGC_SW_A 0x5f1d0 #define PIPEDMC_BLOCK_PKGC_SW_B 0x5F5d0 #define PIPEDMC_BLOCK_PKGC_SW(pipe) _MMIO_PIPE(pipe, \ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2d0e04eae7630..8822c639a4f4b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2128,12 +2128,14 @@ #define GEN12_PIPEDMC_INTERRUPT REG_BIT(26) /* tgl+ */ #define GEN12_PIPEDMC_FAULT REG_BIT(25) /* tgl-mtl */ #define MTL_PIPEDMC_ATS_FAULT REG_BIT(24) /* mtl */ +#define GEN12_PIPEDMC_FLIPQ_DONE REG_BIT(24) /* tgl-adl */ #define GEN11_PIPE_PLANE7_FAULT REG_BIT(22) /* icl/tgl */ #define GEN11_PIPE_PLANE6_FAULT REG_BIT(21) /* icl/tgl */ #define GEN11_PIPE_PLANE5_FAULT REG_BIT(20) /* icl+ */ #define GEN12_PIPE_VBLANK_UNMOD REG_BIT(19) /* tgl+ */ #define MTL_PLANE_ATS_FAULT REG_BIT(18) /* mtl+ */ #define GEN11_PIPE_PLANE7_FLIP_DONE REG_BIT(18) /* icl/tgl */ +#define MTL_PIPEDMC_FLIPQ_DONE REG_BIT(17) /* mtl */ #define GEN11_PIPE_PLANE6_FLIP_DONE REG_BIT(17) /* icl/tgl */ #define GEN11_PIPE_PLANE5_FLIP_DONE REG_BIT(16) /* icl+ */ #define GEN12_DSB_2_INT REG_BIT(15) /* tgl+ */ -- GitLab From 50a9875122ac0de222d617b233871f85418c7eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 12 May 2025 13:33:54 +0300 Subject: [PATCH 0103/1479] drm/i915/dmc: Define all DMC event IDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define all the DMC event IDs to make life less misrable when having to deal with these. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250512103358.15724-4-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/intel_dmc.c | 12 +- drivers/gpu/drm/i915/display/intel_dmc_regs.h | 271 +++++++++++++++++- 2 files changed, 272 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 16dc52a8302c8..e9aee3d5daf69 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -427,7 +427,7 @@ static void disable_event_handler(struct intel_display *display, REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, DMC_EVT_CTL_TYPE_EDGE_0_1) | REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, - DMC_EVT_CTL_EVENT_ID_FALSE)); + DMC_EVENT_FALSE)); intel_de_write(display, htp_reg, 0); } @@ -576,10 +576,10 @@ void intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank(struct intel_display REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, DMC_EVT_CTL_TYPE_EDGE_0_1) | REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, - DMC_EVT_CTL_EVENT_ID_VBLANK_A); + PIPEDMC_EVENT_VBLANK); else val = REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, - DMC_EVT_CTL_EVENT_ID_FALSE) | + DMC_EVENT_FALSE) | REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, DMC_EVT_CTL_TYPE_EDGE_0_1); @@ -620,12 +620,12 @@ static bool disable_dmc_evt(struct intel_display *display, /* also disable the flip queue event on the main DMC on TGL */ if (display->platform.tigerlake && - REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == DMC_EVT_CTL_EVENT_ID_CLK_MSEC) + REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == MAINDMC_EVENT_CLK_MSEC) return true; /* also disable the HRR event on the main DMC on TGL/ADLS */ if ((display->platform.tigerlake || display->platform.alderlake_s) && - REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == DMC_EVT_CTL_EVENT_ID_VBLANK_A) + REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == MAINDMC_EVENT_VBLANK_A) return true; return false; @@ -641,7 +641,7 @@ static u32 dmc_mmiodata(struct intel_display *display, return REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, DMC_EVT_CTL_TYPE_EDGE_0_1) | REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, - DMC_EVT_CTL_EVENT_ID_FALSE); + DMC_EVENT_FALSE); else return dmc->dmc_info[dmc_id].mmiodata[i]; } diff --git a/drivers/gpu/drm/i915/display/intel_dmc_regs.h b/drivers/gpu/drm/i915/display/intel_dmc_regs.h index e8ac0e1be7649..edd4e69319b97 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_dmc_regs.h @@ -8,6 +8,272 @@ #include "i915_reg_defs.h" +enum dmc_event_id { + DMC_EVENT_TRUE = 0x0, + DMC_EVENT_FALSE = 0x1, +}; + +enum maindmc_event_id { + MAINDMC_EVENT_CMP_ZERO = 0x8, + MAINDMC_EVENT_CMP_ODD = 0x9, + MAINDMC_EVENT_CMP_NEG = 0xa, + MAINDMC_EVENT_CMP_CARRY = 0xb, + + MAINDMC_EVENT_TMR0_DONE = 0x14, + MAINDMC_EVENT_TMR1_DONE = 0x15, + MAINDMC_EVENT_TMR2_DONE = 0x16, + MAINDMC_EVENT_COUNT0_DONE = 0x17, + MAINDMC_EVENT_COUNT1_DONE = 0x18, + MAINDMC_EVENT_PERF_CNTR_DARBF = 0x19, + + MAINDMC_EVENT_SCANLINE_INRANGE_FQ_A_TRIGGER = 0x22, + MAINDMC_EVENT_SCANLINE_INRANGE_FQ_B_TRIGGER = 0x23, + MAINDMC_EVENT_SCANLINE_INRANGE_FQ_C_TRIGGER = 0x24, + MAINDMC_EVENT_SCANLINE_INRANGE_FQ_D_TRIGGER = 0x25, + MAINDMC_EVENT_1KHZ_FQ_A_TRIGGER = 0x26, + MAINDMC_EVENT_1KHZ_FQ_B_TRIGGER = 0x27, + MAINDMC_EVENT_1KHZ_FQ_C_TRIGGER = 0x28, + MAINDMC_EVENT_1KHZ_FQ_D_TRIGGER = 0x29, + MAINDMC_EVENT_SCANLINE_COMP_A = 0x2a, + MAINDMC_EVENT_SCANLINE_COMP_B = 0x2b, + MAINDMC_EVENT_SCANLINE_COMP_C = 0x2c, + MAINDMC_EVENT_SCANLINE_COMP_D = 0x2d, + MAINDMC_EVENT_VBLANK_DELAYED_A = 0x2e, + MAINDMC_EVENT_VBLANK_DELAYED_B = 0x2f, + MAINDMC_EVENT_VBLANK_DELAYED_C = 0x30, + MAINDMC_EVENT_VBLANK_DELAYED_D = 0x31, + MAINDMC_EVENT_VBLANK_A = 0x32, + MAINDMC_EVENT_VBLANK_B = 0x33, + MAINDMC_EVENT_VBLANK_C = 0x34, + MAINDMC_EVENT_VBLANK_D = 0x35, + MAINDMC_EVENT_HBLANK_A = 0x36, + MAINDMC_EVENT_HBLANK_B = 0x37, + MAINDMC_EVENT_HBLANK_C = 0x38, + MAINDMC_EVENT_HBLANK_D = 0x39, + MAINDMC_EVENT_VSYNC_A = 0x3a, + MAINDMC_EVENT_VSYNC_B = 0x3b, + MAINDMC_EVENT_VSYNC_C = 0x3c, + MAINDMC_EVENT_VSYNC_D = 0x3d, + MAINDMC_EVENT_SCANLINE_A = 0x3e, + MAINDMC_EVENT_SCANLINE_B = 0x3f, + MAINDMC_EVENT_SCANLINE_C = 0x40, + MAINDMC_EVENT_SCANLINE_D = 0x41, + + MAINDMC_EVENT_PLANE1_FLIP_A = 0x42, + MAINDMC_EVENT_PLANE2_FLIP_A = 0x43, + MAINDMC_EVENT_PLANE3_FLIP_A = 0x44, + MAINDMC_EVENT_PLANE4_FLIP_A = 0x45, + MAINDMC_EVENT_PLANE5_FLIP_A = 0x46, + MAINDMC_EVENT_PLANE6_FLIP_A = 0x47, + MAINDMC_EVENT_PLANE7_FLIP_A = 0x48, + MAINDMC_EVENT_PLANE1_FLIP_B = 0x49, + MAINDMC_EVENT_PLANE2_FLIP_B = 0x4a, + MAINDMC_EVENT_PLANE3_FLIP_B = 0x4b, + MAINDMC_EVENT_PLANE4_FLIP_B = 0x4c, + MAINDMC_EVENT_PLANE5_FLIP_B = 0x4d, + MAINDMC_EVENT_PLANE6_FLIP_B = 0x4e, + MAINDMC_EVENT_PLANE7_FLIP_B = 0x4f, + MAINDMC_EVENT_PLANE1_FLIP_C = 0x50, + MAINDMC_EVENT_PLANE2_FLIP_C = 0x51, + MAINDMC_EVENT_PLANE3_FLIP_C = 0x52, + MAINDMC_EVENT_PLANE4_FLIP_C = 0x53, + MAINDMC_EVENT_PLANE5_FLIP_C = 0x54, + MAINDMC_EVENT_PLANE6_FLIP_C = 0x55, + MAINDMC_EVENT_PLANE7_FLIP_C = 0x56, + MAINDMC_EVENT_PLANE1_FLIP_D = 0x57, + MAINDMC_EVENT_PLANE2_FLIP_D = 0x58, + MAINDMC_EVENT_PLANE3_FLIP_D = 0x59, + MAINDMC_EVENT_PLANE4_FLIP_D = 0x5a, + MAINDMC_EVENT_PLANE5_FLIP_D = 0x5b, + MAINDMC_EVENT_PLANE6_FLIP_D = 0x5c, + MAINDMC_EVENT_PLANE7_FLIP_D = 0x5d, + MAINDMC_EVENT_PLANE1_FLIP_DONE_A = 0x5e, + MAINDMC_EVENT_PLANE2_FLIP_DONE_A = 0x5f, + MAINDMC_EVENT_PLANE3_FLIP_DONE_A = 0x60, + MAINDMC_EVENT_PLANE4_FLIP_DONE_A = 0x61, + MAINDMC_EVENT_PLANE5_FLIP_DONE_A = 0x62, + MAINDMC_EVENT_PLANE6_FLIP_DONE_A = 0x63, + MAINDMC_EVENT_PLANE7_FLIP_DONE_A = 0x64, + MAINDMC_EVENT_PLANE1_FLIP_DONE_B = 0x65, + MAINDMC_EVENT_PLANE2_FLIP_DONE_B = 0x66, + MAINDMC_EVENT_PLANE3_FLIP_DONE_B = 0x67, + MAINDMC_EVENT_PLANE4_FLIP_DONE_B = 0x68, + MAINDMC_EVENT_PLANE5_FLIP_DONE_B = 0x69, + MAINDMC_EVENT_PLANE6_FLIP_DONE_B = 0x6a, + MAINDMC_EVENT_PLANE7_FLIP_DONE_B = 0x6b, + MAINDMC_EVENT_PLANE1_FLIP_DONE_C = 0x6c, + MAINDMC_EVENT_PLANE2_FLIP_DONE_C = 0x6d, + MAINDMC_EVENT_PLANE3_FLIP_DONE_C = 0x6e, + MAINDMC_EVENT_PLANE4_FLIP_DONE_C = 0x6f, + MAINDMC_EVENT_PLANE5_FLIP_DONE_C = 0x70, + MAINDMC_EVENT_PLANE6_FLIP_DONE_C = 0x71, + MAINDMC_EVENT_PLANE7_FLIP_DONE_C = 0x72, + MAINDMC_EVENT_PLANE1_FLIP_DONE_D = 0x73, + MAINDMC_EVENT_PLANE2_FLIP_DONE_D = 0x74, + MAINDMC_EVENT_PLANE3_FLIP_DONE_D = 0x75, + MAINDMC_EVENT_PLANE4_FLIP_DONE_D = 0x76, + MAINDMC_EVENT_PLANE5_FLIP_DONE_D = 0x77, + MAINDMC_EVENT_PLANE6_FLIP_DONE_D = 0x78, + MAINDMC_EVENT_PLANE7_FLIP_DONE_D = 0x79, + + MAINDMC_EVENT_WIDI_GTT_FAULT_SL1 = 0x7d, + MAINDMC_EVENT_WIDI_GTT_FAULT_SL2 = 0x7e, + MAINDMC_EVENT_WIDI_CAP_ACTIVE_SL1 = 0x7f, + MAINDMC_EVENT_WIDI_CAP_ACTIVE_SL2 = 0x80, + + MAINDMC_EVENT_RENUKE_A = 0x85, + MAINDMC_EVENT_RENUKE_B = 0x86, + MAINDMC_EVENT_RENUKE_C = 0x87, + MAINDMC_EVENT_RENUKE_D = 0x88, + MAINDMC_EVENT_DPFC_FIFO_FULL_A = 0x89, + MAINDMC_EVENT_DPFC_FIFO_FULL_B = 0x8a, + MAINDMC_EVENT_DPFC_FIFO_FULL_C = 0x8b, + MAINDMC_EVENT_DPFC_FIFO_FULL_D = 0x8c, + MAINDMC_EVENT_DPFC_PIXEL_CNT_MISMATCH_A = 0x8d, + MAINDMC_EVENT_DPFC_PIXEL_CNT_MISMATCH_B = 0x8e, + MAINDMC_EVENT_DPFC_PIXEL_CNT_MISMATCH_C = 0x8f, + MAINDMC_EVENT_DPFC_PIXEL_CNT_MISMATCH_D = 0x90, + MAINDMC_EVENT_DPFC_COMPTAG_UNDERRUN_A = 0x91, + MAINDMC_EVENT_DPFC_COMPTAG_UNDERRUN_B = 0x92, + MAINDMC_EVENT_DPFC_COMPTAG_UNDERRUN_C = 0x93, + MAINDMC_EVENT_DPFC_COMPTAG_UNDERRUN_D = 0x94, + MAINDMC_EVENT_DPFC_FIFO_NOT_EMPTY_A = 0x95, + MAINDMC_EVENT_DPFC_FIFO_NOT_EMPTY_B = 0x96, + MAINDMC_EVENT_DPFC_FIFO_NOT_EMPTY_C = 0x97, + MAINDMC_EVENT_DPFC_FIFO_NOT_EMPTY_D = 0x98, + MAINDMC_EVENT_DPFC_COMPTAG_MISMATCH_A = 0x99, + MAINDMC_EVENT_DPFC_COMPTAG_MISMATCH_B = 0x9a, + MAINDMC_EVENT_DPFC_COMPTAG_MISMATCH_C = 0x9b, + MAINDMC_EVENT_DPFC_COMPTAG_MISMATCH_D = 0x9c, + MAINDMC_EVENT_DISP_PCH_INT = 0x9d, + MAINDMC_EVENT_GTT_ERR = 0x9e, + MAINDMC_EVENT_VTD_ERR = 0x9f, + MAINDMC_EVENT_FULL_FQ_WAKE_TRIGGER_A = 0xa0, + MAINDMC_EVENT_FULL_FQ_WAKE_TRIGGER_B = 0xa1, + MAINDMC_EVENT_FULL_FQ_WAKE_TRIGGER_C = 0xa2, + MAINDMC_EVENT_FULL_FQ_WAKE_TRIGGER_D = 0xa3, + MAINDMC_EVENT_PIPEDMC_CHICKEN_FW_EVENT_A = 0xa4, + MAINDMC_EVENT_PIPEDMC_CHICKEN_FW_EVENT_B = 0xa5, + MAINDMC_EVENT_PIPEDMC_CHICKEN_FW_EVENT_C = 0xa6, + MAINDMC_EVENT_PIPEDMC_CHICKEN_FW_EVENT_D = 0xa7, + + MAINDMC_EVENT_DC_CLOCK_OFF_START_EDP = 0xb2, + MAINDMC_EVENT_DC_CLOCK_OFF_START_DSI = 0xb3, + MAINDMC_EVENT_DCPR_DMC_CSR_START = 0xb4, + MAINDMC_EVENT_IN_PSR = 0xb5, + + MAINDMC_EVENT_IN_MEMUP = 0xb7, + MAINDMC_EVENT_IN_VGA = 0xb8, + + MAINDMC_EVENT_IN_KVM_SESSION = 0xba, + MAINDMC_EVENT_DEWAKE = 0xbb, + + MAINDMC_EVENT_TRAP_HIT = 0xbd, + MAINDMC_EVENT_CLK_USEC = 0xbe, + MAINDMC_EVENT_CLK_MSEC = 0xbf, + + MAINDMC_EVENT_CHICKEN1 = 0xc8, + MAINDMC_EVENT_CHICKEN2 = 0xc9, + MAINDMC_EVENT_CHICKEN3 = 0xca, + MAINDMC_EVENT_DDT_UBP = 0xcb, + + MAINDMC_EVENT_HP_LATENCY = 0xcd, + MAINDMC_EVENT_LP_LATENCY = 0xce, + MAINDMC_EVENT_WIDI_LP_REQ_SL1 = 0xcf, + MAINDMC_EVENT_WIDI_LP_REQ_SL2 = 0xd0, + + MAINDMC_EVENT_DG_DMC_EVT_0 = 0xd3, + MAINDMC_EVENT_DG_DMC_EVT_1 = 0xd4, + MAINDMC_EVENT_DG_DMC_EVT_2 = 0xd5, + MAINDMC_EVENT_DG_DMC_EVT_3 = 0xd6, + MAINDMC_EVENT_DG_DMC_EVT_4 = 0xd7, + MAINDMC_EVENT_DACFE_CLK_STOP = 0xd8, + MAINDMC_EVENT_DACFE_AZILIA_SDI_WAKE = 0xd9, + MAINDMC_EVENT_AUDIO_DOUBLE_FUNC_GRP_RST = 0xda, + MAINDMC_EVENT_AUDIO_CMD_VALID = 0xdb, + MAINDMC_EVENT_AUDIO_FRM_SYNC_BCLK = 0xdc, + MAINDMC_EVENT_AUDIO_FRM_SYNC_CDCLK = 0xdd, + MAINDMC_EVENT_AUDIO_PRESENCE_DETECT_A = 0xde, + MAINDMC_EVENT_AUDIO_PRESENCE_DETECT_B = 0xdf, + MAINDMC_EVENT_AUDIO_PRESENCE_DETECT_C = 0xe0, + MAINDMC_EVENT_AUDIO_PRESENCE_DETECT_E = 0xe1, + MAINDMC_EVENT_CMTG_SCANLINE_IN_GB_DC6v = 0xe2, + MAINDMC_EVENT_DCPR_CMTG_SCANLINE_OUTSIDE_GB = 0xe3, + MAINDMC_EVENT_DC6v_BACKWARD_COMPAT = 0xe4, + MAINDMC_EVENT_DPMA_PM_ABORT = 0xe5, + + MAINDMC_EVENT_STACK_OVF = 0xfc, + MAINDMC_EVENT_NO_CLAIM = 0xfd, + MAINDMC_EVENT_UNK_CMD = 0xfe, + MAINDMC_EVENT_HTP_MOD = 0xff, +}; + +enum pipedmc_event_id { + PIPEDMC_EVENT_TMR0_DONE = 0x14, + PIPEDMC_EVENT_TMR1_DONE = 0x15, + PIPEDMC_EVENT_TMR2_DONE = 0x16, + PIPEDMC_EVENT_COUNT0_DONE = 0x17, + PIPEDMC_EVENT_COUNT1_DONE = 0x18, + PIPEDMC_EVENT_PGA_PGB_RESTORE_DONE = 0x19, + PIPEDMC_EVENT_PG1_PG2_RESTORE_DONE = 0x1a, + PIPEDMC_EVENT_PGA_PGB_SAVE_DONE = 0x1b, + PIPEDMC_EVENT_PG1_PG2_SAVE_DONE = 0x1c, + + PIPEDMC_EVENT_FULL_FQ_WAKE_TRIGGER = 0x2b, + PIPEDMC_EVENT_1KHZ_FQ_TRIGGER = 0x2c, + PIPEDMC_EVENT_SCANLINE_INRANGE_FQ_TRIGGER = 0x2d, + PIPEDMC_EVENT_SCANLINE_INRANGE = 0x2e, + PIPEDMC_EVENT_SCANLINE_OUTRANGE = 0x2f, + PIPEDMC_EVENT_SCANLINE_EQUAL = 0x30, + PIPEDMC_EVENT_DELAYED_VBLANK = 0x31, + PIPEDMC_EVENT_VBLANK = 0x32, + PIPEDMC_EVENT_HBLANK = 0x33, + PIPEDMC_EVENT_VSYNC = 0x34, + PIPEDMC_EVENT_SCANLINE_FROM_DMUX = 0x35, + PIPEDMC_EVENT_PLANE1_FLIP = 0x36, + PIPEDMC_EVENT_PLANE2_FLIP = 0x37, + PIPEDMC_EVENT_PLANE3_FLIP = 0x38, + PIPEDMC_EVENT_PLANE4_FLIP = 0x39, + PIPEDMC_EVENT_PLANE5_FLIP = 0x3a, + PIPEDMC_EVENT_PLANE6_FLIP = 0x3b, + PIPEDMC_EVENT_PLANE7_FLIP = 0x3c, + PIPEDMC_EVENT_ADAPTIVE_DCB_TRIGGER = 0x3d, + + PIPEDMC_EVENT_PLANE1_FLIP_DONE = 0x56, + PIPEDMC_EVENT_PLANE2_FLIP_DONE = 0x57, + PIPEDMC_EVENT_PLANE3_FLIP_DONE = 0x58, + PIPEDMC_EVENT_PLANE4_FLIP_DONE = 0x59, + PIPEDMC_EVENT_PLANE5_FLIP_DONE = 0x5a, + PIPEDMC_EVENT_PLANE6_FLIP_DONE = 0x5b, + PIPEDMC_EVENT_PLANE7_FLIP_DONE = 0x5c, + + PIPEDMC_EVENT_GTT_ERR = 0x9b, + + PIPEDMC_EVENT_IN_PSR = 0xb5, + PIPEDMC_EVENT_DSI_DMC_IDLE = 0xb6, + PIPEDMC_EVENT_PSR2_DMC_IDLE = 0xb7, + PIPEDMC_EVENT_IN_VGA = 0xb8, + + PIPEDMC_EVENT_TRAP_HIT = 0xbd, + PIPEDMC_EVENT_CLK_USEC = 0xbe, + PIPEDMC_EVENT_CLK_MSEC = 0xbf, + + PIPEDMC_EVENT_CHICKEN1 = 0xc8, + PIPEDMC_EVENT_CHICKEN2 = 0xc9, + PIPEDMC_EVENT_CHICKEN3 = 0xca, + PIPEDMC_EVENT_DDT_UBP = 0xcb, + + PIPEDMC_EVENT_LP_LATENCY = 0xce, + + PIPEDMC_EVENT_LACE_PART_A_HIST_TRIGGER = 0xdf, + PIPEDMC_EVENT_LACE_PART_B_HIST_TRIGGER = 0xe0, + + PIPEDMC_EVENT_STACK_OVF = 0xfc, + PIPEDMC_EVENT_NO_CLAIM = 0xfd, + PIPEDMC_EVENT_UNK_CMD = 0xfe, + PIPEDMC_EVENT_HTP_MOD = 0xff, +}; + #define DMC_PROGRAM(addr, i) _MMIO((addr) + (i) * 4) #define DMC_SSP_BASE_ADDR_GEN9 0x00002FC0 @@ -93,12 +359,7 @@ #define DMC_EVT_CTL_TYPE_LEVEL_1 1 #define DMC_EVT_CTL_TYPE_EDGE_1_0 2 #define DMC_EVT_CTL_TYPE_EDGE_0_1 3 - #define DMC_EVT_CTL_EVENT_ID_MASK REG_GENMASK(15, 8) -#define DMC_EVT_CTL_EVENT_ID_FALSE 0x01 -#define DMC_EVT_CTL_EVENT_ID_VBLANK_A 0x32 /* main DMC */ -/* An event handler scheduled to run at a 1 kHz frequency. */ -#define DMC_EVT_CTL_EVENT_ID_CLK_MSEC 0xbf #define DMC_HTP_ADDR_SKL 0x00500034 #define DMC_SSP_BASE _MMIO(0x8F074) -- GitLab From 4c47d656f89a207562f99a174181789d45f571f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 12 May 2025 13:33:55 +0300 Subject: [PATCH 0104/1479] drm/i915/dmc: Extract dmc_evt_ctl_disable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have two copies of the code to generate the "disable this event" value for the DMC_EVT_CTL registers. Extract to a helper. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250512103358.15724-5-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/intel_dmc.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index e9aee3d5daf69..af1854cc6d148 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -539,6 +539,14 @@ void intel_dmc_disable_pipe(struct intel_display *display, enum pipe pipe) } } +static u32 dmc_evt_ctl_disable(void) +{ + return REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, + DMC_EVT_CTL_TYPE_EDGE_0_1) | + REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, + DMC_EVENT_FALSE); +} + /** * intel_dmc_block_pkgc() - block PKG C-state * @display: display instance @@ -578,10 +586,7 @@ void intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank(struct intel_display REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, PIPEDMC_EVENT_VBLANK); else - val = REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, - DMC_EVENT_FALSE) | - REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, - DMC_EVT_CTL_TYPE_EDGE_0_1); + val = dmc_evt_ctl_disable(); intel_de_write(display, MTL_PIPEDMC_EVT_CTL_4(pipe), val); @@ -638,10 +643,7 @@ static u32 dmc_mmiodata(struct intel_display *display, if (disable_dmc_evt(display, dmc_id, dmc->dmc_info[dmc_id].mmioaddr[i], dmc->dmc_info[dmc_id].mmiodata[i])) - return REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, - DMC_EVT_CTL_TYPE_EDGE_0_1) | - REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, - DMC_EVENT_FALSE); + return dmc_evt_ctl_disable(); else return dmc->dmc_info[dmc_id].mmiodata[i]; } -- GitLab From 583710251f6380b973bc594d54bcf4c131c81805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 12 May 2025 13:33:56 +0300 Subject: [PATCH 0105/1479] drm/i915/dmc: Relocate is_dmc_evt_{ctl,htp}_reg() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move is_dmc_evt_ctl_reg() to a slightly earlier position in the file so that we can reuse it in the pkgc workaround code. Also move is_dmc_evt_htp_reg() just to keep the two together. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250512103358.15724-6-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/intel_dmc.c | 40 ++++++++++++------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index af1854cc6d148..09a1933657c40 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -547,6 +547,26 @@ static u32 dmc_evt_ctl_disable(void) DMC_EVENT_FALSE); } +static bool is_dmc_evt_ctl_reg(struct intel_display *display, + enum intel_dmc_id dmc_id, i915_reg_t reg) +{ + u32 offset = i915_mmio_reg_offset(reg); + u32 start = i915_mmio_reg_offset(DMC_EVT_CTL(display, dmc_id, 0)); + u32 end = i915_mmio_reg_offset(DMC_EVT_CTL(display, dmc_id, DMC_EVENT_HANDLER_COUNT_GEN12)); + + return offset >= start && offset < end; +} + +static bool is_dmc_evt_htp_reg(struct intel_display *display, + enum intel_dmc_id dmc_id, i915_reg_t reg) +{ + u32 offset = i915_mmio_reg_offset(reg); + u32 start = i915_mmio_reg_offset(DMC_EVT_HTP(display, dmc_id, 0)); + u32 end = i915_mmio_reg_offset(DMC_EVT_HTP(display, dmc_id, DMC_EVENT_HANDLER_COUNT_GEN12)); + + return offset >= start && offset < end; +} + /** * intel_dmc_block_pkgc() - block PKG C-state * @display: display instance @@ -592,26 +612,6 @@ void intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank(struct intel_display val); } -static bool is_dmc_evt_ctl_reg(struct intel_display *display, - enum intel_dmc_id dmc_id, i915_reg_t reg) -{ - u32 offset = i915_mmio_reg_offset(reg); - u32 start = i915_mmio_reg_offset(DMC_EVT_CTL(display, dmc_id, 0)); - u32 end = i915_mmio_reg_offset(DMC_EVT_CTL(display, dmc_id, DMC_EVENT_HANDLER_COUNT_GEN12)); - - return offset >= start && offset < end; -} - -static bool is_dmc_evt_htp_reg(struct intel_display *display, - enum intel_dmc_id dmc_id, i915_reg_t reg) -{ - u32 offset = i915_mmio_reg_offset(reg); - u32 start = i915_mmio_reg_offset(DMC_EVT_HTP(display, dmc_id, 0)); - u32 end = i915_mmio_reg_offset(DMC_EVT_HTP(display, dmc_id, DMC_EVENT_HANDLER_COUNT_GEN12)); - - return offset >= start && offset < end; -} - static bool disable_dmc_evt(struct intel_display *display, enum intel_dmc_id dmc_id, i915_reg_t reg, u32 data) -- GitLab From d9dd810dd404ecb7bdfd3294bfb8d932e6066e05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 12 May 2025 13:33:57 +0300 Subject: [PATCH 0106/1479] drm/i915/dmc: Extract is_event_handler() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the helper to determine if the mmio reg+data are the event handler register (DMC_EVT_CTL) for a specific event. We'll have another use for this for runtime event handler enable/disable. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250512103358.15724-7-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/intel_dmc.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 09a1933657c40..9ab3ac3c1658e 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -567,6 +567,15 @@ static bool is_dmc_evt_htp_reg(struct intel_display *display, return offset >= start && offset < end; } +static bool is_event_handler(struct intel_display *display, + enum intel_dmc_id dmc_id, + unsigned int event_id, + i915_reg_t reg, u32 data) +{ + return is_dmc_evt_ctl_reg(display, dmc_id, reg) && + REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == event_id; +} + /** * intel_dmc_block_pkgc() - block PKG C-state * @display: display instance @@ -625,12 +634,12 @@ static bool disable_dmc_evt(struct intel_display *display, /* also disable the flip queue event on the main DMC on TGL */ if (display->platform.tigerlake && - REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == MAINDMC_EVENT_CLK_MSEC) + is_event_handler(display, dmc_id, MAINDMC_EVENT_CLK_MSEC, reg, data)) return true; /* also disable the HRR event on the main DMC on TGL/ADLS */ if ((display->platform.tigerlake || display->platform.alderlake_s) && - REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == MAINDMC_EVENT_VBLANK_A) + is_event_handler(display, dmc_id, MAINDMC_EVENT_VBLANK_A, reg, data)) return true; return false; -- GitLab From d65c47f976cc4c01ec1b4f9f113606f44f384de9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 12 May 2025 13:33:58 +0300 Subject: [PATCH 0107/1479] drm/i915/dmc: Introduce dmc_configure_event() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of hardcoding the event handler indices (for runtime event handler enable/disable) we can simply look for the handler with the appropriate event type. This isolates us from the firmware details a bit better. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250512103358.15724-8-ville.syrjala@linux.intel.com Reviewed-by: Luca Coelho --- drivers/gpu/drm/i915/display/intel_dmc.c | 39 +++++++++++++------ drivers/gpu/drm/i915/display/intel_dmc_regs.h | 6 --- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 9ab3ac3c1658e..a7ba17361d63b 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -576,6 +576,31 @@ static bool is_event_handler(struct intel_display *display, REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == event_id; } +static void dmc_configure_event(struct intel_display *display, + enum intel_dmc_id dmc_id, + unsigned int event_id, + bool enable) +{ + struct intel_dmc *dmc = display_to_dmc(display); + int num_handlers = 0; + int i; + + for (i = 0; i < dmc->dmc_info[dmc_id].mmio_count; i++) { + i915_reg_t reg = dmc->dmc_info[dmc_id].mmioaddr[i]; + u32 data = dmc->dmc_info[dmc_id].mmiodata[i]; + + if (!is_event_handler(display, dmc_id, event_id, reg, data)) + continue; + + intel_de_write(display, reg, enable ? data : dmc_evt_ctl_disable()); + num_handlers++; + } + + drm_WARN_ONCE(display->drm, num_handlers != 1, + "DMC %d has %d handlers for event 0x%x\n", + dmc_id, num_handlers, event_id); +} + /** * intel_dmc_block_pkgc() - block PKG C-state * @display: display instance @@ -606,19 +631,9 @@ void intel_dmc_block_pkgc(struct intel_display *display, enum pipe pipe, void intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank(struct intel_display *display, enum pipe pipe, bool enable) { - u32 val; - - if (enable) - val = DMC_EVT_CTL_ENABLE | DMC_EVT_CTL_RECURRING | - REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, - DMC_EVT_CTL_TYPE_EDGE_0_1) | - REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, - PIPEDMC_EVENT_VBLANK); - else - val = dmc_evt_ctl_disable(); + enum intel_dmc_id dmc_id = PIPE_TO_DMC_ID(pipe); - intel_de_write(display, MTL_PIPEDMC_EVT_CTL_4(pipe), - val); + dmc_configure_event(display, dmc_id, PIPEDMC_EVENT_VBLANK, enable); } static bool disable_dmc_evt(struct intel_display *display, diff --git a/drivers/gpu/drm/i915/display/intel_dmc_regs.h b/drivers/gpu/drm/i915/display/intel_dmc_regs.h index edd4e69319b97..d8e7156774544 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_dmc_regs.h @@ -287,12 +287,6 @@ enum pipedmc_event_id { #define MTL_PIPEDMC_CONTROL _MMIO(0x45250) #define PIPEDMC_ENABLE_MTL(pipe) REG_BIT(((pipe) - PIPE_A) * 4) -#define _MTL_PIPEDMC_EVT_CTL_4_A 0x5f044 -#define _MTL_PIPEDMC_EVT_CTL_4_B 0x5f444 -#define MTL_PIPEDMC_EVT_CTL_4(pipe) _MMIO_PIPE(pipe, \ - _MTL_PIPEDMC_EVT_CTL_4_A, \ - _MTL_PIPEDMC_EVT_CTL_4_B) - #define _PIPEDMC_STATUS_A 0x5f06c #define _PIPEDMC_STATUS_B 0x5f46c #define PIPEDMC_STATUS(pipe) _MMIO_PIPE((pipe), _PIPEDMC_STATUS_A, _PIPEDMC_STATUS_B) -- GitLab From 921ddb37d87c13eb811b8a3280377e4dab73eccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Pi=C3=B3rkowski?= Date: Tue, 13 May 2025 09:13:21 +0200 Subject: [PATCH 0108/1479] drm/xe/pf: Don't allow LMEM provisioning if LMTT isn't available on the device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The LMEM provisioning is applicable only on platforms with LMTT. v2: - new commit description - use xe_gt_assert in xe_gt_sriov_pf_config_set_lmem instead return error, - disable pf_lmem_info if LMTT is not available v3: fix condition in xe_gt_assert v4: rebase Signed-off-by: Piotr Piórkowski Cc: Michal Wajdeczko Reviewed-by: Stuart Summers Signed-off-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250513071321.700464-1-piotr.piorkowski@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 6 ++++-- drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index 2420a548cacc1..3556c41c041b5 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -1520,6 +1520,8 @@ int xe_gt_sriov_pf_config_set_lmem(struct xe_gt *gt, unsigned int vfid, u64 size { int err; + xe_gt_assert(gt, xe_device_has_lmtt(gt_to_xe(gt))); + mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); if (vfid) err = pf_provision_vf_lmem(gt, vfid, size); @@ -1629,7 +1631,7 @@ int xe_gt_sriov_pf_config_set_fair_lmem(struct xe_gt *gt, unsigned int vfid, xe_gt_assert(gt, num_vfs); xe_gt_assert(gt, !xe_gt_is_media_type(gt)); - if (!IS_DGFX(gt_to_xe(gt))) + if (!xe_device_has_lmtt(gt_to_xe(gt))) return 0; mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); @@ -2163,7 +2165,7 @@ static int pf_validate_vf_config(struct xe_gt *gt, unsigned int vfid) valid_all = valid_all && valid_ggtt; valid_any = valid_any || (valid_ggtt && is_primary); - if (IS_DGFX(xe)) { + if (xe_device_has_lmtt(xe)) { bool valid_lmem = pf_get_vf_config_lmem(primary_gt, vfid); valid_any = valid_any || (valid_lmem && is_primary); diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c index 0fe47f41b63c8..13970d5a2867d 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c @@ -308,7 +308,7 @@ static void pf_add_config_attrs(struct xe_gt *gt, struct dentry *parent, unsigne if (!xe_gt_is_media_type(gt)) { debugfs_create_file_unsafe(vfid ? "ggtt_quota" : "ggtt_spare", 0644, parent, parent, &ggtt_fops); - if (IS_DGFX(gt_to_xe(gt))) + if (xe_device_has_lmtt(gt_to_xe(gt))) debugfs_create_file_unsafe(vfid ? "lmem_quota" : "lmem_spare", 0644, parent, parent, &lmem_fops); } @@ -558,7 +558,7 @@ void xe_gt_sriov_pf_debugfs_register(struct xe_gt *gt, struct dentry *root) drm_debugfs_create_files(pf_ggtt_info, ARRAY_SIZE(pf_ggtt_info), pfdentry, minor); - if (IS_DGFX(gt_to_xe(gt))) + if (xe_device_has_lmtt(gt_to_xe(gt))) drm_debugfs_create_files(pf_lmem_info, ARRAY_SIZE(pf_lmem_info), pfdentry, minor); -- GitLab From a383cf218ef8bb35d4c03958bd956573b65cf778 Mon Sep 17 00:00:00 2001 From: Tejas Upadhyay Date: Tue, 6 May 2025 19:53:00 +0530 Subject: [PATCH 0109/1479] drm/xe/mocs: Check if all domains awake Check if all domains are awake specially for LNCF regs Fixes: 1182bc74b39b ("drm/xe: Fix MOCS debugfs LNCF readout") Improvements-suggested-by: Himal Prasad Ghimiray Reviewed-by: Badal Nilawar Link: https://patchwork.freedesktop.org/patch/msgid/20250506142300.1865783-1-tejas.upadhyay@intel.com Signed-off-by: Tejas Upadhyay --- drivers/gpu/drm/xe/xe_mocs.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_mocs.c b/drivers/gpu/drm/xe/xe_mocs.c index 31dade91a0897..0c737413fcb68 100644 --- a/drivers/gpu/drm/xe/xe_mocs.c +++ b/drivers/gpu/drm/xe/xe_mocs.c @@ -775,22 +775,23 @@ void xe_mocs_init(struct xe_gt *gt) void xe_mocs_dump(struct xe_gt *gt, struct drm_printer *p) { struct xe_device *xe = gt_to_xe(gt); + enum xe_force_wake_domains domain; struct xe_mocs_info table; unsigned int fw_ref, flags; flags = get_mocs_settings(xe, &table); + domain = flags & HAS_LNCF_MOCS ? XE_FORCEWAKE_ALL : XE_FW_GT; xe_pm_runtime_get_noresume(xe); - fw_ref = xe_force_wake_get(gt_to_fw(gt), - flags & HAS_LNCF_MOCS ? - XE_FORCEWAKE_ALL : XE_FW_GT); - if (!fw_ref) + fw_ref = xe_force_wake_get(gt_to_fw(gt), domain); + + if (!xe_force_wake_ref_has_domain(fw_ref, domain)) goto err_fw; table.ops->dump(&table, flags, gt, p); - xe_force_wake_put(gt_to_fw(gt), fw_ref); err_fw: + xe_force_wake_put(gt_to_fw(gt), fw_ref); xe_pm_runtime_put(xe); } -- GitLab From adc215791ab2dac76b847258cdc10bf8046f0659 Mon Sep 17 00:00:00 2001 From: Philipp Stanner Date: Thu, 24 Apr 2025 15:02:51 +0200 Subject: [PATCH 0110/1479] drm/nouveau: nouveau_fence: Standardize list iterations nouveau_fence.c iterates over lists in a non-canonical way. Since the operations done are just basic for-each-loops and list-empty checks, they should be written in the standard form. Use standard list operations. Signed-off-by: Philipp Stanner Link: https://lore.kernel.org/r/20250424130254.42046-3-phasta@kernel.org Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nouveau/nouveau_fence.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 6ded8c2b6d3bf..761c174cb286a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -83,13 +83,11 @@ nouveau_local_fence(struct dma_fence *fence, struct nouveau_drm *drm) void nouveau_fence_context_kill(struct nouveau_fence_chan *fctx, int error) { - struct nouveau_fence *fence; + struct nouveau_fence *fence, *tmp; unsigned long flags; spin_lock_irqsave(&fctx->lock, flags); - while (!list_empty(&fctx->pending)) { - fence = list_entry(fctx->pending.next, typeof(*fence), head); - + list_for_each_entry_safe(fence, tmp, &fctx->pending, head) { if (error && !dma_fence_is_signaled_locked(&fence->base)) dma_fence_set_error(&fence->base, error); @@ -130,13 +128,11 @@ nouveau_fence_context_free(struct nouveau_fence_chan *fctx) static int nouveau_fence_update(struct nouveau_channel *chan, struct nouveau_fence_chan *fctx) { - struct nouveau_fence *fence; + struct nouveau_fence *fence, *tmp; int drop = 0; u32 seq = fctx->read(chan); - while (!list_empty(&fctx->pending)) { - fence = list_entry(fctx->pending.next, typeof(*fence), head); - + list_for_each_entry_safe(fence, tmp, &fctx->pending, head) { if ((int)(seq - fence->base.seqno) < 0) break; @@ -151,15 +147,14 @@ nouveau_fence_uevent_work(struct work_struct *work) { struct nouveau_fence_chan *fctx = container_of(work, struct nouveau_fence_chan, uevent_work); + struct nouveau_channel *chan; + struct nouveau_fence *fence; unsigned long flags; int drop = 0; spin_lock_irqsave(&fctx->lock, flags); - if (!list_empty(&fctx->pending)) { - struct nouveau_fence *fence; - struct nouveau_channel *chan; - - fence = list_entry(fctx->pending.next, typeof(*fence), head); + fence = list_first_entry_or_null(&fctx->pending, typeof(*fence), head); + if (fence) { chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock)); if (nouveau_fence_update(chan, fctx)) drop = 1; -- GitLab From 2c0ddff2a60d00fa6f02de053e63e72c06f19e82 Mon Sep 17 00:00:00 2001 From: Philipp Stanner Date: Thu, 24 Apr 2025 15:02:52 +0200 Subject: [PATCH 0111/1479] drm/nouveau: Simplify calls to nvif_event_block() nouveau_fence_signal() returns a de-facto boolean to indicate when nvif_event_block() shall be called. The code can be made more compact and readable by calling nvif_event_block() in nouveau_fence_update() directly. Make those calls in nouveau_fence.c more canonical. Signed-off-by: Philipp Stanner Link: https://lore.kernel.org/r/20250424130254.42046-4-phasta@kernel.org Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nouveau/nouveau_fence.c | 31 +++++++++++-------------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 761c174cb286a..2b79bcb7da161 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -50,10 +50,10 @@ nouveau_fctx(struct nouveau_fence *fence) return container_of(fence->base.lock, struct nouveau_fence_chan, lock); } -static int +static bool nouveau_fence_signal(struct nouveau_fence *fence) { - int drop = 0; + bool drop = false; dma_fence_signal_locked(&fence->base); list_del(&fence->head); @@ -63,7 +63,7 @@ nouveau_fence_signal(struct nouveau_fence *fence) struct nouveau_fence_chan *fctx = nouveau_fctx(fence); if (!--fctx->notify_ref) - drop = 1; + drop = true; } dma_fence_put(&fence->base); @@ -125,21 +125,23 @@ nouveau_fence_context_free(struct nouveau_fence_chan *fctx) kref_put(&fctx->fence_ref, nouveau_fence_context_put); } -static int +static void nouveau_fence_update(struct nouveau_channel *chan, struct nouveau_fence_chan *fctx) { struct nouveau_fence *fence, *tmp; - int drop = 0; + bool drop = false; u32 seq = fctx->read(chan); list_for_each_entry_safe(fence, tmp, &fctx->pending, head) { if ((int)(seq - fence->base.seqno) < 0) break; - drop |= nouveau_fence_signal(fence); + if (nouveau_fence_signal(fence)) + drop = true; } - return drop; + if (drop) + nvif_event_block(&fctx->event); } static void @@ -150,18 +152,13 @@ nouveau_fence_uevent_work(struct work_struct *work) struct nouveau_channel *chan; struct nouveau_fence *fence; unsigned long flags; - int drop = 0; spin_lock_irqsave(&fctx->lock, flags); fence = list_first_entry_or_null(&fctx->pending, typeof(*fence), head); if (fence) { chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock)); - if (nouveau_fence_update(chan, fctx)) - drop = 1; + nouveau_fence_update(chan, fctx); } - if (drop) - nvif_event_block(&fctx->event); - spin_unlock_irqrestore(&fctx->lock, flags); } @@ -241,9 +238,7 @@ nouveau_fence_emit(struct nouveau_fence *fence) return -ENODEV; } - if (nouveau_fence_update(chan, fctx)) - nvif_event_block(&fctx->event); - + nouveau_fence_update(chan, fctx); list_add_tail(&fence->head, &fctx->pending); spin_unlock_irq(&fctx->lock); } @@ -265,8 +260,8 @@ nouveau_fence_done(struct nouveau_fence *fence) spin_lock_irqsave(&fctx->lock, flags); chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock)); - if (chan && nouveau_fence_update(chan, fctx)) - nvif_event_block(&fctx->event); + if (chan) + nouveau_fence_update(chan, fctx); spin_unlock_irqrestore(&fctx->lock, flags); } return dma_fence_is_signaled(&fence->base); -- GitLab From 2628009dba602d9959c9318c7732851780073523 Mon Sep 17 00:00:00 2001 From: Philipp Stanner Date: Thu, 24 Apr 2025 15:02:53 +0200 Subject: [PATCH 0112/1479] drm/nouveau: Simplify nouveau_fence_done() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nouveau_fence_done() contains an if branch that checks whether a nouveau_fence has either of the two existing nouveau_fence backend ops, which will always evaluate to true. Remove the surplus check. Signed-off-by: Philipp Stanner Reviewed-by: Christian König Link: https://lore.kernel.org/r/20250424130254.42046-5-phasta@kernel.org Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nouveau/nouveau_fence.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 2b79bcb7da161..fb9811938c827 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -249,21 +249,19 @@ nouveau_fence_emit(struct nouveau_fence *fence) bool nouveau_fence_done(struct nouveau_fence *fence) { - if (fence->base.ops == &nouveau_fence_ops_legacy || - fence->base.ops == &nouveau_fence_ops_uevent) { - struct nouveau_fence_chan *fctx = nouveau_fctx(fence); - struct nouveau_channel *chan; - unsigned long flags; + struct nouveau_fence_chan *fctx = nouveau_fctx(fence); + struct nouveau_channel *chan; + unsigned long flags; - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->base.flags)) - return true; + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->base.flags)) + return true; + + spin_lock_irqsave(&fctx->lock, flags); + chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock)); + if (chan) + nouveau_fence_update(chan, fctx); + spin_unlock_irqrestore(&fctx->lock, flags); - spin_lock_irqsave(&fctx->lock, flags); - chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock)); - if (chan) - nouveau_fence_update(chan, fctx); - spin_unlock_irqrestore(&fctx->lock, flags); - } return dma_fence_is_signaled(&fence->base); } -- GitLab From e0677e52545349b76a946c75fea89aa698aeb97a Mon Sep 17 00:00:00 2001 From: Philipp Stanner Date: Thu, 24 Apr 2025 15:02:54 +0200 Subject: [PATCH 0113/1479] drm/nouveau: Check dma_fence in canonical way In nouveau_fence_done(), a fence is checked for being signaled by manually evaluating the base fence's bits. This can be done in a canonical manner through dma_fence_is_signaled(). Replace the bit-check with dma_fence_is_signaled(). Signed-off-by: Philipp Stanner Link: https://lore.kernel.org/r/20250424130254.42046-6-phasta@kernel.org Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nouveau/nouveau_fence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index fb9811938c827..d5654e26d5bce 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -253,7 +253,7 @@ nouveau_fence_done(struct nouveau_fence *fence) struct nouveau_channel *chan; unsigned long flags; - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->base.flags)) + if (dma_fence_is_signaled(&fence->base)) return true; spin_lock_irqsave(&fctx->lock, flags); -- GitLab From 1c57014325ef2b62459c8482768a842f9c40cd0c Mon Sep 17 00:00:00 2001 From: Gareth Yu Date: Fri, 9 May 2025 17:25:39 +0800 Subject: [PATCH 0114/1479] drm/i915/dsi: Enforce pipeline flush with DSI HS transfer With all of the boundary conditions when streaming the commands B2B in our validation (part of the reason we added the flush), the Flush effectively serializes the transmission of each command enqueued within the command dispatcher to one per V. Blank line which simplifies the behavior of the High Speed Arbitration. So, unless we absolutely have to burst these to the Sink, we should be using the Pipeline Flush bit to serialize the commands. Bspec: 19742, 50193 Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14247 Cc: Suraj Kandpal Cc: Jani Nikula Signed-off-by: Gareth Yu Link: https://lore.kernel.org/r/20250509092539.763389-1-gareth.yu@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/icl_dsi.c | 4 ++-- drivers/gpu/drm/i915/display/icl_dsi_regs.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index ca7033251e916..28dab9320aedd 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -192,12 +192,12 @@ static int dsi_send_pkt_hdr(struct intel_dsi_host *host, else tmp &= ~PAYLOAD_PRESENT; - tmp &= ~VBLANK_FENCE; + tmp &= ~(VBLANK_FENCE | LP_DATA_TRANSFER | PIPELINE_FLUSH); if (enable_lpdt) tmp |= LP_DATA_TRANSFER; else - tmp &= ~LP_DATA_TRANSFER; + tmp |= PIPELINE_FLUSH; tmp &= ~(PARAM_WC_MASK | VC_MASK | DT_MASK); tmp |= ((packet->header[0] & VC_MASK) << VC_SHIFT); diff --git a/drivers/gpu/drm/i915/display/icl_dsi_regs.h b/drivers/gpu/drm/i915/display/icl_dsi_regs.h index d4845ac65acce..b601b7632339a 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi_regs.h +++ b/drivers/gpu/drm/i915/display/icl_dsi_regs.h @@ -272,6 +272,7 @@ #define PAYLOAD_PRESENT (1 << 31) #define LP_DATA_TRANSFER (1 << 30) #define VBLANK_FENCE (1 << 29) +#define PIPELINE_FLUSH (1 << 28) #define PARAM_WC_MASK (0xffff << 8) #define PARAM_WC_LOWER_SHIFT 8 #define PARAM_WC_UPPER_SHIFT 16 -- GitLab From 4b1f230c875d05186604b61a28e6c7db6bd1424d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 30 Apr 2025 11:06:32 +0300 Subject: [PATCH 0115/1479] drm/nouveau/fifo: small cleanup in nvkm_chan_cctx_get() "&chan->cgrp->mutex" and "&cgrp->mutex" are the same thing. Use "&cgrp->mutex" consistently. It looks nicer and it silences a Smatch static checker warning. Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/aBHaCM66pXaP84ei@stanley.mountain Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index 7d4716dcd5129..f5cd7f7c48b44 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -104,7 +104,7 @@ nvkm_chan_cctx_get(struct nvkm_chan *chan, struct nvkm_engn *engn, struct nvkm_c if (cctx) { refcount_inc(&cctx->refs); *pcctx = cctx; - mutex_unlock(&chan->cgrp->mutex); + mutex_unlock(&cgrp->mutex); return 0; } -- GitLab From 01738c4f4725005b8a8cdf0205761cb24b192a23 Mon Sep 17 00:00:00 2001 From: Zhang Enpei Date: Thu, 15 May 2025 20:11:08 +0800 Subject: [PATCH 0116/1479] drm/nouveau/dp: convert to use ERR_CAST() As opposed to open-code, use ERR_CAST to clearly indicate that this is a pointer to an error value and a type conversion is performed. Signed-off-by: Zhang Enpei Link: https://lore.kernel.org/r/20250515201108576jof-gkjSxRfMaGDgKo-pc@zte.com.cn Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c index 99110ab2f44dc..43ad467d09db7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c @@ -646,7 +646,7 @@ r535_conn_new(struct nvkm_disp *disp, u32 id) ctrl = nvkm_gsp_rm_ctrl_get(&disp->rm.objcom, NV0073_CTRL_CMD_SPECIFIC_GET_CONNECTOR_DATA, sizeof(*ctrl)); if (IS_ERR(ctrl)) - return (void *)ctrl; + return ERR_CAST(ctrl); ctrl->subDeviceInstance = 0; ctrl->displayId = BIT(id); -- GitLab From 3330b71caff6cdc387fdad68a895c9c81cc2f477 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 15 May 2025 14:11:10 -0700 Subject: [PATCH 0117/1479] drm/panel-edp: Add BOE NV133WUM-N61 panel entry Add an eDP panel for BOE NV133WUM-N61, which appears to be a 3rd panel option on the lenevo x13s laptop. edid: 00 ff ff ff ff ff ff 00 09 e5 64 09 00 00 00 00 16 1e 01 04 a5 1d 12 78 03 55 8e a7 51 4c 9c 26 0f 52 53 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 74 3c 80 a0 70 b0 28 40 30 20 36 00 1e b3 10 00 00 1a 5d 30 80 a0 70 b0 28 40 30 20 36 00 1e b3 10 00 00 1a 00 00 00 fe 00 42 4f 45 20 48 46 0a 20 20 20 20 20 20 00 00 00 fe 00 4e 56 31 33 33 57 55 4d 2d 4e 36 31 0a 00 7d datasheet: https://datasheet4u.com/pdf-down/N/V/1/NV133WUM-N61-BOE.pdf v2: Actually get the panel name correct in the table Signed-off-by: Rob Clark Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20250515211110.8806-1-robdclark@gmail.com --- drivers/gpu/drm/panel/panel-edp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index 90e8c154a9788..00dae545832e4 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1923,6 +1923,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('B', 'O', 'E', 0x094b, &delay_200_500_e50, "NT116WHM-N21"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0951, &delay_200_500_e80, "NV116WHM-N47"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x095f, &delay_200_500_e50, "NE135FBM-N41 v8.1"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x0964, &delay_200_500_e50, "NV133WUM-N61"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x096e, &delay_200_500_e50_po2e200, "NV116WHM-T07 V8.0"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0979, &delay_200_500_e50, "NV116WHM-N49 V8.0"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x098d, &boe_nv110wtm_n61.delay, "NV110WTM-N61"), -- GitLab From 5666e27a50666755f8a842f53dd68d6983126ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Fri, 16 May 2025 09:30:19 +0300 Subject: [PATCH 0118/1479] drm/i915/psr: Do not read PSR2_SU_STATUS on AlderLake and onwards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bspec comment on PSR2_SU_STATUS: "This register has been tied-off since DG2/ADL-P (it returns zeros only) and it has been removed on Xe2_LPD." v2: fix inversed logic Bspec: 69889 Signed-off-by: Jouni Högander Reviewed-by: Mika Kahola Link: https://lore.kernel.org/r/20250516063019.2126702-1-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 34 ++++++++++++++---------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 430ad4ef71466..cd833b63ea6b7 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -4021,24 +4021,30 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) int frame; /* - * Reading all 3 registers before hand to minimize crossing a - * frame boundary between register reads + * PSR2_SU_STATUS register has been tied-off since DG2/ADL-P + * (it returns zeros only) and it has been removed on Xe2_LPD. */ - for (frame = 0; frame < PSR2_SU_STATUS_FRAMES; frame += 3) { - val = intel_de_read(display, - PSR2_SU_STATUS(display, cpu_transcoder, frame)); - su_frames_val[frame / 3] = val; - } + if (DISPLAY_VER(display) < 13) { + /* + * Reading all 3 registers before hand to minimize crossing a + * frame boundary between register reads + */ + for (frame = 0; frame < PSR2_SU_STATUS_FRAMES; frame += 3) { + val = intel_de_read(display, + PSR2_SU_STATUS(display, cpu_transcoder, frame)); + su_frames_val[frame / 3] = val; + } - seq_puts(m, "Frame:\tPSR2 SU blocks:\n"); + seq_puts(m, "Frame:\tPSR2 SU blocks:\n"); - for (frame = 0; frame < PSR2_SU_STATUS_FRAMES; frame++) { - u32 su_blocks; + for (frame = 0; frame < PSR2_SU_STATUS_FRAMES; frame++) { + u32 su_blocks; - su_blocks = su_frames_val[frame / 3] & - PSR2_SU_STATUS_MASK(frame); - su_blocks = su_blocks >> PSR2_SU_STATUS_SHIFT(frame); - seq_printf(m, "%d\t%d\n", frame, su_blocks); + su_blocks = su_frames_val[frame / 3] & + PSR2_SU_STATUS_MASK(frame); + su_blocks = su_blocks >> PSR2_SU_STATUS_SHIFT(frame); + seq_printf(m, "%d\t%d\n", frame, su_blocks); + } } seq_printf(m, "PSR2 selective fetch: %s\n", -- GitLab From e1123e617e510a3652fc707155adc43bb3fe4160 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Mon, 5 May 2025 09:09:11 +0530 Subject: [PATCH 0119/1479] drm/i915/vrr: Program EMP_AS_SDP_TL for DP AS SDP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The register EMP_AS_SDP_TL (MTL) was introduced for configuring the double buffering point and transmission line for all HDMI2.1 Extended Metadata Packets (VT-EMP for VRR, CVT-EMP for DSC etc). This was also intended to be configured for DP to HDMI2.1 PCON to support VRR. From BMG and LNL+ onwards, this register was extended to Display Port Adaptive Sync SDP to have a common register to configure double buffering point and transmission line for both HDMI EMPs and DP VRR related packets. Currently, we do not support VRR for either native HDMI or via PCON. However we need to configure this for DP SDP case. As per the spec, program the register to set Vsync start as the double buffering point for DP AS SDP. v2: -Make the helper more readable. (Jani) -Add more information in commit message and comment. Bspec:70984, 71197 Signed-off-by: Ankit Nautiyal Tested-by: Jouni Högander Reviewed-by: Jouni Högander Link: https://lore.kernel.org/r/20250505033911.393628-1-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_vrr.c | 23 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_vrr_regs.h | 6 +++++ 2 files changed, 29 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index c6565baf815a1..c55b8144e234f 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -576,6 +576,25 @@ bool intel_vrr_always_use_vrr_tg(struct intel_display *display) return false; } +static +void intel_vrr_set_db_point_and_transmission_line(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + + /* + * For BMG and LNL+ onwards the EMP_AS_SDP_TL is used for programming + * double buffering point and transmission line for VRR packets for + * HDMI2.1/DP/eDP/DP->HDMI2.1 PCON. + * Since currently we support VRR only for DP/eDP, so this is programmed + * to for Adaptive Sync SDP to Vsync start. + */ + if (DISPLAY_VERx100(display) == 1401 || DISPLAY_VER(display) >= 20) + intel_de_write(display, + EMP_AS_SDP_TL(display, cpu_transcoder), + EMP_AS_SDP_DB_TL(crtc_state->vrr.vsync_start)); +} + void intel_vrr_enable(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); @@ -595,6 +614,8 @@ void intel_vrr_enable(const struct intel_crtc_state *crtc_state) TRANS_PUSH_EN); if (!intel_vrr_always_use_vrr_tg(display)) { + intel_vrr_set_db_point_and_transmission_line(crtc_state); + if (crtc_state->cmrr.enable) { intel_de_write(display, TRANS_VRR_CTL(display, cpu_transcoder), VRR_CTL_VRR_ENABLE | VRR_CTL_CMRR_ENABLE | @@ -646,6 +667,8 @@ void intel_vrr_transcoder_enable(const struct intel_crtc_state *crtc_state) intel_de_write(display, TRANS_PUSH(display, cpu_transcoder), TRANS_PUSH_EN); + intel_vrr_set_db_point_and_transmission_line(crtc_state); + intel_de_write(display, TRANS_VRR_CTL(display, cpu_transcoder), VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state)); } diff --git a/drivers/gpu/drm/i915/display/intel_vrr_regs.h b/drivers/gpu/drm/i915/display/intel_vrr_regs.h index 6ed0e0dc97e76..09cdd50d6187f 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr_regs.h +++ b/drivers/gpu/drm/i915/display/intel_vrr_regs.h @@ -108,6 +108,12 @@ #define VRR_VSYNC_START_MASK REG_GENMASK(12, 0) #define VRR_VSYNC_START(vsync_start) REG_FIELD_PREP(VRR_VSYNC_START_MASK, (vsync_start)) +/* Common register for HDMI EMP and DP AS SDP */ +#define _EMP_AS_SDP_TL_A 0x60204 +#define EMP_AS_SDP_DB_TL_MASK REG_GENMASK(12, 0) +#define EMP_AS_SDP_TL(dev_priv, trans) _MMIO_TRANS2(dev_priv, trans, _EMP_AS_SDP_TL_A) +#define EMP_AS_SDP_DB_TL(db_transmit_line) REG_FIELD_PREP(EMP_AS_SDP_DB_TL_MASK, (db_transmit_line)) + /*CMRR Registers*/ #define _TRANS_CMRR_M_LO_A 0x604F0 -- GitLab From 17486cf3df5320752cc67ee8bcb2379d1b9de76c Mon Sep 17 00:00:00 2001 From: Aradhya Bhatia Date: Fri, 16 May 2025 14:19:02 +0000 Subject: [PATCH 0120/1479] drm/xe/guc: Make creation of SLPC debugfs files conditional Platforms that do not support SLPC are exempted from the GuC PC support. The GuC PC does not get initialized, and neither do its BOs get created. This causes a problem because the GuC PC debugfs file is still being created. Whenever the file is attempted to read, it causes a NULL pointer dereference on the supposed BO of the GuC PC. So, make the creation of SLPC debugfs files conditional to when SLPC features are supported. Fixes: aaab5404b16f ("drm/xe: Introduce GuC PC debugfs") Suggested-by: Matt Roper Reviewed-by: Tejas Upadhyay Reviewed-by: Stuart Summers Signed-off-by: Aradhya Bhatia Link: https://lore.kernel.org/r/20250516141902.5614-1-aradhya.bhatia@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_guc_debugfs.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_debugfs.c b/drivers/gpu/drm/xe/xe_guc_debugfs.c index f33013f8a0f38..0b102ab46c4df 100644 --- a/drivers/gpu/drm/xe/xe_guc_debugfs.c +++ b/drivers/gpu/drm/xe/xe_guc_debugfs.c @@ -113,23 +113,34 @@ static const struct drm_info_list vf_safe_debugfs_list[] = { { "guc_ctb", .show = guc_debugfs_show, .data = guc_ctb }, }; +/* For GuC debugfs files that require the SLPC support */ +static const struct drm_info_list slpc_debugfs_list[] = { + { "guc_pc", .show = guc_debugfs_show, .data = guc_pc }, +}; + /* everything else should be added here */ static const struct drm_info_list pf_only_debugfs_list[] = { { "guc_log", .show = guc_debugfs_show, .data = guc_log }, { "guc_log_dmesg", .show = guc_debugfs_show, .data = guc_log_dmesg }, - { "guc_pc", .show = guc_debugfs_show, .data = guc_pc }, }; void xe_guc_debugfs_register(struct xe_guc *guc, struct dentry *parent) { - struct drm_minor *minor = guc_to_xe(guc)->drm.primary; + struct xe_device *xe = guc_to_xe(guc); + struct drm_minor *minor = xe->drm.primary; drm_debugfs_create_files(vf_safe_debugfs_list, ARRAY_SIZE(vf_safe_debugfs_list), parent, minor); - if (!IS_SRIOV_VF(guc_to_xe(guc))) + if (!IS_SRIOV_VF(xe)) { drm_debugfs_create_files(pf_only_debugfs_list, ARRAY_SIZE(pf_only_debugfs_list), parent, minor); + + if (!xe->info.skip_guc_pc) + drm_debugfs_create_files(slpc_debugfs_list, + ARRAY_SIZE(slpc_debugfs_list), + parent, minor); + } } -- GitLab From a7f87deac2295d11865048bcb9c2de369b52ed93 Mon Sep 17 00:00:00 2001 From: Aradhya Bhatia Date: Fri, 16 May 2025 12:43:55 +0000 Subject: [PATCH 0121/1479] drm/xe: Default auto_link_downgrade status to false xe_pcode_read() can return back successfully without updating the variable 'val'. This can cause an arbitrary value to show up in the sysfs file. Allow the auto_link_downgrade_status to default to 0 to avoid any arbitrary value from coming up. Fixes: 0e414bf7ad01 ("drm/xe: Expose PCIe link downgrade attributes") Reviewed-by: Tejas Upadhyay Signed-off-by: Aradhya Bhatia Link: https://lore.kernel.org/r/20250516124355.4872-1-aradhya.bhatia@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_device_sysfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_device_sysfs.c b/drivers/gpu/drm/xe/xe_device_sysfs.c index 9628e9a0a0af5..2e657692e5b5f 100644 --- a/drivers/gpu/drm/xe/xe_device_sysfs.c +++ b/drivers/gpu/drm/xe/xe_device_sysfs.c @@ -124,7 +124,8 @@ auto_link_downgrade_status_show(struct device *dev, struct device_attribute *att { struct pci_dev *pdev = to_pci_dev(dev); struct xe_device *xe = pdev_to_xe_device(pdev); - u32 val; + /* default the auto_link_downgrade status to 0 */ + u32 val = 0; int ret; xe_pm_runtime_get(xe); -- GitLab From 6f446bbe412ab3d75651d1cc52e31aaf801dbea8 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Sun, 18 May 2025 22:54:11 +0000 Subject: [PATCH 0122/1479] dt-bindings: gpu: mali-utgard: Add Rockchip RK3528 compatible Rockchip RK3528 SoC has a Mali-450 MP2. Add a compatible for it. Signed-off-by: Jonas Karlman Acked-by: Conor Dooley Signed-off-by: Heiko Stuebner Link: https://lore.kernel.org/r/20250518225418.682182-2-jonas@kwiboo.se --- Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml b/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml index 9318817ea1357..c8d0d9192d92c 100644 --- a/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml +++ b/Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml @@ -47,6 +47,7 @@ properties: - hisilicon,hi6220-mali - mediatek,mt7623-mali - rockchip,rk3328-mali + - rockchip,rk3528-mali - const: arm,mali-450 # "arm,mali-300" @@ -148,6 +149,7 @@ allOf: - rockchip,rk3188-mali - rockchip,rk3228-mali - rockchip,rk3328-mali + - rockchip,rk3528-mali then: required: - resets -- GitLab From d2662cf8f44a68deb6c76ad9f1d9f29dbf7ba601 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 13 May 2025 15:30:10 +0000 Subject: [PATCH 0123/1479] drm/xe: Use xe_mmio_read32() to read mtcfg register The mtcfg register is a 32-bit register and should therefore be accessed using xe_mmio_read32(). Other 3 changes per codestyle suggestion: " xe_mmio.c:83: CHECK: Alignment should match open parenthesis xe_mmio.c:131: CHECK: Comparison to NULL could be written "!xe->mmio.regs" xe_mmio.c:315: CHECK: line length of 103 exceeds 100 columns " Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs") Reviewed-by: Tejas Upadhyay Cc: Matt Roper Signed-off-by: Shuicheng Lin Link: https://lore.kernel.org/r/20250513153010.3464767-1-shuicheng.lin@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_mmio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c index 096c38cc51c83..7357458bc0d21 100644 --- a/drivers/gpu/drm/xe/xe_mmio.c +++ b/drivers/gpu/drm/xe/xe_mmio.c @@ -75,12 +75,12 @@ static void mmio_multi_tile_setup(struct xe_device *xe, size_t tile_mmio_size) * is fine as it's going to the root tile's mmio, that's * guaranteed to be initialized earlier in xe_mmio_probe_early() */ - mtcfg = xe_mmio_read64_2x32(mmio, XEHP_MTCFG_ADDR); + mtcfg = xe_mmio_read32(mmio, XEHP_MTCFG_ADDR); tile_count = REG_FIELD_GET(TILE_COUNT, mtcfg) + 1; if (tile_count < xe->info.tile_count) { drm_info(&xe->drm, "tile_count: %d, reduced_tile_count %d\n", - xe->info.tile_count, tile_count); + xe->info.tile_count, tile_count); xe->info.tile_count = tile_count; /* @@ -128,7 +128,7 @@ int xe_mmio_probe_early(struct xe_device *xe) */ xe->mmio.size = pci_resource_len(pdev, GTTMMADR_BAR); xe->mmio.regs = pci_iomap(pdev, GTTMMADR_BAR, 0); - if (xe->mmio.regs == NULL) { + if (!xe->mmio.regs) { drm_err(&xe->drm, "failed to map registers\n"); return -EIO; } @@ -312,8 +312,8 @@ u64 xe_mmio_read64_2x32(struct xe_mmio *mmio, struct xe_reg reg) return (u64)udw << 32 | ldw; } -static int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us, - u32 *out_val, bool atomic, bool expect_match) +static int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val, + u32 timeout_us, u32 *out_val, bool atomic, bool expect_match) { ktime_t cur = ktime_get_raw(); const ktime_t end = ktime_add_us(cur, timeout_us); -- GitLab From 099593a28138b48feea5be8ce700e5bc4565e31d Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Fri, 9 May 2025 11:15:59 +0800 Subject: [PATCH 0124/1479] drm/rockchip: cleanup fb when drm_gem_fb_afbc_init failed In the function drm_gem_fb_init_with_funcs, the framebuffer (fb) and its corresponding object ID have already been registered. So we need to cleanup the drm framebuffer if the subsequent execution of drm_gem_fb_afbc_init fails. Directly call drm_framebuffer_put to ensure that all fb related resources are cleanup. Fixes: 7707f7227f09 ("drm/rockchip: Add support for afbc") Signed-off-by: Andy Yan Signed-off-by: Heiko Stuebner Link: https://lore.kernel.org/r/20250509031607.2542187-1-andyshrk@163.com --- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index dcc1f07632c3a..5829ee061c61b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -52,16 +52,9 @@ rockchip_fb_create(struct drm_device *dev, struct drm_file *file, } if (drm_is_afbc(mode_cmd->modifier[0])) { - int ret, i; - ret = drm_gem_fb_afbc_init(dev, mode_cmd, afbc_fb); if (ret) { - struct drm_gem_object **obj = afbc_fb->base.obj; - - for (i = 0; i < info->num_planes; ++i) - drm_gem_object_put(obj[i]); - - kfree(afbc_fb); + drm_framebuffer_put(&afbc_fb->base); return ERR_PTR(ret); } } -- GitLab From ce6c4580334a45f3840834c880f395003f5bbc93 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 5 Mar 2025 13:00:25 +0200 Subject: [PATCH 0125/1479] accel/habanalabs: Switch to use %ptTs Use %ptTs instead of open-coded variant to print contents of time64_t type in human readable form. This changes N/A output to 1970-01-01 00:00:00 for zero timestamps, but it's used only in the dev_err() output and won't break anything. Signed-off-by: Andy Shevchenko Acked-by: Yaron Avizrat Reviewed-by: Koby Elbaz Link: https://lore.kernel.org/r/20250305110126.2134307-1-andriy.shevchenko@linux.intel.com Signed-off-by: Koby Elbaz --- drivers/accel/habanalabs/common/device.c | 25 +++--------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/drivers/accel/habanalabs/common/device.c b/drivers/accel/habanalabs/common/device.c index 68eebed3b050f..80fa08bf57bdc 100644 --- a/drivers/accel/habanalabs/common/device.c +++ b/drivers/accel/habanalabs/common/device.c @@ -1066,28 +1066,11 @@ static bool is_pci_link_healthy(struct hl_device *hdev) return (device_id == hdev->pdev->device); } -static void stringify_time_of_last_heartbeat(struct hl_device *hdev, char *time_str, size_t size, - bool is_pq_hb) -{ - time64_t seconds = is_pq_hb ? hdev->heartbeat_debug_info.last_pq_heartbeat_ts - : hdev->heartbeat_debug_info.last_eq_heartbeat_ts; - struct tm tm; - - if (!seconds) - return; - - time64_to_tm(seconds, 0, &tm); - - snprintf(time_str, size, "%ld-%02d-%02d %02d:%02d:%02d (UTC)", - tm.tm_year + 1900, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); -} - static bool hl_device_eq_heartbeat_received(struct hl_device *hdev) { struct eq_heartbeat_debug_info *heartbeat_debug_info = &hdev->heartbeat_debug_info; u32 cpu_q_id = heartbeat_debug_info->cpu_queue_id, pq_pi_mask = (HL_QUEUE_LENGTH << 1) - 1; struct asic_fixed_properties *prop = &hdev->asic_prop; - char pq_time_str[64] = "N/A", eq_time_str[64] = "N/A"; if (!prop->cpucp_info.eq_health_check_supported) return true; @@ -1095,17 +1078,15 @@ static bool hl_device_eq_heartbeat_received(struct hl_device *hdev) if (!hdev->eq_heartbeat_received) { dev_err(hdev->dev, "EQ heartbeat event was not received!\n"); - stringify_time_of_last_heartbeat(hdev, pq_time_str, sizeof(pq_time_str), true); - stringify_time_of_last_heartbeat(hdev, eq_time_str, sizeof(eq_time_str), false); dev_err(hdev->dev, - "EQ: {CI %u, HB counter %u, last HB time: %s}, PQ: {PI: %u, CI: %u (%u), last HB time: %s}\n", + "EQ: {CI %u, HB counter %u, last HB time: %ptTs}, PQ: {PI: %u, CI: %u (%u), last HB time: %ptTs}\n", hdev->event_queue.ci, heartbeat_debug_info->heartbeat_event_counter, - eq_time_str, + &hdev->heartbeat_debug_info.last_eq_heartbeat_ts, hdev->kernel_queues[cpu_q_id].pi, atomic_read(&hdev->kernel_queues[cpu_q_id].ci), atomic_read(&hdev->kernel_queues[cpu_q_id].ci) & pq_pi_mask, - pq_time_str); + &hdev->heartbeat_debug_info.last_pq_heartbeat_ts); hl_eq_dump(hdev, &hdev->event_queue); -- GitLab From 537d00c8fda47250c2a763eea2b8a86708e029b0 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:48 +0530 Subject: [PATCH 0126/1479] drm/i915/dpll: Rename intel_dpll Rename intel_dpll to intel_dpll_global so that intel_shared_dpll can be renamed to intel_dpll in an effort to move away from the shared naming convention. Also intel_dpll according to it's comment tracks global dpll rather than individual hence making more sense this gets changed. Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-2-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_display_core.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index b4937e1023606..6fc213f84e73e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -122,7 +122,7 @@ struct intel_audio { * intel_{prepare,enable,disable}_shared_dpll. Must be global rather than per * dpll, because on some platforms plls share registers. */ -struct intel_dpll { +struct intel_dpll_global { struct mutex lock; int num_shared_dpll; @@ -570,7 +570,7 @@ struct intel_display { /* Grouping using named structs. Keep sorted. */ struct drm_dp_tunnel_mgr *dp_tunnel_mgr; struct intel_audio audio; - struct intel_dpll dpll; + struct intel_dpll_global dpll; struct intel_fbc *fbc[I915_MAX_FBCS]; struct intel_frontbuffer_tracking fb_tracking; struct intel_hotplug hotplug; -- GitLab From e12c9b439f2cbcb574cd71ff7e14121b59ef0fe4 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:49 +0530 Subject: [PATCH 0127/1479] drm/i915/dpll: Rename intel_dpll_funcs Rename intel_dpll_funcs to intel_dpll_global_funcs so that later on intel_shared_dpll_funcs can be renamed to intel_dpll_funcs. This is done to move away from the shared naming convention since starting MTL dpll's are not shared among PHYs. Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-3-suraj.kandpal@intel.com --- .../gpu/drm/i915/display/intel_display_core.h | 4 ++-- drivers/gpu/drm/i915/display/intel_dpll.c | 22 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 6fc213f84e73e..e0221e514326b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -42,7 +42,7 @@ struct intel_color_funcs; struct intel_crtc; struct intel_crtc_state; struct intel_dmc; -struct intel_dpll_funcs; +struct intel_dpll_global_funcs; struct intel_dpll_mgr; struct intel_fbdev; struct intel_fdi_funcs; @@ -300,7 +300,7 @@ struct intel_display { const struct intel_cdclk_funcs *cdclk; /* Display pll funcs */ - const struct intel_dpll_funcs *dpll; + const struct intel_dpll_global_funcs *dpll; /* irq display functions */ const struct intel_hotplug_funcs *hotplug; diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index dd7a29c10b5d8..c13fb37ea584f 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -25,7 +25,7 @@ #include "vlv_dpio_phy_regs.h" #include "vlv_sideband.h" -struct intel_dpll_funcs { +struct intel_dpll_global_funcs { int (*crtc_compute_clock)(struct intel_atomic_state *state, struct intel_crtc *crtc); int (*crtc_get_shared_dpll)(struct intel_atomic_state *state, @@ -1691,45 +1691,45 @@ static int i8xx_crtc_compute_clock(struct intel_atomic_state *state, return 0; } -static const struct intel_dpll_funcs mtl_dpll_funcs = { +static const struct intel_dpll_global_funcs mtl_dpll_funcs = { .crtc_compute_clock = mtl_crtc_compute_clock, }; -static const struct intel_dpll_funcs dg2_dpll_funcs = { +static const struct intel_dpll_global_funcs dg2_dpll_funcs = { .crtc_compute_clock = dg2_crtc_compute_clock, }; -static const struct intel_dpll_funcs hsw_dpll_funcs = { +static const struct intel_dpll_global_funcs hsw_dpll_funcs = { .crtc_compute_clock = hsw_crtc_compute_clock, .crtc_get_shared_dpll = hsw_crtc_get_shared_dpll, }; -static const struct intel_dpll_funcs ilk_dpll_funcs = { +static const struct intel_dpll_global_funcs ilk_dpll_funcs = { .crtc_compute_clock = ilk_crtc_compute_clock, .crtc_get_shared_dpll = ilk_crtc_get_shared_dpll, }; -static const struct intel_dpll_funcs chv_dpll_funcs = { +static const struct intel_dpll_global_funcs chv_dpll_funcs = { .crtc_compute_clock = chv_crtc_compute_clock, }; -static const struct intel_dpll_funcs vlv_dpll_funcs = { +static const struct intel_dpll_global_funcs vlv_dpll_funcs = { .crtc_compute_clock = vlv_crtc_compute_clock, }; -static const struct intel_dpll_funcs g4x_dpll_funcs = { +static const struct intel_dpll_global_funcs g4x_dpll_funcs = { .crtc_compute_clock = g4x_crtc_compute_clock, }; -static const struct intel_dpll_funcs pnv_dpll_funcs = { +static const struct intel_dpll_global_funcs pnv_dpll_funcs = { .crtc_compute_clock = pnv_crtc_compute_clock, }; -static const struct intel_dpll_funcs i9xx_dpll_funcs = { +static const struct intel_dpll_global_funcs i9xx_dpll_funcs = { .crtc_compute_clock = i9xx_crtc_compute_clock, }; -static const struct intel_dpll_funcs i8xx_dpll_funcs = { +static const struct intel_dpll_global_funcs i8xx_dpll_funcs = { .crtc_compute_clock = i8xx_crtc_compute_clock, }; -- GitLab From 139f267322d617dd9a6ac75d2e2b40110920e94c Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:50 +0530 Subject: [PATCH 0128/1479] drm/i915/dpll: Rename intel_shared_dpll_state Rename intel_shared_dpll_state to just intel_dpll_state since it may not necessarily store share dpll state info specially since DISPLAY_VER >= 14 PLL's are not shared. Also change the name of variables which may have been associated as a shared_dpll. Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-4-suraj.kandpal@intel.com --- .../drm/i915/display/intel_display_types.h | 2 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 56 +++++++++---------- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 8 +-- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 056219272c36e..9df7795b9327a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -595,7 +595,7 @@ struct intel_atomic_state { bool dpll_set, modeset; - struct intel_shared_dpll_state shared_dpll[I915_NUM_PLLS]; + struct intel_dpll_state dpll_state[I915_NUM_PLLS]; struct intel_dp_tunnel_inherited_state *inherited_dp_tunnels; diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 9da051a3f4550..6b4eb230f4b3c 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -122,17 +122,17 @@ struct intel_dpll_mgr { static void intel_atomic_duplicate_dpll_state(struct intel_display *display, - struct intel_shared_dpll_state *shared_dpll) + struct intel_dpll_state *dpll_state) { struct intel_shared_dpll *pll; int i; /* Copy shared dpll state */ for_each_shared_dpll(display, pll, i) - shared_dpll[pll->index] = pll->state; + dpll_state[pll->index] = pll->state; } -static struct intel_shared_dpll_state * +static struct intel_dpll_state * intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s) { struct intel_atomic_state *state = to_intel_atomic_state(s); @@ -144,10 +144,10 @@ intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s) state->dpll_set = true; intel_atomic_duplicate_dpll_state(display, - state->shared_dpll); + state->dpll_state); } - return state->shared_dpll; + return state->dpll_state; } /** @@ -365,11 +365,11 @@ intel_find_shared_dpll(struct intel_atomic_state *state, { struct intel_display *display = to_intel_display(crtc); unsigned long dpll_mask_all = intel_dpll_mask_all(display); - struct intel_shared_dpll_state *shared_dpll; + struct intel_dpll_state *dpll_state; struct intel_shared_dpll *unused_pll = NULL; enum intel_dpll_id id; - shared_dpll = intel_atomic_get_shared_dpll_state(&state->base); + dpll_state = intel_atomic_get_shared_dpll_state(&state->base); drm_WARN_ON(display->drm, dpll_mask & ~dpll_mask_all); @@ -381,20 +381,20 @@ intel_find_shared_dpll(struct intel_atomic_state *state, continue; /* Only want to check enabled timings first */ - if (shared_dpll[pll->index].pipe_mask == 0) { + if (dpll_state[pll->index].pipe_mask == 0) { if (!unused_pll) unused_pll = pll; continue; } if (memcmp(dpll_hw_state, - &shared_dpll[pll->index].hw_state, + &dpll_state[pll->index].hw_state, sizeof(*dpll_hw_state)) == 0) { drm_dbg_kms(display->drm, "[CRTC:%d:%s] sharing existing %s (pipe mask 0x%x, active 0x%x)\n", crtc->base.base.id, crtc->base.name, pll->info->name, - shared_dpll[pll->index].pipe_mask, + dpll_state[pll->index].pipe_mask, pll->active_mask); return pll; } @@ -415,20 +415,20 @@ intel_find_shared_dpll(struct intel_atomic_state *state, * intel_reference_shared_dpll_crtc - Get a DPLL reference for a CRTC * @crtc: CRTC on which behalf the reference is taken * @pll: DPLL for which the reference is taken - * @shared_dpll_state: the DPLL atomic state in which the reference is tracked + * @dpll_state: the DPLL atomic state in which the reference is tracked * * Take a reference for @pll tracking the use of it by @crtc. */ static void intel_reference_shared_dpll_crtc(const struct intel_crtc *crtc, const struct intel_shared_dpll *pll, - struct intel_shared_dpll_state *shared_dpll_state) + struct intel_dpll_state *dpll_state) { struct intel_display *display = to_intel_display(crtc); - drm_WARN_ON(display->drm, (shared_dpll_state->pipe_mask & BIT(crtc->pipe)) != 0); + drm_WARN_ON(display->drm, (dpll_state->pipe_mask & BIT(crtc->pipe)) != 0); - shared_dpll_state->pipe_mask |= BIT(crtc->pipe); + dpll_state->pipe_mask |= BIT(crtc->pipe); drm_dbg_kms(display->drm, "[CRTC:%d:%s] reserving %s\n", crtc->base.base.id, crtc->base.name, pll->info->name); @@ -440,34 +440,34 @@ intel_reference_shared_dpll(struct intel_atomic_state *state, const struct intel_shared_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { - struct intel_shared_dpll_state *shared_dpll; + struct intel_dpll_state *dpll_state; - shared_dpll = intel_atomic_get_shared_dpll_state(&state->base); + dpll_state = intel_atomic_get_shared_dpll_state(&state->base); - if (shared_dpll[pll->index].pipe_mask == 0) - shared_dpll[pll->index].hw_state = *dpll_hw_state; + if (dpll_state[pll->index].pipe_mask == 0) + dpll_state[pll->index].hw_state = *dpll_hw_state; - intel_reference_shared_dpll_crtc(crtc, pll, &shared_dpll[pll->index]); + intel_reference_shared_dpll_crtc(crtc, pll, &dpll_state[pll->index]); } /** * intel_unreference_shared_dpll_crtc - Drop a DPLL reference for a CRTC * @crtc: CRTC on which behalf the reference is dropped * @pll: DPLL for which the reference is dropped - * @shared_dpll_state: the DPLL atomic state in which the reference is tracked + * @dpll_state: the DPLL atomic state in which the reference is tracked * * Drop a reference for @pll tracking the end of use of it by @crtc. */ void intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, const struct intel_shared_dpll *pll, - struct intel_shared_dpll_state *shared_dpll_state) + struct intel_dpll_state *dpll_state) { struct intel_display *display = to_intel_display(crtc); - drm_WARN_ON(display->drm, (shared_dpll_state->pipe_mask & BIT(crtc->pipe)) == 0); + drm_WARN_ON(display->drm, (dpll_state->pipe_mask & BIT(crtc->pipe)) == 0); - shared_dpll_state->pipe_mask &= ~BIT(crtc->pipe); + dpll_state->pipe_mask &= ~BIT(crtc->pipe); drm_dbg_kms(display->drm, "[CRTC:%d:%s] releasing %s\n", crtc->base.base.id, crtc->base.name, pll->info->name); @@ -477,11 +477,11 @@ static void intel_unreference_shared_dpll(struct intel_atomic_state *state, const struct intel_crtc *crtc, const struct intel_shared_dpll *pll) { - struct intel_shared_dpll_state *shared_dpll; + struct intel_dpll_state *dpll_state; - shared_dpll = intel_atomic_get_shared_dpll_state(&state->base); + dpll_state = intel_atomic_get_shared_dpll_state(&state->base); - intel_unreference_shared_dpll_crtc(crtc, pll, &shared_dpll[pll->index]); + intel_unreference_shared_dpll_crtc(crtc, pll, &dpll_state[pll->index]); } static void intel_put_dpll(struct intel_atomic_state *state, @@ -514,7 +514,7 @@ static void intel_put_dpll(struct intel_atomic_state *state, void intel_shared_dpll_swap_state(struct intel_atomic_state *state) { struct intel_display *display = to_intel_display(state); - struct intel_shared_dpll_state *shared_dpll = state->shared_dpll; + struct intel_dpll_state *dpll_state = state->dpll_state; struct intel_shared_dpll *pll; int i; @@ -522,7 +522,7 @@ void intel_shared_dpll_swap_state(struct intel_atomic_state *state) return; for_each_shared_dpll(display, pll, i) - swap(pll->state, shared_dpll[pll->index]); + swap(pll->state, dpll_state[pll->index]); } static bool ibx_pch_dpll_get_hw_state(struct intel_display *display, diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index caffb084830ce..fe6c676737bb4 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -280,7 +280,7 @@ struct intel_dpll_hw_state { }; /** - * struct intel_shared_dpll_state - hold the DPLL atomic state + * struct intel_dpll_state - hold the DPLL atomic state * * This structure holds an atomic state for the DPLL, that can represent * either its current state (in struct &intel_shared_dpll) or a desired @@ -289,7 +289,7 @@ struct intel_dpll_hw_state { * * See also intel_reserve_shared_dplls() and intel_release_shared_dplls(). */ -struct intel_shared_dpll_state { +struct intel_dpll_state { /** * @pipe_mask: mask of pipes using this DPLL, active or not */ @@ -353,7 +353,7 @@ struct intel_shared_dpll { * Store the state for the pll, including its hw state * and CRTCs using it. */ - struct intel_shared_dpll_state state; + struct intel_dpll_state state; /** * @index: index for atomic state @@ -406,7 +406,7 @@ void intel_release_shared_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, const struct intel_shared_dpll *pll, - struct intel_shared_dpll_state *shared_dpll_state); + struct intel_dpll_state *shared_dpll_state); void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state, enum icl_port_dpll_id port_dpll_id); void intel_update_active_dpll(struct intel_atomic_state *state, -- GitLab From 958a33200ac7c85e95b5a5c93bb3b2004b752aed Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:51 +0530 Subject: [PATCH 0129/1479] drm/i915/dpll: Rename macro for_each_shared_dpll Rename the macro for_each_shared_dpll to for_each_dpll since this loop will not necessarily be used for only shared dpll in future. Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-5-suraj.kandpal@intel.com --- .../gpu/drm/i915/display/intel_display_debugfs.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 16 ++++++++-------- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 2 +- drivers/gpu/drm/i915/display/intel_pch_refclk.c | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 9df8995e5bac6..11a7fec202327 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -627,7 +627,7 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused) display->dpll.ref_clks.nssc, display->dpll.ref_clks.ssc); - for_each_shared_dpll(display, pll, i) { + for_each_dpll(display, pll, i) { drm_printf(&p, "DPLL%i: %s, id: %i\n", pll->index, pll->info->name, pll->info->id); drm_printf(&p, " pipe_mask: 0x%x, active: 0x%x, on: %s\n", diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 6b4eb230f4b3c..9974fdb6eaeb5 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -127,8 +127,8 @@ intel_atomic_duplicate_dpll_state(struct intel_display *display, struct intel_shared_dpll *pll; int i; - /* Copy shared dpll state */ - for_each_shared_dpll(display, pll, i) + /* Copy dpll state */ + for_each_dpll(display, pll, i) dpll_state[pll->index] = pll->state; } @@ -165,7 +165,7 @@ intel_get_shared_dpll_by_id(struct intel_display *display, struct intel_shared_dpll *pll; int i; - for_each_shared_dpll(display, pll, i) { + for_each_dpll(display, pll, i) { if (pll->info->id == id) return pll; } @@ -348,7 +348,7 @@ intel_dpll_mask_all(struct intel_display *display) unsigned long dpll_mask = 0; int i; - for_each_shared_dpll(display, pll, i) { + for_each_dpll(display, pll, i) { drm_WARN_ON(display->drm, dpll_mask & BIT(pll->info->id)); dpll_mask |= BIT(pll->info->id); @@ -521,7 +521,7 @@ void intel_shared_dpll_swap_state(struct intel_atomic_state *state) if (!state->dpll_set) return; - for_each_shared_dpll(display, pll, i) + for_each_dpll(display, pll, i) swap(pll->state, dpll_state[pll->index]); } @@ -4542,7 +4542,7 @@ void intel_dpll_readout_hw_state(struct intel_display *display) struct intel_shared_dpll *pll; int i; - for_each_shared_dpll(display, pll, i) + for_each_dpll(display, pll, i) readout_dpll_hw_state(display, pll); } @@ -4571,7 +4571,7 @@ void intel_dpll_sanitize_state(struct intel_display *display) intel_cx0_pll_power_save_wa(display); - for_each_shared_dpll(display, pll, i) + for_each_dpll(display, pll, i) sanitize_dpll_state(display, pll); } @@ -4720,6 +4720,6 @@ void intel_shared_dpll_verify_disabled(struct intel_atomic_state *state) struct intel_shared_dpll *pll; int i; - for_each_shared_dpll(display, pll, i) + for_each_dpll(display, pll, i) verify_single_dpll_state(display, pll, NULL, NULL); } diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index fe6c676737bb4..d930724868313 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -30,7 +30,7 @@ #include "intel_display_power.h" #include "intel_wakeref.h" -#define for_each_shared_dpll(__display, __pll, __i) \ +#define for_each_dpll(__display, __pll, __i) \ for ((__i) = 0; (__i) < (__display)->dpll.num_shared_dpll && \ ((__pll) = &(__display)->dpll.shared_dplls[(__i)]) ; (__i)++) diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c index 693b90e3dfc3c..8bec55deff9fe 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_refclk.c +++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c @@ -535,7 +535,7 @@ static void ilk_init_pch_refclk(struct intel_display *display) } /* Check if any DPLLs are using the SSC source */ - for_each_shared_dpll(display, pll, i) { + for_each_dpll(display, pll, i) { u32 temp; temp = intel_de_read(display, PCH_DPLL(pll->info->id)); -- GitLab From 6cc235f79adb7aa594ebe18070d3b3c8d1ae1d30 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:52 +0530 Subject: [PATCH 0130/1479] drm/i915/dpll: Rename intel_shared_dpll_funcs Rename intel_shared_dpll_funcs to intel_dpll_funcs since it needs to represent both shared and individual dplls. --v2 -Change intel_global_dpll to intel_dpll_global to be more in line with the naming standard where the name should start with the file name [Jani] --v3 -Drop shared and global altogether [Jani] --v4 -Keep declarations sorted [Jani] Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-6-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 24 +++++++++---------- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 9974fdb6eaeb5..bdad4d72cc013 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -64,7 +64,7 @@ */ /* platform specific hooks for managing DPLLs */ -struct intel_shared_dpll_funcs { +struct intel_dpll_funcs { /* * Hook for enabling the pll, called from intel_enable_shared_dpll() if * the pll is not already enabled. @@ -670,7 +670,7 @@ static bool ibx_compare_hw_state(const struct intel_dpll_hw_state *_a, a->fp1 == b->fp1; } -static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = { +static const struct intel_dpll_funcs ibx_pch_dpll_funcs = { .enable = ibx_pch_dpll_enable, .disable = ibx_pch_dpll_disable, .get_hw_state = ibx_pch_dpll_get_hw_state, @@ -1270,14 +1270,14 @@ static bool hsw_compare_hw_state(const struct intel_dpll_hw_state *_a, a->spll == b->spll; } -static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = { +static const struct intel_dpll_funcs hsw_ddi_wrpll_funcs = { .enable = hsw_ddi_wrpll_enable, .disable = hsw_ddi_wrpll_disable, .get_hw_state = hsw_ddi_wrpll_get_hw_state, .get_freq = hsw_ddi_wrpll_get_freq, }; -static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = { +static const struct intel_dpll_funcs hsw_ddi_spll_funcs = { .enable = hsw_ddi_spll_enable, .disable = hsw_ddi_spll_disable, .get_hw_state = hsw_ddi_spll_get_hw_state, @@ -1302,7 +1302,7 @@ static bool hsw_ddi_lcpll_get_hw_state(struct intel_display *display, return true; } -static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = { +static const struct intel_dpll_funcs hsw_ddi_lcpll_funcs = { .enable = hsw_ddi_lcpll_enable, .disable = hsw_ddi_lcpll_disable, .get_hw_state = hsw_ddi_lcpll_get_hw_state, @@ -2004,14 +2004,14 @@ static bool skl_compare_hw_state(const struct intel_dpll_hw_state *_a, a->cfgcr2 == b->cfgcr2; } -static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = { +static const struct intel_dpll_funcs skl_ddi_pll_funcs = { .enable = skl_ddi_pll_enable, .disable = skl_ddi_pll_disable, .get_hw_state = skl_ddi_pll_get_hw_state, .get_freq = skl_ddi_pll_get_freq, }; -static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = { +static const struct intel_dpll_funcs skl_ddi_dpll0_funcs = { .enable = skl_ddi_dpll0_enable, .disable = skl_ddi_dpll0_disable, .get_hw_state = skl_ddi_dpll0_get_hw_state, @@ -2486,7 +2486,7 @@ static bool bxt_compare_hw_state(const struct intel_dpll_hw_state *_a, a->pcsdw12 == b->pcsdw12; } -static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = { +static const struct intel_dpll_funcs bxt_ddi_pll_funcs = { .enable = bxt_ddi_pll_enable, .disable = bxt_ddi_pll_disable, .get_hw_state = bxt_ddi_pll_get_hw_state, @@ -4129,21 +4129,21 @@ static bool icl_compare_hw_state(const struct intel_dpll_hw_state *_a, a->mg_pll_tdc_coldst_bias == b->mg_pll_tdc_coldst_bias; } -static const struct intel_shared_dpll_funcs combo_pll_funcs = { +static const struct intel_dpll_funcs combo_pll_funcs = { .enable = combo_pll_enable, .disable = combo_pll_disable, .get_hw_state = combo_pll_get_hw_state, .get_freq = icl_ddi_combo_pll_get_freq, }; -static const struct intel_shared_dpll_funcs tbt_pll_funcs = { +static const struct intel_dpll_funcs tbt_pll_funcs = { .enable = tbt_pll_enable, .disable = tbt_pll_disable, .get_hw_state = tbt_pll_get_hw_state, .get_freq = icl_ddi_tbt_pll_get_freq, }; -static const struct intel_shared_dpll_funcs mg_pll_funcs = { +static const struct intel_dpll_funcs mg_pll_funcs = { .enable = mg_pll_enable, .disable = mg_pll_disable, .get_hw_state = mg_pll_get_hw_state, @@ -4191,7 +4191,7 @@ static const struct intel_dpll_mgr ehl_pll_mgr = { .compare_hw_state = icl_compare_hw_state, }; -static const struct intel_shared_dpll_funcs dkl_pll_funcs = { +static const struct intel_dpll_funcs dkl_pll_funcs = { .enable = mg_pll_enable, .disable = mg_pll_disable, .get_hw_state = dkl_pll_get_hw_state, diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index d930724868313..28f464d504fb5 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -39,9 +39,9 @@ struct drm_printer; struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; +struct intel_dpll_funcs; struct intel_encoder; struct intel_shared_dpll; -struct intel_shared_dpll_funcs; /** * enum intel_dpll_id - possible DPLL ids @@ -314,7 +314,7 @@ struct dpll_info { /** * @funcs: platform specific hooks */ - const struct intel_shared_dpll_funcs *funcs; + const struct intel_dpll_funcs *funcs; /** * @id: unique identifier for this DPLL -- GitLab From 386a183259482f3db971ac3c6b7a9126e8444034 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:53 +0530 Subject: [PATCH 0131/1479] drm/i915/dpll: Rename intel_shared_dpll Rename intel_shared_dpll to intel_dpll to represent both shared and individual dplls. Since from MTL each PHY has it's own PLL making the shared PLL naming a little outdated. In an effort to make this framework accepting of future changes this needs to be done. --v2 -Use intel_dpll_global to make sure names start with the filename [Jani/Ville] -Explain the need of this rename [Jani] --v3 -Just keep it intel_dpll [Jani] --v4 -Fix comment [Jani] -Use just num_dpll and dplls [Jani] Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-7-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 2 +- drivers/gpu/drm/i915/display/intel_ddi.c | 52 ++-- drivers/gpu/drm/i915/display/intel_ddi.h | 6 +- drivers/gpu/drm/i915/display/intel_display.c | 12 +- .../gpu/drm/i915/display/intel_display_core.h | 4 +- .../drm/i915/display/intel_display_debugfs.c | 2 +- .../drm/i915/display/intel_display_types.h | 6 +- drivers/gpu/drm/i915/display/intel_dpll.c | 4 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 228 +++++++++--------- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 18 +- drivers/gpu/drm/i915/display/intel_fdi.c | 2 +- drivers/gpu/drm/i915/display/intel_lvds.c | 2 +- .../drm/i915/display/intel_modeset_setup.c | 8 +- .../gpu/drm/i915/display/intel_pch_display.c | 10 +- .../gpu/drm/i915/display/intel_pch_refclk.c | 2 +- 15 files changed, 179 insertions(+), 179 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 28dab9320aedd..026361354e6fc 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -658,7 +658,7 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder, { struct intel_display *display = to_intel_display(encoder); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); - struct intel_shared_dpll *pll = crtc_state->shared_dpll; + struct intel_dpll *pll = crtc_state->intel_dpll; enum phy phy; u32 val; diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 74132c1d63858..4d631cbc81d28 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -236,7 +236,7 @@ static void intel_wait_ddi_buf_active(struct intel_encoder *encoder) port_name(port)); } -static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll) +static u32 hsw_pll_to_ddi_pll_sel(const struct intel_dpll *pll) { switch (pll->info->id) { case DPLL_ID_WRPLL1: @@ -260,7 +260,7 @@ static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll) static u32 icl_pll_to_ddi_clk_sel(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; int clock = crtc_state->port_clock; const enum intel_dpll_id id = pll->info->id; @@ -1561,7 +1561,7 @@ static bool _icl_ddi_is_clock_enabled(struct intel_display *display, i915_reg_t return !(intel_de_read(display, reg) & clk_off); } -static struct intel_shared_dpll * +static struct intel_dpll * _icl_ddi_get_pll(struct intel_display *display, i915_reg_t reg, u32 clk_sel_mask, u32 clk_sel_shift) { @@ -1576,7 +1576,7 @@ static void adls_ddi_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; enum phy phy = intel_encoder_to_phy(encoder); if (drm_WARN_ON(display->drm, !pll)) @@ -1606,7 +1606,7 @@ static bool adls_ddi_is_clock_enabled(struct intel_encoder *encoder) ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); } -static struct intel_shared_dpll *adls_ddi_get_pll(struct intel_encoder *encoder) +static struct intel_dpll *adls_ddi_get_pll(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); @@ -1620,7 +1620,7 @@ static void rkl_ddi_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; enum phy phy = intel_encoder_to_phy(encoder); if (drm_WARN_ON(display->drm, !pll)) @@ -1650,7 +1650,7 @@ static bool rkl_ddi_is_clock_enabled(struct intel_encoder *encoder) RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); } -static struct intel_shared_dpll *rkl_ddi_get_pll(struct intel_encoder *encoder) +static struct intel_dpll *rkl_ddi_get_pll(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); @@ -1664,7 +1664,7 @@ static void dg1_ddi_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; enum phy phy = intel_encoder_to_phy(encoder); if (drm_WARN_ON(display->drm, !pll)) @@ -1703,7 +1703,7 @@ static bool dg1_ddi_is_clock_enabled(struct intel_encoder *encoder) DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); } -static struct intel_shared_dpll *dg1_ddi_get_pll(struct intel_encoder *encoder) +static struct intel_dpll *dg1_ddi_get_pll(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); @@ -1730,7 +1730,7 @@ static void icl_ddi_combo_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; enum phy phy = intel_encoder_to_phy(encoder); if (drm_WARN_ON(display->drm, !pll)) @@ -1760,7 +1760,7 @@ static bool icl_ddi_combo_is_clock_enabled(struct intel_encoder *encoder) ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); } -struct intel_shared_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder) +struct intel_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); @@ -1774,7 +1774,7 @@ static void jsl_ddi_tc_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; enum port port = encoder->port; if (drm_WARN_ON(display->drm, !pll)) @@ -1817,7 +1817,7 @@ static void icl_ddi_tc_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; enum tc_port tc_port = intel_encoder_to_tc(encoder); enum port port = encoder->port; @@ -1868,7 +1868,7 @@ static bool icl_ddi_tc_is_clock_enabled(struct intel_encoder *encoder) return !(tmp & ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port)); } -static struct intel_shared_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encoder) +static struct intel_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); enum tc_port tc_port = intel_encoder_to_tc(encoder); @@ -1898,7 +1898,7 @@ static struct intel_shared_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encode return intel_get_shared_dpll_by_id(display, id); } -static struct intel_shared_dpll *bxt_ddi_get_pll(struct intel_encoder *encoder) +static struct intel_dpll *bxt_ddi_get_pll(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder->base.dev); enum intel_dpll_id id; @@ -1925,7 +1925,7 @@ static void skl_ddi_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; enum port port = encoder->port; if (drm_WARN_ON(display->drm, !pll)) @@ -1967,7 +1967,7 @@ static bool skl_ddi_is_clock_enabled(struct intel_encoder *encoder) return !(intel_de_read(display, DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_OFF(port)); } -static struct intel_shared_dpll *skl_ddi_get_pll(struct intel_encoder *encoder) +static struct intel_dpll *skl_ddi_get_pll(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); enum port port = encoder->port; @@ -1993,7 +1993,7 @@ void hsw_ddi_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; enum port port = encoder->port; if (drm_WARN_ON(display->drm, !pll)) @@ -2018,7 +2018,7 @@ bool hsw_ddi_is_clock_enabled(struct intel_encoder *encoder) return intel_de_read(display, PORT_CLK_SEL(port)) != PORT_CLK_SEL_NONE; } -static struct intel_shared_dpll *hsw_ddi_get_pll(struct intel_encoder *encoder) +static struct intel_dpll *hsw_ddi_get_pll(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); enum port port = encoder->port; @@ -4187,7 +4187,7 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, void intel_ddi_get_clock(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { struct intel_display *display = to_intel_display(encoder); enum icl_port_dpll_id port_dpll_id = ICL_PORT_DPLL_DEFAULT; @@ -4203,7 +4203,7 @@ void intel_ddi_get_clock(struct intel_encoder *encoder, icl_set_active_port_dpll(crtc_state, port_dpll_id); - crtc_state->port_clock = intel_dpll_get_freq(display, crtc_state->shared_dpll, + crtc_state->port_clock = intel_dpll_get_freq(display, crtc_state->intel_dpll, &crtc_state->dpll_hw_state); } @@ -4257,7 +4257,7 @@ static void icl_ddi_combo_get_config(struct intel_encoder *encoder, intel_ddi_get_config(encoder, crtc_state); } -static bool icl_ddi_tc_pll_is_tbt(const struct intel_shared_dpll *pll) +static bool icl_ddi_tc_pll_is_tbt(const struct intel_dpll *pll) { return pll->info->id == DPLL_ID_ICL_TBTPLL; } @@ -4267,7 +4267,7 @@ icl_ddi_tc_port_pll_type(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); - const struct intel_shared_dpll *pll = crtc_state->shared_dpll; + const struct intel_dpll *pll = crtc_state->intel_dpll; if (drm_WARN_ON(display->drm, !pll)) return ICL_PORT_DPLL_DEFAULT; @@ -4290,7 +4290,7 @@ intel_ddi_port_pll_type(struct intel_encoder *encoder, static void icl_ddi_tc_get_clock(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { struct intel_display *display = to_intel_display(encoder); enum icl_port_dpll_id port_dpll_id; @@ -4313,10 +4313,10 @@ static void icl_ddi_tc_get_clock(struct intel_encoder *encoder, icl_set_active_port_dpll(crtc_state, port_dpll_id); - if (icl_ddi_tc_pll_is_tbt(crtc_state->shared_dpll)) + if (icl_ddi_tc_pll_is_tbt(crtc_state->intel_dpll)) crtc_state->port_clock = icl_calc_tbt_pll_link(display, encoder->port); else - crtc_state->port_clock = intel_dpll_get_freq(display, crtc_state->shared_dpll, + crtc_state->port_clock = intel_dpll_get_freq(display, crtc_state->intel_dpll, &crtc_state->dpll_hw_state); } diff --git a/drivers/gpu/drm/i915/display/intel_ddi.h b/drivers/gpu/drm/i915/display/intel_ddi.h index 353eb04079e9c..f6f511bb04314 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.h +++ b/drivers/gpu/drm/i915/display/intel_ddi.h @@ -16,9 +16,9 @@ struct intel_crtc; struct intel_crtc_state; struct intel_display; struct intel_dp; +struct intel_dpll; struct intel_dpll_hw_state; struct intel_encoder; -struct intel_shared_dpll; enum pipe; enum port; enum transcoder; @@ -40,7 +40,7 @@ void intel_ddi_enable_clock(struct intel_encoder *encoder, void intel_ddi_disable_clock(struct intel_encoder *encoder); void intel_ddi_get_clock(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, - struct intel_shared_dpll *pll); + struct intel_dpll *pll); void hsw_ddi_enable_clock(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void hsw_ddi_disable_clock(struct intel_encoder *encoder); @@ -50,7 +50,7 @@ intel_ddi_port_pll_type(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void hsw_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state); -struct intel_shared_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder); +struct intel_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder); void hsw_prepare_dp_ddi_buffers(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void intel_wait_ddi_buf_idle(struct intel_display *display, enum port port); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 1b09f8ae76ffe..20a940af0db12 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1325,7 +1325,7 @@ static void intel_encoders_update_prepare(struct intel_atomic_state *state) if (intel_crtc_needs_modeset(new_crtc_state)) continue; - new_crtc_state->shared_dpll = old_crtc_state->shared_dpll; + new_crtc_state->intel_dpll = old_crtc_state->intel_dpll; new_crtc_state->dpll_hw_state = old_crtc_state->dpll_hw_state; } } @@ -1663,7 +1663,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, intel_encoders_pre_pll_enable(state, crtc); - if (new_crtc_state->shared_dpll) + if (new_crtc_state->intel_dpll) intel_enable_shared_dpll(new_crtc_state); intel_encoders_pre_enable(state, crtc); @@ -1959,7 +1959,7 @@ static void get_crtc_power_domains(struct intel_crtc_state *crtc_state, if (HAS_DDI(display) && crtc_state->has_audio) set_bit(POWER_DOMAIN_AUDIO_MMIO, mask->bits); - if (crtc_state->shared_dpll) + if (crtc_state->intel_dpll) set_bit(POWER_DOMAIN_DISPLAY_CORE, mask->bits); if (crtc_state->dsc.compression_enable) @@ -4509,7 +4509,7 @@ copy_joiner_crtc_state_modeset(struct intel_atomic_state *state, /* preserve some things from the slave's original crtc state */ saved_state->uapi = secondary_crtc_state->uapi; saved_state->scaler_state = secondary_crtc_state->scaler_state; - saved_state->shared_dpll = secondary_crtc_state->shared_dpll; + saved_state->intel_dpll = secondary_crtc_state->intel_dpll; saved_state->crc_enabled = secondary_crtc_state->crc_enabled; intel_crtc_free_hw_state(secondary_crtc_state); @@ -4572,7 +4572,7 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state, saved_state->uapi = crtc_state->uapi; saved_state->inherited = crtc_state->inherited; saved_state->scaler_state = crtc_state->scaler_state; - saved_state->shared_dpll = crtc_state->shared_dpll; + saved_state->intel_dpll = crtc_state->intel_dpll; saved_state->dpll_hw_state = crtc_state->dpll_hw_state; memcpy(saved_state->icl_port_dplls, crtc_state->icl_port_dplls, sizeof(saved_state->icl_port_dplls)); @@ -5326,7 +5326,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL(double_wide); if (display->dpll.mgr) - PIPE_CONF_CHECK_P(shared_dpll); + PIPE_CONF_CHECK_P(intel_dpll); /* FIXME convert everything over the dpll_mgr */ if (display->dpll.mgr || HAS_GMCH(display)) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index e0221e514326b..5f5dd2722d99c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -125,8 +125,8 @@ struct intel_audio { struct intel_dpll_global { struct mutex lock; - int num_shared_dpll; - struct intel_shared_dpll shared_dplls[I915_NUM_PLLS]; + int num_dpll; + struct intel_dpll dplls[I915_NUM_PLLS]; const struct intel_dpll_mgr *mgr; struct { diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 11a7fec202327..3c323f694e694 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -618,7 +618,7 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused) { struct intel_display *display = node_to_intel_display(m->private); struct drm_printer p = drm_seq_file_printer(m); - struct intel_shared_dpll *pll; + struct intel_dpll *pll; int i; drm_modeset_lock_all(display->drm); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 9df7795b9327a..b8836d29a7214 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1079,8 +1079,8 @@ struct intel_crtc_state { * haswell. */ struct dpll dpll; - /* Selected dpll when shared or NULL. */ - struct intel_shared_dpll *shared_dpll; + /* Selected dpll or NULL. */ + struct intel_dpll *intel_dpll; /* Actual register state of the dpll, for shared dpll cross-checking. */ struct intel_dpll_hw_state dpll_hw_state; @@ -1090,7 +1090,7 @@ struct intel_crtc_state { * setting shared_dpll and dpll_hw_state to one of these reserved ones. */ struct icl_port_dpll { - struct intel_shared_dpll *pll; + struct intel_dpll *pll; struct intel_dpll_hw_state hw_state; } icl_port_dplls[ICL_PORT_DPLL_COUNT]; diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index c13fb37ea584f..9db46439592ea 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1768,9 +1768,9 @@ int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state, int ret; drm_WARN_ON(display->drm, !intel_crtc_needs_modeset(crtc_state)); - drm_WARN_ON(display->drm, !crtc_state->hw.enable && crtc_state->shared_dpll); + drm_WARN_ON(display->drm, !crtc_state->hw.enable && crtc_state->intel_dpll); - if (!crtc_state->hw.enable || crtc_state->shared_dpll) + if (!crtc_state->hw.enable || crtc_state->intel_dpll) return 0; if (!display->funcs.dpll->crtc_get_shared_dpll) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index bdad4d72cc013..6fbbc5e89f3ce 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -70,7 +70,7 @@ struct intel_dpll_funcs { * the pll is not already enabled. */ void (*enable)(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state); /* @@ -79,7 +79,7 @@ struct intel_dpll_funcs { * tracked users for it. */ void (*disable)(struct intel_display *display, - struct intel_shared_dpll *pll); + struct intel_dpll *pll); /* * Hook for reading the values currently programmed to the DPLL @@ -87,7 +87,7 @@ struct intel_dpll_funcs { * verification after a mode set. */ bool (*get_hw_state)(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state); /* @@ -95,7 +95,7 @@ struct intel_dpll_funcs { * in state. */ int (*get_freq)(struct intel_display *i915, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state); }; @@ -124,7 +124,7 @@ static void intel_atomic_duplicate_dpll_state(struct intel_display *display, struct intel_dpll_state *dpll_state) { - struct intel_shared_dpll *pll; + struct intel_dpll *pll; int i; /* Copy dpll state */ @@ -158,11 +158,11 @@ intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s) * Returns: * A pointer to the DPLL with @id */ -struct intel_shared_dpll * +struct intel_dpll * intel_get_shared_dpll_by_id(struct intel_display *display, enum intel_dpll_id id) { - struct intel_shared_dpll *pll; + struct intel_dpll *pll; int i; for_each_dpll(display, pll, i) { @@ -176,7 +176,7 @@ intel_get_shared_dpll_by_id(struct intel_display *display, /* For ILK+ */ void assert_shared_dpll(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, bool state) { bool cur_state; @@ -205,7 +205,7 @@ enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port) static i915_reg_t intel_combo_pll_enable_reg(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { if (display->platform.dg1) return DG1_DPLL_ENABLE(pll->info->id); @@ -218,7 +218,7 @@ intel_combo_pll_enable_reg(struct intel_display *display, static i915_reg_t intel_tc_pll_enable_reg(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { const enum intel_dpll_id id = pll->info->id; enum tc_port tc_port = icl_pll_id_to_tc_port(id); @@ -230,7 +230,7 @@ intel_tc_pll_enable_reg(struct intel_display *display, } static void _intel_enable_shared_dpll(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { if (pll->info->power_domain) pll->wakeref = intel_display_power_get(display, pll->info->power_domain); @@ -240,7 +240,7 @@ static void _intel_enable_shared_dpll(struct intel_display *display, } static void _intel_disable_shared_dpll(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { pll->info->funcs->disable(display, pll); pll->on = false; @@ -259,7 +259,7 @@ void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct intel_shared_dpll *pll = crtc_state->shared_dpll; + struct intel_dpll *pll = crtc_state->intel_dpll; unsigned int pipe_mask = intel_crtc_joined_pipe_mask(crtc_state); unsigned int old_mask; @@ -305,7 +305,7 @@ void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct intel_shared_dpll *pll = crtc_state->shared_dpll; + struct intel_dpll *pll = crtc_state->intel_dpll; unsigned int pipe_mask = intel_crtc_joined_pipe_mask(crtc_state); /* PCH only available on ILK+ */ @@ -344,7 +344,7 @@ void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state) static unsigned long intel_dpll_mask_all(struct intel_display *display) { - struct intel_shared_dpll *pll; + struct intel_dpll *pll; unsigned long dpll_mask = 0; int i; @@ -357,7 +357,7 @@ intel_dpll_mask_all(struct intel_display *display) return dpll_mask; } -static struct intel_shared_dpll * +static struct intel_dpll * intel_find_shared_dpll(struct intel_atomic_state *state, const struct intel_crtc *crtc, const struct intel_dpll_hw_state *dpll_hw_state, @@ -366,7 +366,7 @@ intel_find_shared_dpll(struct intel_atomic_state *state, struct intel_display *display = to_intel_display(crtc); unsigned long dpll_mask_all = intel_dpll_mask_all(display); struct intel_dpll_state *dpll_state; - struct intel_shared_dpll *unused_pll = NULL; + struct intel_dpll *unused_pll = NULL; enum intel_dpll_id id; dpll_state = intel_atomic_get_shared_dpll_state(&state->base); @@ -374,7 +374,7 @@ intel_find_shared_dpll(struct intel_atomic_state *state, drm_WARN_ON(display->drm, dpll_mask & ~dpll_mask_all); for_each_set_bit(id, &dpll_mask, fls(dpll_mask_all)) { - struct intel_shared_dpll *pll; + struct intel_dpll *pll; pll = intel_get_shared_dpll_by_id(display, id); if (!pll) @@ -421,7 +421,7 @@ intel_find_shared_dpll(struct intel_atomic_state *state, */ static void intel_reference_shared_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, struct intel_dpll_state *dpll_state) { struct intel_display *display = to_intel_display(crtc); @@ -437,7 +437,7 @@ intel_reference_shared_dpll_crtc(const struct intel_crtc *crtc, static void intel_reference_shared_dpll(struct intel_atomic_state *state, const struct intel_crtc *crtc, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { struct intel_dpll_state *dpll_state; @@ -460,7 +460,7 @@ intel_reference_shared_dpll(struct intel_atomic_state *state, */ void intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, struct intel_dpll_state *dpll_state) { struct intel_display *display = to_intel_display(crtc); @@ -475,7 +475,7 @@ intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, static void intel_unreference_shared_dpll(struct intel_atomic_state *state, const struct intel_crtc *crtc, - const struct intel_shared_dpll *pll) + const struct intel_dpll *pll) { struct intel_dpll_state *dpll_state; @@ -492,12 +492,12 @@ static void intel_put_dpll(struct intel_atomic_state *state, struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - new_crtc_state->shared_dpll = NULL; + new_crtc_state->intel_dpll = NULL; - if (!old_crtc_state->shared_dpll) + if (!old_crtc_state->intel_dpll) return; - intel_unreference_shared_dpll(state, crtc, old_crtc_state->shared_dpll); + intel_unreference_shared_dpll(state, crtc, old_crtc_state->intel_dpll); } /** @@ -515,7 +515,7 @@ void intel_shared_dpll_swap_state(struct intel_atomic_state *state) { struct intel_display *display = to_intel_display(state); struct intel_dpll_state *dpll_state = state->dpll_state; - struct intel_shared_dpll *pll; + struct intel_dpll *pll; int i; if (!state->dpll_set) @@ -526,7 +526,7 @@ void intel_shared_dpll_swap_state(struct intel_atomic_state *state) } static bool ibx_pch_dpll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { struct i9xx_dpll_hw_state *hw_state = &dpll_hw_state->i9xx; @@ -562,7 +562,7 @@ static void ibx_assert_pch_refclk_enabled(struct intel_display *display) } static void ibx_pch_dpll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct i9xx_dpll_hw_state *hw_state = &dpll_hw_state->i9xx; @@ -591,7 +591,7 @@ static void ibx_pch_dpll_enable(struct intel_display *display, } static void ibx_pch_dpll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { const enum intel_dpll_id id = pll->info->id; @@ -614,7 +614,7 @@ static int ibx_get_dpll(struct intel_atomic_state *state, struct intel_display *display = to_intel_display(state); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - struct intel_shared_dpll *pll; + struct intel_dpll *pll; enum intel_dpll_id id; if (HAS_PCH_IBX(display)) { @@ -640,7 +640,7 @@ static int ibx_get_dpll(struct intel_atomic_state *state, intel_reference_shared_dpll(state, crtc, pll, &crtc_state->dpll_hw_state); - crtc_state->shared_dpll = pll; + crtc_state->intel_dpll = pll; return 0; } @@ -692,7 +692,7 @@ static const struct intel_dpll_mgr pch_pll_mgr = { }; static void hsw_ddi_wrpll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; @@ -704,7 +704,7 @@ static void hsw_ddi_wrpll_enable(struct intel_display *display, } static void hsw_ddi_spll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; @@ -715,7 +715,7 @@ static void hsw_ddi_spll_enable(struct intel_display *display, } static void hsw_ddi_wrpll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { const enum intel_dpll_id id = pll->info->id; @@ -731,7 +731,7 @@ static void hsw_ddi_wrpll_disable(struct intel_display *display, } static void hsw_ddi_spll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { enum intel_dpll_id id = pll->info->id; @@ -747,7 +747,7 @@ static void hsw_ddi_spll_disable(struct intel_display *display, } static bool hsw_ddi_wrpll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; @@ -769,7 +769,7 @@ static bool hsw_ddi_wrpll_get_hw_state(struct intel_display *display, } static bool hsw_ddi_spll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; @@ -996,7 +996,7 @@ hsw_ddi_calculate_wrpll(int clock /* in Hz */, } static int hsw_ddi_wrpll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; @@ -1059,7 +1059,7 @@ hsw_ddi_wrpll_compute_dpll(struct intel_atomic_state *state, return 0; } -static struct intel_shared_dpll * +static struct intel_dpll * hsw_ddi_wrpll_get_dpll(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -1090,11 +1090,11 @@ hsw_ddi_lcpll_compute_dpll(struct intel_crtc_state *crtc_state) } } -static struct intel_shared_dpll * +static struct intel_dpll * hsw_ddi_lcpll_get_dpll(struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); - struct intel_shared_dpll *pll; + struct intel_dpll *pll; enum intel_dpll_id pll_id; int clock = crtc_state->port_clock; @@ -1122,7 +1122,7 @@ hsw_ddi_lcpll_get_dpll(struct intel_crtc_state *crtc_state) } static int hsw_ddi_lcpll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { int link_clock = 0; @@ -1162,7 +1162,7 @@ hsw_ddi_spll_compute_dpll(struct intel_atomic_state *state, return 0; } -static struct intel_shared_dpll * +static struct intel_dpll * hsw_ddi_spll_get_dpll(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -1174,7 +1174,7 @@ hsw_ddi_spll_get_dpll(struct intel_atomic_state *state, } static int hsw_ddi_spll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; @@ -1221,7 +1221,7 @@ static int hsw_get_dpll(struct intel_atomic_state *state, { struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - struct intel_shared_dpll *pll = NULL; + struct intel_dpll *pll = NULL; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) pll = hsw_ddi_wrpll_get_dpll(state, crtc); @@ -1236,7 +1236,7 @@ static int hsw_get_dpll(struct intel_atomic_state *state, intel_reference_shared_dpll(state, crtc, pll, &crtc_state->dpll_hw_state); - crtc_state->shared_dpll = pll; + crtc_state->intel_dpll = pll; return 0; } @@ -1285,18 +1285,18 @@ static const struct intel_dpll_funcs hsw_ddi_spll_funcs = { }; static void hsw_ddi_lcpll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *hw_state) { } static void hsw_ddi_lcpll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { } static bool hsw_ddi_lcpll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { return true; @@ -1364,7 +1364,7 @@ static const struct skl_dpll_regs skl_dpll_regs[4] = { }; static void skl_ddi_pll_write_ctrl1(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct skl_dpll_hw_state *hw_state) { const enum intel_dpll_id id = pll->info->id; @@ -1378,7 +1378,7 @@ static void skl_ddi_pll_write_ctrl1(struct intel_display *display, } static void skl_ddi_pll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; @@ -1400,7 +1400,7 @@ static void skl_ddi_pll_enable(struct intel_display *display, } static void skl_ddi_dpll0_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; @@ -1409,7 +1409,7 @@ static void skl_ddi_dpll0_enable(struct intel_display *display, } static void skl_ddi_pll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { const struct skl_dpll_regs *regs = skl_dpll_regs; const enum intel_dpll_id id = pll->info->id; @@ -1420,12 +1420,12 @@ static void skl_ddi_pll_disable(struct intel_display *display, } static void skl_ddi_dpll0_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { } static bool skl_ddi_pll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; @@ -1463,7 +1463,7 @@ static bool skl_ddi_pll_get_hw_state(struct intel_display *display, } static bool skl_ddi_dpll0_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; @@ -1736,7 +1736,7 @@ skl_ddi_calculate_wrpll(int clock, } static int skl_ddi_wrpll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; @@ -1884,7 +1884,7 @@ skl_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state) } static int skl_ddi_lcpll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; @@ -1939,7 +1939,7 @@ static int skl_get_dpll(struct intel_atomic_state *state, { struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - struct intel_shared_dpll *pll; + struct intel_dpll *pll; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) pll = intel_find_shared_dpll(state, crtc, @@ -1957,13 +1957,13 @@ static int skl_get_dpll(struct intel_atomic_state *state, intel_reference_shared_dpll(state, crtc, pll, &crtc_state->dpll_hw_state); - crtc_state->shared_dpll = pll; + crtc_state->intel_dpll = pll; return 0; } static int skl_ddi_pll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; @@ -2038,7 +2038,7 @@ static const struct intel_dpll_mgr skl_pll_mgr = { }; static void bxt_ddi_pll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct bxt_dpll_hw_state *hw_state = &dpll_hw_state->bxt; @@ -2141,7 +2141,7 @@ static void bxt_ddi_pll_enable(struct intel_display *display, } static void bxt_ddi_pll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */ @@ -2160,7 +2160,7 @@ static void bxt_ddi_pll_disable(struct intel_display *display, } static bool bxt_ddi_pll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { struct bxt_dpll_hw_state *hw_state = &dpll_hw_state->bxt; @@ -2360,7 +2360,7 @@ static int bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state, } static int bxt_ddi_pll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct bxt_dpll_hw_state *hw_state = &dpll_hw_state->bxt; @@ -2429,7 +2429,7 @@ static int bxt_get_dpll(struct intel_atomic_state *state, struct intel_display *display = to_intel_display(state); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - struct intel_shared_dpll *pll; + struct intel_dpll *pll; enum intel_dpll_id id; /* 1:1 mapping between ports and PLLs */ @@ -2442,7 +2442,7 @@ static int bxt_get_dpll(struct intel_atomic_state *state, intel_reference_shared_dpll(state, crtc, pll, &crtc_state->dpll_hw_state); - crtc_state->shared_dpll = pll; + crtc_state->intel_dpll = pll; return 0; } @@ -2755,7 +2755,7 @@ static int icl_calc_tbt_pll(struct intel_crtc_state *crtc_state, } static int icl_ddi_tbt_pll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { /* @@ -2826,7 +2826,7 @@ icl_calc_wrpll(struct intel_crtc_state *crtc_state, } static int icl_ddi_combo_pll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; @@ -3199,7 +3199,7 @@ static int icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, } static int icl_ddi_mg_pll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; @@ -3285,7 +3285,7 @@ void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state, struct icl_port_dpll *port_dpll = &crtc_state->icl_port_dplls[port_dpll_id]; - crtc_state->shared_dpll = port_dpll->pll; + crtc_state->intel_dpll = port_dpll->pll; crtc_state->dpll_hw_state = port_dpll->hw_state; } @@ -3428,8 +3428,8 @@ static int icl_compute_tc_phy_dplls(struct intel_atomic_state *state, return ret; /* this is mainly for the fastset check */ - if (old_crtc_state->shared_dpll && - old_crtc_state->shared_dpll->info->id == DPLL_ID_ICL_TBTPLL) + if (old_crtc_state->intel_dpll && + old_crtc_state->intel_dpll->info->id == DPLL_ID_ICL_TBTPLL) icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_DEFAULT); else icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_MG_PHY); @@ -3521,7 +3521,7 @@ static void icl_put_dplls(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); enum icl_port_dpll_id id; - new_crtc_state->shared_dpll = NULL; + new_crtc_state->intel_dpll = NULL; for (id = ICL_PORT_DPLL_DEFAULT; id < ICL_PORT_DPLL_COUNT; id++) { const struct icl_port_dpll *old_port_dpll = @@ -3539,7 +3539,7 @@ static void icl_put_dplls(struct intel_atomic_state *state, } static bool mg_pll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; @@ -3606,7 +3606,7 @@ static bool mg_pll_get_hw_state(struct intel_display *display, } static bool dkl_pll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; @@ -3678,7 +3678,7 @@ static bool dkl_pll_get_hw_state(struct intel_display *display, } static bool icl_pll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state, i915_reg_t enable_reg) { @@ -3739,7 +3739,7 @@ static bool icl_pll_get_hw_state(struct intel_display *display, } static bool combo_pll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { i915_reg_t enable_reg = intel_combo_pll_enable_reg(display, pll); @@ -3748,14 +3748,14 @@ static bool combo_pll_get_hw_state(struct intel_display *display, } static bool tbt_pll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { return icl_pll_get_hw_state(display, pll, dpll_hw_state, TBT_PLL_ENABLE); } static void icl_dpll_write(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct icl_dpll_hw_state *hw_state) { const enum intel_dpll_id id = pll->info->id; @@ -3797,7 +3797,7 @@ static void icl_dpll_write(struct intel_display *display, } static void icl_mg_pll_write(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct icl_dpll_hw_state *hw_state) { enum tc_port tc_port = icl_pll_id_to_tc_port(pll->info->id); @@ -3840,7 +3840,7 @@ static void icl_mg_pll_write(struct intel_display *display, } static void dkl_pll_write(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct icl_dpll_hw_state *hw_state) { enum tc_port tc_port = icl_pll_id_to_tc_port(pll->info->id); @@ -3905,7 +3905,7 @@ static void dkl_pll_write(struct intel_display *display, } static void icl_pll_power_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, i915_reg_t enable_reg) { intel_de_rmw(display, enable_reg, 0, PLL_POWER_ENABLE); @@ -3920,7 +3920,7 @@ static void icl_pll_power_enable(struct intel_display *display, } static void icl_pll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, i915_reg_t enable_reg) { intel_de_rmw(display, enable_reg, 0, PLL_ENABLE); @@ -3930,7 +3930,7 @@ static void icl_pll_enable(struct intel_display *display, drm_err(display->drm, "PLL %d not locked\n", pll->info->id); } -static void adlp_cmtg_clock_gating_wa(struct intel_display *display, struct intel_shared_dpll *pll) +static void adlp_cmtg_clock_gating_wa(struct intel_display *display, struct intel_dpll *pll) { u32 val; @@ -3955,7 +3955,7 @@ static void adlp_cmtg_clock_gating_wa(struct intel_display *display, struct inte } static void combo_pll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; @@ -3979,7 +3979,7 @@ static void combo_pll_enable(struct intel_display *display, } static void tbt_pll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; @@ -4000,7 +4000,7 @@ static void tbt_pll_enable(struct intel_display *display, } static void mg_pll_enable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; @@ -4025,7 +4025,7 @@ static void mg_pll_enable(struct intel_display *display, } static void icl_pll_disable(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, i915_reg_t enable_reg) { /* The first steps are done by intel_ddi_post_disable(). */ @@ -4056,7 +4056,7 @@ static void icl_pll_disable(struct intel_display *display, } static void combo_pll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { i915_reg_t enable_reg = intel_combo_pll_enable_reg(display, pll); @@ -4064,13 +4064,13 @@ static void combo_pll_disable(struct intel_display *display, } static void tbt_pll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { icl_pll_disable(display, pll, TBT_PLL_ENABLE); } static void mg_pll_disable(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { i915_reg_t enable_reg = intel_tc_pll_enable_reg(display, pll); @@ -4346,19 +4346,19 @@ void intel_shared_dpll_init(struct intel_display *display) for (i = 0; dpll_info[i].name; i++) { if (drm_WARN_ON(display->drm, - i >= ARRAY_SIZE(display->dpll.shared_dplls))) + i >= ARRAY_SIZE(display->dpll.dplls))) break; /* must fit into unsigned long bitmask on 32bit */ if (drm_WARN_ON(display->drm, dpll_info[i].id >= 32)) break; - display->dpll.shared_dplls[i].info = &dpll_info[i]; - display->dpll.shared_dplls[i].index = i; + display->dpll.dplls[i].info = &dpll_info[i]; + display->dpll.dplls[i].index = i; } display->dpll.mgr = dpll_mgr; - display->dpll.num_shared_dpll = i; + display->dpll.num_dpll = i; } /** @@ -4482,7 +4482,7 @@ void intel_update_active_dpll(struct intel_atomic_state *state, * Return the output frequency corresponding to @pll's passed in @dpll_hw_state. */ int intel_dpll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state) { if (drm_WARN_ON(display->drm, !pll->info->funcs->get_freq)) @@ -4500,14 +4500,14 @@ int intel_dpll_get_freq(struct intel_display *display, * Read out @pll's hardware state into @dpll_hw_state. */ bool intel_dpll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state) { return pll->info->funcs->get_hw_state(display, pll, dpll_hw_state); } static void readout_dpll_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { struct intel_crtc *crtc; @@ -4521,7 +4521,7 @@ static void readout_dpll_hw_state(struct intel_display *display, struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); - if (crtc_state->hw.active && crtc_state->shared_dpll == pll) + if (crtc_state->hw.active && crtc_state->intel_dpll == pll) intel_reference_shared_dpll_crtc(crtc, pll, &pll->state); } pll->active_mask = pll->state.pipe_mask; @@ -4539,7 +4539,7 @@ void intel_dpll_update_ref_clks(struct intel_display *display) void intel_dpll_readout_hw_state(struct intel_display *display) { - struct intel_shared_dpll *pll; + struct intel_dpll *pll; int i; for_each_dpll(display, pll, i) @@ -4547,7 +4547,7 @@ void intel_dpll_readout_hw_state(struct intel_display *display) } static void sanitize_dpll_state(struct intel_display *display, - struct intel_shared_dpll *pll) + struct intel_dpll *pll) { if (!pll->on) return; @@ -4566,7 +4566,7 @@ static void sanitize_dpll_state(struct intel_display *display, void intel_dpll_sanitize_state(struct intel_display *display) { - struct intel_shared_dpll *pll; + struct intel_dpll *pll; int i; intel_cx0_pll_power_save_wa(display); @@ -4623,7 +4623,7 @@ bool intel_dpll_compare_hw_state(struct intel_display *display, static void verify_single_dpll_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_crtc *crtc, const struct intel_crtc_state *new_crtc_state) { @@ -4676,8 +4676,8 @@ verify_single_dpll_state(struct intel_display *display, pll->info->name); } -static bool has_alt_port_dpll(const struct intel_shared_dpll *old_pll, - const struct intel_shared_dpll *new_pll) +static bool has_alt_port_dpll(const struct intel_dpll *old_pll, + const struct intel_dpll *new_pll) { return old_pll && new_pll && old_pll != new_pll && (old_pll->info->is_alt_port_dpll || new_pll->info->is_alt_port_dpll); @@ -4692,22 +4692,22 @@ void intel_shared_dpll_state_verify(struct intel_atomic_state *state, const struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - if (new_crtc_state->shared_dpll) - verify_single_dpll_state(display, new_crtc_state->shared_dpll, + if (new_crtc_state->intel_dpll) + verify_single_dpll_state(display, new_crtc_state->intel_dpll, crtc, new_crtc_state); - if (old_crtc_state->shared_dpll && - old_crtc_state->shared_dpll != new_crtc_state->shared_dpll) { + if (old_crtc_state->intel_dpll && + old_crtc_state->intel_dpll != new_crtc_state->intel_dpll) { u8 pipe_mask = BIT(crtc->pipe); - struct intel_shared_dpll *pll = old_crtc_state->shared_dpll; + struct intel_dpll *pll = old_crtc_state->intel_dpll; INTEL_DISPLAY_STATE_WARN(display, pll->active_mask & pipe_mask, "%s: pll active mismatch (didn't expect pipe %c in active mask (0x%x))\n", pll->info->name, pipe_name(crtc->pipe), pll->active_mask); /* TC ports have both MG/TC and TBT PLL referenced simultaneously */ - INTEL_DISPLAY_STATE_WARN(display, !has_alt_port_dpll(old_crtc_state->shared_dpll, - new_crtc_state->shared_dpll) && + INTEL_DISPLAY_STATE_WARN(display, !has_alt_port_dpll(old_crtc_state->intel_dpll, + new_crtc_state->intel_dpll) && pll->state.pipe_mask & pipe_mask, "%s: pll enabled crtcs mismatch (found pipe %c in enabled mask (0x%x))\n", pll->info->name, pipe_name(crtc->pipe), pll->state.pipe_mask); @@ -4717,7 +4717,7 @@ void intel_shared_dpll_state_verify(struct intel_atomic_state *state, void intel_shared_dpll_verify_disabled(struct intel_atomic_state *state) { struct intel_display *display = to_intel_display(state); - struct intel_shared_dpll *pll; + struct intel_dpll *pll; int i; for_each_dpll(display, pll, i) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index 28f464d504fb5..ea3fb7002e653 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -31,8 +31,8 @@ #include "intel_wakeref.h" #define for_each_dpll(__display, __pll, __i) \ - for ((__i) = 0; (__i) < (__display)->dpll.num_shared_dpll && \ - ((__pll) = &(__display)->dpll.shared_dplls[(__i)]) ; (__i)++) + for ((__i) = 0; (__i) < (__display)->dpll.num_dpll && \ + ((__pll) = &(__display)->dpll.dplls[(__i)]) ; (__i)++) enum tc_port; struct drm_printer; @@ -344,9 +344,9 @@ struct dpll_info { }; /** - * struct intel_shared_dpll - display PLL with tracked state and users + * struct intel_dpll - display PLL with tracked state and users */ -struct intel_shared_dpll { +struct intel_dpll { /** * @state: * @@ -388,11 +388,11 @@ struct intel_shared_dpll { #define SKL_DPLL3 3 /* shared dpll functions */ -struct intel_shared_dpll * +struct intel_dpll * intel_get_shared_dpll_by_id(struct intel_display *display, enum intel_dpll_id id); void assert_shared_dpll(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, bool state); #define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true) #define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false) @@ -405,7 +405,7 @@ int intel_reserve_shared_dplls(struct intel_atomic_state *state, void intel_release_shared_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, struct intel_dpll_state *shared_dpll_state); void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state, enum icl_port_dpll_id port_dpll_id); @@ -413,10 +413,10 @@ void intel_update_active_dpll(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder); int intel_dpll_get_freq(struct intel_display *display, - const struct intel_shared_dpll *pll, + const struct intel_dpll *pll, const struct intel_dpll_hw_state *dpll_hw_state); bool intel_dpll_get_hw_state(struct intel_display *display, - struct intel_shared_dpll *pll, + struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state); void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state); void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c index 169bbe154b5c5..b1d2ba9b7295f 100644 --- a/drivers/gpu/drm/i915/display/intel_fdi.c +++ b/drivers/gpu/drm/i915/display/intel_fdi.c @@ -910,7 +910,7 @@ void hsw_fdi_link_train(struct intel_encoder *encoder, intel_de_write(display, FDI_RX_CTL(PIPE_A), rx_ctl_val); /* Configure Port Clock Select */ - drm_WARN_ON(display->drm, crtc_state->shared_dpll->info->id != DPLL_ID_SPLL); + drm_WARN_ON(display->drm, crtc_state->intel_dpll->info->id != DPLL_ID_SPLL); intel_ddi_enable_clock(encoder, crtc_state); /* Start the training iterating through available voltages and emphasis, diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 8ce7c630da527..ec8f38fba1785 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -249,7 +249,7 @@ static void intel_pre_enable_lvds(struct intel_atomic_state *state, if (HAS_PCH_SPLIT(display)) { assert_fdi_rx_pll_disabled(display, pipe); - assert_shared_dpll_disabled(display, crtc_state->shared_dpll); + assert_shared_dpll_disabled(display, crtc_state->intel_dpll); } else { assert_pll_disabled(display, pipe); } diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index 0325b0c9506dd..46e0002a13586 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -92,10 +92,10 @@ static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc, crtc->active = false; crtc->base.enabled = false; - if (crtc_state->shared_dpll) + if (crtc_state->intel_dpll) intel_unreference_shared_dpll_crtc(crtc, - crtc_state->shared_dpll, - &crtc_state->shared_dpll->state); + crtc_state->intel_dpll, + &crtc_state->intel_dpll->state); } static void set_encoder_for_connector(struct intel_connector *connector, @@ -565,7 +565,7 @@ static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state) */ return display->platform.sandybridge && crtc_state->hw.active && - crtc_state->shared_dpll && + crtc_state->intel_dpll && crtc_state->port_clock == 0; } diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index 1743ebf551cbe..b38305c16e77c 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -251,7 +251,7 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) u32 val, pipeconf_val; /* Make sure PCH DPLL is enabled */ - assert_shared_dpll_enabled(display, crtc_state->shared_dpll); + assert_shared_dpll_enabled(display, crtc_state->intel_dpll); /* FDI must be feeding us bits for PCH ports */ assert_fdi_tx_enabled(display, pipe); @@ -381,7 +381,7 @@ void ilk_pch_enable(struct intel_atomic_state *state, temp = intel_de_read(display, PCH_DPLL_SEL); temp |= TRANS_DPLL_ENABLE(pipe); sel = TRANS_DPLLB_SEL(pipe); - if (crtc_state->shared_dpll == + if (crtc_state->intel_dpll == intel_get_shared_dpll_by_id(display, DPLL_ID_PCH_PLL_B)) temp |= sel; else @@ -496,7 +496,7 @@ void ilk_pch_get_config(struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct intel_shared_dpll *pll; + struct intel_dpll *pll; enum pipe pipe = crtc->pipe; enum intel_dpll_id pll_id; bool pll_active; @@ -528,8 +528,8 @@ void ilk_pch_get_config(struct intel_crtc_state *crtc_state) pll_id = DPLL_ID_PCH_PLL_A; } - crtc_state->shared_dpll = intel_get_shared_dpll_by_id(display, pll_id); - pll = crtc_state->shared_dpll; + crtc_state->intel_dpll = intel_get_shared_dpll_by_id(display, pll_id); + pll = crtc_state->intel_dpll; pll_active = intel_dpll_get_hw_state(display, pll, &crtc_state->dpll_hw_state); diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c index 8bec55deff9fe..9f6102d7c7be7 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_refclk.c +++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c @@ -499,7 +499,7 @@ static void lpt_init_pch_refclk(struct intel_display *display) static void ilk_init_pch_refclk(struct intel_display *display) { struct intel_encoder *encoder; - struct intel_shared_dpll *pll; + struct intel_dpll *pll; int i; u32 val, final; bool has_lvds = false; -- GitLab From 2b3b9a8faf56a61634e734afc01da9a9ea1265cf Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:54 +0530 Subject: [PATCH 0132/1479] drm/i915/dpll: Move away from using shared dpll Rename functions to move away from using shared dpll in the dpll framework as much as possible since dpll may not always be shared. --v2 -Use intel_dpll_global instead of global_dpll [Jani] --v3 -Just use intel_dpll [Jani] --v4 -Drop the global from comments [Jani] Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-8-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 14 +- drivers/gpu/drm/i915/display/intel_display.c | 8 +- .../drm/i915/display/intel_display_driver.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll.c | 10 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 235 +++++++++--------- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 52 ++-- drivers/gpu/drm/i915/display/intel_lvds.c | 2 +- .../drm/i915/display/intel_modeset_setup.c | 6 +- .../drm/i915/display/intel_modeset_verify.c | 4 +- .../gpu/drm/i915/display/intel_pch_display.c | 14 +- 10 files changed, 173 insertions(+), 174 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 4d631cbc81d28..11ebcb40c91f6 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1569,7 +1569,7 @@ _icl_ddi_get_pll(struct intel_display *display, i915_reg_t reg, id = (intel_de_read(display, reg) & clk_sel_mask) >> clk_sel_shift; - return intel_get_shared_dpll_by_id(display, id); + return intel_get_dpll_by_id(display, id); } static void adls_ddi_enable_clock(struct intel_encoder *encoder, @@ -1723,7 +1723,7 @@ static struct intel_dpll *dg1_ddi_get_pll(struct intel_encoder *encoder) if (phy >= PHY_C) id += DPLL_ID_DG1_DPLL2; - return intel_get_shared_dpll_by_id(display, id); + return intel_get_dpll_by_id(display, id); } static void icl_ddi_combo_enable_clock(struct intel_encoder *encoder, @@ -1895,7 +1895,7 @@ static struct intel_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encoder) return NULL; } - return intel_get_shared_dpll_by_id(display, id); + return intel_get_dpll_by_id(display, id); } static struct intel_dpll *bxt_ddi_get_pll(struct intel_encoder *encoder) @@ -1918,7 +1918,7 @@ static struct intel_dpll *bxt_ddi_get_pll(struct intel_encoder *encoder) return NULL; } - return intel_get_shared_dpll_by_id(display, id); + return intel_get_dpll_by_id(display, id); } static void skl_ddi_enable_clock(struct intel_encoder *encoder, @@ -1986,7 +1986,7 @@ static struct intel_dpll *skl_ddi_get_pll(struct intel_encoder *encoder) id = (tmp & DPLL_CTRL2_DDI_CLK_SEL_MASK(port)) >> DPLL_CTRL2_DDI_CLK_SEL_SHIFT(port); - return intel_get_shared_dpll_by_id(display, id); + return intel_get_dpll_by_id(display, id); } void hsw_ddi_enable_clock(struct intel_encoder *encoder, @@ -2053,7 +2053,7 @@ static struct intel_dpll *hsw_ddi_get_pll(struct intel_encoder *encoder) return NULL; } - return intel_get_shared_dpll_by_id(display, id); + return intel_get_dpll_by_id(display, id); } void intel_ddi_enable_clock(struct intel_encoder *encoder, @@ -2760,7 +2760,7 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state, * 4. Enable the port PLL. * * The PLL enabling itself was already done before this function by - * hsw_crtc_enable()->intel_enable_shared_dpll(). We need only + * hsw_crtc_enable()->intel_enable_dpll(). We need only * configure the PLL to port mapping here. */ intel_ddi_enable_clock(encoder, crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 20a940af0db12..858d9397b6708 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1664,7 +1664,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, intel_encoders_pre_pll_enable(state, crtc); if (new_crtc_state->intel_dpll) - intel_enable_shared_dpll(new_crtc_state); + intel_enable_dpll(new_crtc_state); intel_encoders_pre_enable(state, crtc); @@ -1793,7 +1793,7 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, intel_encoders_disable(state, crtc); intel_encoders_post_disable(state, crtc); - intel_disable_shared_dpll(old_crtc_state); + intel_disable_dpll(old_crtc_state); intel_encoders_post_pll_disable(state, crtc); @@ -6436,7 +6436,7 @@ int intel_atomic_check(struct drm_device *dev, any_ms = true; - intel_release_shared_dplls(state, crtc); + intel_release_dplls(state, crtc); } if (any_ms && !check_digital_port_conflicts(state)) { @@ -7533,7 +7533,7 @@ static int intel_atomic_swap_state(struct intel_atomic_state *state) intel_atomic_swap_global_state(state); - intel_shared_dpll_swap_state(state); + intel_dpll_swap_state(state); intel_atomic_track_fbs(state); diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c index 5c74ab5fd1aa5..16d91be02bb91 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.c +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c @@ -446,7 +446,7 @@ int intel_display_driver_probe_nogem(struct intel_display *display) } intel_plane_possible_crtcs_init(display); - intel_shared_dpll_init(display); + intel_dpll_init(display); intel_fdi_pll_freq_update(display); intel_update_czclk(display); diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 9db46439592ea..80de897a761fb 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1162,7 +1162,7 @@ static int hsw_crtc_compute_clock(struct intel_atomic_state *state, intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) return 0; - ret = intel_compute_shared_dplls(state, crtc, encoder); + ret = intel_compute_dplls(state, crtc, encoder); if (ret) return ret; @@ -1190,7 +1190,7 @@ static int hsw_crtc_get_shared_dpll(struct intel_atomic_state *state, intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) return 0; - return intel_reserve_shared_dplls(state, crtc, encoder); + return intel_reserve_dplls(state, crtc, encoder); } static int dg2_crtc_compute_clock(struct intel_atomic_state *state, @@ -1224,7 +1224,7 @@ static int mtl_crtc_compute_clock(struct intel_atomic_state *state, if (ret) return ret; - /* TODO: Do the readback via intel_compute_shared_dplls() */ + /* TODO: Do the readback via intel_compute_dplls() */ crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->dpll_hw_state.cx0pll); crtc_state->hw.adjusted_mode.crtc_clock = intel_crtc_dotclock(crtc_state); @@ -1395,7 +1395,7 @@ static int ilk_crtc_compute_clock(struct intel_atomic_state *state, ilk_compute_dpll(crtc_state, &crtc_state->dpll, &crtc_state->dpll); - ret = intel_compute_shared_dplls(state, crtc, NULL); + ret = intel_compute_dplls(state, crtc, NULL); if (ret) return ret; @@ -1415,7 +1415,7 @@ static int ilk_crtc_get_shared_dpll(struct intel_atomic_state *state, if (!crtc_state->has_pch_encoder) return 0; - return intel_reserve_shared_dplls(state, crtc, NULL); + return intel_reserve_dplls(state, crtc, NULL); } static u32 vlv_dpll(const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 6fbbc5e89f3ce..69271892067a8 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -52,21 +52,21 @@ * share a PLL if their configurations match. * * This file provides an abstraction over display PLLs. The function - * intel_shared_dpll_init() initializes the PLLs for the given platform. The + * intel_dpll_init() initializes the PLLs for the given platform. The * users of a PLL are tracked and that tracking is integrated with the atomic * modset interface. During an atomic operation, required PLLs can be reserved * for a given CRTC and encoder configuration by calling - * intel_reserve_shared_dplls() and previously reserved PLLs can be released - * with intel_release_shared_dplls(). + * intel_reserve_dplls() and previously reserved PLLs can be released + * with intel_release_dplls(). * Changes to the users are first staged in the atomic state, and then made - * effective by calling intel_shared_dpll_swap_state() during the atomic + * effective by calling intel_dpll_swap_state() during the atomic * commit phase. */ /* platform specific hooks for managing DPLLs */ struct intel_dpll_funcs { /* - * Hook for enabling the pll, called from intel_enable_shared_dpll() if + * Hook for enabling the pll, called from intel_enable_dpll() if * the pll is not already enabled. */ void (*enable)(struct intel_display *display, @@ -74,7 +74,7 @@ struct intel_dpll_funcs { const struct intel_dpll_hw_state *dpll_hw_state); /* - * Hook for disabling the pll, called from intel_disable_shared_dpll() + * Hook for disabling the pll, called from intel_disable_dpll() * only when it is safe to disable the pll, i.e., there are no more * tracked users for it. */ @@ -133,7 +133,7 @@ intel_atomic_duplicate_dpll_state(struct intel_display *display, } static struct intel_dpll_state * -intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s) +intel_atomic_get_dpll_state(struct drm_atomic_state *s) { struct intel_atomic_state *state = to_intel_atomic_state(s); struct intel_display *display = to_intel_display(state); @@ -151,7 +151,7 @@ intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s) } /** - * intel_get_shared_dpll_by_id - get a DPLL given its id + * intel_get_dpll_by_id - get a DPLL given its id * @display: intel_display device instance * @id: pll id * @@ -159,8 +159,8 @@ intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s) * A pointer to the DPLL with @id */ struct intel_dpll * -intel_get_shared_dpll_by_id(struct intel_display *display, - enum intel_dpll_id id) +intel_get_dpll_by_id(struct intel_display *display, + enum intel_dpll_id id) { struct intel_dpll *pll; int i; @@ -175,9 +175,9 @@ intel_get_shared_dpll_by_id(struct intel_display *display, } /* For ILK+ */ -void assert_shared_dpll(struct intel_display *display, - struct intel_dpll *pll, - bool state) +void assert_dpll(struct intel_display *display, + struct intel_dpll *pll, + bool state) { bool cur_state; struct intel_dpll_hw_state hw_state; @@ -250,12 +250,12 @@ static void _intel_disable_shared_dpll(struct intel_display *display, } /** - * intel_enable_shared_dpll - enable a CRTC's shared DPLL - * @crtc_state: CRTC, and its state, which has a shared DPLL + * intel_enable_dpll - enable a CRTC's DPLL + * @crtc_state: CRTC, and its state, which has a DPLL * - * Enable the shared DPLL used by @crtc. + * Enable DPLL used by @crtc. */ -void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state) +void intel_enable_dpll(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -282,7 +282,7 @@ void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state) if (old_mask) { drm_WARN_ON(display->drm, !pll->on); - assert_shared_dpll_enabled(display, pll); + assert_dpll_enabled(display, pll); goto out; } drm_WARN_ON(display->drm, pll->on); @@ -296,12 +296,12 @@ void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state) } /** - * intel_disable_shared_dpll - disable a CRTC's shared DPLL + * intel_disable_dpll - disable a CRTC's shared DPLL * @crtc_state: CRTC, and its state, which has a shared DPLL * - * Disable the shared DPLL used by @crtc. + * Disable DPLL used by @crtc. */ -void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state) +void intel_disable_dpll(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -326,7 +326,7 @@ void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state) pll->info->name, pll->active_mask, pll->on, crtc->base.base.id, crtc->base.name); - assert_shared_dpll_enabled(display, pll); + assert_dpll_enabled(display, pll); drm_WARN_ON(display->drm, !pll->on); pll->active_mask &= ~pipe_mask; @@ -358,10 +358,10 @@ intel_dpll_mask_all(struct intel_display *display) } static struct intel_dpll * -intel_find_shared_dpll(struct intel_atomic_state *state, - const struct intel_crtc *crtc, - const struct intel_dpll_hw_state *dpll_hw_state, - unsigned long dpll_mask) +intel_find_dpll(struct intel_atomic_state *state, + const struct intel_crtc *crtc, + const struct intel_dpll_hw_state *dpll_hw_state, + unsigned long dpll_mask) { struct intel_display *display = to_intel_display(crtc); unsigned long dpll_mask_all = intel_dpll_mask_all(display); @@ -369,14 +369,14 @@ intel_find_shared_dpll(struct intel_atomic_state *state, struct intel_dpll *unused_pll = NULL; enum intel_dpll_id id; - dpll_state = intel_atomic_get_shared_dpll_state(&state->base); + dpll_state = intel_atomic_get_dpll_state(&state->base); drm_WARN_ON(display->drm, dpll_mask & ~dpll_mask_all); for_each_set_bit(id, &dpll_mask, fls(dpll_mask_all)) { struct intel_dpll *pll; - pll = intel_get_shared_dpll_by_id(display, id); + pll = intel_get_dpll_by_id(display, id); if (!pll) continue; @@ -412,7 +412,7 @@ intel_find_shared_dpll(struct intel_atomic_state *state, } /** - * intel_reference_shared_dpll_crtc - Get a DPLL reference for a CRTC + * intel_reference_dpll_crtc - Get a DPLL reference for a CRTC * @crtc: CRTC on which behalf the reference is taken * @pll: DPLL for which the reference is taken * @dpll_state: the DPLL atomic state in which the reference is tracked @@ -420,9 +420,9 @@ intel_find_shared_dpll(struct intel_atomic_state *state, * Take a reference for @pll tracking the use of it by @crtc. */ static void -intel_reference_shared_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_dpll *pll, - struct intel_dpll_state *dpll_state) +intel_reference_dpll_crtc(const struct intel_crtc *crtc, + const struct intel_dpll *pll, + struct intel_dpll_state *dpll_state) { struct intel_display *display = to_intel_display(crtc); @@ -435,23 +435,23 @@ intel_reference_shared_dpll_crtc(const struct intel_crtc *crtc, } static void -intel_reference_shared_dpll(struct intel_atomic_state *state, - const struct intel_crtc *crtc, - const struct intel_dpll *pll, - const struct intel_dpll_hw_state *dpll_hw_state) +intel_reference_dpll(struct intel_atomic_state *state, + const struct intel_crtc *crtc, + const struct intel_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) { struct intel_dpll_state *dpll_state; - dpll_state = intel_atomic_get_shared_dpll_state(&state->base); + dpll_state = intel_atomic_get_dpll_state(&state->base); if (dpll_state[pll->index].pipe_mask == 0) dpll_state[pll->index].hw_state = *dpll_hw_state; - intel_reference_shared_dpll_crtc(crtc, pll, &dpll_state[pll->index]); + intel_reference_dpll_crtc(crtc, pll, &dpll_state[pll->index]); } /** - * intel_unreference_shared_dpll_crtc - Drop a DPLL reference for a CRTC + * intel_unreference_dpll_crtc - Drop a DPLL reference for a CRTC * @crtc: CRTC on which behalf the reference is dropped * @pll: DPLL for which the reference is dropped * @dpll_state: the DPLL atomic state in which the reference is tracked @@ -459,9 +459,9 @@ intel_reference_shared_dpll(struct intel_atomic_state *state, * Drop a reference for @pll tracking the end of use of it by @crtc. */ void -intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_dpll *pll, - struct intel_dpll_state *dpll_state) +intel_unreference_dpll_crtc(const struct intel_crtc *crtc, + const struct intel_dpll *pll, + struct intel_dpll_state *dpll_state) { struct intel_display *display = to_intel_display(crtc); @@ -473,15 +473,15 @@ intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, crtc->base.base.id, crtc->base.name, pll->info->name); } -static void intel_unreference_shared_dpll(struct intel_atomic_state *state, - const struct intel_crtc *crtc, - const struct intel_dpll *pll) +static void intel_unreference_dpll(struct intel_atomic_state *state, + const struct intel_crtc *crtc, + const struct intel_dpll *pll) { struct intel_dpll_state *dpll_state; - dpll_state = intel_atomic_get_shared_dpll_state(&state->base); + dpll_state = intel_atomic_get_dpll_state(&state->base); - intel_unreference_shared_dpll_crtc(crtc, pll, &dpll_state[pll->index]); + intel_unreference_dpll_crtc(crtc, pll, &dpll_state[pll->index]); } static void intel_put_dpll(struct intel_atomic_state *state, @@ -497,11 +497,11 @@ static void intel_put_dpll(struct intel_atomic_state *state, if (!old_crtc_state->intel_dpll) return; - intel_unreference_shared_dpll(state, crtc, old_crtc_state->intel_dpll); + intel_unreference_dpll(state, crtc, old_crtc_state->intel_dpll); } /** - * intel_shared_dpll_swap_state - make atomic DPLL configuration effective + * intel_dpll_swap_state - make atomic DPLL configuration effective * @state: atomic state * * This is the dpll version of drm_atomic_helper_swap_state() since the @@ -511,7 +511,7 @@ static void intel_put_dpll(struct intel_atomic_state *state, * i.e. it also puts the current state into @state, even though there is no * need for that at this moment. */ -void intel_shared_dpll_swap_state(struct intel_atomic_state *state) +void intel_dpll_swap_state(struct intel_atomic_state *state) { struct intel_display *display = to_intel_display(state); struct intel_dpll_state *dpll_state = state->dpll_state; @@ -620,25 +620,25 @@ static int ibx_get_dpll(struct intel_atomic_state *state, if (HAS_PCH_IBX(display)) { /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */ id = (enum intel_dpll_id) crtc->pipe; - pll = intel_get_shared_dpll_by_id(display, id); + pll = intel_get_dpll_by_id(display, id); drm_dbg_kms(display->drm, "[CRTC:%d:%s] using pre-allocated %s\n", crtc->base.base.id, crtc->base.name, pll->info->name); } else { - pll = intel_find_shared_dpll(state, crtc, - &crtc_state->dpll_hw_state, - BIT(DPLL_ID_PCH_PLL_B) | - BIT(DPLL_ID_PCH_PLL_A)); + pll = intel_find_dpll(state, crtc, + &crtc_state->dpll_hw_state, + BIT(DPLL_ID_PCH_PLL_B) | + BIT(DPLL_ID_PCH_PLL_A)); } if (!pll) return -EINVAL; /* reference the pll */ - intel_reference_shared_dpll(state, crtc, - pll, &crtc_state->dpll_hw_state); + intel_reference_dpll(state, crtc, + pll, &crtc_state->dpll_hw_state); crtc_state->intel_dpll = pll; @@ -1066,7 +1066,7 @@ hsw_ddi_wrpll_get_dpll(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - return intel_find_shared_dpll(state, crtc, + return intel_find_dpll(state, crtc, &crtc_state->dpll_hw_state, BIT(DPLL_ID_WRPLL2) | BIT(DPLL_ID_WRPLL1)); @@ -1113,7 +1113,7 @@ hsw_ddi_lcpll_get_dpll(struct intel_crtc_state *crtc_state) return NULL; } - pll = intel_get_shared_dpll_by_id(display, pll_id); + pll = intel_get_dpll_by_id(display, pll_id); if (!pll) return NULL; @@ -1169,7 +1169,7 @@ hsw_ddi_spll_get_dpll(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - return intel_find_shared_dpll(state, crtc, &crtc_state->dpll_hw_state, + return intel_find_dpll(state, crtc, &crtc_state->dpll_hw_state, BIT(DPLL_ID_SPLL)); } @@ -1233,8 +1233,8 @@ static int hsw_get_dpll(struct intel_atomic_state *state, if (!pll) return -EINVAL; - intel_reference_shared_dpll(state, crtc, - pll, &crtc_state->dpll_hw_state); + intel_reference_dpll(state, crtc, + pll, &crtc_state->dpll_hw_state); crtc_state->intel_dpll = pll; @@ -1942,20 +1942,20 @@ static int skl_get_dpll(struct intel_atomic_state *state, struct intel_dpll *pll; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) - pll = intel_find_shared_dpll(state, crtc, - &crtc_state->dpll_hw_state, - BIT(DPLL_ID_SKL_DPLL0)); + pll = intel_find_dpll(state, crtc, + &crtc_state->dpll_hw_state, + BIT(DPLL_ID_SKL_DPLL0)); else - pll = intel_find_shared_dpll(state, crtc, - &crtc_state->dpll_hw_state, - BIT(DPLL_ID_SKL_DPLL3) | - BIT(DPLL_ID_SKL_DPLL2) | - BIT(DPLL_ID_SKL_DPLL1)); + pll = intel_find_dpll(state, crtc, + &crtc_state->dpll_hw_state, + BIT(DPLL_ID_SKL_DPLL3) | + BIT(DPLL_ID_SKL_DPLL2) | + BIT(DPLL_ID_SKL_DPLL1)); if (!pll) return -EINVAL; - intel_reference_shared_dpll(state, crtc, - pll, &crtc_state->dpll_hw_state); + intel_reference_dpll(state, crtc, + pll, &crtc_state->dpll_hw_state); crtc_state->intel_dpll = pll; @@ -2434,13 +2434,13 @@ static int bxt_get_dpll(struct intel_atomic_state *state, /* 1:1 mapping between ports and PLLs */ id = (enum intel_dpll_id) encoder->port; - pll = intel_get_shared_dpll_by_id(display, id); + pll = intel_get_dpll_by_id(display, id); drm_dbg_kms(display->drm, "[CRTC:%d:%s] using pre-allocated %s\n", crtc->base.base.id, crtc->base.name, pll->info->name); - intel_reference_shared_dpll(state, crtc, - pll, &crtc_state->dpll_hw_state); + intel_reference_dpll(state, crtc, + pll, &crtc_state->dpll_hw_state); crtc_state->intel_dpll = pll; @@ -3388,14 +3388,14 @@ static int icl_get_combo_phy_dpll(struct intel_atomic_state *state, /* Eliminate DPLLs from consideration if reserved by HTI */ dpll_mask &= ~intel_hti_dpll_mask(display); - port_dpll->pll = intel_find_shared_dpll(state, crtc, - &port_dpll->hw_state, - dpll_mask); + port_dpll->pll = intel_find_dpll(state, crtc, + &port_dpll->hw_state, + dpll_mask); if (!port_dpll->pll) return -EINVAL; - intel_reference_shared_dpll(state, crtc, - port_dpll->pll, &port_dpll->hw_state); + intel_reference_dpll(state, crtc, + port_dpll->pll, &port_dpll->hw_state); icl_update_active_dpll(state, crtc, encoder); @@ -3452,26 +3452,25 @@ static int icl_get_tc_phy_dplls(struct intel_atomic_state *state, int ret; port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; - port_dpll->pll = intel_find_shared_dpll(state, crtc, - &port_dpll->hw_state, - BIT(DPLL_ID_ICL_TBTPLL)); + port_dpll->pll = intel_find_dpll(state, crtc, + &port_dpll->hw_state, + BIT(DPLL_ID_ICL_TBTPLL)); if (!port_dpll->pll) return -EINVAL; - intel_reference_shared_dpll(state, crtc, - port_dpll->pll, &port_dpll->hw_state); - + intel_reference_dpll(state, crtc, + port_dpll->pll, &port_dpll->hw_state); port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY]; dpll_id = icl_tc_port_to_pll_id(intel_encoder_to_tc(encoder)); - port_dpll->pll = intel_find_shared_dpll(state, crtc, - &port_dpll->hw_state, - BIT(dpll_id)); + port_dpll->pll = intel_find_dpll(state, crtc, + &port_dpll->hw_state, + BIT(dpll_id)); if (!port_dpll->pll) { ret = -EINVAL; goto err_unreference_tbt_pll; } - intel_reference_shared_dpll(state, crtc, - port_dpll->pll, &port_dpll->hw_state); + intel_reference_dpll(state, crtc, + port_dpll->pll, &port_dpll->hw_state); icl_update_active_dpll(state, crtc, encoder); @@ -3479,7 +3478,7 @@ static int icl_get_tc_phy_dplls(struct intel_atomic_state *state, err_unreference_tbt_pll: port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; - intel_unreference_shared_dpll(state, crtc, port_dpll->pll); + intel_unreference_dpll(state, crtc, port_dpll->pll); return ret; } @@ -3534,7 +3533,7 @@ static void icl_put_dplls(struct intel_atomic_state *state, if (!old_port_dpll->pll) continue; - intel_unreference_shared_dpll(state, crtc, old_port_dpll->pll); + intel_unreference_dpll(state, crtc, old_port_dpll->pll); } } @@ -4300,12 +4299,12 @@ static const struct intel_dpll_mgr adlp_pll_mgr = { }; /** - * intel_shared_dpll_init - Initialize shared DPLLs + * intel_dpll_init - Initialize DPLLs * @display: intel_display device * - * Initialize shared DPLLs for @display. + * Initialize DPLLs for @display. */ -void intel_shared_dpll_init(struct intel_display *display) +void intel_dpll_init(struct intel_display *display) { const struct intel_dpll_mgr *dpll_mgr = NULL; const struct dpll_info *dpll_info; @@ -4362,7 +4361,7 @@ void intel_shared_dpll_init(struct intel_display *display) } /** - * intel_compute_shared_dplls - compute DPLL state CRTC and encoder combination + * intel_compute_dplls - compute DPLL state CRTC and encoder combination * @state: atomic state * @crtc: CRTC to compute DPLLs for * @encoder: encoder @@ -4370,14 +4369,14 @@ void intel_shared_dpll_init(struct intel_display *display) * This function computes the DPLL state for the given CRTC and encoder. * * The new configuration in the atomic commit @state is made effective by - * calling intel_shared_dpll_swap_state(). + * calling intel_dpll_swap_state(). * * Returns: * 0 on success, negative error code on failure. */ -int intel_compute_shared_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder) +int intel_compute_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(state); const struct intel_dpll_mgr *dpll_mgr = display->dpll.mgr; @@ -4389,7 +4388,7 @@ int intel_compute_shared_dplls(struct intel_atomic_state *state, } /** - * intel_reserve_shared_dplls - reserve DPLLs for CRTC and encoder combination + * intel_reserve_dplls - reserve DPLLs for CRTC and encoder combination * @state: atomic state * @crtc: CRTC to reserve DPLLs for * @encoder: encoder @@ -4399,18 +4398,18 @@ int intel_compute_shared_dplls(struct intel_atomic_state *state, * state. * * The new configuration in the atomic commit @state is made effective by - * calling intel_shared_dpll_swap_state(). + * calling intel_dpll_swap_state(). * * The reserved DPLLs should be released by calling - * intel_release_shared_dplls(). + * intel_release_dplls(). * * Returns: * 0 if all required DPLLs were successfully reserved, * negative error code otherwise. */ -int intel_reserve_shared_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder) +int intel_reserve_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(state); const struct intel_dpll_mgr *dpll_mgr = display->dpll.mgr; @@ -4422,18 +4421,18 @@ int intel_reserve_shared_dplls(struct intel_atomic_state *state, } /** - * intel_release_shared_dplls - end use of DPLLs by CRTC in atomic state + * intel_release_dplls - end use of DPLLs by CRTC in atomic state * @state: atomic state * @crtc: crtc from which the DPLLs are to be released * - * This function releases all DPLLs reserved by intel_reserve_shared_dplls() + * This function releases all DPLLs reserved by intel_reserve_dplls() * from the current atomic commit @state and the old @crtc atomic state. * * The new configuration in the atomic commit @state is made effective by - * calling intel_shared_dpll_swap_state(). + * calling intel_dpll_swap_state(). */ -void intel_release_shared_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc) +void intel_release_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(state); const struct intel_dpll_mgr *dpll_mgr = display->dpll.mgr; @@ -4441,7 +4440,7 @@ void intel_release_shared_dplls(struct intel_atomic_state *state, /* * FIXME: this function is called for every platform having a * compute_clock hook, even though the platform doesn't yet support - * the shared DPLL framework and intel_reserve_shared_dplls() is not + * the DPLL framework and intel_reserve_dplls() is not * called on those. */ if (!dpll_mgr) @@ -4457,7 +4456,7 @@ void intel_release_shared_dplls(struct intel_atomic_state *state, * @encoder: encoder determining the type of port DPLL * * Update the active DPLL for the given @crtc/@encoder in @crtc's atomic state, - * from the port DPLLs reserved previously by intel_reserve_shared_dplls(). The + * from the port DPLLs reserved previously by intel_reserve_dplls(). The * DPLL selected will be based on the current mode of the encoder's port. */ void intel_update_active_dpll(struct intel_atomic_state *state, @@ -4522,7 +4521,7 @@ static void readout_dpll_hw_state(struct intel_display *display, to_intel_crtc_state(crtc->base.state); if (crtc_state->hw.active && crtc_state->intel_dpll == pll) - intel_reference_shared_dpll_crtc(crtc, pll, &pll->state); + intel_reference_dpll_crtc(crtc, pll, &pll->state); } pll->active_mask = pll->state.pipe_mask; @@ -4683,8 +4682,8 @@ static bool has_alt_port_dpll(const struct intel_dpll *old_pll, (old_pll->info->is_alt_port_dpll || new_pll->info->is_alt_port_dpll); } -void intel_shared_dpll_state_verify(struct intel_atomic_state *state, - struct intel_crtc *crtc) +void intel_dpll_state_verify(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(state); const struct intel_crtc_state *old_crtc_state = @@ -4714,7 +4713,7 @@ void intel_shared_dpll_state_verify(struct intel_atomic_state *state, } } -void intel_shared_dpll_verify_disabled(struct intel_atomic_state *state) +void intel_dpll_verify_disabled(struct intel_atomic_state *state) { struct intel_display *display = to_intel_display(state); struct intel_dpll *pll; diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index ea3fb7002e653..60391a5b52ff2 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -387,26 +387,26 @@ struct intel_dpll { #define SKL_DPLL2 2 #define SKL_DPLL3 3 -/* shared dpll functions */ +/* dpll functions */ struct intel_dpll * -intel_get_shared_dpll_by_id(struct intel_display *display, - enum intel_dpll_id id); -void assert_shared_dpll(struct intel_display *display, - struct intel_dpll *pll, - bool state); -#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true) -#define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false) -int intel_compute_shared_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder); -int intel_reserve_shared_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder); -void intel_release_shared_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc); -void intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_dpll *pll, - struct intel_dpll_state *shared_dpll_state); +intel_get_dpll_by_id(struct intel_display *display, + enum intel_dpll_id id); +void assert_dpll(struct intel_display *display, + struct intel_dpll *pll, + bool state); +#define assert_dpll_enabled(d, p) assert_dpll(d, p, true) +#define assert_dpll_disabled(d, p) assert_dpll(d, p, false) +int intel_compute_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder); +int intel_reserve_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder); +void intel_release_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc); +void intel_unreference_dpll_crtc(const struct intel_crtc *crtc, + const struct intel_dpll *pll, + struct intel_dpll_state *shared_dpll_state); void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state, enum icl_port_dpll_id port_dpll_id); void intel_update_active_dpll(struct intel_atomic_state *state, @@ -418,10 +418,10 @@ int intel_dpll_get_freq(struct intel_display *display, bool intel_dpll_get_hw_state(struct intel_display *display, struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state); -void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state); -void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state); -void intel_shared_dpll_swap_state(struct intel_atomic_state *state); -void intel_shared_dpll_init(struct intel_display *display); +void intel_enable_dpll(const struct intel_crtc_state *crtc_state); +void intel_disable_dpll(const struct intel_crtc_state *crtc_state); +void intel_dpll_swap_state(struct intel_atomic_state *state); +void intel_dpll_init(struct intel_display *display); void intel_dpll_update_ref_clks(struct intel_display *display); void intel_dpll_readout_hw_state(struct intel_display *display); void intel_dpll_sanitize_state(struct intel_display *display); @@ -435,8 +435,8 @@ bool intel_dpll_compare_hw_state(struct intel_display *display, enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port); bool intel_dpll_is_combophy(enum intel_dpll_id id); -void intel_shared_dpll_state_verify(struct intel_atomic_state *state, - struct intel_crtc *crtc); -void intel_shared_dpll_verify_disabled(struct intel_atomic_state *state); +void intel_dpll_state_verify(struct intel_atomic_state *state, + struct intel_crtc *crtc); +void intel_dpll_verify_disabled(struct intel_atomic_state *state); #endif /* _INTEL_DPLL_MGR_H_ */ diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index ec8f38fba1785..f07c7ef561483 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -249,7 +249,7 @@ static void intel_pre_enable_lvds(struct intel_atomic_state *state, if (HAS_PCH_SPLIT(display)) { assert_fdi_rx_pll_disabled(display, pipe); - assert_shared_dpll_disabled(display, crtc_state->intel_dpll); + assert_dpll_disabled(display, crtc_state->intel_dpll); } else { assert_pll_disabled(display, pipe); } diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index 46e0002a13586..ed4f305e0d3ea 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -93,9 +93,9 @@ static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc, crtc->base.enabled = false; if (crtc_state->intel_dpll) - intel_unreference_shared_dpll_crtc(crtc, - crtc_state->intel_dpll, - &crtc_state->intel_dpll->state); + intel_unreference_dpll_crtc(crtc, + crtc_state->intel_dpll, + &crtc_state->intel_dpll->state); } static void set_encoder_for_connector(struct intel_connector *connector, diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c index 766a9983665a8..f2f6b9d9afa10 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c @@ -243,7 +243,7 @@ void intel_modeset_verify_crtc(struct intel_atomic_state *state, intel_wm_state_verify(state, crtc); verify_connector_state(state, crtc); verify_crtc_state(state, crtc); - intel_shared_dpll_state_verify(state, crtc); + intel_dpll_state_verify(state, crtc); intel_mpllb_state_verify(state, crtc); intel_cx0pll_state_verify(state, crtc); } @@ -252,5 +252,5 @@ void intel_modeset_verify_disabled(struct intel_atomic_state *state) { verify_encoder_state(state); verify_connector_state(state, NULL); - intel_shared_dpll_verify_disabled(state); + intel_dpll_verify_disabled(state); } diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index b38305c16e77c..b59b3c94f7113 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -251,7 +251,7 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) u32 val, pipeconf_val; /* Make sure PCH DPLL is enabled */ - assert_shared_dpll_enabled(display, crtc_state->intel_dpll); + assert_dpll_enabled(display, crtc_state->intel_dpll); /* FDI must be feeding us bits for PCH ports */ assert_fdi_tx_enabled(display, pipe); @@ -382,7 +382,7 @@ void ilk_pch_enable(struct intel_atomic_state *state, temp |= TRANS_DPLL_ENABLE(pipe); sel = TRANS_DPLLB_SEL(pipe); if (crtc_state->intel_dpll == - intel_get_shared_dpll_by_id(display, DPLL_ID_PCH_PLL_B)) + intel_get_dpll_by_id(display, DPLL_ID_PCH_PLL_B)) temp |= sel; else temp &= ~sel; @@ -394,11 +394,11 @@ void ilk_pch_enable(struct intel_atomic_state *state, * transcoder, and we actually should do this to not upset any PCH * transcoder that already use the clock when we share it. * - * Note that enable_shared_dpll tries to do the right thing, but - * get_shared_dpll unconditionally resets the pll - we need that + * Note that enable_dpll tries to do the right thing, but + * get_dpll unconditionally resets the pll - we need that * to have the right LVDS enable sequence. */ - intel_enable_shared_dpll(crtc_state); + intel_enable_dpll(crtc_state); /* set transcoder timing, panel must allow it */ assert_pps_unlocked(display, pipe); @@ -472,7 +472,7 @@ void ilk_pch_post_disable(struct intel_atomic_state *state, ilk_fdi_pll_disable(crtc); - intel_disable_shared_dpll(old_crtc_state); + intel_disable_dpll(old_crtc_state); } static void ilk_pch_clock_get(struct intel_crtc_state *crtc_state) @@ -528,7 +528,7 @@ void ilk_pch_get_config(struct intel_crtc_state *crtc_state) pll_id = DPLL_ID_PCH_PLL_A; } - crtc_state->intel_dpll = intel_get_shared_dpll_by_id(display, pll_id); + crtc_state->intel_dpll = intel_get_dpll_by_id(display, pll_id); pll = crtc_state->intel_dpll; pll_active = intel_dpll_get_hw_state(display, pll, -- GitLab From 7e9a4cbbc5106a6bd7fc50ebc50bb8a8d68aca75 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:55 +0530 Subject: [PATCH 0133/1479] drm/i915/dpll: Rename crtc_get_shared_dpll Rename crtc_get_shared_dpll to take into the individual PLL framework which came in at DISPLAY_VER >= 14. Also having shared dpll stuff also in intel_dpll.c is just confusing. --v2 -Change naming to dpll_global to keep consistency with rest of the naming --v3 -Just use intel_dpll [Jani] --v4 -Modify commit message [Jani] Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-9-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll.c | 24 ++++++++++---------- drivers/gpu/drm/i915/display/intel_dpll.h | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 858d9397b6708..bb57e6a980643 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4225,7 +4225,7 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state, crtc_state->update_wm_post = true; if (intel_crtc_needs_modeset(crtc_state)) { - ret = intel_dpll_crtc_get_shared_dpll(state, crtc); + ret = intel_dpll_crtc_get_dpll(state, crtc); if (ret) return ret; } diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 80de897a761fb..4f8be9ac9f8af 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -28,8 +28,8 @@ struct intel_dpll_global_funcs { int (*crtc_compute_clock)(struct intel_atomic_state *state, struct intel_crtc *crtc); - int (*crtc_get_shared_dpll)(struct intel_atomic_state *state, - struct intel_crtc *crtc); + int (*crtc_get_dpll)(struct intel_atomic_state *state, + struct intel_crtc *crtc); }; struct intel_limit { @@ -1177,8 +1177,8 @@ static int hsw_crtc_compute_clock(struct intel_atomic_state *state, return 0; } -static int hsw_crtc_get_shared_dpll(struct intel_atomic_state *state, - struct intel_crtc *crtc) +static int hsw_crtc_get_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(state); struct intel_crtc_state *crtc_state = @@ -1405,8 +1405,8 @@ static int ilk_crtc_compute_clock(struct intel_atomic_state *state, return ret; } -static int ilk_crtc_get_shared_dpll(struct intel_atomic_state *state, - struct intel_crtc *crtc) +static int ilk_crtc_get_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); @@ -1701,12 +1701,12 @@ static const struct intel_dpll_global_funcs dg2_dpll_funcs = { static const struct intel_dpll_global_funcs hsw_dpll_funcs = { .crtc_compute_clock = hsw_crtc_compute_clock, - .crtc_get_shared_dpll = hsw_crtc_get_shared_dpll, + .crtc_get_dpll = hsw_crtc_get_dpll, }; static const struct intel_dpll_global_funcs ilk_dpll_funcs = { .crtc_compute_clock = ilk_crtc_compute_clock, - .crtc_get_shared_dpll = ilk_crtc_get_shared_dpll, + .crtc_get_dpll = ilk_crtc_get_dpll, }; static const struct intel_dpll_global_funcs chv_dpll_funcs = { @@ -1759,8 +1759,8 @@ int intel_dpll_crtc_compute_clock(struct intel_atomic_state *state, return 0; } -int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state, - struct intel_crtc *crtc) +int intel_dpll_crtc_get_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(state); struct intel_crtc_state *crtc_state = @@ -1773,10 +1773,10 @@ int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state, if (!crtc_state->hw.enable || crtc_state->intel_dpll) return 0; - if (!display->funcs.dpll->crtc_get_shared_dpll) + if (!display->funcs.dpll->crtc_get_dpll) return 0; - ret = display->funcs.dpll->crtc_get_shared_dpll(state, crtc); + ret = display->funcs.dpll->crtc_get_dpll(state, crtc); if (ret) { drm_dbg_kms(display->drm, "[CRTC:%d:%s] Couldn't get a shared DPLL\n", crtc->base.base.id, crtc->base.name); diff --git a/drivers/gpu/drm/i915/display/intel_dpll.h b/drivers/gpu/drm/i915/display/intel_dpll.h index 280e90a57c875..3444a2dd3166e 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.h +++ b/drivers/gpu/drm/i915/display/intel_dpll.h @@ -19,8 +19,8 @@ struct intel_dpll_hw_state; void intel_dpll_init_clock_hook(struct intel_display *display); int intel_dpll_crtc_compute_clock(struct intel_atomic_state *state, struct intel_crtc *crtc); -int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state, - struct intel_crtc *crtc); +int intel_dpll_crtc_get_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc); int i9xx_calc_dpll_params(int refclk, struct dpll *clock); u32 i9xx_dpll_compute_fp(const struct dpll *dpll); void i9xx_dpll_get_hw_state(struct intel_crtc *crtc, -- GitLab From 38c5854a184cb681e0b25d675de27c1f0aa53917 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:56 +0530 Subject: [PATCH 0134/1479] drm/i915/dpll: Rename intel_[enable/disable]_dpll Rename intel_[enable/disable]_dpll to intel_dpll_[enable/disable] in an effort to make sure all functions that are exported start with the filename. Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-10-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++-- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 8 ++++---- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 4 ++-- drivers/gpu/drm/i915/display/intel_pch_display.c | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index bb57e6a980643..27e1cce02faa8 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1664,7 +1664,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, intel_encoders_pre_pll_enable(state, crtc); if (new_crtc_state->intel_dpll) - intel_enable_dpll(new_crtc_state); + intel_dpll_enable(new_crtc_state); intel_encoders_pre_enable(state, crtc); @@ -1793,7 +1793,7 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, intel_encoders_disable(state, crtc); intel_encoders_post_disable(state, crtc); - intel_disable_dpll(old_crtc_state); + intel_dpll_disable(old_crtc_state); intel_encoders_post_pll_disable(state, crtc); diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 69271892067a8..2b592423e1d15 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -250,12 +250,12 @@ static void _intel_disable_shared_dpll(struct intel_display *display, } /** - * intel_enable_dpll - enable a CRTC's DPLL + * intel_dpll_enable - enable a CRTC's DPLL * @crtc_state: CRTC, and its state, which has a DPLL * * Enable DPLL used by @crtc. */ -void intel_enable_dpll(const struct intel_crtc_state *crtc_state) +void intel_dpll_enable(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -296,12 +296,12 @@ void intel_enable_dpll(const struct intel_crtc_state *crtc_state) } /** - * intel_disable_dpll - disable a CRTC's shared DPLL + * intel_dpll_disable - disable a CRTC's shared DPLL * @crtc_state: CRTC, and its state, which has a shared DPLL * * Disable DPLL used by @crtc. */ -void intel_disable_dpll(const struct intel_crtc_state *crtc_state) +void intel_dpll_disable(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index 60391a5b52ff2..88a81c850cf06 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -418,8 +418,8 @@ int intel_dpll_get_freq(struct intel_display *display, bool intel_dpll_get_hw_state(struct intel_display *display, struct intel_dpll *pll, struct intel_dpll_hw_state *dpll_hw_state); -void intel_enable_dpll(const struct intel_crtc_state *crtc_state); -void intel_disable_dpll(const struct intel_crtc_state *crtc_state); +void intel_dpll_enable(const struct intel_crtc_state *crtc_state); +void intel_dpll_disable(const struct intel_crtc_state *crtc_state); void intel_dpll_swap_state(struct intel_atomic_state *state); void intel_dpll_init(struct intel_display *display); void intel_dpll_update_ref_clks(struct intel_display *display); diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index b59b3c94f7113..ca85596dfc9e3 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -394,11 +394,11 @@ void ilk_pch_enable(struct intel_atomic_state *state, * transcoder, and we actually should do this to not upset any PCH * transcoder that already use the clock when we share it. * - * Note that enable_dpll tries to do the right thing, but + * Note that dpll_enable tries to do the right thing, but * get_dpll unconditionally resets the pll - we need that * to have the right LVDS enable sequence. */ - intel_enable_dpll(crtc_state); + intel_dpll_enable(crtc_state); /* set transcoder timing, panel must allow it */ assert_pps_unlocked(display, pipe); @@ -472,7 +472,7 @@ void ilk_pch_post_disable(struct intel_atomic_state *state, ilk_fdi_pll_disable(crtc); - intel_disable_dpll(old_crtc_state); + intel_dpll_disable(old_crtc_state); } static void ilk_pch_clock_get(struct intel_crtc_state *crtc_state) -- GitLab From 3b65a01ab590684e5b68c15940ef3ab2a6a72303 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:57 +0530 Subject: [PATCH 0135/1479] drm/i915/dpll: Rename intel_unreference_dpll_crtc Rename intel_unreference_dpll_crtc to intel_dpll_crtc_put in an effort to keep names of exported functions start with the filename. --v2 -Make the new name more sensible [Jani] Signed-off-by: Suraj Kandpal Reviewed-by: Mika Kahola Link: https://lore.kernel.org/r/20250515071801.2221120-11-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 10 +++++----- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 6 +++--- drivers/gpu/drm/i915/display/intel_modeset_setup.c | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 2b592423e1d15..1265bc4b4307a 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -451,7 +451,7 @@ intel_reference_dpll(struct intel_atomic_state *state, } /** - * intel_unreference_dpll_crtc - Drop a DPLL reference for a CRTC + * intel_dpll_crtc_put - Drop a DPLL reference for a CRTC * @crtc: CRTC on which behalf the reference is dropped * @pll: DPLL for which the reference is dropped * @dpll_state: the DPLL atomic state in which the reference is tracked @@ -459,9 +459,9 @@ intel_reference_dpll(struct intel_atomic_state *state, * Drop a reference for @pll tracking the end of use of it by @crtc. */ void -intel_unreference_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_dpll *pll, - struct intel_dpll_state *dpll_state) +intel_dpll_crtc_put(const struct intel_crtc *crtc, + const struct intel_dpll *pll, + struct intel_dpll_state *dpll_state) { struct intel_display *display = to_intel_display(crtc); @@ -481,7 +481,7 @@ static void intel_unreference_dpll(struct intel_atomic_state *state, dpll_state = intel_atomic_get_dpll_state(&state->base); - intel_unreference_dpll_crtc(crtc, pll, &dpll_state[pll->index]); + intel_dpll_crtc_put(crtc, pll, &dpll_state[pll->index]); } static void intel_put_dpll(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index 88a81c850cf06..f8ba7b52a7adc 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -404,9 +404,9 @@ int intel_reserve_dplls(struct intel_atomic_state *state, struct intel_encoder *encoder); void intel_release_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc); -void intel_unreference_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_dpll *pll, - struct intel_dpll_state *shared_dpll_state); +void intel_dpll_crtc_put(const struct intel_crtc *crtc, + const struct intel_dpll *pll, + struct intel_dpll_state *shared_dpll_state); void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state, enum icl_port_dpll_id port_dpll_id); void intel_update_active_dpll(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index ed4f305e0d3ea..22c5302e37982 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -93,9 +93,9 @@ static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc, crtc->base.enabled = false; if (crtc_state->intel_dpll) - intel_unreference_dpll_crtc(crtc, - crtc_state->intel_dpll, - &crtc_state->intel_dpll->state); + intel_dpll_crtc_put(crtc, + crtc_state->intel_dpll, + &crtc_state->intel_dpll->state); } static void set_encoder_for_connector(struct intel_connector *connector, -- GitLab From c51686d8d3576bef6f842d0191214564613c4af6 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:58 +0530 Subject: [PATCH 0136/1479] drm/i915/dpll: Rename intel_reference_dpll_crtc Rename intel_reference_dpll_crtc to intel_dpll_crtc_get in an effort to have all the exported functions have the name start with file name. Signed-off-by: Suraj Kandpal Reviewed-by: Mika Kahola Link: https://lore.kernel.org/r/20250515071801.2221120-12-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 1265bc4b4307a..db15d4f0328c4 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -412,7 +412,7 @@ intel_find_dpll(struct intel_atomic_state *state, } /** - * intel_reference_dpll_crtc - Get a DPLL reference for a CRTC + * intel_dpll_crtc_get - Get a DPLL reference for a CRTC * @crtc: CRTC on which behalf the reference is taken * @pll: DPLL for which the reference is taken * @dpll_state: the DPLL atomic state in which the reference is tracked @@ -420,9 +420,9 @@ intel_find_dpll(struct intel_atomic_state *state, * Take a reference for @pll tracking the use of it by @crtc. */ static void -intel_reference_dpll_crtc(const struct intel_crtc *crtc, - const struct intel_dpll *pll, - struct intel_dpll_state *dpll_state) +intel_dpll_crtc_get(const struct intel_crtc *crtc, + const struct intel_dpll *pll, + struct intel_dpll_state *dpll_state) { struct intel_display *display = to_intel_display(crtc); @@ -447,7 +447,7 @@ intel_reference_dpll(struct intel_atomic_state *state, if (dpll_state[pll->index].pipe_mask == 0) dpll_state[pll->index].hw_state = *dpll_hw_state; - intel_reference_dpll_crtc(crtc, pll, &dpll_state[pll->index]); + intel_dpll_crtc_get(crtc, pll, &dpll_state[pll->index]); } /** @@ -4521,7 +4521,7 @@ static void readout_dpll_hw_state(struct intel_display *display, to_intel_crtc_state(crtc->base.state); if (crtc_state->hw.active && crtc_state->intel_dpll == pll) - intel_reference_dpll_crtc(crtc, pll, &pll->state); + intel_dpll_crtc_get(crtc, pll, &pll->state); } pll->active_mask = pll->state.pipe_mask; -- GitLab From bb90401b847b3702ea2f9ba727be15e697d53528 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:47:59 +0530 Subject: [PATCH 0137/1479] drm/i915/dpll: Rename intel__dpll Rename intel__dpll to intel_dpll_ in an effort to keep names of exported functions start with the filename. Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-13-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll.c | 4 +-- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 26 +++++++++---------- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 10 +++---- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 27e1cce02faa8..c894e4d0d4881 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6436,7 +6436,7 @@ int intel_atomic_check(struct drm_device *dev, any_ms = true; - intel_release_dplls(state, crtc); + intel_dpll_release(state, crtc); } if (any_ms && !check_digital_port_conflicts(state)) { diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 4f8be9ac9f8af..83147a578c09f 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1190,7 +1190,7 @@ static int hsw_crtc_get_dpll(struct intel_atomic_state *state, intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) return 0; - return intel_reserve_dplls(state, crtc, encoder); + return intel_dpll_reserve(state, crtc, encoder); } static int dg2_crtc_compute_clock(struct intel_atomic_state *state, @@ -1415,7 +1415,7 @@ static int ilk_crtc_get_dpll(struct intel_atomic_state *state, if (!crtc_state->has_pch_encoder) return 0; - return intel_reserve_dplls(state, crtc, NULL); + return intel_dpll_reserve(state, crtc, NULL); } static u32 vlv_dpll(const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index db15d4f0328c4..6f56a80592424 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -56,8 +56,8 @@ * users of a PLL are tracked and that tracking is integrated with the atomic * modset interface. During an atomic operation, required PLLs can be reserved * for a given CRTC and encoder configuration by calling - * intel_reserve_dplls() and previously reserved PLLs can be released - * with intel_release_dplls(). + * intel_dpll_reserve() and previously reserved PLLs can be released + * with intel_dpll_release(). * Changes to the users are first staged in the atomic state, and then made * effective by calling intel_dpll_swap_state() during the atomic * commit phase. @@ -4388,7 +4388,7 @@ int intel_compute_dplls(struct intel_atomic_state *state, } /** - * intel_reserve_dplls - reserve DPLLs for CRTC and encoder combination + * intel_dpll_reserve - reserve DPLLs for CRTC and encoder combination * @state: atomic state * @crtc: CRTC to reserve DPLLs for * @encoder: encoder @@ -4401,15 +4401,15 @@ int intel_compute_dplls(struct intel_atomic_state *state, * calling intel_dpll_swap_state(). * * The reserved DPLLs should be released by calling - * intel_release_dplls(). + * intel_dpll_release(). * * Returns: * 0 if all required DPLLs were successfully reserved, * negative error code otherwise. */ -int intel_reserve_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder) +int intel_dpll_reserve(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(state); const struct intel_dpll_mgr *dpll_mgr = display->dpll.mgr; @@ -4421,18 +4421,18 @@ int intel_reserve_dplls(struct intel_atomic_state *state, } /** - * intel_release_dplls - end use of DPLLs by CRTC in atomic state + * intel_dpll_release - end use of DPLLs by CRTC in atomic state * @state: atomic state * @crtc: crtc from which the DPLLs are to be released * - * This function releases all DPLLs reserved by intel_reserve_dplls() + * This function releases all DPLLs reserved by intel_dpll_reserve() * from the current atomic commit @state and the old @crtc atomic state. * * The new configuration in the atomic commit @state is made effective by * calling intel_dpll_swap_state(). */ -void intel_release_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc) +void intel_dpll_release(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(state); const struct intel_dpll_mgr *dpll_mgr = display->dpll.mgr; @@ -4440,7 +4440,7 @@ void intel_release_dplls(struct intel_atomic_state *state, /* * FIXME: this function is called for every platform having a * compute_clock hook, even though the platform doesn't yet support - * the DPLL framework and intel_reserve_dplls() is not + * the DPLL framework and intel_dpll_reserve() is not * called on those. */ if (!dpll_mgr) @@ -4456,7 +4456,7 @@ void intel_release_dplls(struct intel_atomic_state *state, * @encoder: encoder determining the type of port DPLL * * Update the active DPLL for the given @crtc/@encoder in @crtc's atomic state, - * from the port DPLLs reserved previously by intel_reserve_dplls(). The + * from the port DPLLs reserved previously by intel_dpll_reserve(). The * DPLL selected will be based on the current mode of the encoder's port. */ void intel_update_active_dpll(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index f8ba7b52a7adc..9c8a91b9639c0 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -399,11 +399,11 @@ void assert_dpll(struct intel_display *display, int intel_compute_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder); -int intel_reserve_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder); -void intel_release_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc); +int intel_dpll_reserve(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder); +void intel_dpll_release(struct intel_atomic_state *state, + struct intel_crtc *crtc); void intel_dpll_crtc_put(const struct intel_crtc *crtc, const struct intel_dpll *pll, struct intel_dpll_state *shared_dpll_state); -- GitLab From 71325aa5a0f18969f642fcc2a1cbb77624d357aa Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:48:00 +0530 Subject: [PATCH 0138/1479] drm/i915/dpll: Rename intel_compute_dpll Rename intel_compute_dpll to intel_dpll_compute in an effort to make sure all function names that are exported have the filename at start. Signed-off-by: Suraj Kandpal Reviewed-by: Jani Nikula Link: https://lore.kernel.org/r/20250515071801.2221120-14-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_dpll.c | 6 +++--- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 8 ++++---- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 83147a578c09f..db98e2758271e 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1162,7 +1162,7 @@ static int hsw_crtc_compute_clock(struct intel_atomic_state *state, intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) return 0; - ret = intel_compute_dplls(state, crtc, encoder); + ret = intel_dpll_compute(state, crtc, encoder); if (ret) return ret; @@ -1224,7 +1224,7 @@ static int mtl_crtc_compute_clock(struct intel_atomic_state *state, if (ret) return ret; - /* TODO: Do the readback via intel_compute_dplls() */ + /* TODO: Do the readback via intel_dpll_compute() */ crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->dpll_hw_state.cx0pll); crtc_state->hw.adjusted_mode.crtc_clock = intel_crtc_dotclock(crtc_state); @@ -1395,7 +1395,7 @@ static int ilk_crtc_compute_clock(struct intel_atomic_state *state, ilk_compute_dpll(crtc_state, &crtc_state->dpll, &crtc_state->dpll); - ret = intel_compute_dplls(state, crtc, NULL); + ret = intel_dpll_compute(state, crtc, NULL); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 6f56a80592424..bf66cbe5a11cc 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4361,7 +4361,7 @@ void intel_dpll_init(struct intel_display *display) } /** - * intel_compute_dplls - compute DPLL state CRTC and encoder combination + * intel_dpll_compute - compute DPLL state CRTC and encoder combination * @state: atomic state * @crtc: CRTC to compute DPLLs for * @encoder: encoder @@ -4374,9 +4374,9 @@ void intel_dpll_init(struct intel_display *display) * Returns: * 0 on success, negative error code on failure. */ -int intel_compute_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder) +int intel_dpll_compute(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(state); const struct intel_dpll_mgr *dpll_mgr = display->dpll.mgr; diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index 9c8a91b9639c0..b388310af9c3e 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -396,9 +396,9 @@ void assert_dpll(struct intel_display *display, bool state); #define assert_dpll_enabled(d, p) assert_dpll(d, p, true) #define assert_dpll_disabled(d, p) assert_dpll(d, p, false) -int intel_compute_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder); +int intel_dpll_compute(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder); int intel_dpll_reserve(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder); -- GitLab From 99354ec6409f716488887fc8094a1e63b7d35af3 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 15 May 2025 12:48:01 +0530 Subject: [PATCH 0139/1479] drm/i915/dpll: Rename intel_update_active_dpll Rename intel_update_active_dpll to intel_dpll_update_active in an effort to have function names which are exported to start with filenames they are exported from. Signed-off-by: Suraj Kandpal Reviewed-by: Mika Kahola Link: https://lore.kernel.org/r/20250515071801.2221120-15-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 4 ++-- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 11ebcb40c91f6..0e6d618b53565 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3650,7 +3650,7 @@ void intel_ddi_update_active_dpll(struct intel_atomic_state *state, for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc, intel_crtc_joined_pipe_mask(crtc_state)) - intel_update_active_dpll(state, pipe_crtc, encoder); + intel_dpll_update_active(state, pipe_crtc, encoder); } /* diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index bf66cbe5a11cc..28b3f5ea4219a 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4450,7 +4450,7 @@ void intel_dpll_release(struct intel_atomic_state *state, } /** - * intel_update_active_dpll - update the active DPLL for a CRTC/encoder + * intel_dpll_update_active - update the active DPLL for a CRTC/encoder * @state: atomic state * @crtc: the CRTC for which to update the active DPLL * @encoder: encoder determining the type of port DPLL @@ -4459,7 +4459,7 @@ void intel_dpll_release(struct intel_atomic_state *state, * from the port DPLLs reserved previously by intel_dpll_reserve(). The * DPLL selected will be based on the current mode of the encoder's port. */ -void intel_update_active_dpll(struct intel_atomic_state *state, +void intel_dpll_update_active(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder) { diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index b388310af9c3e..f131bdd1c975d 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -409,7 +409,7 @@ void intel_dpll_crtc_put(const struct intel_crtc *crtc, struct intel_dpll_state *shared_dpll_state); void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state, enum icl_port_dpll_id port_dpll_id); -void intel_update_active_dpll(struct intel_atomic_state *state, +void intel_dpll_update_active(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder); int intel_dpll_get_freq(struct intel_display *display, -- GitLab From c3a48363cf1f76147088b1adb518136ac5df86a0 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 19 May 2025 16:34:17 +0300 Subject: [PATCH 0140/1479] drm/i915/dp_mst: Work around Thunderbolt sink disconnect after SINK_COUNT_ESI read Due to a problem in the iTBT DP-in adapter's firmware the sink on a TBT link may get disconnected inadvertently if the SINK_COUNT_ESI and the DP_LINK_SERVICE_IRQ_VECTOR_ESI0 registers are read in a single AUX transaction. Work around the issue by reading these registers in separate transactions. The issue affects MTL+ platforms and will be fixed in the DP-in adapter firmware, however releasing that firmware fix may take some time and is not guaranteed to be available for all systems. Based on this apply the workaround on affected platforms. See HSD #13013007775. v2: Cc'ing Mika Westerberg. Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13760 Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14147 Cc: Mika Westerberg Cc: stable@vger.kernel.org Reviewed-by: Mika Westerberg Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250519133417.1469181-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 21297bc4cc00d..208a953b04a2f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4538,6 +4538,23 @@ intel_dp_mst_disconnect(struct intel_dp *intel_dp) static bool intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *esi) { + struct intel_display *display = to_intel_display(intel_dp); + + /* + * Display WA for HSD #13013007775: mtl/arl/lnl + * Read the sink count and link service IRQ registers in separate + * transactions to prevent disconnecting the sink on a TBT link + * inadvertently. + */ + if (IS_DISPLAY_VER(display, 14, 20) && !display->platform.battlemage) { + if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT_ESI, esi, 3) != 3) + return false; + + /* DP_SINK_COUNT_ESI + 3 == DP_LINK_SERVICE_IRQ_VECTOR_ESI0 */ + return drm_dp_dpcd_readb(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, + &esi[3]) == 1; + } + return drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT_ESI, esi, 4) == 4; } -- GitLab From cb8d4323302c7ad6b8baa1f5ca29f6186b30f316 Mon Sep 17 00:00:00 2001 From: Devarsh Thakkar Date: Wed, 7 May 2025 23:36:29 +0530 Subject: [PATCH 0141/1479] dt-bindings: display: ti,am65x-dss: Add support for AM62L DSS The DSS controller on TI's AM62L SoC is an update from that on TI's AM625/AM65x/AM62A7 SoC. The AM62L DSS [1] only supports a single display pipeline using a single overlay manager, single video port and a single video lite pipeline which does not support scaling. The output of video port is routed to SoC boundary via DPI interface and the DPI signals from the video port are also routed to DSI Tx controller present within the SoC. [1]: Section 11.7 (Display Subsystem and Peripherals) Link : https://www.ti.com/lit/pdf/sprujb4 Reviewed-by: Krzysztof Kozlowski Reviewed-by: Jayesh Choudhary Reviewed-by: Tomi Valkeinen Signed-off-by: Devarsh Thakkar Link: https://lore.kernel.org/r/20250507180631.874930-2-devarsht@ti.com Signed-off-by: Tomi Valkeinen --- .../bindings/display/ti/ti,am65x-dss.yaml | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml index 31c4ffcb599cd..a5b13cb7bc730 100644 --- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml +++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml @@ -12,18 +12,25 @@ maintainers: - Tomi Valkeinen description: | - The AM625 and AM65x TI Keystone Display SubSystem with two output + The AM625 and AM65x TI Keystone Display SubSystem has two output ports and two video planes. In AM65x DSS, the first video port supports 1 OLDI TX and in AM625 DSS, the first video port output is internally routed to 2 OLDI TXes. The second video port supports DPI format. The first plane is full video plane with all features and the second is a "lite plane" without scaling support. + The AM62L display subsystem has a single output port which supports DPI + format but it only supports single video "lite plane" which does not support + scaling. The output port is routed to SoC boundary via DPI interface and same + DPI signals are also routed internally to DSI Tx controller present within the + SoC. Due to clocking limitations only one of the interface i.e. either DSI or + DPI can be used at once. properties: compatible: enum: - ti,am625-dss - ti,am62a7-dss + - ti,am62l-dss - ti,am65x-dss reg: @@ -91,6 +98,8 @@ properties: For AM625 DSS, the internal DPI output port node from video port 1. For AM62A7 DSS, the port is tied off inside the SoC. + For AM62L DSS, the DSS DPI output port node from video port 1 + or DSI Tx controller node connected to video port 1. port@1: $ref: /schemas/graph.yaml#/properties/port @@ -123,6 +132,16 @@ allOf: ports: properties: port@0: false + - if: + properties: + compatible: + contains: + const: ti,am62l-dss + then: + properties: + ports: + properties: + port@1: false required: - compatible -- GitLab From e019f515c969cef78187b9cb87c6da06b47568b2 Mon Sep 17 00:00:00 2001 From: Devarsh Thakkar Date: Wed, 7 May 2025 23:36:30 +0530 Subject: [PATCH 0142/1479] drm/tidss: Update infrastructure to support K3 DSS cut-down versions SoCs like AM62Lx support cut-down version of K3 DSS where although same register space is supported as in other K3 DSS supported SoCs such as AM65x, AM62x, AM62Ax but some of the resources such as planes and corresponding register spaces are truncated. For e.g. AM62Lx has only single VIDL pipeline supported, so corresponding register spaces for other video pipelines need to be skipped. To add a generic support for future SoCs where one or more video pipelines can get truncated from the parent register space, move the video plane related information to vid_info struct which will also have a field to indicate hardware index of each of the available video planes, so that driver only maps and programs those video pipes and skips the unavailable ones. While at it, also change the num_planes field in the features structure to num_vid so that all places in code which use vid_info structure are highlighted in the code. Signed-off-by: Devarsh Thakkar Reviewed-by: Tomi Valkeinen Link: https://lore.kernel.org/r/20250507180631.874930-3-devarsht@ti.com Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/tidss/tidss_crtc.c | 4 +- drivers/gpu/drm/tidss/tidss_dispc.c | 154 +++++++++++++++++++++------- drivers/gpu/drm/tidss/tidss_dispc.h | 11 +- drivers/gpu/drm/tidss/tidss_kms.c | 2 +- drivers/gpu/drm/tidss/tidss_plane.c | 2 +- 5 files changed, 127 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c b/drivers/gpu/drm/tidss/tidss_crtc.c index 94f8e3178df58..a2f40a5c77030 100644 --- a/drivers/gpu/drm/tidss/tidss_crtc.c +++ b/drivers/gpu/drm/tidss/tidss_crtc.c @@ -130,7 +130,7 @@ static void tidss_crtc_position_planes(struct tidss_device *tidss, !to_tidss_crtc_state(cstate)->plane_pos_changed) return; - for (layer = 0; layer < tidss->feat->num_planes; layer++) { + for (layer = 0; layer < tidss->feat->num_vids ; layer++) { struct drm_plane_state *pstate; struct drm_plane *plane; bool layer_active = false; @@ -271,7 +271,7 @@ static void tidss_crtc_atomic_disable(struct drm_crtc *crtc, * another videoport, the DSS will report sync lost issues. Disable all * the layers here as a work-around. */ - for (u32 layer = 0; layer < tidss->feat->num_planes; layer++) + for (u32 layer = 0; layer < tidss->feat->num_vids; layer++) dispc_ovr_enable_layer(tidss->dispc, tcrtc->hw_videoport, layer, false); diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c index cacb5f3d8085b..774c608c88b50 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc.c +++ b/drivers/gpu/drm/tidss/tidss_dispc.c @@ -103,9 +103,16 @@ const struct dispc_features dispc_k2g_feats = { }, }, - .num_planes = 1, - .vid_name = { "vid1" }, - .vid_lite = { false }, + .num_vids = 1, + + .vid_info = { + { + .name = "vid1", + .is_lite = false, + .hw_id = 0, + }, + }, + .vid_order = { 0 }, }; @@ -178,11 +185,22 @@ const struct dispc_features dispc_am65x_feats = { }, }, - .num_planes = 2, + .num_vids = 2, /* note: vid is plane_id 0 and vidl1 is plane_id 1 */ - .vid_name = { "vid", "vidl1" }, - .vid_lite = { false, true, }, - .vid_order = { 1, 0 }, + .vid_info = { + { + .name = "vid", + .is_lite = false, + .hw_id = 0, + }, + { + .name = "vidl1", + .is_lite = true, + .hw_id = 1, + }, + }, + + .vid_order = {1, 0}, }; static const u16 tidss_j721e_common_regs[DISPC_COMMON_REG_TABLE_LEN] = { @@ -267,9 +285,32 @@ const struct dispc_features dispc_j721e_feats = { .gamma_type = TIDSS_GAMMA_10BIT, }, }, - .num_planes = 4, - .vid_name = { "vid1", "vidl1", "vid2", "vidl2" }, - .vid_lite = { 0, 1, 0, 1, }, + + .num_vids = 4, + + .vid_info = { + { + .name = "vid1", + .is_lite = false, + .hw_id = 0, + }, + { + .name = "vidl1", + .is_lite = true, + .hw_id = 1, + }, + { + .name = "vid2", + .is_lite = false, + .hw_id = 2, + }, + { + .name = "vidl2", + .is_lite = true, + .hw_id = 3, + }, + }, + .vid_order = { 1, 3, 0, 2 }, }; @@ -315,11 +356,23 @@ const struct dispc_features dispc_am625_feats = { }, }, - .num_planes = 2, + .num_vids = 2, + /* note: vid is plane_id 0 and vidl1 is plane_id 1 */ - .vid_name = { "vid", "vidl1" }, - .vid_lite = { false, true, }, - .vid_order = { 1, 0 }, + .vid_info = { + { + .name = "vid", + .is_lite = false, + .hw_id = 0, + }, + { + .name = "vidl1", + .is_lite = true, + .hw_id = 1, + } + }, + + .vid_order = {1, 0}, }; const struct dispc_features dispc_am62a7_feats = { @@ -369,11 +422,22 @@ const struct dispc_features dispc_am62a7_feats = { }, }, - .num_planes = 2, - /* note: vid is plane_id 0 and vidl1 is plane_id 1 */ - .vid_name = { "vid", "vidl1" }, - .vid_lite = { false, true, }, - .vid_order = { 1, 0 }, + .num_vids = 2, + + .vid_info = { + { + .name = "vid", + .is_lite = false, + .hw_id = 0, + }, + { + .name = "vidl1", + .is_lite = true, + .hw_id = 1, + } + }, + + .vid_order = {1, 0}, }; static const u16 *dispc_common_regmap; @@ -734,7 +798,8 @@ static void dispc_k3_vp_write_irqstatus(struct dispc_device *dispc, static dispc_irq_t dispc_k3_vid_read_irqstatus(struct dispc_device *dispc, u32 hw_plane) { - u32 stat = dispc_read(dispc, DISPC_VID_IRQSTATUS(hw_plane)); + u32 hw_id = dispc->feat->vid_info[hw_plane].hw_id; + u32 stat = dispc_read(dispc, DISPC_VID_IRQSTATUS(hw_id)); return dispc_vid_irq_from_raw(stat, hw_plane); } @@ -742,9 +807,10 @@ static dispc_irq_t dispc_k3_vid_read_irqstatus(struct dispc_device *dispc, static void dispc_k3_vid_write_irqstatus(struct dispc_device *dispc, u32 hw_plane, dispc_irq_t vidstat) { + u32 hw_id = dispc->feat->vid_info[hw_plane].hw_id; u32 stat = dispc_vid_irq_to_raw(vidstat, hw_plane); - dispc_write(dispc, DISPC_VID_IRQSTATUS(hw_plane), stat); + dispc_write(dispc, DISPC_VID_IRQSTATUS(hw_id), stat); } static dispc_irq_t dispc_k3_vp_read_irqenable(struct dispc_device *dispc, @@ -766,7 +832,8 @@ static void dispc_k3_vp_set_irqenable(struct dispc_device *dispc, static dispc_irq_t dispc_k3_vid_read_irqenable(struct dispc_device *dispc, u32 hw_plane) { - u32 stat = dispc_read(dispc, DISPC_VID_IRQENABLE(hw_plane)); + u32 hw_id = dispc->feat->vid_info[hw_plane].hw_id; + u32 stat = dispc_read(dispc, DISPC_VID_IRQENABLE(hw_id)); return dispc_vid_irq_from_raw(stat, hw_plane); } @@ -774,9 +841,10 @@ static dispc_irq_t dispc_k3_vid_read_irqenable(struct dispc_device *dispc, static void dispc_k3_vid_set_irqenable(struct dispc_device *dispc, u32 hw_plane, dispc_irq_t vidstat) { + u32 hw_id = dispc->feat->vid_info[hw_plane].hw_id; u32 stat = dispc_vid_irq_to_raw(vidstat, hw_plane); - dispc_write(dispc, DISPC_VID_IRQENABLE(hw_plane), stat); + dispc_write(dispc, DISPC_VID_IRQENABLE(hw_id), stat); } static @@ -788,7 +856,8 @@ void dispc_k3_clear_irqstatus(struct dispc_device *dispc, dispc_irq_t clearmask) if (clearmask & DSS_IRQ_VP_MASK(i)) dispc_k3_vp_write_irqstatus(dispc, i, clearmask); } - for (i = 0; i < dispc->feat->num_planes; ++i) { + + for (i = 0; i < dispc->feat->num_vids; ++i) { if (clearmask & DSS_IRQ_PLANE_MASK(i)) dispc_k3_vid_write_irqstatus(dispc, i, clearmask); } @@ -809,7 +878,7 @@ dispc_irq_t dispc_k3_read_and_clear_irqstatus(struct dispc_device *dispc) for (i = 0; i < dispc->feat->num_vps; ++i) status |= dispc_k3_vp_read_irqstatus(dispc, i); - for (i = 0; i < dispc->feat->num_planes; ++i) + for (i = 0; i < dispc->feat->num_vids; ++i) status |= dispc_k3_vid_read_irqstatus(dispc, i); dispc_k3_clear_irqstatus(dispc, status); @@ -825,7 +894,7 @@ static dispc_irq_t dispc_k3_read_irqenable(struct dispc_device *dispc) for (i = 0; i < dispc->feat->num_vps; ++i) enable |= dispc_k3_vp_read_irqenable(dispc, i); - for (i = 0; i < dispc->feat->num_planes; ++i) + for (i = 0; i < dispc->feat->num_vids; ++i) enable |= dispc_k3_vid_read_irqenable(dispc, i); return enable; @@ -851,12 +920,15 @@ static void dispc_k3_set_irqenable(struct dispc_device *dispc, main_disable |= BIT(i); /* VP IRQ */ } - for (i = 0; i < dispc->feat->num_planes; ++i) { + for (i = 0; i < dispc->feat->num_vids; ++i) { + u32 hw_id = dispc->feat->vid_info[i].hw_id; + dispc_k3_vid_set_irqenable(dispc, i, mask); + if (mask & DSS_IRQ_PLANE_MASK(i)) - main_enable |= BIT(i + 4); /* VID IRQ */ + main_enable |= BIT(hw_id + 4); /* VID IRQ */ else - main_disable |= BIT(i + 4); /* VID IRQ */ + main_disable |= BIT(hw_id + 4); /* VID IRQ */ } if (main_enable) @@ -1358,8 +1430,10 @@ static void dispc_am65x_ovr_set_plane(struct dispc_device *dispc, u32 hw_plane, u32 hw_videoport, u32 x, u32 y, u32 layer) { + u32 hw_id = dispc->feat->vid_info[hw_plane].hw_id; + OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer), - hw_plane, 4, 1); + hw_id, 4, 1); OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer), x, 17, 6); OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer), @@ -1370,8 +1444,10 @@ static void dispc_j721e_ovr_set_plane(struct dispc_device *dispc, u32 hw_plane, u32 hw_videoport, u32 x, u32 y, u32 layer) { + u32 hw_id = dispc->feat->vid_info[hw_plane].hw_id; + OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer), - hw_plane, 4, 1); + hw_id, 4, 1); OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES2(layer), x, 13, 0); OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES2(layer), @@ -2025,7 +2101,7 @@ int dispc_plane_check(struct dispc_device *dispc, u32 hw_plane, const struct drm_plane_state *state, u32 hw_videoport) { - bool lite = dispc->feat->vid_lite[hw_plane]; + bool lite = dispc->feat->vid_info[hw_plane].is_lite; u32 fourcc = state->fb->format->format; bool need_scaling = state->src_w >> 16 != state->crtc_w || state->src_h >> 16 != state->crtc_h; @@ -2096,7 +2172,7 @@ void dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane, const struct drm_plane_state *state, u32 hw_videoport) { - bool lite = dispc->feat->vid_lite[hw_plane]; + bool lite = dispc->feat->vid_info[hw_plane].is_lite; u32 fourcc = state->fb->format->format; u16 cpp = state->fb->format->cpp[0]; u32 fb_width = state->fb->pitches[0] / cpp; @@ -2210,7 +2286,7 @@ static void dispc_k2g_plane_init(struct dispc_device *dispc) /* MFLAG_START = MFLAGNORMALSTARTMODE */ REG_FLD_MOD(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE, 0, 6, 6); - for (hw_plane = 0; hw_plane < dispc->feat->num_planes; hw_plane++) { + for (hw_plane = 0; hw_plane < dispc->feat->num_vids; hw_plane++) { u32 size = dispc_vid_get_fifo_size(dispc, hw_plane); u32 thr_low, thr_high; u32 mflag_low, mflag_high; @@ -2226,7 +2302,7 @@ static void dispc_k2g_plane_init(struct dispc_device *dispc) dev_dbg(dispc->dev, "%s: bufsize %u, buf_threshold %u/%u, mflag threshold %u/%u preload %u\n", - dispc->feat->vid_name[hw_plane], + dispc->feat->vid_info[hw_plane].name, size, thr_high, thr_low, mflag_high, mflag_low, @@ -2265,7 +2341,7 @@ static void dispc_k3_plane_init(struct dispc_device *dispc) /* MFLAG_START = MFLAGNORMALSTARTMODE */ REG_FLD_MOD(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE, 0, 6, 6); - for (hw_plane = 0; hw_plane < dispc->feat->num_planes; hw_plane++) { + for (hw_plane = 0; hw_plane < dispc->feat->num_vids; hw_plane++) { u32 size = dispc_vid_get_fifo_size(dispc, hw_plane); u32 thr_low, thr_high; u32 mflag_low, mflag_high; @@ -2281,7 +2357,7 @@ static void dispc_k3_plane_init(struct dispc_device *dispc) dev_dbg(dispc->dev, "%s: bufsize %u, buf_threshold %u/%u, mflag threshold %u/%u preload %u\n", - dispc->feat->vid_name[hw_plane], + dispc->feat->vid_info[hw_plane].name, size, thr_high, thr_low, mflag_high, mflag_low, @@ -2898,8 +2974,8 @@ int dispc_init(struct tidss_device *tidss) if (r) return r; - for (i = 0; i < dispc->feat->num_planes; i++) { - r = dispc_iomap_resource(pdev, dispc->feat->vid_name[i], + for (i = 0; i < dispc->feat->num_vids; i++) { + r = dispc_iomap_resource(pdev, dispc->feat->vid_info[i].name, &dispc->base_vid[i]); if (r) return r; diff --git a/drivers/gpu/drm/tidss/tidss_dispc.h b/drivers/gpu/drm/tidss/tidss_dispc.h index 086327d51a903..72a0146e57d5f 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc.h +++ b/drivers/gpu/drm/tidss/tidss_dispc.h @@ -46,6 +46,12 @@ struct dispc_features_scaling { u32 xinc_max; }; +struct dispc_vid_info { + const char *name; /* Should match dt reg names */ + u32 hw_id; + bool is_lite; +}; + struct dispc_errata { bool i2000; /* DSS Does Not Support YUV Pixel Data Formats */ }; @@ -82,9 +88,8 @@ struct dispc_features { const char *vpclk_name[TIDSS_MAX_PORTS]; /* Should match dt clk names */ const enum dispc_vp_bus_type vp_bus_type[TIDSS_MAX_PORTS]; struct tidss_vp_feat vp_feat; - u32 num_planes; - const char *vid_name[TIDSS_MAX_PLANES]; /* Should match dt reg names */ - bool vid_lite[TIDSS_MAX_PLANES]; + u32 num_vids; + struct dispc_vid_info vid_info[TIDSS_MAX_PLANES]; u32 vid_order[TIDSS_MAX_PLANES]; }; diff --git a/drivers/gpu/drm/tidss/tidss_kms.c b/drivers/gpu/drm/tidss/tidss_kms.c index f371518f86971..19432c08ec6bd 100644 --- a/drivers/gpu/drm/tidss/tidss_kms.c +++ b/drivers/gpu/drm/tidss/tidss_kms.c @@ -115,7 +115,7 @@ static int tidss_dispc_modeset_init(struct tidss_device *tidss) const struct dispc_features *feat = tidss->feat; u32 max_vps = feat->num_vps; - u32 max_planes = feat->num_planes; + u32 max_planes = feat->num_vids; struct pipe pipes[TIDSS_MAX_PORTS]; u32 num_pipes = 0; diff --git a/drivers/gpu/drm/tidss/tidss_plane.c b/drivers/gpu/drm/tidss/tidss_plane.c index 719412e6c3460..142ae81951a09 100644 --- a/drivers/gpu/drm/tidss/tidss_plane.c +++ b/drivers/gpu/drm/tidss/tidss_plane.c @@ -200,7 +200,7 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss, struct tidss_plane *tplane; enum drm_plane_type type; u32 possible_crtcs; - u32 num_planes = tidss->feat->num_planes; + u32 num_planes = tidss->feat->num_vids; u32 color_encodings = (BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709)); u32 color_ranges = (BIT(DRM_COLOR_YCBCR_FULL_RANGE) | -- GitLab From 46a7c081be700d802741f26d2e9acf1861ee88f1 Mon Sep 17 00:00:00 2001 From: Devarsh Thakkar Date: Wed, 7 May 2025 23:36:31 +0530 Subject: [PATCH 0143/1479] drm/tidss: Add support for AM62L display subsystem Enable display for AM62L DSS [1] which supports only a single display pipeline using a single overlay manager, single video port and a single video lite pipeline which does not support scaling. The output of video port is routed to SoC boundary via DPI interface and the DPI signals from the video port are also routed to DSI Tx controller present within the SoC. [1]: Section 11.7 (Display Subsystem and Peripherals) Link : https://www.ti.com/lit/pdf/sprujb4 Signed-off-by: Devarsh Thakkar Reviewed-by: Tomi Valkeinen Link: https://lore.kernel.org/r/20250507180631.874930-4-devarsht@ti.com Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/tidss/tidss_dispc.c | 41 +++++++++++++++++++++++++++++ drivers/gpu/drm/tidss/tidss_dispc.h | 2 ++ drivers/gpu/drm/tidss/tidss_drv.c | 1 + 3 files changed, 44 insertions(+) diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c index 774c608c88b50..21363ccbd7637 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc.c +++ b/drivers/gpu/drm/tidss/tidss_dispc.c @@ -440,6 +440,42 @@ const struct dispc_features dispc_am62a7_feats = { .vid_order = {1, 0}, }; +const struct dispc_features dispc_am62l_feats = { + .max_pclk_khz = { + [DISPC_VP_DPI] = 165000, + }, + + .subrev = DISPC_AM62L, + + .common = "common", + .common_regs = tidss_am65x_common_regs, + + .num_vps = 1, + .vp_name = { "vp1" }, + .ovr_name = { "ovr1" }, + .vpclk_name = { "vp1" }, + .vp_bus_type = { DISPC_VP_DPI }, + + .vp_feat = { .color = { + .has_ctm = true, + .gamma_size = 256, + .gamma_type = TIDSS_GAMMA_8BIT, + }, + }, + + .num_vids = 1, + + .vid_info = { + { + .name = "vidl1", + .is_lite = true, + .hw_id = 1, + } + }, + + .vid_order = {0}, +}; + static const u16 *dispc_common_regmap; struct dss_vp_data { @@ -951,6 +987,7 @@ dispc_irq_t dispc_read_and_clear_irqstatus(struct dispc_device *dispc) return dispc_k2g_read_and_clear_irqstatus(dispc); case DISPC_AM625: case DISPC_AM62A7: + case DISPC_AM62L: case DISPC_AM65X: case DISPC_J721E: return dispc_k3_read_and_clear_irqstatus(dispc); @@ -968,6 +1005,7 @@ void dispc_set_irqenable(struct dispc_device *dispc, dispc_irq_t mask) break; case DISPC_AM625: case DISPC_AM62A7: + case DISPC_AM62L: case DISPC_AM65X: case DISPC_J721E: dispc_k3_set_irqenable(dispc, mask); @@ -1464,6 +1502,7 @@ void dispc_ovr_set_plane(struct dispc_device *dispc, u32 hw_plane, break; case DISPC_AM625: case DISPC_AM62A7: + case DISPC_AM62L: case DISPC_AM65X: dispc_am65x_ovr_set_plane(dispc, hw_plane, hw_videoport, x, y, layer); @@ -2384,6 +2423,7 @@ static void dispc_plane_init(struct dispc_device *dispc) break; case DISPC_AM625: case DISPC_AM62A7: + case DISPC_AM62L: case DISPC_AM65X: case DISPC_J721E: dispc_k3_plane_init(dispc); @@ -2492,6 +2532,7 @@ static void dispc_vp_write_gamma_table(struct dispc_device *dispc, break; case DISPC_AM625: case DISPC_AM62A7: + case DISPC_AM62L: case DISPC_AM65X: dispc_am65x_vp_write_gamma_table(dispc, hw_videoport); break; diff --git a/drivers/gpu/drm/tidss/tidss_dispc.h b/drivers/gpu/drm/tidss/tidss_dispc.h index 72a0146e57d5f..28958514b8f51 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc.h +++ b/drivers/gpu/drm/tidss/tidss_dispc.h @@ -67,6 +67,7 @@ enum dispc_vp_bus_type { enum dispc_dss_subrevision { DISPC_K2G, DISPC_AM625, + DISPC_AM62L, DISPC_AM62A7, DISPC_AM65X, DISPC_J721E, @@ -96,6 +97,7 @@ struct dispc_features { extern const struct dispc_features dispc_k2g_feats; extern const struct dispc_features dispc_am625_feats; extern const struct dispc_features dispc_am62a7_feats; +extern const struct dispc_features dispc_am62l_feats; extern const struct dispc_features dispc_am65x_feats; extern const struct dispc_features dispc_j721e_feats; diff --git a/drivers/gpu/drm/tidss/tidss_drv.c b/drivers/gpu/drm/tidss/tidss_drv.c index d4652e8cc28c1..f2a4f659f574c 100644 --- a/drivers/gpu/drm/tidss/tidss_drv.c +++ b/drivers/gpu/drm/tidss/tidss_drv.c @@ -242,6 +242,7 @@ static const struct of_device_id tidss_of_table[] = { { .compatible = "ti,k2g-dss", .data = &dispc_k2g_feats, }, { .compatible = "ti,am625-dss", .data = &dispc_am625_feats, }, { .compatible = "ti,am62a7-dss", .data = &dispc_am62a7_feats, }, + { .compatible = "ti,am62l-dss", .data = &dispc_am62l_feats, }, { .compatible = "ti,am65x-dss", .data = &dispc_am65x_feats, }, { .compatible = "ti,j721e-dss", .data = &dispc_j721e_feats, }, { } -- GitLab From a4b4e3fd536763b3405c70ef97a6e7f9af8a00dc Mon Sep 17 00:00:00 2001 From: Ernest Van Hoecke Date: Tue, 20 May 2025 14:43:28 +0200 Subject: [PATCH 0144/1479] drm/panel-edp: Add support for AUO G156HAN03.0 panel AUO G156HAN03.0 EDID: 00 ff ff ff ff ff ff 00 06 af ed 30 00 00 00 00 1a 1c 01 04 a5 22 13 78 02 05 b5 94 59 59 92 28 1d 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 78 37 80 b4 70 38 2e 40 6c 30 aa 00 58 c1 10 00 00 18 00 00 00 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 fe 00 41 55 4f 0a 20 20 20 20 20 20 20 20 20 00 00 00 fe 00 47 31 35 36 48 41 4e 30 33 2e 30 20 0a 00 bb Signed-off-by: Ernest Van Hoecke Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20250520124332.71705-1-ernest.vanhoecke@toradex.com --- drivers/gpu/drm/panel/panel-edp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index 00dae545832e4..9adbe0f114213 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1869,6 +1869,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('A', 'U', 'O', 0x235c, &delay_200_500_e50, "B116XTN02.3"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x239b, &delay_200_500_e50, "B116XAN06.1"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x255c, &delay_200_500_e50, "B116XTN02.5"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x30ed, &delay_200_500_e50, "G156HAN03.0"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x403d, &delay_200_500_e50, "B140HAN04.0"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAN04.0"), EDP_PANEL_ENTRY2('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAK01.0", -- GitLab From dcab7a228f4ea9cda3f5b0a1f0679e046d23d7f7 Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Fri, 16 May 2025 15:16:54 +0300 Subject: [PATCH 0145/1479] drm/i915/display: Add check for alloc_ordered_workqueue() and alloc_workqueue() Add check for the return value of alloc_ordered_workqueue() and alloc_workqueue(). Furthermore, if some allocations fail, cleanup works are added to avoid potential memory leak problem. Fixes: 40053823baad ("drm/i915/display: move modeset probe/remove functions to intel_display_driver.c") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/20d3d096c6a4907636f8a1389b3b4dd753ca356e.1747397638.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../drm/i915/display/intel_display_driver.c | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c index 16d91be02bb91..581787d0452e6 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.c +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c @@ -244,31 +244,45 @@ int intel_display_driver_probe_noirq(struct intel_display *display) intel_dmc_init(display); display->wq.modeset = alloc_ordered_workqueue("i915_modeset", 0); + if (!display->wq.modeset) { + ret = -ENOMEM; + goto cleanup_vga_client_pw_domain_dmc; + } + display->wq.flip = alloc_workqueue("i915_flip", WQ_HIGHPRI | WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE); + if (!display->wq.flip) { + ret = -ENOMEM; + goto cleanup_wq_modeset; + } + display->wq.cleanup = alloc_workqueue("i915_cleanup", WQ_HIGHPRI, 0); + if (!display->wq.cleanup) { + ret = -ENOMEM; + goto cleanup_wq_flip; + } intel_mode_config_init(display); ret = intel_cdclk_init(display); if (ret) - goto cleanup_vga_client_pw_domain_dmc; + goto cleanup_wq_cleanup; ret = intel_color_init(display); if (ret) - goto cleanup_vga_client_pw_domain_dmc; + goto cleanup_wq_cleanup; ret = intel_dbuf_init(display); if (ret) - goto cleanup_vga_client_pw_domain_dmc; + goto cleanup_wq_cleanup; ret = intel_bw_init(display); if (ret) - goto cleanup_vga_client_pw_domain_dmc; + goto cleanup_wq_cleanup; ret = intel_pmdemand_init(display); if (ret) - goto cleanup_vga_client_pw_domain_dmc; + goto cleanup_wq_cleanup; intel_init_quirks(display); @@ -276,6 +290,12 @@ int intel_display_driver_probe_noirq(struct intel_display *display) return 0; +cleanup_wq_cleanup: + destroy_workqueue(display->wq.cleanup); +cleanup_wq_flip: + destroy_workqueue(display->wq.flip); +cleanup_wq_modeset: + destroy_workqueue(display->wq.modeset); cleanup_vga_client_pw_domain_dmc: intel_dmc_fini(display); intel_power_domains_driver_remove(display); -- GitLab From 5b62d63395d5b7d4094e7cd380bccae4b25415cb Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Fri, 16 May 2025 15:16:55 +0300 Subject: [PATCH 0146/1479] drm/xe/display: Add check for alloc_ordered_workqueue() Add check for the return value of alloc_ordered_workqueue() in xe_display_create() to catch potential exception. Fixes: 44e694958b95 ("drm/xe/display: Implement display support") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/4ee1b0e5d1626ce1dde2e82af05c2edaed50c3aa.1747397638.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/display/xe_display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 699f401eff101..df897d08255c7 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -112,6 +112,8 @@ int xe_display_create(struct xe_device *xe) spin_lock_init(&display->fb_tracking.lock); display->hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0); + if (!display->hotplug.dp_wq) + return -ENOMEM; return drmm_add_action_or_reset(&xe->drm, display_destroy, NULL); } -- GitLab From b617341e4801e2f0ea7aeb63fae0fa438f7cd601 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 16 May 2025 15:16:56 +0300 Subject: [PATCH 0147/1479] drm/xe/display: drop duplicate display->fb_tracking.lock init The spinlock is initialized in intel_display_driver_early_probe(). Drop the extra init. Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/f895a8a43c61a6e60db8e1eb698919ce0faab27c.1747397638.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/display/xe_display.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index df897d08255c7..9513b03847a82 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -109,8 +109,6 @@ int xe_display_create(struct xe_device *xe) xe->display = &xe->__display; - spin_lock_init(&display->fb_tracking.lock); - display->hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0); if (!display->hotplug.dp_wq) return -ENOMEM; -- GitLab From ed23224b3f5e5e938e5c97d246678702df98eb93 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 16 May 2025 15:16:57 +0300 Subject: [PATCH 0148/1479] drm/i915/display: move hotplug.dp_wq init from xe and i915 to display The workqueue init and destroy belongs in display. Move it. Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/4730167548a40dc2abe38cd084809b74de988f1a.1747397638.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../gpu/drm/i915/display/intel_display_driver.c | 11 ++++++++++- drivers/gpu/drm/i915/i915_driver.c | 13 +------------ drivers/gpu/drm/xe/display/xe_display.c | 16 +--------------- 3 files changed, 12 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c index 581787d0452e6..2bdafab9b6d00 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.c +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c @@ -243,10 +243,16 @@ int intel_display_driver_probe_noirq(struct intel_display *display) intel_dmc_init(display); + display->hotplug.dp_wq = alloc_ordered_workqueue("intel-dp", 0); + if (!display->hotplug.dp_wq) { + ret = -ENOMEM; + goto cleanup_vga_client_pw_domain_dmc; + } + display->wq.modeset = alloc_ordered_workqueue("i915_modeset", 0); if (!display->wq.modeset) { ret = -ENOMEM; - goto cleanup_vga_client_pw_domain_dmc; + goto cleanup_wq_dp; } display->wq.flip = alloc_workqueue("i915_flip", WQ_HIGHPRI | @@ -296,6 +302,8 @@ int intel_display_driver_probe_noirq(struct intel_display *display) destroy_workqueue(display->wq.flip); cleanup_wq_modeset: destroy_workqueue(display->wq.modeset); +cleanup_wq_dp: + destroy_workqueue(display->hotplug.dp_wq); cleanup_vga_client_pw_domain_dmc: intel_dmc_fini(display); intel_power_domains_driver_remove(display); @@ -631,6 +639,7 @@ void intel_display_driver_remove_noirq(struct intel_display *display) intel_gmbus_teardown(display); + destroy_workqueue(display->hotplug.dp_wq); destroy_workqueue(display->wq.flip); destroy_workqueue(display->wq.modeset); destroy_workqueue(display->wq.cleanup); diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 5c69d14a7673e..950b7ad8d675f 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -115,8 +115,6 @@ static const struct drm_driver i915_drm_driver; static int i915_workqueues_init(struct drm_i915_private *dev_priv) { - struct intel_display *display = dev_priv->display; - /* * The i915 workqueue is primarily used for batched retirement of * requests (and thus managing bo) once the task has been completed @@ -135,10 +133,6 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv) if (dev_priv->wq == NULL) goto out_err; - display->hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0); - if (!display->hotplug.dp_wq) - goto out_free_wq; - /* * The unordered i915 workqueue should be used for all work * scheduling that do not require running in order, which used @@ -147,12 +141,10 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv) */ dev_priv->unordered_wq = alloc_workqueue("i915-unordered", 0, 0); if (dev_priv->unordered_wq == NULL) - goto out_free_dp_wq; + goto out_free_wq; return 0; -out_free_dp_wq: - destroy_workqueue(display->hotplug.dp_wq); out_free_wq: destroy_workqueue(dev_priv->wq); out_err: @@ -163,10 +155,7 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv) static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv) { - struct intel_display *display = dev_priv->display; - destroy_workqueue(dev_priv->unordered_wq); - destroy_workqueue(display->hotplug.dp_wq); destroy_workqueue(dev_priv->wq); } diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 9513b03847a82..b0f5624177bdb 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -83,14 +83,6 @@ static void unset_display_features(struct xe_device *xe) xe->drm.driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC); } -static void display_destroy(struct drm_device *dev, void *dummy) -{ - struct xe_device *xe = to_xe_device(dev); - struct intel_display *display = xe->display; - - destroy_workqueue(display->hotplug.dp_wq); -} - /** * xe_display_create - create display struct * @xe: XE device instance @@ -105,15 +97,9 @@ static void display_destroy(struct drm_device *dev, void *dummy) int xe_display_create(struct xe_device *xe) { /* TODO: Allocate display dynamically. */ - struct intel_display *display = &xe->__display; - xe->display = &xe->__display; - display->hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0); - if (!display->hotplug.dp_wq) - return -ENOMEM; - - return drmm_add_action_or_reset(&xe->drm, display_destroy, NULL); + return 0; } static void xe_display_fini_early(void *arg) -- GitLab From 1e2803e565af3b7463c7615347510f7093945633 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 16 May 2025 15:16:58 +0300 Subject: [PATCH 0149/1479] drm/xe/display: move xe->display initialization to xe_display_probe() The future goal is to have intel_display_device_probe() create struct intel_display. As the first step, postpone xe->display initialization right before that call. This is the same location as in i915. There's a subtle functional change here: xe->display will now be initialized only if xe->info.probe_display. The xe_display_create() function becomes empty, and can be removed. Move its documentation to xe_display_probe() Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/6c3075739d84cecea258d686c3ef38455a61191c.1747397638.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/display/xe_display.c | 33 +++++++++++-------------- drivers/gpu/drm/xe/display/xe_display.h | 4 --- drivers/gpu/drm/xe/xe_device.c | 4 --- 3 files changed, 14 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index b0f5624177bdb..c35444637620f 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -83,25 +83,6 @@ static void unset_display_features(struct xe_device *xe) xe->drm.driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC); } -/** - * xe_display_create - create display struct - * @xe: XE device instance - * - * Initialize all fields used by the display part. - * - * TODO: once everything can be inside a single struct, make the struct opaque - * to the rest of xe and return it to be xe->display. - * - * Returns: 0 on success - */ -int xe_display_create(struct xe_device *xe) -{ - /* TODO: Allocate display dynamically. */ - xe->display = &xe->__display; - - return 0; -} - static void xe_display_fini_early(void *arg) { struct xe_device *xe = arg; @@ -524,6 +505,17 @@ static void display_device_remove(struct drm_device *dev, void *arg) intel_display_device_remove(display); } +/** + * xe_display_probe - probe display and create display struct + * @xe: XE device instance + * + * Initialize all fields used by the display part. + * + * TODO: once everything can be inside a single struct, make the struct opaque + * to the rest of xe and return it to be xe->display. + * + * Returns: 0 on success + */ int xe_display_probe(struct xe_device *xe) { struct pci_dev *pdev = to_pci_dev(xe->drm.dev); @@ -533,6 +525,9 @@ int xe_display_probe(struct xe_device *xe) if (!xe->info.probe_display) goto no_display; + /* TODO: Allocate display dynamically. */ + xe->display = &xe->__display; + display = intel_display_device_probe(pdev); err = drmm_add_action_or_reset(&xe->drm, display_device_remove, display); diff --git a/drivers/gpu/drm/xe/display/xe_display.h b/drivers/gpu/drm/xe/display/xe_display.h index 46e14f8dee28a..e533aa4750bc1 100644 --- a/drivers/gpu/drm/xe/display/xe_display.h +++ b/drivers/gpu/drm/xe/display/xe_display.h @@ -15,8 +15,6 @@ struct drm_driver; bool xe_display_driver_probe_defer(struct pci_dev *pdev); void xe_display_driver_set_hooks(struct drm_driver *driver); -int xe_display_create(struct xe_device *xe); - int xe_display_probe(struct xe_device *xe); int xe_display_init_early(struct xe_device *xe); @@ -46,8 +44,6 @@ static inline int xe_display_driver_probe_defer(struct pci_dev *pdev) { return 0 static inline void xe_display_driver_set_hooks(struct drm_driver *driver) { } static inline void xe_display_driver_remove(struct xe_device *xe) {} -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_early(struct xe_device *xe) { return 0; } diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index c02c4c4e94128..b615d8ed38a21 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -493,10 +493,6 @@ struct xe_device *xe_device_create(struct pci_dev *pdev, if (err) goto err; - err = xe_display_create(xe); - if (WARN_ON(err)) - goto err; - return xe; err: -- GitLab From 7e49ab36e6f3fb6edc250609ece1548bf80c50cc Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 16 May 2025 15:16:59 +0300 Subject: [PATCH 0150/1479] drm/xe/display: add notes about how early a few functions can be called xe_display_driver_probe_defer() and xe_display_driver_set_hooks() get called before either struct xe_device or struct intel_display exist. Make a note of that. Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/937ea1e16e970a6f6944b94c6a9c216d36e728d1.1747397638.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/display/xe_display.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index c35444637620f..8b2aa7dc6e076 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -48,6 +48,8 @@ static bool has_display(struct xe_device *xe) * early on * @pdev: PCI device * + * Note: This is called before xe or display device creation. + * * Returns: true if probe needs to be deferred, false otherwise */ bool xe_display_driver_probe_defer(struct pci_dev *pdev) @@ -65,6 +67,8 @@ bool xe_display_driver_probe_defer(struct pci_dev *pdev) * Set features and function hooks in @driver that are needed for driving the * display IP. This sets the driver's capability of driving display, regardless * if the device has it enabled + * + * Note: This is called before xe or display device creation. */ void xe_display_driver_set_hooks(struct drm_driver *driver) { -- GitLab From 5a9f299f956ef9764f56044cfca7aafa23cea1d1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 16 May 2025 15:17:00 +0300 Subject: [PATCH 0151/1479] drm/xe/display: use xe->display to decide whether to do anything Since we only initialize xe->display when xe->info.probe_display, we can use !xe->display to bail out early. This seems cleaner and more accurate than relying on xe->info.probe_display, since xe->display may indeed be NULL. Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/945d2a987214044a81f4816684972961b772b45a.1747397638.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/display/xe_display.c | 40 ++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 8b2aa7dc6e076..1e59b6dd2c3bd 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -92,7 +92,7 @@ static void xe_display_fini_early(void *arg) struct xe_device *xe = arg; struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; intel_display_driver_remove_nogem(display); @@ -106,7 +106,7 @@ int xe_display_init_early(struct xe_device *xe) struct intel_display *display = xe->display; int err; - if (!xe->info.probe_display) + if (!display) return 0; /* Fake uncore lock */ @@ -160,7 +160,7 @@ int xe_display_init(struct xe_device *xe) struct intel_display *display = xe->display; int err; - if (!xe->info.probe_display) + if (!display) return 0; err = intel_display_driver_probe(display); @@ -174,7 +174,7 @@ void xe_display_register(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; intel_display_driver_register(display); @@ -185,7 +185,7 @@ void xe_display_unregister(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; intel_power_domains_disable(display); @@ -198,7 +198,7 @@ void xe_display_irq_handler(struct xe_device *xe, u32 master_ctl) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; if (master_ctl & DISPLAY_IRQ) @@ -209,7 +209,7 @@ void xe_display_irq_enable(struct xe_device *xe, u32 gu_misc_iir) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; if (gu_misc_iir & GU_MISC_GSE) @@ -220,7 +220,7 @@ void xe_display_irq_reset(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; gen11_display_irq_reset(display); @@ -230,7 +230,7 @@ void xe_display_irq_postinstall(struct xe_device *xe, struct xe_gt *gt) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; if (gt->info.id == XE_GT0) @@ -271,7 +271,7 @@ static void xe_display_enable_d3cold(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; /* @@ -294,7 +294,7 @@ static void xe_display_disable_d3cold(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; intel_dmc_resume(display); @@ -319,7 +319,7 @@ 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) + if (!display) return; /* @@ -353,7 +353,7 @@ void xe_display_pm_shutdown(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; intel_power_domains_disable(display); @@ -384,7 +384,7 @@ void xe_display_pm_runtime_suspend(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; if (xe->d3cold.allowed) { @@ -400,7 +400,7 @@ void xe_display_pm_suspend_late(struct xe_device *xe) struct intel_display *display = xe->display; bool s2idle = suspend_to_idle(); - if (!xe->info.probe_display) + if (!display) return; intel_display_power_suspend_late(display, s2idle); @@ -410,7 +410,7 @@ void xe_display_pm_runtime_suspend_late(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; if (xe->d3cold.allowed) @@ -428,7 +428,7 @@ void xe_display_pm_shutdown_late(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; /* @@ -443,7 +443,7 @@ void xe_display_pm_resume_early(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; intel_display_power_resume_early(display); @@ -453,7 +453,7 @@ void xe_display_pm_resume(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; intel_dmc_resume(display); @@ -488,7 +488,7 @@ void xe_display_pm_runtime_resume(struct xe_device *xe) { struct intel_display *display = xe->display; - if (!xe->info.probe_display) + if (!display) return; if (xe->d3cold.allowed) { -- GitLab From fa3769e09be76142d51c617d7d0c72d9c725a49d Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 17 May 2025 04:59:37 +0300 Subject: [PATCH 0152/1479] drm/bridge: move private data to the end of the struct WHen adding HDMI fields I didn't notice the private: declaration for HPD fields. Move private fields to the end of the struct drm_bride to have clear distinction between private and public fields. Reviewed-by: Maxime Ripard Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250517-drm-hdmi-connector-cec-v6-1-35651db6f19b@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- include/drm/drm_bridge.h | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 4e418a29a9ff9..286f6fb3fe2b8 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -977,21 +977,6 @@ struct drm_bridge { * @ddc: Associated I2C adapter for DDC access, if any. */ struct i2c_adapter *ddc; - /** private: */ - /** - * @hpd_mutex: Protects the @hpd_cb and @hpd_data fields. - */ - struct mutex hpd_mutex; - /** - * @hpd_cb: Hot plug detection callback, registered with - * drm_bridge_hpd_enable(). - */ - void (*hpd_cb)(void *data, enum drm_connector_status status); - /** - * @hpd_data: Private data passed to the Hot plug detection callback - * @hpd_cb. - */ - void *hpd_data; /** * @vendor: Vendor of the product to be used for the SPD InfoFrame @@ -1043,6 +1028,22 @@ struct drm_bridge { * not used. */ int hdmi_audio_dai_port; + + /** private: */ + /** + * @hpd_mutex: Protects the @hpd_cb and @hpd_data fields. + */ + struct mutex hpd_mutex; + /** + * @hpd_cb: Hot plug detection callback, registered with + * drm_bridge_hpd_enable(). + */ + void (*hpd_cb)(void *data, enum drm_connector_status status); + /** + * @hpd_data: Private data passed to the Hot plug detection callback + * @hpd_cb. + */ + void *hpd_data; }; static inline struct drm_bridge * -- GitLab From d9f9bae6752f5a0280a80d1bc524cabd0d60c886 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 17 May 2025 04:59:38 +0300 Subject: [PATCH 0153/1479] drm/bridge: allow limiting I2S formats By default HDMI codec registers all formats supported on the I2S bus. Allow bridges (and connectors) to limit the list of the PCM formats supported by the HDMI codec. Reviewed-by: Maxime Ripard Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250517-drm-hdmi-connector-cec-v6-2-35651db6f19b@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/display/drm_bridge_connector.c | 1 + drivers/gpu/drm/display/drm_hdmi_audio_helper.c | 3 +++ drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- include/drm/display/drm_hdmi_audio_helper.h | 1 + include/drm/drm_bridge.h | 8 ++++++++ 5 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 7d2e499ea5dec..381a0f9d4259b 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -717,6 +717,7 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, ret = drm_connector_hdmi_audio_init(connector, dev, &drm_bridge_connector_hdmi_audio_funcs, bridge->hdmi_audio_max_i2s_playback_channels, + bridge->hdmi_audio_i2s_formats, bridge->hdmi_audio_spdif_playback, bridge->hdmi_audio_dai_port); if (ret) diff --git a/drivers/gpu/drm/display/drm_hdmi_audio_helper.c b/drivers/gpu/drm/display/drm_hdmi_audio_helper.c index 05afc9f0bdd6b..21c93bdd8648c 100644 --- a/drivers/gpu/drm/display/drm_hdmi_audio_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_audio_helper.c @@ -142,6 +142,7 @@ static const struct hdmi_codec_ops drm_connector_hdmi_audio_ops = { * @hdmi_codec_dev: device to be used as a parent for the HDMI Codec * @funcs: callbacks for this HDMI Codec * @max_i2s_playback_channels: maximum number of playback I2S channels + * @i2s_formats: set of I2S formats (use 0 for a bus-specific set) * @spdif_playback: set if HDMI codec has S/PDIF playback port * @dai_port: sound DAI port, -1 if it is not enabled * @@ -154,6 +155,7 @@ int drm_connector_hdmi_audio_init(struct drm_connector *connector, struct device *hdmi_codec_dev, const struct drm_connector_hdmi_audio_funcs *funcs, unsigned int max_i2s_playback_channels, + u64 i2s_formats, bool spdif_playback, int dai_port) { @@ -161,6 +163,7 @@ int drm_connector_hdmi_audio_init(struct drm_connector *connector, .ops = &drm_connector_hdmi_audio_ops, .max_i2s_channels = max_i2s_playback_channels, .i2s = !!max_i2s_playback_channels, + .i2s_formats = i2s_formats, .spdif = spdif_playback, .no_i2s_capture = true, .no_spdif_capture = true, diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index a29a6ef266f9a..4797ed1c21f47 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -562,7 +562,7 @@ static int vc4_hdmi_connector_init(struct drm_device *dev, ret = drm_connector_hdmi_audio_init(connector, dev->dev, &vc4_hdmi_audio_funcs, - 8, false, -1); + 8, 0, false, -1); if (ret) return ret; diff --git a/include/drm/display/drm_hdmi_audio_helper.h b/include/drm/display/drm_hdmi_audio_helper.h index c9a6faef4109f..44d910bdc72dd 100644 --- a/include/drm/display/drm_hdmi_audio_helper.h +++ b/include/drm/display/drm_hdmi_audio_helper.h @@ -14,6 +14,7 @@ int drm_connector_hdmi_audio_init(struct drm_connector *connector, struct device *hdmi_codec_dev, const struct drm_connector_hdmi_audio_funcs *funcs, unsigned int max_i2s_playback_channels, + u64 i2s_formats, bool spdif_playback, int sound_dai_port); void drm_connector_hdmi_audio_plugged_notify(struct drm_connector *connector, diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 286f6fb3fe2b8..db0d374d863b0 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -1016,6 +1016,14 @@ struct drm_bridge { */ int hdmi_audio_max_i2s_playback_channels; + /** + * @hdmi_audio_i2s_formats: supported I2S formats, optional. The + * default is to allow all formats supported by the corresponding I2S + * bus driver. This is only used for bridges setting + * @DRM_BRIDGE_OP_HDMI_AUDIO or @DRM_BRIDGE_OP_DP_AUDIO. + */ + u64 hdmi_audio_i2s_formats; + /** * @hdmi_audio_spdif_playback: set if this bridge has S/PDIF playback * port for @DRM_BRIDGE_OP_HDMI_AUDIO or @DRM_BRIDGE_OP_DP_AUDIO. -- GitLab From e72cd597c35012146bfe77b736a30fee3e77e61e Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 17 May 2025 04:59:39 +0300 Subject: [PATCH 0154/1479] drm/connector: add CEC-related fields As a preparation to adding HDMI CEC helper code, add CEC-related fields to the struct drm_connector. The callbacks abstract CEC infrastructure in order to support CEC adapters and CEC notifiers in a universal way. CEC data is a void pointer as it allows us to make CEC data helper-specific. For example, currently it will be either cec_notifier or cec_adapter + drm_connector_hdmi_cec_funcs. Later cec-pin might store platform callbacks here. DP CEC might need to store AUX pointer, etc. Signed-off-by: Dmitry Baryshkov Reviewed-by: Maxime Ripard Link: https://lore.kernel.org/r/20250517-drm-hdmi-connector-cec-v6-3-35651db6f19b@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/drm_connector.c | 41 ++++++++++++++++++++++++++++ include/drm/drm_connector.h | 48 +++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 48b08c9611a7b..395e1bf006bd2 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -279,6 +279,7 @@ static int drm_connector_init_only(struct drm_device *dev, INIT_LIST_HEAD(&connector->probed_modes); INIT_LIST_HEAD(&connector->modes); mutex_init(&connector->mutex); + mutex_init(&connector->cec.mutex); mutex_init(&connector->eld_mutex); mutex_init(&connector->edid_override_mutex); mutex_init(&connector->hdmi.infoframes.lock); @@ -701,6 +702,46 @@ static void drm_mode_remove(struct drm_connector *connector, drm_mode_destroy(connector->dev, mode); } +/** + * drm_connector_cec_phys_addr_invalidate - invalidate CEC physical address + * @connector: connector undergoing CEC operation + * + * Invalidated CEC physical address set for this DRM connector. + */ +void drm_connector_cec_phys_addr_invalidate(struct drm_connector *connector) +{ + mutex_lock(&connector->cec.mutex); + + if (connector->cec.funcs && + connector->cec.funcs->phys_addr_invalidate) + connector->cec.funcs->phys_addr_invalidate(connector); + + mutex_unlock(&connector->cec.mutex); +} +EXPORT_SYMBOL(drm_connector_cec_phys_addr_invalidate); + +/** + * drm_connector_cec_phys_addr_set - propagate CEC physical address + * @connector: connector undergoing CEC operation + * + * Propagate CEC physical address from the display_info to this DRM connector. + */ +void drm_connector_cec_phys_addr_set(struct drm_connector *connector) +{ + u16 addr; + + mutex_lock(&connector->cec.mutex); + + addr = connector->display_info.source_physical_address; + + if (connector->cec.funcs && + connector->cec.funcs->phys_addr_set) + connector->cec.funcs->phys_addr_set(connector, addr); + + mutex_unlock(&connector->cec.mutex); +} +EXPORT_SYMBOL(drm_connector_cec_phys_addr_set); + /** * drm_connector_cleanup - cleans up an initialised connector * @connector: connector to cleanup diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index f13d597370a30..73903c3c842f3 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1191,6 +1191,29 @@ struct drm_connector_hdmi_audio_funcs { bool enable, int direction); }; +void drm_connector_cec_phys_addr_invalidate(struct drm_connector *connector); +void drm_connector_cec_phys_addr_set(struct drm_connector *connector); + +/** + * struct drm_connector_cec_funcs - drm_hdmi_connector control functions + */ +struct drm_connector_cec_funcs { + /** + * @phys_addr_invalidate: mark CEC physical address as invalid + * + * The callback to mark CEC physical address as invalid, abstracting + * the operation. + */ + void (*phys_addr_invalidate)(struct drm_connector *connector); + + /** + * @phys_addr_set: set CEC physical address + * + * The callback to set CEC physical address, abstracting the operation. + */ + void (*phys_addr_set)(struct drm_connector *connector, u16 addr); +}; + /** * struct drm_connector_hdmi_funcs - drm_hdmi_connector control functions */ @@ -1832,6 +1855,26 @@ struct drm_connector_hdmi { } infoframes; }; +/** + * struct drm_connector_cec - DRM Connector CEC-related structure + */ +struct drm_connector_cec { + /** + * @mutex: protects all fields in this structure. + */ + struct mutex mutex; + + /** + * @funcs: CEC Control Functions + */ + const struct drm_connector_cec_funcs *funcs; + + /** + * @data: CEC implementation-specific data + */ + void *data; +}; + /** * struct drm_connector - central DRM connector control structure * @@ -2253,6 +2296,11 @@ struct drm_connector { * @hdmi_audio: HDMI codec properties and non-DRM state. */ struct drm_connector_hdmi_audio hdmi_audio; + + /** + * @cec: CEC-related data. + */ + struct drm_connector_cec cec; }; #define obj_to_connector(x) container_of(x, struct drm_connector, base) -- GitLab From bcc8553b6228d0387ff64978a03efa3c8983dd2f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 17 May 2025 04:59:40 +0300 Subject: [PATCH 0155/1479] drm/display: move CEC_CORE selection to DRM_DISPLAY_HELPER THe Kconfig symbol DRM_DISPLAY_DP_AUX_CEC is a boolean which simply toggles whether DP_AUX_CEC support should be built into the drm_display_helper (which can be eithera module or built-in into the kernel). If DRM_DISPLAY_DP_AUX_CEC is selected, then CEC_CORE is selected to be built-in into the kernel even if DRM_DISPLAY_HELPER is selected to be built as a module. Move CEC_CORE selection to the latter symbol in order to allow it to be built as a module. Signed-off-by: Dmitry Baryshkov Reviewed-by: Maxime Ripard Link: https://lore.kernel.org/r/20250517-drm-hdmi-connector-cec-v6-4-35651db6f19b@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/display/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig index 8d22b7627d41f..3666e791d6d6e 100644 --- a/drivers/gpu/drm/display/Kconfig +++ b/drivers/gpu/drm/display/Kconfig @@ -8,6 +8,7 @@ config DRM_DISPLAY_DP_AUX_BUS config DRM_DISPLAY_HELPER tristate depends on DRM + select CEC_CORE if DRM_DISPLAY_DP_AUX_CEC help DRM helpers for display adapters. @@ -23,7 +24,6 @@ config DRM_BRIDGE_CONNECTOR config DRM_DISPLAY_DP_AUX_CEC bool "Enable DisplayPort CEC-Tunneling-over-AUX HDMI support" select DRM_DISPLAY_DP_HELPER - select CEC_CORE help Choose this option if you want to enable HDMI CEC support for DisplayPort/USB-C to HDMI adapters. -- GitLab From 8b1a8f8b2002d31136d83e4d730b4cb41e9ee868 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 17 May 2025 04:59:41 +0300 Subject: [PATCH 0156/1479] drm/display: add CEC helpers code Add generic CEC helpers to be used by HDMI drivers. Both notifier and and adapter are supported for registration. Once registered, the driver can call common set of functions to update physical address, to invalidate it or to unregister CEC data. Unlike drm_connector_cec_funcs (which provides interface common to all implementations, including, but not limited to the CEC adapter, CEC notifier, CEC pin-based adapter, etc) the struct drm_connector_hdmi_cec_adapter_ops provides callbacks specific to the CEC adapter implementations. Signed-off-by: Dmitry Baryshkov Reviewed-by: Maxime Ripard Link: https://lore.kernel.org/r/20250517-drm-hdmi-connector-cec-v6-5-35651db6f19b@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/display/Kconfig | 12 +- drivers/gpu/drm/display/Makefile | 4 + drivers/gpu/drm/display/drm_hdmi_cec_helper.c | 192 ++++++++++++++++++ .../display/drm_hdmi_cec_notifier_helper.c | 64 ++++++ include/drm/display/drm_hdmi_cec_helper.h | 72 +++++++ 5 files changed, 343 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/display/drm_hdmi_cec_helper.c create mode 100644 drivers/gpu/drm/display/drm_hdmi_cec_notifier_helper.c create mode 100644 include/drm/display/drm_hdmi_cec_helper.h diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig index 3666e791d6d6e..6376ea01ec309 100644 --- a/drivers/gpu/drm/display/Kconfig +++ b/drivers/gpu/drm/display/Kconfig @@ -8,7 +8,7 @@ config DRM_DISPLAY_DP_AUX_BUS config DRM_DISPLAY_HELPER tristate depends on DRM - select CEC_CORE if DRM_DISPLAY_DP_AUX_CEC + select CEC_CORE if DRM_DISPLAY_DP_AUX_CEC || DRM_DISPLAY_HDMI_CEC_HELPER || CEC_NOTIFIER help DRM helpers for display adapters. @@ -82,6 +82,16 @@ config DRM_DISPLAY_HDMI_AUDIO_HELPER DRM display helpers for HDMI Audio functionality (generic HDMI Codec implementation). +config DRM_DISPLAY_HDMI_CEC_HELPER + bool + help + DRM display helpers for HDMI CEC implementation. + +config DRM_DISPLAY_HDMI_CEC_NOTIFIER_HELPER + def_bool CEC_NOTIFIER + help + DRM display helpers for HDMI CEC notifiers implementation. + config DRM_DISPLAY_HDMI_HELPER bool help diff --git a/drivers/gpu/drm/display/Makefile b/drivers/gpu/drm/display/Makefile index b17879b957d54..0ff4a1ad02220 100644 --- a/drivers/gpu/drm/display/Makefile +++ b/drivers/gpu/drm/display/Makefile @@ -16,6 +16,10 @@ drm_display_helper-$(CONFIG_DRM_DISPLAY_DSC_HELPER) += \ drm_display_helper-$(CONFIG_DRM_DISPLAY_HDCP_HELPER) += drm_hdcp_helper.o drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_AUDIO_HELPER) += \ drm_hdmi_audio_helper.o +drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_CEC_HELPER) += \ + drm_hdmi_cec_helper.o +drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_CEC_NOTIFIER_HELPER) += \ + drm_hdmi_cec_notifier_helper.o drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_HELPER) += \ drm_hdmi_helper.o \ drm_scdc_helper.o diff --git a/drivers/gpu/drm/display/drm_hdmi_cec_helper.c b/drivers/gpu/drm/display/drm_hdmi_cec_helper.c new file mode 100644 index 0000000000000..a25f605090431 --- /dev/null +++ b/drivers/gpu/drm/display/drm_hdmi_cec_helper.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (c) 2024 Linaro Ltd + */ + +#include +#include +#include +#include + +#include + +#include + +struct drm_connector_hdmi_cec_data { + struct cec_adapter *adapter; + const struct drm_connector_hdmi_cec_funcs *funcs; +}; + +static int drm_connector_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) +{ + struct drm_connector *connector = cec_get_drvdata(adap); + struct drm_connector_hdmi_cec_data *data = connector->cec.data; + + return data->funcs->enable(connector, enable); +} + +static int drm_connector_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 logical_addr) +{ + struct drm_connector *connector = cec_get_drvdata(adap); + struct drm_connector_hdmi_cec_data *data = connector->cec.data; + + return data->funcs->log_addr(connector, logical_addr); +} + +static int drm_connector_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, + u32 signal_free_time, struct cec_msg *msg) +{ + struct drm_connector *connector = cec_get_drvdata(adap); + struct drm_connector_hdmi_cec_data *data = connector->cec.data; + + return data->funcs->transmit(connector, attempts, signal_free_time, msg); +} + +static const struct cec_adap_ops drm_connector_hdmi_cec_adap_ops = { + .adap_enable = drm_connector_hdmi_cec_adap_enable, + .adap_log_addr = drm_connector_hdmi_cec_adap_log_addr, + .adap_transmit = drm_connector_hdmi_cec_adap_transmit, +}; + +static void drm_connector_hdmi_cec_adapter_phys_addr_invalidate(struct drm_connector *connector) +{ + struct drm_connector_hdmi_cec_data *data = connector->cec.data; + + cec_phys_addr_invalidate(data->adapter); +} + +static void drm_connector_hdmi_cec_adapter_phys_addr_set(struct drm_connector *connector, + u16 addr) +{ + struct drm_connector_hdmi_cec_data *data = connector->cec.data; + + cec_s_phys_addr(data->adapter, addr, false); +} + +static void drm_connector_hdmi_cec_adapter_unregister(struct drm_device *dev, void *res) +{ + struct drm_connector *connector = res; + struct drm_connector_hdmi_cec_data *data = connector->cec.data; + + cec_delete_adapter(data->adapter); + + if (data->funcs->uninit) + data->funcs->uninit(connector); + + kfree(data); + connector->cec.data = NULL; +} + +static struct drm_connector_cec_funcs drm_connector_hdmi_cec_adapter_funcs = { + .phys_addr_invalidate = drm_connector_hdmi_cec_adapter_phys_addr_invalidate, + .phys_addr_set = drm_connector_hdmi_cec_adapter_phys_addr_set, +}; + +int drmm_connector_hdmi_cec_register(struct drm_connector *connector, + const struct drm_connector_hdmi_cec_funcs *funcs, + const char *name, + u8 available_las, + struct device *dev) +{ + struct drm_connector_hdmi_cec_data *data; + struct cec_connector_info conn_info; + struct cec_adapter *cec_adap; + int ret; + + if (!funcs->init || !funcs->enable || !funcs->log_addr || !funcs->transmit) + return -EINVAL; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->funcs = funcs; + + cec_adap = cec_allocate_adapter(&drm_connector_hdmi_cec_adap_ops, connector, name, + CEC_CAP_DEFAULTS | CEC_CAP_CONNECTOR_INFO, + available_las ? : CEC_MAX_LOG_ADDRS); + ret = PTR_ERR_OR_ZERO(cec_adap); + if (ret < 0) + goto err_free; + + cec_fill_conn_info_from_drm(&conn_info, connector); + cec_s_conn_info(cec_adap, &conn_info); + + data->adapter = cec_adap; + + mutex_lock(&connector->cec.mutex); + + connector->cec.data = data; + connector->cec.funcs = &drm_connector_hdmi_cec_adapter_funcs; + + ret = funcs->init(connector); + if (ret < 0) + goto err_delete_adapter; + + /* + * NOTE: the CEC adapter will be unregistered by drmm cleanup from + * drm_managed_release(), which is called from drm_dev_release() + * during device unbind. + * + * However, the CEC framework cleans up the CEC adapter only when the + * last user has closed its file descriptor, so we don't need to handle + * it in DRM. + * + * Before that CEC framework makes sure that even if the userspace + * still holds CEC device open, all calls will be shortcut via + * cec_is_registered(), making sure that there is no access to the + * freed memory. + */ + ret = cec_register_adapter(cec_adap, dev); + if (ret < 0) + goto err_delete_adapter; + + mutex_unlock(&connector->cec.mutex); + + return drmm_add_action_or_reset(connector->dev, + drm_connector_hdmi_cec_adapter_unregister, + connector); + +err_delete_adapter: + cec_delete_adapter(cec_adap); + + connector->cec.data = NULL; + + mutex_unlock(&connector->cec.mutex); + +err_free: + kfree(data); + + return ret; +} +EXPORT_SYMBOL(drmm_connector_hdmi_cec_register); + +void drm_connector_hdmi_cec_received_msg(struct drm_connector *connector, + struct cec_msg *msg) +{ + struct drm_connector_hdmi_cec_data *data = connector->cec.data; + + cec_received_msg(data->adapter, msg); +} +EXPORT_SYMBOL(drm_connector_hdmi_cec_received_msg); + +void drm_connector_hdmi_cec_transmit_attempt_done(struct drm_connector *connector, + u8 status) +{ + struct drm_connector_hdmi_cec_data *data = connector->cec.data; + + cec_transmit_attempt_done(data->adapter, status); +} +EXPORT_SYMBOL(drm_connector_hdmi_cec_transmit_attempt_done); + +void drm_connector_hdmi_cec_transmit_done(struct drm_connector *connector, + u8 status, + u8 arb_lost_cnt, u8 nack_cnt, + u8 low_drive_cnt, u8 error_cnt) +{ + struct drm_connector_hdmi_cec_data *data = connector->cec.data; + + cec_transmit_done(data->adapter, status, + arb_lost_cnt, nack_cnt, low_drive_cnt, error_cnt); +} +EXPORT_SYMBOL(drm_connector_hdmi_cec_transmit_done); diff --git a/drivers/gpu/drm/display/drm_hdmi_cec_notifier_helper.c b/drivers/gpu/drm/display/drm_hdmi_cec_notifier_helper.c new file mode 100644 index 0000000000000..28f8e008cc59f --- /dev/null +++ b/drivers/gpu/drm/display/drm_hdmi_cec_notifier_helper.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (c) 2024 Linaro Ltd + */ + +#include +#include +#include +#include + +#include + +#include +#include + +static void drm_connector_hdmi_cec_notifier_phys_addr_invalidate(struct drm_connector *connector) +{ + cec_notifier_phys_addr_invalidate(connector->cec.data); +} + +static void drm_connector_hdmi_cec_notifier_phys_addr_set(struct drm_connector *connector, + u16 addr) +{ + cec_notifier_set_phys_addr(connector->cec.data, addr); +} + +static void drm_connector_hdmi_cec_notifier_unregister(struct drm_device *dev, void *res) +{ + struct drm_connector *connector = res; + + cec_notifier_conn_unregister(connector->cec.data); + connector->cec.data = NULL; +} + +static const struct drm_connector_cec_funcs drm_connector_cec_notifier_funcs = { + .phys_addr_invalidate = drm_connector_hdmi_cec_notifier_phys_addr_invalidate, + .phys_addr_set = drm_connector_hdmi_cec_notifier_phys_addr_set, +}; + +int drmm_connector_hdmi_cec_notifier_register(struct drm_connector *connector, + const char *port_name, + struct device *dev) +{ + struct cec_connector_info conn_info; + struct cec_notifier *notifier; + + cec_fill_conn_info_from_drm(&conn_info, connector); + + notifier = cec_notifier_conn_register(dev, port_name, &conn_info); + if (!notifier) + return -ENOMEM; + + mutex_lock(&connector->cec.mutex); + + connector->cec.data = notifier; + connector->cec.funcs = &drm_connector_cec_notifier_funcs; + + mutex_unlock(&connector->cec.mutex); + + return drmm_add_action_or_reset(connector->dev, + drm_connector_hdmi_cec_notifier_unregister, + connector); +} +EXPORT_SYMBOL(drmm_connector_hdmi_cec_notifier_register); diff --git a/include/drm/display/drm_hdmi_cec_helper.h b/include/drm/display/drm_hdmi_cec_helper.h new file mode 100644 index 0000000000000..fd8f4d2f02c1e --- /dev/null +++ b/include/drm/display/drm_hdmi_cec_helper.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef DRM_DISPLAY_HDMI_CEC_HELPER +#define DRM_DISPLAY_HDMI_CEC_HELPER + +#include + +struct drm_connector; + +struct cec_msg; +struct device; + +struct drm_connector_hdmi_cec_funcs { + /** + * @init: perform hardware-specific initialization before registering the CEC adapter + */ + int (*init)(struct drm_connector *connector); + + /** + * @uninit: perform hardware-specific teardown for the CEC adapter + */ + void (*uninit)(struct drm_connector *connector); + + /** + * @enable: enable or disable CEC adapter + */ + int (*enable)(struct drm_connector *connector, bool enable); + + /** + * @log_addr: set adapter's logical address, can be called multiple + * times if adapter supports several LAs + */ + int (*log_addr)(struct drm_connector *connector, u8 logical_addr); + + /** + * @transmit: start transmission of the specified CEC message + */ + int (*transmit)(struct drm_connector *connector, u8 attempts, + u32 signal_free_time, struct cec_msg *msg); +}; + +int drmm_connector_hdmi_cec_register(struct drm_connector *connector, + const struct drm_connector_hdmi_cec_funcs *funcs, + const char *name, + u8 available_las, + struct device *dev); + +void drm_connector_hdmi_cec_received_msg(struct drm_connector *connector, + struct cec_msg *msg); + +void drm_connector_hdmi_cec_transmit_done(struct drm_connector *connector, + u8 status, + u8 arb_lost_cnt, u8 nack_cnt, + u8 low_drive_cnt, u8 error_cnt); + +void drm_connector_hdmi_cec_transmit_attempt_done(struct drm_connector *connector, + u8 status); + +#if IS_ENABLED(CONFIG_DRM_DISPLAY_HDMI_CEC_NOTIFIER_HELPER) +int drmm_connector_hdmi_cec_notifier_register(struct drm_connector *connector, + const char *port_name, + struct device *dev); +#else +static inline int drmm_connector_hdmi_cec_notifier_register(struct drm_connector *connector, + const char *port_name, + struct device *dev) +{ + return 0; +} +#endif + +#endif -- GitLab From 603ce85427043ecb29ef737c1b350901ce3ebf09 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 17 May 2025 04:59:42 +0300 Subject: [PATCH 0157/1479] drm/display: hdmi-state-helper: handle CEC physical address Call HDMI CEC helpers in order to update physical address of the adapter. Reviewed-by: Maxime Ripard Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250517-drm-hdmi-connector-cec-v6-6-35651db6f19b@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/display/drm_hdmi_state_helper.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index d9d9948b29e9d..bae7aa624f7db 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -1081,9 +1082,10 @@ drm_atomic_helper_connector_hdmi_update(struct drm_connector *connector, const struct drm_edid *drm_edid; if (status == connector_status_disconnected) { - // TODO: also handle CEC and scramber, HDMI sink disconnected. + // TODO: also handle scramber, HDMI sink disconnected. drm_connector_hdmi_audio_plugged_notify(connector, false); drm_edid_connector_update(connector, NULL); + drm_connector_cec_phys_addr_invalidate(connector); return; } @@ -1097,8 +1099,9 @@ drm_atomic_helper_connector_hdmi_update(struct drm_connector *connector, drm_edid_free(drm_edid); if (status == connector_status_connected) { - // TODO: also handle CEC and scramber, HDMI sink is now connected. + // TODO: also handle scramber, HDMI sink is now connected. drm_connector_hdmi_audio_plugged_notify(connector, true); + drm_connector_cec_phys_addr_set(connector); } } -- GitLab From 65a2575a68e4ff03ba887b5aef679fc95405fcd2 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 17 May 2025 04:59:44 +0300 Subject: [PATCH 0158/1479] drm/display: bridge-connector: hook in CEC notifier support Allow HDMI DRM bridges to create CEC notifier. Physical address is handled automatically by drm_atomic_helper_connector_hdmi_hotplug() being called from .detect() path. Signed-off-by: Dmitry Baryshkov Reviewed-by: Maxime Ripard Link: https://lore.kernel.org/r/20250517-drm-hdmi-connector-cec-v6-8-35651db6f19b@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- .../gpu/drm/display/drm_bridge_connector.c | 24 +++++++++++++++++++ include/drm/drm_bridge.h | 11 +++++++++ 2 files changed, 35 insertions(+) diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 381a0f9d4259b..0377dcd691a87 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -113,6 +114,13 @@ struct drm_bridge_connector { * &DRM_BRIDGE_OP_DP_AUDIO). */ struct drm_bridge *bridge_dp_audio; + /** + * @bridge_hdmi_cec: + * + * The bridge in the chain that implements CEC support, if any (see + * DRM_BRIDGE_OP_HDMI_CEC_NOTIFIER). + */ + struct drm_bridge *bridge_hdmi_cec; }; #define to_drm_bridge_connector(x) \ @@ -662,6 +670,13 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, bridge_connector->bridge_dp_audio = bridge; } + if (bridge->ops & DRM_BRIDGE_OP_HDMI_CEC_NOTIFIER) { + if (bridge_connector->bridge_hdmi_cec) + return ERR_PTR(-EBUSY); + + bridge_connector->bridge_hdmi_cec = bridge; + } + if (!drm_bridge_get_next_bridge(bridge)) connector_type = bridge->type; @@ -724,6 +739,15 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, return ERR_PTR(ret); } + if (bridge_connector->bridge_hdmi_cec && + bridge_connector->bridge_hdmi_cec->ops & DRM_BRIDGE_OP_HDMI_CEC_NOTIFIER) { + ret = drmm_connector_hdmi_cec_notifier_register(connector, + NULL, + bridge->hdmi_cec_dev); + if (ret) + return ERR_PTR(ret); + } + drm_connector_helper_add(connector, &drm_bridge_connector_helper_funcs); if (bridge_connector->bridge_hpd) diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index db0d374d863b0..0e5f6a007d536 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -907,6 +907,11 @@ enum drm_bridge_ops { * flag. */ DRM_BRIDGE_OP_DP_AUDIO = BIT(6), + /** + * @DRM_BRIDGE_OP_HDMI_CEC_NOTIFIER: The bridge requires CEC notifier + * to be present. + */ + DRM_BRIDGE_OP_HDMI_CEC_NOTIFIER = BIT(7), }; /** @@ -1003,6 +1008,12 @@ struct drm_bridge { */ unsigned int max_bpc; + /** + * @hdmi_cec_dev: device to be used as a containing device for CEC + * functions. + */ + struct device *hdmi_cec_dev; + /** * @hdmi_audio_dev: device to be used as a parent for the HDMI Codec if * either of @DRM_BRIDGE_OP_HDMI_AUDIO or @DRM_BRIDGE_OP_DP_AUDIO is set. -- GitLab From a74288c8ded7c34624e50b4aa8ca37ae6cc03df4 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 17 May 2025 04:59:45 +0300 Subject: [PATCH 0159/1479] drm/display: bridge-connector: handle CEC adapters Implement necessary glue code to let DRM bridge drivers to implement CEC adapters support. Signed-off-by: Dmitry Baryshkov Reviewed-by: Maxime Ripard Link: https://lore.kernel.org/r/20250517-drm-hdmi-connector-cec-v6-9-35651db6f19b@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/display/Kconfig | 1 + .../gpu/drm/display/drm_bridge_connector.c | 82 +++++++++++++++++++ include/drm/drm_bridge.h | 26 ++++++ 3 files changed, 109 insertions(+) diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig index 6376ea01ec309..df09cf9a8ca19 100644 --- a/drivers/gpu/drm/display/Kconfig +++ b/drivers/gpu/drm/display/Kconfig @@ -17,6 +17,7 @@ if DRM_DISPLAY_HELPER config DRM_BRIDGE_CONNECTOR bool select DRM_DISPLAY_HDMI_AUDIO_HELPER + select DRM_DISPLAY_HDMI_CEC_HELPER select DRM_DISPLAY_HDMI_STATE_HELPER help DRM connector implementation terminating DRM bridge chains. diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 0377dcd691a87..58846e26f1e1b 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -554,6 +554,65 @@ static const struct drm_connector_hdmi_audio_funcs drm_bridge_connector_hdmi_aud .mute_stream = drm_bridge_connector_audio_mute_stream, }; +static int drm_bridge_connector_hdmi_cec_enable(struct drm_connector *connector, bool enable) +{ + struct drm_bridge_connector *bridge_connector = + to_drm_bridge_connector(connector); + struct drm_bridge *bridge; + + bridge = bridge_connector->bridge_hdmi_cec; + + return bridge->funcs->hdmi_cec_enable(bridge, enable); +} + +static int drm_bridge_connector_hdmi_cec_log_addr(struct drm_connector *connector, u8 logical_addr) +{ + struct drm_bridge_connector *bridge_connector = + to_drm_bridge_connector(connector); + struct drm_bridge *bridge; + + bridge = bridge_connector->bridge_hdmi_cec; + + return bridge->funcs->hdmi_cec_log_addr(bridge, logical_addr); +} + +static int drm_bridge_connector_hdmi_cec_transmit(struct drm_connector *connector, + u8 attempts, + u32 signal_free_time, + struct cec_msg *msg) +{ + struct drm_bridge_connector *bridge_connector = + to_drm_bridge_connector(connector); + struct drm_bridge *bridge; + + bridge = bridge_connector->bridge_hdmi_cec; + + return bridge->funcs->hdmi_cec_transmit(bridge, attempts, + signal_free_time, + msg); +} + +static int drm_bridge_connector_hdmi_cec_init(struct drm_connector *connector) +{ + struct drm_bridge_connector *bridge_connector = + to_drm_bridge_connector(connector); + struct drm_bridge *bridge; + + bridge = bridge_connector->bridge_hdmi_cec; + + if (!bridge->funcs->hdmi_cec_init) + return 0; + + return bridge->funcs->hdmi_cec_init(connector, bridge); +} + +static const struct drm_connector_hdmi_cec_funcs drm_bridge_connector_hdmi_cec_funcs = { + .init = drm_bridge_connector_hdmi_cec_init, + .enable = drm_bridge_connector_hdmi_cec_enable, + .log_addr = drm_bridge_connector_hdmi_cec_log_addr, + .transmit = drm_bridge_connector_hdmi_cec_transmit, +}; + /* ----------------------------------------------------------------------------- * Bridge Connector Initialisation */ @@ -677,6 +736,18 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, bridge_connector->bridge_hdmi_cec = bridge; } + if (bridge->ops & DRM_BRIDGE_OP_HDMI_CEC_ADAPTER) { + if (bridge_connector->bridge_hdmi_cec) + return ERR_PTR(-EBUSY); + + bridge_connector->bridge_hdmi_cec = bridge; + + if (!bridge->funcs->hdmi_cec_enable || + !bridge->funcs->hdmi_cec_log_addr || + !bridge->funcs->hdmi_cec_transmit) + return ERR_PTR(-EINVAL); + } + if (!drm_bridge_get_next_bridge(bridge)) connector_type = bridge->type; @@ -748,6 +819,17 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, return ERR_PTR(ret); } + if (bridge_connector->bridge_hdmi_cec && + bridge_connector->bridge_hdmi_cec->ops & DRM_BRIDGE_OP_HDMI_CEC_ADAPTER) { + ret = drmm_connector_hdmi_cec_register(connector, + &drm_bridge_connector_hdmi_cec_funcs, + bridge->hdmi_cec_adapter_name, + bridge->hdmi_cec_available_las, + bridge->hdmi_cec_dev); + if (ret) + return ERR_PTR(ret); + } + drm_connector_helper_add(connector, &drm_bridge_connector_helper_funcs); if (bridge_connector->bridge_hpd) diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 0e5f6a007d536..cc9f7df38102e 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -32,6 +32,7 @@ #include #include +struct cec_msg; struct device_node; struct drm_bridge; @@ -737,6 +738,16 @@ struct drm_bridge_funcs { struct drm_bridge *bridge, bool enable, int direction); + int (*hdmi_cec_init)(struct drm_connector *connector, + struct drm_bridge *bridge); + + int (*hdmi_cec_enable)(struct drm_bridge *bridge, bool enable); + + int (*hdmi_cec_log_addr)(struct drm_bridge *bridge, u8 logical_addr); + + int (*hdmi_cec_transmit)(struct drm_bridge *bridge, u8 attempts, + u32 signal_free_time, struct cec_msg *msg); + /** * @dp_audio_startup: * @@ -912,6 +923,11 @@ enum drm_bridge_ops { * to be present. */ DRM_BRIDGE_OP_HDMI_CEC_NOTIFIER = BIT(7), + /** + * @DRM_BRIDGE_OP_HDMI_CEC_ADAPTER: The bridge requires CEC notifier + * to be present. + */ + DRM_BRIDGE_OP_HDMI_CEC_ADAPTER = BIT(8), }; /** @@ -1048,6 +1064,16 @@ struct drm_bridge { */ int hdmi_audio_dai_port; + /** + * @hdmi_cec_adapter_name: the name of the adapter to register + */ + const char *hdmi_cec_adapter_name; + + /** + * @hdmi_cec_available_las: number of logical addresses, CEC_MAX_LOG_ADDRS if unset + */ + u8 hdmi_cec_available_las; + /** private: */ /** * @hpd_mutex: Protects the @hpd_cb and @hpd_data fields. -- GitLab From ae01d3183d2763ed27ab71f4ef5402b683d9ad8a Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 17 May 2025 04:59:46 +0300 Subject: [PATCH 0160/1479] drm/bridge: adv7511: switch to the HDMI connector helpers Rewrite the ADV7511 driver to use implementation provided by the DRM HDMI connector framework, including the Audio and CEC bits. Drop the in-bridge connector support and use drm_bridge_connector if the host requires the connector to be provided by the bridge. Note: currently only AVI InfoFrames are supported. Existing driver doesn't support programming any other InfoFrames directly and Audio InfoFrame seems to be programmed using individual bits and pieces rather than programming it directly. Signed-off-by: Dmitry Baryshkov Reviewed-by: Maxime Ripard Link: https://lore.kernel.org/r/20250517-drm-hdmi-connector-cec-v6-10-35651db6f19b@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/bridge/adv7511/Kconfig | 5 +- drivers/gpu/drm/bridge/adv7511/adv7511.h | 52 +-- .../gpu/drm/bridge/adv7511/adv7511_audio.c | 77 +--- drivers/gpu/drm/bridge/adv7511/adv7511_cec.c | 57 ++- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 345 ++++++++---------- drivers/gpu/drm/bridge/adv7511/adv7533.c | 4 - 6 files changed, 212 insertions(+), 328 deletions(-) diff --git a/drivers/gpu/drm/bridge/adv7511/Kconfig b/drivers/gpu/drm/bridge/adv7511/Kconfig index f46a5e26b5dd6..59a5256ce8a6e 100644 --- a/drivers/gpu/drm/bridge/adv7511/Kconfig +++ b/drivers/gpu/drm/bridge/adv7511/Kconfig @@ -5,6 +5,9 @@ config DRM_I2C_ADV7511 select DRM_KMS_HELPER select REGMAP_I2C select DRM_MIPI_DSI + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR + select DRM_DISPLAY_HDMI_STATE_HELPER help Support for the Analog Devices ADV7511(W)/13/33/35 HDMI encoders. @@ -19,7 +22,7 @@ config DRM_I2C_ADV7511_AUDIO config DRM_I2C_ADV7511_CEC bool "ADV7511/33/35 HDMI CEC driver" depends on DRM_I2C_ADV7511 - select CEC_CORE + select DRM_DISPLAY_HDMI_CEC_HELPER default y help When selected the HDMI transmitter will support the CEC feature. diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h index ec0b7f3d889c4..0ecce9e4947ad 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511.h +++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h @@ -313,16 +313,11 @@ enum adv7511_csc_scaling { * @csc_enable: Whether to enable color space conversion * @csc_scaling_factor: Color space conversion scaling factor * @csc_coefficents: Color space conversion coefficents - * @hdmi_mode: Whether to use HDMI or DVI output mode - * @avi_infoframe: HDMI infoframe */ struct adv7511_video_config { bool csc_enable; enum adv7511_csc_scaling csc_scaling_factor; const uint16_t *csc_coefficents; - - bool hdmi_mode; - struct hdmi_avi_infoframe avi_infoframe; }; enum adv7511_type { @@ -337,6 +332,7 @@ struct adv7511_chip_info { enum adv7511_type type; unsigned int max_mode_clock_khz; unsigned int max_lane_freq_khz; + const char *name; const char * const *supply_names; unsigned int num_supplies; unsigned int reg_cec_offset; @@ -371,7 +367,7 @@ struct adv7511 { struct work_struct hpd_work; struct drm_bridge bridge; - struct drm_connector connector; + struct drm_connector *cec_connector; bool embedded_sync; enum adv7511_sync_polarity vsync_polarity; @@ -389,9 +385,7 @@ struct adv7511 { bool use_timing_gen; const struct adv7511_chip_info *info; - struct platform_device *audio_pdev; - struct cec_adapter *cec_adap; u8 cec_addr[ADV7511_MAX_ADDRS]; u8 cec_valid_addrs; bool cec_enabled_adap; @@ -399,16 +393,24 @@ struct adv7511 { u32 cec_clk_freq; }; +static inline struct adv7511 *bridge_to_adv7511(struct drm_bridge *bridge) +{ + return container_of(bridge, struct adv7511, bridge); +} + #ifdef CONFIG_DRM_I2C_ADV7511_CEC -int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511); +int adv7511_cec_init(struct drm_connector *connector, + struct drm_bridge *bridge); +int adv7511_cec_enable(struct drm_bridge *bridge, bool enable); +int adv7511_cec_log_addr(struct drm_bridge *bridge, u8 addr); +int adv7511_cec_transmit(struct drm_bridge *bridge, u8 attempts, + u32 signal_free_time, struct cec_msg *msg); int adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1); #else -static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511) -{ - regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, - ADV7511_CEC_CTRL_POWER_DOWN); - return 0; -} +#define adv7511_cec_init NULL +#define adv7511_cec_enable NULL +#define adv7511_cec_log_addr NULL +#define adv7511_cec_transmit NULL #endif void adv7533_dsi_power_on(struct adv7511 *adv); @@ -421,16 +423,18 @@ int adv7533_attach_dsi(struct adv7511 *adv); int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv); #ifdef CONFIG_DRM_I2C_ADV7511_AUDIO -int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511); -void adv7511_audio_exit(struct adv7511 *adv7511); +int adv7511_hdmi_audio_startup(struct drm_connector *connector, + struct drm_bridge *bridge); +void adv7511_hdmi_audio_shutdown(struct drm_connector *connector, + struct drm_bridge *bridge); +int adv7511_hdmi_audio_prepare(struct drm_connector *connector, + struct drm_bridge *bridge, + struct hdmi_codec_daifmt *fmt, + struct hdmi_codec_params *hparms); #else /*CONFIG_DRM_I2C_ADV7511_AUDIO */ -static inline int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511) -{ - return 0; -} -static inline void adv7511_audio_exit(struct adv7511 *adv7511) -{ -} +#define adv7511_hdmi_audio_startup NULL +#define adv7511_hdmi_audio_shutdown NULL +#define adv7511_hdmi_audio_prepare NULL #endif /* CONFIG_DRM_I2C_ADV7511_AUDIO */ #endif /* __DRM_I2C_ADV7511_H__ */ diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c index 1ff8c815ec798..915c3b9672162 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c @@ -55,11 +55,12 @@ static int adv7511_update_cts_n(struct adv7511 *adv7511) return 0; } -static int adv7511_hdmi_hw_params(struct device *dev, void *data, - struct hdmi_codec_daifmt *fmt, - struct hdmi_codec_params *hparms) +int adv7511_hdmi_audio_prepare(struct drm_connector *connector, + struct drm_bridge *bridge, + struct hdmi_codec_daifmt *fmt, + struct hdmi_codec_params *hparms) { - struct adv7511 *adv7511 = dev_get_drvdata(dev); + struct adv7511 *adv7511 = bridge_to_adv7511(bridge); unsigned int audio_source, i2s_format = 0; unsigned int invert_clock; unsigned int rate; @@ -167,9 +168,10 @@ static int adv7511_hdmi_hw_params(struct device *dev, void *data, return 0; } -static int audio_startup(struct device *dev, void *data) +int adv7511_hdmi_audio_startup(struct drm_connector *connector, + struct drm_bridge *bridge) { - struct adv7511 *adv7511 = dev_get_drvdata(dev); + struct adv7511 *adv7511 = bridge_to_adv7511(bridge); regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG, BIT(7), 0); @@ -204,69 +206,12 @@ static int audio_startup(struct device *dev, void *data) return 0; } -static void audio_shutdown(struct device *dev, void *data) +void adv7511_hdmi_audio_shutdown(struct drm_connector *connector, + struct drm_bridge *bridge) { - struct adv7511 *adv7511 = dev_get_drvdata(dev); + struct adv7511 *adv7511 = bridge_to_adv7511(bridge); if (adv7511->audio_source == ADV7511_AUDIO_SOURCE_SPDIF) regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG, BIT(7), 0); } - -static int adv7511_hdmi_i2s_get_dai_id(struct snd_soc_component *component, - struct device_node *endpoint, - void *data) -{ - struct of_endpoint of_ep; - int ret; - - ret = of_graph_parse_endpoint(endpoint, &of_ep); - if (ret < 0) - return ret; - - /* - * HDMI sound should be located as reg = <2> - * Then, it is sound port 0 - */ - if (of_ep.port == 2) - return 0; - - return -EINVAL; -} - -static const struct hdmi_codec_ops adv7511_codec_ops = { - .hw_params = adv7511_hdmi_hw_params, - .audio_shutdown = audio_shutdown, - .audio_startup = audio_startup, - .get_dai_id = adv7511_hdmi_i2s_get_dai_id, -}; - -static const struct hdmi_codec_pdata codec_data = { - .ops = &adv7511_codec_ops, - .i2s_formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | - SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE), - .max_i2s_channels = 2, - .i2s = 1, - .no_i2s_capture = 1, - .spdif = 1, - .no_spdif_capture = 1, -}; - -int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511) -{ - adv7511->audio_pdev = platform_device_register_data(dev, - HDMI_CODEC_DRV_NAME, - PLATFORM_DEVID_AUTO, - &codec_data, - sizeof(codec_data)); - return PTR_ERR_OR_ZERO(adv7511->audio_pdev); -} - -void adv7511_audio_exit(struct adv7511 *adv7511) -{ - if (adv7511->audio_pdev) { - platform_device_unregister(adv7511->audio_pdev); - adv7511->audio_pdev = NULL; - } -} diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c index 2e9c88a2b5ed4..822265426f58a 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c @@ -12,6 +12,8 @@ #include +#include + #include "adv7511.h" static const u8 ADV7511_REG_CEC_RX_FRAME_HDR[] = { @@ -44,8 +46,8 @@ static void adv_cec_tx_raw_status(struct adv7511 *adv7511, u8 tx_raw_status) return; if (tx_raw_status & ADV7511_INT1_CEC_TX_ARBIT_LOST) { - cec_transmit_attempt_done(adv7511->cec_adap, - CEC_TX_STATUS_ARB_LOST); + drm_connector_hdmi_cec_transmit_attempt_done(adv7511->cec_connector, + CEC_TX_STATUS_ARB_LOST); return; } if (tx_raw_status & ADV7511_INT1_CEC_TX_RETRY_TIMEOUT) { @@ -72,12 +74,14 @@ static void adv_cec_tx_raw_status(struct adv7511 *adv7511, u8 tx_raw_status) if (low_drive_cnt) status |= CEC_TX_STATUS_LOW_DRIVE; } - cec_transmit_done(adv7511->cec_adap, status, - 0, nack_cnt, low_drive_cnt, err_cnt); + drm_connector_hdmi_cec_transmit_done(adv7511->cec_connector, status, + 0, nack_cnt, low_drive_cnt, + err_cnt); return; } if (tx_raw_status & ADV7511_INT1_CEC_TX_READY) { - cec_transmit_attempt_done(adv7511->cec_adap, CEC_TX_STATUS_OK); + drm_connector_hdmi_cec_transmit_attempt_done(adv7511->cec_connector, + CEC_TX_STATUS_OK); return; } } @@ -116,7 +120,7 @@ static void adv7511_cec_rx(struct adv7511 *adv7511, int rx_buf) regmap_update_bits(adv7511->regmap_cec, ADV7511_REG_CEC_RX_BUFFERS + offset, BIT(rx_buf), 0); - cec_received_msg(adv7511->cec_adap, &msg); + drm_connector_hdmi_cec_received_msg(adv7511->cec_connector, &msg); } int adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1) @@ -179,9 +183,9 @@ int adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1) return IRQ_HANDLED; } -static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable) +int adv7511_cec_enable(struct drm_bridge *bridge, bool enable) { - struct adv7511 *adv7511 = cec_get_drvdata(adap); + struct adv7511 *adv7511 = bridge_to_adv7511(bridge); unsigned int offset = adv7511->info->reg_cec_offset; if (adv7511->i2c_cec == NULL) @@ -225,9 +229,9 @@ static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable) return 0; } -static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr) +int adv7511_cec_log_addr(struct drm_bridge *bridge, u8 addr) { - struct adv7511 *adv7511 = cec_get_drvdata(adap); + struct adv7511 *adv7511 = bridge_to_adv7511(bridge); unsigned int offset = adv7511->info->reg_cec_offset; unsigned int i, free_idx = ADV7511_MAX_ADDRS; @@ -293,10 +297,10 @@ static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr) return 0; } -static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, - u32 signal_free_time, struct cec_msg *msg) +int adv7511_cec_transmit(struct drm_bridge *bridge, u8 attempts, + u32 signal_free_time, struct cec_msg *msg) { - struct adv7511 *adv7511 = cec_get_drvdata(adap); + struct adv7511 *adv7511 = bridge_to_adv7511(bridge); unsigned int offset = adv7511->info->reg_cec_offset; u8 len = msg->len; unsigned int i; @@ -328,12 +332,6 @@ static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, return 0; } -static const struct cec_adap_ops adv7511_cec_adap_ops = { - .adap_enable = adv7511_cec_adap_enable, - .adap_log_addr = adv7511_cec_adap_log_addr, - .adap_transmit = adv7511_cec_adap_transmit, -}; - static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511) { adv7511->cec_clk = devm_clk_get(dev, "cec"); @@ -348,20 +346,18 @@ static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511) return 0; } -int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511) +int adv7511_cec_init(struct drm_connector *connector, + struct drm_bridge *bridge) { + struct adv7511 *adv7511 = bridge_to_adv7511(bridge); + struct device *dev = &adv7511->i2c_main->dev; unsigned int offset = adv7511->info->reg_cec_offset; int ret = adv7511_cec_parse_dt(dev, adv7511); if (ret) goto err_cec_parse_dt; - adv7511->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops, - adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS); - if (IS_ERR(adv7511->cec_adap)) { - ret = PTR_ERR(adv7511->cec_adap); - goto err_cec_alloc; - } + adv7511->cec_connector = connector; regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, 0); /* cec soft reset */ @@ -378,17 +374,8 @@ int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511) ADV7511_REG_CEC_CLK_DIV + offset, ((adv7511->cec_clk_freq / 750000) - 1) << 2); - ret = cec_register_adapter(adv7511->cec_adap, dev); - if (ret) - goto err_cec_register; return 0; -err_cec_register: - cec_delete_adapter(adv7511->cec_adap); - adv7511->cec_adap = NULL; -err_cec_alloc: - dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n", - ret); err_cec_parse_dt: regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, ADV7511_CEC_CTRL_POWER_DOWN); diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index 1257009e850c1..8b7548448615f 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -12,14 +12,17 @@ #include #include -#include +#include #include #include +#include #include #include #include #include +#include +#include #include "adv7511.h" @@ -203,62 +206,37 @@ static const uint16_t adv7511_csc_ycbcr_to_rgb[] = { static void adv7511_set_config_csc(struct adv7511 *adv7511, struct drm_connector *connector, - bool rgb, bool hdmi_mode) + bool rgb) { struct adv7511_video_config config; bool output_format_422, output_format_ycbcr; unsigned int mode; - uint8_t infoframe[17]; - - config.hdmi_mode = hdmi_mode; - - hdmi_avi_infoframe_init(&config.avi_infoframe); - - config.avi_infoframe.scan_mode = HDMI_SCAN_MODE_UNDERSCAN; if (rgb) { config.csc_enable = false; - config.avi_infoframe.colorspace = HDMI_COLORSPACE_RGB; + output_format_422 = false; + output_format_ycbcr = false; } else { config.csc_scaling_factor = ADV7511_CSC_SCALING_4; config.csc_coefficents = adv7511_csc_ycbcr_to_rgb; if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR422) && - config.hdmi_mode) { + connector->display_info.is_hdmi) { config.csc_enable = false; - config.avi_infoframe.colorspace = - HDMI_COLORSPACE_YUV422; - } else { - config.csc_enable = true; - config.avi_infoframe.colorspace = HDMI_COLORSPACE_RGB; - } - } - - if (config.hdmi_mode) { - mode = ADV7511_HDMI_CFG_MODE_HDMI; - - switch (config.avi_infoframe.colorspace) { - case HDMI_COLORSPACE_YUV444: - output_format_422 = false; - output_format_ycbcr = true; - break; - case HDMI_COLORSPACE_YUV422: output_format_422 = true; output_format_ycbcr = true; - break; - default: + } else { + config.csc_enable = true; output_format_422 = false; output_format_ycbcr = false; - break; } - } else { - mode = ADV7511_HDMI_CFG_MODE_DVI; - output_format_422 = false; - output_format_ycbcr = false; } - adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME); + if (connector->display_info.is_hdmi) + mode = ADV7511_HDMI_CFG_MODE_HDMI; + else + mode = ADV7511_HDMI_CFG_MODE_DVI; adv7511_set_colormap(adv7511, config.csc_enable, config.csc_coefficents, @@ -269,15 +247,6 @@ static void adv7511_set_config_csc(struct adv7511 *adv7511, regmap_update_bits(adv7511->regmap, ADV7511_REG_HDCP_HDMI_CFG, ADV7511_HDMI_CFG_MODE_MASK, mode); - - hdmi_avi_infoframe_pack(&config.avi_infoframe, infoframe, - sizeof(infoframe)); - - /* The AVI infoframe id is not configurable */ - regmap_bulk_write(adv7511->regmap, ADV7511_REG_AVI_INFOFRAME_VERSION, - infoframe + 1, sizeof(infoframe) - 1); - - adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME); } static void adv7511_set_link_config(struct adv7511 *adv7511, @@ -446,22 +415,16 @@ static void adv7511_hpd_work(struct work_struct *work) * restore its state. */ if (status == connector_status_connected && - adv7511->connector.status == connector_status_disconnected && + adv7511->status == connector_status_disconnected && adv7511->powered) { regcache_mark_dirty(adv7511->regmap); adv7511_power_on(adv7511); } - if (adv7511->connector.status != status) { - adv7511->connector.status = status; + if (adv7511->status != status) { + adv7511->status = status; - if (adv7511->connector.dev) { - if (status == connector_status_disconnected) - cec_phys_addr_invalidate(adv7511->cec_adap); - drm_kms_helper_hotplug_event(adv7511->connector.dev); - } else { - drm_bridge_hpd_notify(&adv7511->bridge, status); - } + drm_bridge_hpd_notify(&adv7511->bridge, status); } } @@ -636,45 +599,11 @@ static const struct drm_edid *adv7511_edid_read(struct adv7511 *adv7511, if (!adv7511->powered) __adv7511_power_off(adv7511); - if (drm_edid) { - /* - * FIXME: The CEC physical address should be set using - * cec_s_phys_addr(adap, - * connector->display_info.source_physical_address, false) from - * a path that has read the EDID and called - * drm_edid_connector_update(). - */ - const struct edid *edid = drm_edid_raw(drm_edid); - - adv7511_set_config_csc(adv7511, connector, adv7511->rgb, - drm_detect_hdmi_monitor(edid)); - - cec_s_phys_addr_from_edid(adv7511->cec_adap, edid); - } else { - cec_s_phys_addr_from_edid(adv7511->cec_adap, NULL); - } - return drm_edid; } -static int adv7511_get_modes(struct adv7511 *adv7511, - struct drm_connector *connector) -{ - const struct drm_edid *drm_edid; - unsigned int count; - - drm_edid = adv7511_edid_read(adv7511, connector); - - drm_edid_connector_update(connector, drm_edid); - count = drm_edid_connector_add_modes(connector); - - drm_edid_free(drm_edid); - - return count; -} - static enum drm_connector_status -adv7511_detect(struct adv7511 *adv7511, struct drm_connector *connector) +adv7511_detect(struct adv7511 *adv7511) { enum drm_connector_status status; unsigned int val; @@ -699,8 +628,6 @@ adv7511_detect(struct adv7511 *adv7511, struct drm_connector *connector) if (status == connector_status_connected && hpd && adv7511->powered) { regcache_mark_dirty(adv7511->regmap); adv7511_power_on(adv7511); - if (connector) - adv7511_get_modes(adv7511, connector); if (adv7511->status == connector_status_connected) status = connector_status_disconnected; } else { @@ -719,17 +646,7 @@ adv7511_detect(struct adv7511 *adv7511, struct drm_connector *connector) return status; } -static enum drm_mode_status adv7511_mode_valid(struct adv7511 *adv7511, - const struct drm_display_mode *mode) -{ - if (mode->clock > 165000) - return MODE_CLOCK_HIGH; - - return MODE_OK; -} - static void adv7511_mode_set(struct adv7511 *adv7511, - const struct drm_display_mode *mode, const struct drm_display_mode *adj_mode) { unsigned int low_refresh_rate; @@ -800,11 +717,11 @@ static void adv7511_mode_set(struct adv7511 *adv7511, vsync_polarity = 1; } - if (drm_mode_vrefresh(mode) <= 24) + if (drm_mode_vrefresh(adj_mode) <= 24) low_refresh_rate = ADV7511_LOW_REFRESH_RATE_24HZ; - else if (drm_mode_vrefresh(mode) <= 25) + else if (drm_mode_vrefresh(adj_mode) <= 25) low_refresh_rate = ADV7511_LOW_REFRESH_RATE_25HZ; - else if (drm_mode_vrefresh(mode) <= 30) + else if (drm_mode_vrefresh(adj_mode) <= 30) low_refresh_rate = ADV7511_LOW_REFRESH_RATE_30HZ; else low_refresh_rate = ADV7511_LOW_REFRESH_RATE_NONE; @@ -826,77 +743,21 @@ static void adv7511_mode_set(struct adv7511 *adv7511, * supposed to give better results. */ - adv7511->f_tmds = mode->clock; -} - -/* ----------------------------------------------------------------------------- - * DRM Connector Operations - */ - -static struct adv7511 *connector_to_adv7511(struct drm_connector *connector) -{ - return container_of(connector, struct adv7511, connector); + adv7511->f_tmds = adj_mode->clock; } -static int adv7511_connector_get_modes(struct drm_connector *connector) -{ - struct adv7511 *adv = connector_to_adv7511(connector); - - return adv7511_get_modes(adv, connector); -} - -static enum drm_mode_status -adv7511_connector_mode_valid(struct drm_connector *connector, - const struct drm_display_mode *mode) -{ - struct adv7511 *adv = connector_to_adv7511(connector); - - return adv7511_mode_valid(adv, mode); -} - -static struct drm_connector_helper_funcs adv7511_connector_helper_funcs = { - .get_modes = adv7511_connector_get_modes, - .mode_valid = adv7511_connector_mode_valid, -}; - -static enum drm_connector_status -adv7511_connector_detect(struct drm_connector *connector, bool force) -{ - struct adv7511 *adv = connector_to_adv7511(connector); - - return adv7511_detect(adv, connector); -} - -static const struct drm_connector_funcs adv7511_connector_funcs = { - .fill_modes = drm_helper_probe_single_connector_modes, - .detect = adv7511_connector_detect, - .destroy = drm_connector_cleanup, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - static int adv7511_connector_init(struct adv7511 *adv) { struct drm_bridge *bridge = &adv->bridge; - int ret; - - if (adv->i2c_main->irq) - adv->connector.polled = DRM_CONNECTOR_POLL_HPD; - else - adv->connector.polled = DRM_CONNECTOR_POLL_CONNECT | - DRM_CONNECTOR_POLL_DISCONNECT; + struct drm_connector *connector; - ret = drm_connector_init(bridge->dev, &adv->connector, - &adv7511_connector_funcs, - DRM_MODE_CONNECTOR_HDMIA); - if (ret < 0) { + connector = drm_bridge_connector_init(bridge->dev, bridge->encoder); + if (IS_ERR(connector)) { DRM_ERROR("Failed to initialize connector with drm\n"); - return ret; + return PTR_ERR(connector); } - drm_connector_helper_add(&adv->connector, - &adv7511_connector_helper_funcs); - drm_connector_attach_encoder(&adv->connector, bridge->encoder); + + drm_connector_attach_encoder(connector, bridge->encoder); return 0; } @@ -905,7 +766,7 @@ static int adv7511_connector_init(struct adv7511 *adv) * DRM Bridge Operations */ -static struct adv7511 *bridge_to_adv7511(struct drm_bridge *bridge) +static const struct adv7511 *bridge_to_adv7511_const(const struct drm_bridge *bridge) { return container_of(bridge, struct adv7511, bridge); } @@ -914,8 +775,29 @@ static void adv7511_bridge_atomic_enable(struct drm_bridge *bridge, struct drm_atomic_state *state) { struct adv7511 *adv = bridge_to_adv7511(bridge); + struct drm_connector *connector; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; adv7511_power_on(adv); + + connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); + if (WARN_ON(!connector)) + return; + + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (WARN_ON(!conn_state)) + return; + + crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); + if (WARN_ON(!crtc_state)) + return; + + adv7511_set_config_csc(adv, connector, adv->rgb); + + adv7511_mode_set(adv, &crtc_state->adjusted_mode); + + drm_atomic_helper_connector_hdmi_update_infoframes(connector, state); } static void adv7511_bridge_atomic_disable(struct drm_bridge *bridge, @@ -926,13 +808,17 @@ static void adv7511_bridge_atomic_disable(struct drm_bridge *bridge, adv7511_power_off(adv); } -static void adv7511_bridge_mode_set(struct drm_bridge *bridge, - const struct drm_display_mode *mode, - const struct drm_display_mode *adj_mode) +static enum drm_mode_status +adv7511_bridge_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge, + const struct drm_display_mode *mode, + unsigned long long tmds_rate) { - struct adv7511 *adv = bridge_to_adv7511(bridge); + const struct adv7511 *adv = bridge_to_adv7511_const(bridge); - adv7511_mode_set(adv, mode, adj_mode); + if (tmds_rate > 1000ULL * adv->info->max_mode_clock_khz) + return MODE_CLOCK_HIGH; + + return MODE_OK; } static enum drm_mode_status adv7511_bridge_mode_valid(struct drm_bridge *bridge, @@ -941,10 +827,10 @@ static enum drm_mode_status adv7511_bridge_mode_valid(struct drm_bridge *bridge, { struct adv7511 *adv = bridge_to_adv7511(bridge); - if (adv->info->has_dsi) - return adv7533_mode_valid(adv, mode); - else - return adv7511_mode_valid(adv, mode); + if (!adv->info->has_dsi) + return MODE_OK; + + return adv7533_mode_valid(adv, mode); } static int adv7511_bridge_attach(struct drm_bridge *bridge, @@ -978,7 +864,7 @@ static enum drm_connector_status adv7511_bridge_detect(struct drm_bridge *bridge { struct adv7511 *adv = bridge_to_adv7511(bridge); - return adv7511_detect(adv, NULL); + return adv7511_detect(adv); } static const struct drm_edid *adv7511_bridge_edid_read(struct drm_bridge *bridge, @@ -989,28 +875,71 @@ static const struct drm_edid *adv7511_bridge_edid_read(struct drm_bridge *bridge return adv7511_edid_read(adv, connector); } -static void adv7511_bridge_hpd_notify(struct drm_bridge *bridge, - enum drm_connector_status status) +static int adv7511_bridge_hdmi_clear_infoframe(struct drm_bridge *bridge, + enum hdmi_infoframe_type type) { - struct adv7511 *adv = bridge_to_adv7511(bridge); + struct adv7511 *adv7511 = bridge_to_adv7511(bridge); + + switch (type) { + case HDMI_INFOFRAME_TYPE_AVI: + adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME); + break; + default: + drm_dbg_driver(adv7511->bridge.dev, "Unsupported HDMI InfoFrame %x\n", type); + break; + } + + return 0; +} + +static int adv7511_bridge_hdmi_write_infoframe(struct drm_bridge *bridge, + enum hdmi_infoframe_type type, + const u8 *buffer, size_t len) +{ + struct adv7511 *adv7511 = bridge_to_adv7511(bridge); + + adv7511_bridge_hdmi_clear_infoframe(bridge, type); + + switch (type) { + case HDMI_INFOFRAME_TYPE_AVI: + /* The AVI infoframe id is not configurable */ + regmap_bulk_write(adv7511->regmap, ADV7511_REG_AVI_INFOFRAME_VERSION, + buffer + 1, len - 1); - if (status == connector_status_disconnected) - cec_phys_addr_invalidate(adv->cec_adap); + adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME); + break; + default: + drm_dbg_driver(adv7511->bridge.dev, "Unsupported HDMI InfoFrame %x\n", type); + break; + } + + return 0; } static const struct drm_bridge_funcs adv7511_bridge_funcs = { - .mode_set = adv7511_bridge_mode_set, .mode_valid = adv7511_bridge_mode_valid, .attach = adv7511_bridge_attach, .detect = adv7511_bridge_detect, .edid_read = adv7511_bridge_edid_read, - .hpd_notify = adv7511_bridge_hpd_notify, .atomic_enable = adv7511_bridge_atomic_enable, .atomic_disable = adv7511_bridge_atomic_disable, .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, .atomic_reset = drm_atomic_helper_bridge_reset, + + .hdmi_tmds_char_rate_valid = adv7511_bridge_hdmi_tmds_char_rate_valid, + .hdmi_clear_infoframe = adv7511_bridge_hdmi_clear_infoframe, + .hdmi_write_infoframe = adv7511_bridge_hdmi_write_infoframe, + + .hdmi_audio_startup = adv7511_hdmi_audio_startup, + .hdmi_audio_prepare = adv7511_hdmi_audio_prepare, + .hdmi_audio_shutdown = adv7511_hdmi_audio_shutdown, + + .hdmi_cec_init = adv7511_cec_init, + .hdmi_cec_enable = adv7511_cec_enable, + .hdmi_cec_log_addr = adv7511_cec_log_addr, + .hdmi_cec_transmit = adv7511_cec_transmit, }; /* ----------------------------------------------------------------------------- @@ -1323,22 +1252,44 @@ static int adv7511_probe(struct i2c_client *i2c) if (adv7511->info->link_config) adv7511_set_link_config(adv7511, &link_config); - ret = adv7511_cec_init(dev, adv7511); - if (ret) - goto err_unregister_cec; + regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, + ADV7511_CEC_CTRL_POWER_DOWN); adv7511->bridge.funcs = &adv7511_bridge_funcs; - adv7511->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID; + adv7511->bridge.ops = DRM_BRIDGE_OP_DETECT | + DRM_BRIDGE_OP_EDID | + DRM_BRIDGE_OP_HDMI | + DRM_BRIDGE_OP_HDMI_AUDIO | + DRM_BRIDGE_OP_HDMI_CEC_ADAPTER; if (adv7511->i2c_main->irq) adv7511->bridge.ops |= DRM_BRIDGE_OP_HPD; + adv7511->bridge.vendor = "Analog"; + adv7511->bridge.product = adv7511->info->name; + +#ifdef CONFIG_DRM_I2C_ADV7511_AUDIO + adv7511->bridge.hdmi_audio_dev = dev; + adv7511->bridge.hdmi_audio_max_i2s_playback_channels = 2; + adv7511->bridge.hdmi_audio_i2s_formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S20_3LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE), + adv7511->bridge.hdmi_audio_spdif_playback = 1; + adv7511->bridge.hdmi_audio_dai_port = 2; +#endif + +#ifdef CONFIG_DRM_I2C_ADV7511_CEC + adv7511->bridge.hdmi_cec_dev = dev; + adv7511->bridge.hdmi_cec_adapter_name = dev_name(dev); + adv7511->bridge.hdmi_cec_available_las = ADV7511_MAX_ADDRS; +#endif + adv7511->bridge.of_node = dev->of_node; adv7511->bridge.type = DRM_MODE_CONNECTOR_HDMIA; drm_bridge_add(&adv7511->bridge); - adv7511_audio_init(dev, adv7511); - if (i2c->irq) { init_waitqueue_head(&adv7511->wq); @@ -1360,10 +1311,7 @@ static int adv7511_probe(struct i2c_client *i2c) return 0; err_unregister_audio: - adv7511_audio_exit(adv7511); drm_bridge_remove(&adv7511->bridge); -err_unregister_cec: - cec_unregister_adapter(adv7511->cec_adap); i2c_unregister_device(adv7511->i2c_cec); clk_disable_unprepare(adv7511->cec_clk); err_i2c_unregister_packet: @@ -1388,9 +1336,6 @@ static void adv7511_remove(struct i2c_client *i2c) drm_bridge_remove(&adv7511->bridge); - adv7511_audio_exit(adv7511); - - cec_unregister_adapter(adv7511->cec_adap); i2c_unregister_device(adv7511->i2c_cec); clk_disable_unprepare(adv7511->cec_clk); @@ -1400,6 +1345,8 @@ static void adv7511_remove(struct i2c_client *i2c) static const struct adv7511_chip_info adv7511_chip_info = { .type = ADV7511, + .name = "ADV7511", + .max_mode_clock_khz = 165000, .supply_names = adv7511_supply_names, .num_supplies = ARRAY_SIZE(adv7511_supply_names), .link_config = true, @@ -1407,6 +1354,7 @@ static const struct adv7511_chip_info adv7511_chip_info = { static const struct adv7511_chip_info adv7533_chip_info = { .type = ADV7533, + .name = "ADV7533", .max_mode_clock_khz = 80000, .max_lane_freq_khz = 800000, .supply_names = adv7533_supply_names, @@ -1417,6 +1365,7 @@ static const struct adv7511_chip_info adv7533_chip_info = { static const struct adv7511_chip_info adv7535_chip_info = { .type = ADV7535, + .name = "ADV7535", .max_mode_clock_khz = 148500, .max_lane_freq_khz = 891000, .supply_names = adv7533_supply_names, diff --git a/drivers/gpu/drm/bridge/adv7511/adv7533.c b/drivers/gpu/drm/bridge/adv7511/adv7533.c index 122ad91e8a329..b12d422343fc1 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7533.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7533.c @@ -106,10 +106,6 @@ enum drm_mode_status adv7533_mode_valid(struct adv7511 *adv, struct mipi_dsi_device *dsi = adv->dsi; u8 bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); - /* Check max clock for either 7533 or 7535 */ - if (mode->clock > adv->info->max_mode_clock_khz) - return MODE_CLOCK_HIGH; - /* Check max clock for each lane */ if (mode->clock * bpp > adv->info->max_lane_freq_khz * adv->num_dsi_lanes) return MODE_CLOCK_HIGH; -- GitLab From 74ca3ba0d00d1a52486347dbe8fb1c8ebb5dde7e Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:32 -0500 Subject: [PATCH 0161/1479] panel/panel-elida-kd35t133: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-1-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-elida-kd35t133.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-elida-kd35t133.c b/drivers/gpu/drm/panel/panel-elida-kd35t133.c index b904d54374449..1f177834d6298 100644 --- a/drivers/gpu/drm/panel/panel-elida-kd35t133.c +++ b/drivers/gpu/drm/panel/panel-elida-kd35t133.c @@ -206,9 +206,10 @@ static int kd35t133_probe(struct mipi_dsi_device *dsi) struct kd35t133 *ctx; int ret; - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(dev, struct kd35t133, panel, + &kd35t133_funcs, DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ctx->reset_gpio)) { @@ -248,9 +249,6 @@ static int kd35t133_probe(struct mipi_dsi_device *dsi) MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_CLOCK_NON_CONTINUOUS; - drm_panel_init(&ctx->panel, &dsi->dev, &kd35t133_funcs, - DRM_MODE_CONNECTOR_DSI); - ret = drm_panel_of_backlight(&ctx->panel); if (ret) return ret; -- GitLab From 39cfc68b6b24fef5da6c398b654df3686306dfd8 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:33 -0500 Subject: [PATCH 0162/1479] panel/feixin-k101-im2ba02: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-2-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c b/drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c index 986e3e192881b..6225501cb1749 100644 --- a/drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c +++ b/drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c @@ -443,9 +443,11 @@ static int k101_im2ba02_dsi_probe(struct mipi_dsi_device *dsi) unsigned int i; int ret; - ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(&dsi->dev, struct k101_im2ba02, panel, + &k101_im2ba02_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); mipi_dsi_set_drvdata(dsi, ctx); ctx->dsi = dsi; @@ -463,9 +465,6 @@ static int k101_im2ba02_dsi_probe(struct mipi_dsi_device *dsi) return dev_err_probe(&dsi->dev, PTR_ERR(ctx->reset), "Couldn't get our reset GPIO\n"); - drm_panel_init(&ctx->panel, &dsi->dev, &k101_im2ba02_funcs, - DRM_MODE_CONNECTOR_DSI); - ret = drm_panel_of_backlight(&ctx->panel); if (ret) return ret; -- GitLab From 1017366dd161bbd19dd94ba5c2988a323f3d9d2c Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:34 -0500 Subject: [PATCH 0163/1479] panel/fy07024di26a30d: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-3-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c b/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c index 48e3acaecdf33..4f8d6d8c07e4d 100644 --- a/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c +++ b/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c @@ -189,16 +189,14 @@ static int feiyang_dsi_probe(struct mipi_dsi_device *dsi) struct feiyang *ctx; int ret; - ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(&dsi->dev, struct feiyang, panel, + &feiyang_funcs, DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); mipi_dsi_set_drvdata(dsi, ctx); ctx->dsi = dsi; - drm_panel_init(&ctx->panel, &dsi->dev, &feiyang_funcs, - DRM_MODE_CONNECTOR_DSI); - ctx->dvdd = devm_regulator_get(&dsi->dev, "dvdd"); if (IS_ERR(ctx->dvdd)) return dev_err_probe(&dsi->dev, PTR_ERR(ctx->dvdd), -- GitLab From 7b8c32961bcfec26b6542733dca4b39963a6d20a Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:35 -0500 Subject: [PATCH 0164/1479] panel/himax-hx83112a: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-4-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-himax-hx83112a.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-himax-hx83112a.c b/drivers/gpu/drm/panel/panel-himax-hx83112a.c index 47bce087e3393..142cb1cc067ad 100644 --- a/drivers/gpu/drm/panel/panel-himax-hx83112a.c +++ b/drivers/gpu/drm/panel/panel-himax-hx83112a.c @@ -269,9 +269,11 @@ static int hx83112a_probe(struct mipi_dsi_device *dsi) struct hx83112a_panel *ctx; int ret; - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(dev, struct hx83112a_panel, panel, + &hx83112a_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); ctx->supplies[0].supply = "vdd1"; ctx->supplies[1].supply = "vsn"; @@ -295,8 +297,6 @@ static int hx83112a_probe(struct mipi_dsi_device *dsi) MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_CLOCK_NON_CONTINUOUS; - drm_panel_init(&ctx->panel, dev, &hx83112a_panel_funcs, - DRM_MODE_CONNECTOR_DSI); ctx->panel.prepare_prev_first = true; ret = drm_panel_of_backlight(&ctx->panel); -- GitLab From c53c3e87aeb7fc288dcb9dbdb22451e8721771e1 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:36 -0500 Subject: [PATCH 0165/1479] panel/himax-hx8394: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-5-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-himax-hx8394.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-himax-hx8394.c b/drivers/gpu/drm/panel/panel-himax-hx8394.c index ff994bf0e3cc1..0e3bf4ba91890 100644 --- a/drivers/gpu/drm/panel/panel-himax-hx8394.c +++ b/drivers/gpu/drm/panel/panel-himax-hx8394.c @@ -611,9 +611,11 @@ static int hx8394_probe(struct mipi_dsi_device *dsi) struct hx8394 *ctx; int ret; - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(dev, struct hx8394, panel, + &hx8394_drm_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(ctx->reset_gpio)) @@ -645,9 +647,6 @@ static int hx8394_probe(struct mipi_dsi_device *dsi) return dev_err_probe(dev, PTR_ERR(ctx->iovcc), "Failed to request iovcc regulator\n"); - drm_panel_init(&ctx->panel, dev, &hx8394_drm_funcs, - DRM_MODE_CONNECTOR_DSI); - ret = drm_panel_of_backlight(&ctx->panel); if (ret) return ret; -- GitLab From 9609efa05d5ec63de5e758571f1bb85bdec93561 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:37 -0500 Subject: [PATCH 0166/1479] panel/ilitek-ili9322: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-6-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-ilitek-ili9322.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9322.c b/drivers/gpu/drm/panel/panel-ilitek-ili9322.c index 94b7dfef3b5e2..6ed544a83bdd5 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9322.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9322.c @@ -722,9 +722,10 @@ static int ili9322_probe(struct spi_device *spi) int ret; int i; - ili = devm_kzalloc(dev, sizeof(struct ili9322), GFP_KERNEL); - if (!ili) - return -ENOMEM; + ili = devm_drm_panel_alloc(dev, struct ili9322, panel, + &ili9322_drm_funcs, DRM_MODE_CONNECTOR_DPI); + if (IS_ERR(ili)) + return PTR_ERR(ili); spi_set_drvdata(spi, ili); @@ -883,9 +884,6 @@ static int ili9322_probe(struct spi_device *spi) ili->input = ili->conf->input; } - drm_panel_init(&ili->panel, dev, &ili9322_drm_funcs, - DRM_MODE_CONNECTOR_DPI); - drm_panel_add(&ili->panel); return 0; -- GitLab From 75db23f878e6513de8de3ee08184b09f5bf35a96 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:38 -0500 Subject: [PATCH 0167/1479] panel/ilitek-ili9341: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-7-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-ilitek-ili9341.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c index ff39f5dd4097e..bcd561e064654 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c @@ -490,9 +490,11 @@ static int ili9341_dpi_probe(struct spi_device *spi, struct gpio_desc *dc, struct ili9341 *ili; int ret; - ili = devm_kzalloc(dev, sizeof(struct ili9341), GFP_KERNEL); - if (!ili) - return -ENOMEM; + ili = devm_drm_panel_alloc(dev, struct ili9341, panel, + &ili9341_dpi_funcs, + DRM_MODE_CONNECTOR_DPI); + if (IS_ERR(ili)) + return PTR_ERR(ili); ili->dbi = devm_kzalloc(dev, sizeof(struct mipi_dbi), GFP_KERNEL); @@ -526,8 +528,6 @@ static int ili9341_dpi_probe(struct spi_device *spi, struct gpio_desc *dc, } ili->max_spi_speed = ili->conf->max_spi_speed; - drm_panel_init(&ili->panel, dev, &ili9341_dpi_funcs, - DRM_MODE_CONNECTOR_DPI); drm_panel_add(&ili->panel); return 0; -- GitLab From 8500594c9bd132d7e8b1de4b0878786ccdd08723 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:39 -0500 Subject: [PATCH 0168/1479] panel/panel-ili9805: Use refcounted allocation in place of devm_kzalloc() Start using the new helper that does the refcounted allocations Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-8-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-ilitek-ili9805.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9805.c b/drivers/gpu/drm/panel/panel-ilitek-ili9805.c index 1cbc25758bd2b..e6c483851f1f3 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9805.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9805.c @@ -307,9 +307,12 @@ static int ili9805_dsi_probe(struct mipi_dsi_device *dsi) struct ili9805 *ctx; int ret; - ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(&dsi->dev, struct ili9805, panel, + &ili9805_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + mipi_dsi_set_drvdata(dsi, ctx); ctx->dsi = dsi; ctx->desc = of_device_get_match_data(&dsi->dev); @@ -320,9 +323,6 @@ static int ili9805_dsi_probe(struct mipi_dsi_device *dsi) MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_NO_EOT_PACKET; dsi->lanes = 2; - drm_panel_init(&ctx->panel, &dsi->dev, &ili9805_funcs, - DRM_MODE_CONNECTOR_DSI); - ctx->dvdd = devm_regulator_get(&dsi->dev, "dvdd"); if (IS_ERR(ctx->dvdd)) return PTR_ERR(ctx->dvdd); -- GitLab From c15e4acd15e49312ab901b4bde2c789a39e64933 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:40 -0500 Subject: [PATCH 0169/1479] panel/ilitek-ili9806e: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Michael Walle Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-9-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-ilitek-ili9806e.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c b/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c index a3c79ad99d0bd..18aa6222b0c55 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9806e.c @@ -166,9 +166,10 @@ static int ili9806e_dsi_probe(struct mipi_dsi_device *dsi) struct ili9806e_panel *ctx; int i, ret; - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(dev, struct ili9806e_panel, panel, &ili9806e_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); ctx->desc = device_get_match_data(dev); @@ -192,9 +193,6 @@ static int ili9806e_dsi_probe(struct mipi_dsi_device *dsi) dsi->format = ctx->desc->format; dsi->lanes = ctx->desc->lanes; - drm_panel_init(&ctx->panel, dev, &ili9806e_funcs, - DRM_MODE_CONNECTOR_DSI); - ret = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation); if (ret) return dev_err_probe(dev, ret, "Failed to get orientation\n"); -- GitLab From 0678c17add9b42b1e8878499eb9f2b2ca4b0e6fc Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:41 -0500 Subject: [PATCH 0170/1479] panel/ilitek-ili9881c: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-10-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-ilitek-ili9881c.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c index 28cd7560e5db1..aa4192def0935 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c @@ -1506,16 +1506,15 @@ static int ili9881c_dsi_probe(struct mipi_dsi_device *dsi) struct ili9881c *ctx; int ret; - ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(&dsi->dev, struct ili9881c, panel, &ili9881c_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + mipi_dsi_set_drvdata(dsi, ctx); ctx->dsi = dsi; ctx->desc = of_device_get_match_data(&dsi->dev); - drm_panel_init(&ctx->panel, &dsi->dev, &ili9881c_funcs, - DRM_MODE_CONNECTOR_DSI); - ctx->power = devm_regulator_get(&dsi->dev, "power"); if (IS_ERR(ctx->power)) return dev_err_probe(&dsi->dev, PTR_ERR(ctx->power), -- GitLab From 93b6d2ea6f8ae6c8e779d5c5bfa3462f4c174e76 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:42 -0500 Subject: [PATCH 0171/1479] panel/innolux-ej030na: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-11-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-innolux-ej030na.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-innolux-ej030na.c b/drivers/gpu/drm/panel/panel-innolux-ej030na.c index f85b7a4cbb420..b2309900873b2 100644 --- a/drivers/gpu/drm/panel/panel-innolux-ej030na.c +++ b/drivers/gpu/drm/panel/panel-innolux-ej030na.c @@ -204,9 +204,11 @@ static int ej030na_probe(struct spi_device *spi) struct ej030na *priv; int err; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + priv = devm_drm_panel_alloc(dev, struct ej030na, panel, + &ej030na_funcs, + DRM_MODE_CONNECTOR_DPI); + if (IS_ERR(priv)) + return PTR_ERR(priv); priv->spi = spi; spi_set_drvdata(spi, priv); @@ -231,9 +233,6 @@ static int ej030na_probe(struct spi_device *spi) return dev_err_probe(dev, PTR_ERR(priv->reset_gpio), "Failed to get reset GPIO\n"); - drm_panel_init(&priv->panel, dev, &ej030na_funcs, - DRM_MODE_CONNECTOR_DPI); - err = drm_panel_of_backlight(&priv->panel); if (err) return err; -- GitLab From 8015bc283e9025151f5a724f7253c49c1ca939b0 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:43 -0500 Subject: [PATCH 0172/1479] panel/innolux-p079zca: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-12-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-innolux-p079zca.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c index d95c0d4f3e353..80afeeab9475f 100644 --- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c +++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c @@ -382,9 +382,11 @@ static int innolux_panel_add(struct mipi_dsi_device *dsi, struct device *dev = &dsi->dev; int err, i; - innolux = devm_kzalloc(dev, sizeof(*innolux), GFP_KERNEL); - if (!innolux) - return -ENOMEM; + innolux = devm_drm_panel_alloc(dev, struct innolux_panel, base, + &innolux_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(innolux)) + return PTR_ERR(innolux); innolux->desc = desc; @@ -410,9 +412,6 @@ static int innolux_panel_add(struct mipi_dsi_device *dsi, innolux->enable_gpio = NULL; } - drm_panel_init(&innolux->base, dev, &innolux_panel_funcs, - DRM_MODE_CONNECTOR_DSI); - err = drm_panel_of_backlight(&innolux->base); if (err) return err; -- GitLab From 9d20a28650ed8885704e195510435b54cbf07be0 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:44 -0500 Subject: [PATCH 0173/1479] panel/jadard-jd9365da-h3: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-13-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c index eb0f8373258c3..5c2530598ddb9 100644 --- a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c +++ b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c @@ -1120,9 +1120,10 @@ static int jadard_dsi_probe(struct mipi_dsi_device *dsi) struct jadard *jadard; int ret; - jadard = devm_kzalloc(&dsi->dev, sizeof(*jadard), GFP_KERNEL); - if (!jadard) - return -ENOMEM; + jadard = devm_drm_panel_alloc(dev, struct jadard, panel, &jadard_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(jadard)) + return PTR_ERR(jadard); desc = of_device_get_match_data(dev); dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | @@ -1148,9 +1149,6 @@ static int jadard_dsi_probe(struct mipi_dsi_device *dsi) return PTR_ERR(jadard->vccio); } - drm_panel_init(&jadard->panel, dev, &jadard_funcs, - DRM_MODE_CONNECTOR_DSI); - ret = of_drm_get_panel_orientation(dev->of_node, &jadard->orientation); if (ret < 0) return dev_err_probe(dev, ret, "failed to get orientation\n"); -- GitLab From 608cd2887f78332e4346ae6b7bf1f883c306dfbf Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:45 -0500 Subject: [PATCH 0174/1479] panel/jdi-fhd-r63452: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-14-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c b/drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c index 4eb71e85e9e9f..cbe354b51bce3 100644 --- a/drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c +++ b/drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c @@ -175,9 +175,11 @@ static int jdi_fhd_r63452_probe(struct mipi_dsi_device *dsi) struct jdi_fhd_r63452 *ctx; int ret; - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(dev, struct jdi_fhd_r63452, panel, + &jdi_fhd_r63452_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(ctx->reset_gpio)) @@ -192,8 +194,6 @@ static int jdi_fhd_r63452_probe(struct mipi_dsi_device *dsi) dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_CLOCK_NON_CONTINUOUS; - drm_panel_init(&ctx->panel, dev, &jdi_fhd_r63452_panel_funcs, - DRM_MODE_CONNECTOR_DSI); ctx->panel.prepare_prev_first = true; ret = drm_panel_of_backlight(&ctx->panel); -- GitLab From da93b863bd9bcf4e83cc59ac811fc0d74cb25104 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:46 -0500 Subject: [PATCH 0175/1479] panel/ltk050h3146w: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-15-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c index 77f74e6c467e5..0856df5a6ee22 100644 --- a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c +++ b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c @@ -548,9 +548,11 @@ static int ltk050h3146w_probe(struct mipi_dsi_device *dsi) struct ltk050h3146w *ctx; int ret; - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(dev, struct ltk050h3146w, panel, + <k050h3146w_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); ctx->panel_desc = of_device_get_match_data(dev); if (!ctx->panel_desc) @@ -577,9 +579,6 @@ static int ltk050h3146w_probe(struct mipi_dsi_device *dsi) dsi->format = MIPI_DSI_FMT_RGB888; dsi->mode_flags = ctx->panel_desc->mode_flags; - drm_panel_init(&ctx->panel, &dsi->dev, <k050h3146w_funcs, - DRM_MODE_CONNECTOR_DSI); - ret = drm_panel_of_backlight(&ctx->panel); if (ret) return ret; -- GitLab From deafcd1f936d2f2f9beebb19215850653a5526f1 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:47 -0500 Subject: [PATCH 0176/1479] panel/ltk500hd1829: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-16-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c b/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c index 6b18cf00fd4a7..7f19fd5b80600 100644 --- a/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c +++ b/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c @@ -604,9 +604,11 @@ static int ltk500hd1829_probe(struct mipi_dsi_device *dsi) struct device *dev = &dsi->dev; int ret; - ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(dev, struct ltk500hd1829, panel, + <k500hd1829_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); ctx->panel_desc = of_device_get_match_data(dev); if (!ctx->panel_desc) @@ -643,9 +645,6 @@ static int ltk500hd1829_probe(struct mipi_dsi_device *dsi) dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET; - drm_panel_init(&ctx->panel, &dsi->dev, <k500hd1829_funcs, - DRM_MODE_CONNECTOR_DSI); - ret = drm_panel_of_backlight(&ctx->panel); if (ret) return ret; -- GitLab From 89da5d30fa0cc6f4612f9c3e30b61610b6299f64 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:48 -0500 Subject: [PATCH 0177/1479] panel/lg-lg4573: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-17-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-lg-lg4573.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-lg-lg4573.c b/drivers/gpu/drm/panel/panel-lg-lg4573.c index cf246d15b7b62..dec619902c15f 100644 --- a/drivers/gpu/drm/panel/panel-lg-lg4573.c +++ b/drivers/gpu/drm/panel/panel-lg-lg4573.c @@ -243,9 +243,11 @@ static int lg4573_probe(struct spi_device *spi) struct lg4573 *ctx; int ret; - ctx = devm_kzalloc(&spi->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(&spi->dev, struct lg4573, panel, + &lg4573_drm_funcs, + DRM_MODE_CONNECTOR_DPI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); ctx->spi = spi; @@ -258,9 +260,6 @@ static int lg4573_probe(struct spi_device *spi) return ret; } - drm_panel_init(&ctx->panel, &spi->dev, &lg4573_drm_funcs, - DRM_MODE_CONNECTOR_DPI); - drm_panel_add(&ctx->panel); return 0; -- GitLab From b28994ed389017b857248575794e8c340473b79a Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:49 -0500 Subject: [PATCH 0178/1479] panel/lincolntech-lcd197: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-18-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-lincolntech-lcd197.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-lincolntech-lcd197.c b/drivers/gpu/drm/panel/panel-lincolntech-lcd197.c index 032c542aab0f7..24b34443ace02 100644 --- a/drivers/gpu/drm/panel/panel-lincolntech-lcd197.c +++ b/drivers/gpu/drm/panel/panel-lincolntech-lcd197.c @@ -190,9 +190,11 @@ static int lincoln_lcd197_panel_probe(struct mipi_dsi_device *dsi) dsi->mode_flags = (MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST); - lcd = devm_kzalloc(&dsi->dev, sizeof(*lcd), GFP_KERNEL); - if (!lcd) - return -ENOMEM; + lcd = devm_drm_panel_alloc(dev, struct lincoln_lcd197_panel, panel, + &lincoln_lcd197_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(lcd)) + return PTR_ERR(lcd); mipi_dsi_set_drvdata(dsi, lcd); lcd->dsi = dsi; @@ -214,9 +216,6 @@ static int lincoln_lcd197_panel_probe(struct mipi_dsi_device *dsi) return dev_err_probe(dev, PTR_ERR(lcd->reset_gpio), "failed to get reset gpio"); - drm_panel_init(&lcd->panel, dev, - &lincoln_lcd197_panel_funcs, DRM_MODE_CONNECTOR_DSI); - err = drm_panel_of_backlight(&lcd->panel); if (err) return err; -- GitLab From 2a2c7d7d363e0a4afa2042378f5797366d49746c Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:50 -0500 Subject: [PATCH 0179/1479] panel/magnachip-d53e6ea8966: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-19-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-magnachip-d53e6ea8966.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-magnachip-d53e6ea8966.c b/drivers/gpu/drm/panel/panel-magnachip-d53e6ea8966.c index 799c2161fc85b..cde168ec631c4 100644 --- a/drivers/gpu/drm/panel/panel-magnachip-d53e6ea8966.c +++ b/drivers/gpu/drm/panel/panel-magnachip-d53e6ea8966.c @@ -370,9 +370,11 @@ static int d53e6ea8966_probe(struct spi_device *spi) .node = NULL, }; - db = devm_kzalloc(dev, sizeof(*db), GFP_KERNEL); - if (!db) - return -ENOMEM; + db = devm_drm_panel_alloc(dev, struct d53e6ea8966, panel, + &d53e6ea8966_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(db)) + return PTR_ERR(db); spi_set_drvdata(spi, db); @@ -425,9 +427,6 @@ static int d53e6ea8966_probe(struct spi_device *spi) db->dsi_dev->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET; - drm_panel_init(&db->panel, dev, &d53e6ea8966_panel_funcs, - DRM_MODE_CONNECTOR_DSI); - if (db->panel_info->backlight_register) { ret = db->panel_info->backlight_register(db); if (ret < 0) -- GitLab From 47b74d7c5e48415cb8d2903077f93760d5d350c3 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:51 -0500 Subject: [PATCH 0180/1479] panel/mantix-mlaf057we51: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-20-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c b/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c index 4db852ffb0f61..55664f5d5aa5d 100644 --- a/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c +++ b/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c @@ -234,9 +234,11 @@ static int mantix_probe(struct mipi_dsi_device *dsi) struct mantix *ctx; int ret; - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(dev, struct mantix, panel, &mantix_drm_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + ctx->default_mode = of_device_get_match_data(dev); ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); @@ -271,9 +273,6 @@ static int mantix_probe(struct mipi_dsi_device *dsi) if (IS_ERR(ctx->vddi)) return dev_err_probe(dev, PTR_ERR(ctx->vddi), "Failed to request vddi regulator\n"); - drm_panel_init(&ctx->panel, dev, &mantix_drm_funcs, - DRM_MODE_CONNECTOR_DSI); - ret = drm_panel_of_backlight(&ctx->panel); if (ret) return ret; -- GitLab From 417f0eb92c53fab6a9fdb4f09f9db6505bb7a735 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:52 -0500 Subject: [PATCH 0181/1479] panel/newvision-nv3051d: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-21-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-newvision-nv3051d.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-newvision-nv3051d.c b/drivers/gpu/drm/panel/panel-newvision-nv3051d.c index b6429795e8f51..22560384e48e3 100644 --- a/drivers/gpu/drm/panel/panel-newvision-nv3051d.c +++ b/drivers/gpu/drm/panel/panel-newvision-nv3051d.c @@ -361,9 +361,11 @@ static int panel_nv3051d_probe(struct mipi_dsi_device *dsi) struct panel_nv3051d *ctx; int ret; - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(dev, struct panel_nv3051d, panel, + &panel_nv3051d_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); ctx->dev = dev; @@ -391,9 +393,6 @@ static int panel_nv3051d_probe(struct mipi_dsi_device *dsi) dsi->format = MIPI_DSI_FMT_RGB888; dsi->mode_flags = ctx->panel_info->mode_flags; - drm_panel_init(&ctx->panel, &dsi->dev, &panel_nv3051d_funcs, - DRM_MODE_CONNECTOR_DSI); - ret = drm_panel_of_backlight(&ctx->panel); if (ret) return ret; -- GitLab From 5d5da5cef9bdabe455804eb000147ace298cde90 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:53 -0500 Subject: [PATCH 0182/1479] panel/newvision-nv3052c: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-22-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-newvision-nv3052c.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-newvision-nv3052c.c b/drivers/gpu/drm/panel/panel-newvision-nv3052c.c index 06e16a7c14a75..0db9cadd868e5 100644 --- a/drivers/gpu/drm/panel/panel-newvision-nv3052c.c +++ b/drivers/gpu/drm/panel/panel-newvision-nv3052c.c @@ -777,9 +777,10 @@ static int nv3052c_probe(struct spi_device *spi) struct nv3052c *priv; int err; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + priv = devm_drm_panel_alloc(dev, struct nv3052c, panel, &nv3052c_funcs, + DRM_MODE_CONNECTOR_DPI); + if (IS_ERR(priv)) + return PTR_ERR(priv); priv->dev = dev; @@ -803,9 +804,6 @@ static int nv3052c_probe(struct spi_device *spi) spi_set_drvdata(spi, priv); - drm_panel_init(&priv->panel, dev, &nv3052c_funcs, - DRM_MODE_CONNECTOR_DPI); - err = drm_panel_of_backlight(&priv->panel); if (err) return dev_err_probe(dev, err, "Failed to attach backlight\n"); -- GitLab From 3f08c356b881d3d6302de207a98ceec1c511159e Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:54 -0500 Subject: [PATCH 0183/1479] panel/novatek-nt35510: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-23-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-novatek-nt35510.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35510.c b/drivers/gpu/drm/panel/panel-novatek-nt35510.c index 549b86f2cc288..3189d89c7ca00 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt35510.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt35510.c @@ -1087,9 +1087,12 @@ static int nt35510_probe(struct mipi_dsi_device *dsi) struct nt35510 *nt; int ret; - nt = devm_kzalloc(dev, sizeof(struct nt35510), GFP_KERNEL); - if (!nt) - return -ENOMEM; + nt = devm_drm_panel_alloc(dev, struct nt35510, panel, + &nt35510_drm_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(nt)) + return PTR_ERR(nt); + mipi_dsi_set_drvdata(dsi, nt); nt->dev = dev; @@ -1142,9 +1145,6 @@ static int nt35510_probe(struct mipi_dsi_device *dsi) return PTR_ERR(nt->reset_gpio); } - drm_panel_init(&nt->panel, dev, &nt35510_drm_funcs, - DRM_MODE_CONNECTOR_DSI); - /* * First, try to locate an external backlight (such as on GPIO) * if this fails, assume we will want to use the internal backlight -- GitLab From 81cb8735420d9376b565e842fc3a7f65f68e0c23 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:55 -0500 Subject: [PATCH 0184/1479] panel/novatek-nt35560: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-24-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-novatek-nt35560.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35560.c b/drivers/gpu/drm/panel/panel-novatek-nt35560.c index 5bbea734123bc..98f0782c84111 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt35560.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt35560.c @@ -456,9 +456,12 @@ static int nt35560_probe(struct mipi_dsi_device *dsi) struct nt35560 *nt; int ret; - nt = devm_kzalloc(dev, sizeof(struct nt35560), GFP_KERNEL); - if (!nt) - return -ENOMEM; + nt = devm_drm_panel_alloc(dev, struct nt35560, panel, + &nt35560_drm_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(nt)) + return PTR_ERR(nt); + nt->video_mode = of_property_read_bool(dev->of_node, "enforce-video-mode"); @@ -502,9 +505,6 @@ static int nt35560_probe(struct mipi_dsi_device *dsi) return dev_err_probe(dev, PTR_ERR(nt->reset_gpio), "failed to request GPIO\n"); - drm_panel_init(&nt->panel, dev, &nt35560_drm_funcs, - DRM_MODE_CONNECTOR_DSI); - nt->panel.backlight = devm_backlight_device_register(dev, "nt35560", dev, nt, &nt35560_bl_ops, &nt35560_bl_props); if (IS_ERR(nt->panel.backlight)) -- GitLab From e59e1f45246efbd0b0da65753a64ecdaf421776c Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:56 -0500 Subject: [PATCH 0185/1479] panel/novatek-nt35950: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-25-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-novatek-nt35950.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35950.c b/drivers/gpu/drm/panel/panel-novatek-nt35950.c index 08b22b592ab04..94aa6489d99fc 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt35950.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt35950.c @@ -449,9 +449,10 @@ static int nt35950_probe(struct mipi_dsi_device *dsi) const struct mipi_dsi_device_info *info; int i, num_dsis = 1, ret; - nt = devm_kzalloc(dev, sizeof(*nt), GFP_KERNEL); - if (!nt) - return -ENOMEM; + nt = devm_drm_panel_alloc(dev, struct nt35950, panel, &nt35950_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(nt)) + return PTR_ERR(nt); ret = nt35950_sharp_init_vregs(nt, dev); if (ret) @@ -491,9 +492,6 @@ static int nt35950_probe(struct mipi_dsi_device *dsi) nt->dsi[0] = dsi; mipi_dsi_set_drvdata(dsi, nt); - drm_panel_init(&nt->panel, dev, &nt35950_panel_funcs, - DRM_MODE_CONNECTOR_DSI); - ret = drm_panel_of_backlight(&nt->panel); if (ret) { if (num_dsis == 2) -- GitLab From 10868521bdd5e7ff3c41d6adfa116c7c264a08bc Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:57 -0500 Subject: [PATCH 0186/1479] panel/novatek-nt36523: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-26-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-novatek-nt36523.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36523.c b/drivers/gpu/drm/panel/panel-novatek-nt36523.c index 116d67bfa1140..32cf64c7c18be 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt36523.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt36523.c @@ -1171,9 +1171,11 @@ static int nt36523_probe(struct mipi_dsi_device *dsi) const struct mipi_dsi_device_info *info; int i, ret; - pinfo = devm_kzalloc(dev, sizeof(*pinfo), GFP_KERNEL); - if (!pinfo) - return -ENOMEM; + pinfo = devm_drm_panel_alloc(dev, struct panel_info, panel, + &nt36523_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(pinfo)) + return PTR_ERR(pinfo); pinfo->vddio = devm_regulator_get(dev, "vddio"); if (IS_ERR(pinfo->vddio)) @@ -1211,7 +1213,6 @@ static int nt36523_probe(struct mipi_dsi_device *dsi) pinfo->dsi[0] = dsi; mipi_dsi_set_drvdata(dsi, pinfo); - drm_panel_init(&pinfo->panel, dev, &nt36523_panel_funcs, DRM_MODE_CONNECTOR_DSI); ret = of_drm_get_panel_orientation(dev->of_node, &pinfo->orientation); if (ret < 0) { -- GitLab From e41a4813af67b294b9f7573fa9b363845e724399 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:58 -0500 Subject: [PATCH 0187/1479] panel/novatek-nt36672e: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-27-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-novatek-nt36672e.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672e.c b/drivers/gpu/drm/panel/panel-novatek-nt36672e.c index 8c9e04207ba96..c5e00eb55722e 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt36672e.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt36672e.c @@ -522,9 +522,11 @@ static int nt36672e_panel_probe(struct mipi_dsi_device *dsi) struct nt36672e_panel *ctx; int i, ret = 0; - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_panel_alloc(dev, struct nt36672e_panel, panel, + &nt36672e_drm_funcs, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); ctx->desc = of_device_get_match_data(dev); if (!ctx->desc) { @@ -553,8 +555,6 @@ static int nt36672e_panel_probe(struct mipi_dsi_device *dsi) dsi->format = ctx->desc->format; dsi->mode_flags = ctx->desc->mode_flags; - drm_panel_init(&ctx->panel, dev, &nt36672e_drm_funcs, DRM_MODE_CONNECTOR_DSI); - ret = drm_panel_of_backlight(&ctx->panel); if (ret) return dev_err_probe(dev, ret, "Failed to get backlight\n"); -- GitLab From 6e8fba44daa7ec63942d95ad730e0d32455ecede Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:03:59 -0500 Subject: [PATCH 0188/1479] panel/novatek-nt39016: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-28-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-novatek-nt39016.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt39016.c b/drivers/gpu/drm/panel/panel-novatek-nt39016.c index 9fa7654e2b675..a629976bae540 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt39016.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt39016.c @@ -246,9 +246,10 @@ static int nt39016_probe(struct spi_device *spi) struct nt39016 *panel; int err; - panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); - if (!panel) - return -ENOMEM; + panel = devm_drm_panel_alloc(dev, struct nt39016, drm_panel, &nt39016_funcs, + DRM_MODE_CONNECTOR_DPI); + if (IS_ERR(panel)) + return PTR_ERR(panel); spi_set_drvdata(spi, panel); @@ -279,9 +280,6 @@ static int nt39016_probe(struct spi_device *spi) return PTR_ERR(panel->map); } - drm_panel_init(&panel->drm_panel, dev, &nt39016_funcs, - DRM_MODE_CONNECTOR_DPI); - err = drm_panel_of_backlight(&panel->drm_panel); if (err) return dev_err_probe(dev, err, "Failed to get backlight handle\n"); -- GitLab From d2b67baa892a6c412f539eea883092e7c580ccea Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:04:00 -0500 Subject: [PATCH 0189/1479] panel/lcd-olinuxino: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-29-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c index 94ae8c8270b8f..66f99982f360f 100644 --- a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c +++ b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c @@ -175,9 +175,11 @@ static int lcd_olinuxino_probe(struct i2c_client *client) I2C_FUNC_SMBUS_READ_I2C_BLOCK)) return -ENODEV; - lcd = devm_kzalloc(dev, sizeof(*lcd), GFP_KERNEL); - if (!lcd) - return -ENOMEM; + lcd = devm_drm_panel_alloc(dev, struct lcd_olinuxino, panel, + &lcd_olinuxino_funcs, + DRM_MODE_CONNECTOR_DPI); + if (IS_ERR(lcd)) + return PTR_ERR(lcd); i2c_set_clientdata(client, lcd); lcd->dev = dev; @@ -234,9 +236,6 @@ static int lcd_olinuxino_probe(struct i2c_client *client) if (IS_ERR(lcd->enable_gpio)) return PTR_ERR(lcd->enable_gpio); - drm_panel_init(&lcd->panel, dev, &lcd_olinuxino_funcs, - DRM_MODE_CONNECTOR_DPI); - ret = drm_panel_of_backlight(&lcd->panel); if (ret) return ret; -- GitLab From bdfc5b2927062479d3b918d2990a08f3091ef5fa Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Tue, 20 May 2025 22:04:01 -0500 Subject: [PATCH 0190/1479] panel/orisetech-ota5601a: Use refcounted allocation in place of devm_kzalloc() Move to using the new API devm_drm_panel_alloc() to allocate the panel. Reviewed-by: Neil Armstrong Signed-off-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250520-drivers-mass-convert-part2-v3-30-f7ae7b723c68@redhat.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/panel/panel-orisetech-ota5601a.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-orisetech-ota5601a.c b/drivers/gpu/drm/panel/panel-orisetech-ota5601a.c index fc87f61d4400d..3231e84dc66c2 100644 --- a/drivers/gpu/drm/panel/panel-orisetech-ota5601a.c +++ b/drivers/gpu/drm/panel/panel-orisetech-ota5601a.c @@ -237,9 +237,11 @@ static int ota5601a_probe(struct spi_device *spi) struct ota5601a *panel; int err; - panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); - if (!panel) - return -ENOMEM; + panel = devm_drm_panel_alloc(dev, struct ota5601a, drm_panel, + &ota5601a_funcs, + DRM_MODE_CONNECTOR_DPI); + if (IS_ERR(panel)) + return PTR_ERR(panel); spi_set_drvdata(spi, panel); @@ -273,9 +275,6 @@ static int ota5601a_probe(struct spi_device *spi) return PTR_ERR(panel->map); } - drm_panel_init(&panel->drm_panel, dev, &ota5601a_funcs, - DRM_MODE_CONNECTOR_DPI); - err = drm_panel_of_backlight(&panel->drm_panel); if (err) { if (err != -EPROBE_DEFER) -- GitLab From 7a909b2beafbdb0139cb953ce6be4813b6433d1f Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:29 +0200 Subject: [PATCH 0191/1479] drm/bridge: anx7625: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Acked-by: Maxime Ripard Reviewed-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-3-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/bridge/analogix/anx7625.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 8a9079c2ed5c2..0ac4a82c5a6e5 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -2596,7 +2596,6 @@ static int anx7625_link_bridge(struct drm_dp_aux *aux) return ret; } - platform->bridge.funcs = &anx7625_bridge_funcs; platform->bridge.of_node = dev->of_node; if (!anx7625_of_panel_on_aux_bus(dev)) platform->bridge.ops |= DRM_BRIDGE_OP_EDID; @@ -2630,10 +2629,10 @@ static int anx7625_i2c_probe(struct i2c_client *client) return -ENODEV; } - platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); - if (!platform) { + platform = devm_drm_bridge_alloc(dev, struct anx7625_data, bridge, &anx7625_bridge_funcs); + if (IS_ERR(platform)) { DRM_DEV_ERROR(dev, "fail to allocate driver data\n"); - return -ENOMEM; + return PTR_ERR(platform); } pdata = &platform->pdata; -- GitLab From 2b42027f449c9a15e0667d99f76cdb4d775dd201 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:30 +0200 Subject: [PATCH 0192/1479] drm/bridge: cdns-dsi: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Acked-by: Maxime Ripard Reviewed-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-4-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c index b022dd6e6b6e9..7604574da6660 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c @@ -1289,9 +1289,10 @@ static int cdns_dsi_drm_probe(struct platform_device *pdev) int ret, irq; u32 val; - dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL); - if (!dsi) - return -ENOMEM; + dsi = devm_drm_bridge_alloc(&pdev->dev, struct cdns_dsi, input.bridge, + &cdns_dsi_bridge_funcs); + if (IS_ERR(dsi)) + return PTR_ERR(dsi); platform_set_drvdata(pdev, dsi); @@ -1349,7 +1350,6 @@ static int cdns_dsi_drm_probe(struct platform_device *pdev) * CDNS_DPI_INPUT. */ input->id = CDNS_DPI_INPUT; - input->bridge.funcs = &cdns_dsi_bridge_funcs; input->bridge.of_node = pdev->dev.of_node; /* Mask all interrupts before registering the IRQ handler. */ -- GitLab From 0d2577d8f01435b508dd315b6cf7696a8fe0482e Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:31 +0200 Subject: [PATCH 0193/1479] drm/bridge: megachips-stdpxxxx-ge-b850v3-fw: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Acked-by: Maxime Ripard Reviewed-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-5-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- .../gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c index 15a5a1f644fc1..81dde9ed7bcf7 100644 --- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c @@ -225,13 +225,11 @@ static int ge_b850v3_lvds_init(struct device *dev) if (ge_b850v3_lvds_ptr) goto success; - ge_b850v3_lvds_ptr = devm_kzalloc(dev, - sizeof(*ge_b850v3_lvds_ptr), - GFP_KERNEL); - - if (!ge_b850v3_lvds_ptr) { + ge_b850v3_lvds_ptr = devm_drm_bridge_alloc(dev, struct ge_b850v3_lvds, bridge, + &ge_b850v3_lvds_funcs); + if (IS_ERR(ge_b850v3_lvds_ptr)) { mutex_unlock(&ge_b850v3_lvds_dev_mutex); - return -ENOMEM; + return PTR_ERR(ge_b850v3_lvds_ptr); } success: @@ -264,7 +262,6 @@ static int ge_b850v3_register(void) struct device *dev = &stdp4028_i2c->dev; /* drm bridge initialization */ - ge_b850v3_lvds_ptr->bridge.funcs = &ge_b850v3_lvds_funcs; ge_b850v3_lvds_ptr->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID; ge_b850v3_lvds_ptr->bridge.type = DRM_MODE_CONNECTOR_DisplayPort; -- GitLab From 3cb4fec95ef6904d28c72e67ff3f5c748d86abb5 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:32 +0200 Subject: [PATCH 0194/1479] drm/bridge: nxp-ptn3460: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Acked-by: Maxime Ripard Reviewed-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-6-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/bridge/nxp-ptn3460.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c index 25d7c415478b1..7acb11f16dc19 100644 --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c @@ -261,10 +261,10 @@ static int ptn3460_probe(struct i2c_client *client) struct drm_bridge *panel_bridge; int ret; - ptn_bridge = devm_kzalloc(dev, sizeof(*ptn_bridge), GFP_KERNEL); - if (!ptn_bridge) { - return -ENOMEM; - } + ptn_bridge = devm_drm_bridge_alloc(dev, struct ptn3460_bridge, bridge, + &ptn3460_bridge_funcs); + if (IS_ERR(ptn_bridge)) + return PTR_ERR(ptn_bridge); panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0); if (IS_ERR(panel_bridge)) @@ -300,7 +300,6 @@ static int ptn3460_probe(struct i2c_client *client) return ret; } - ptn_bridge->bridge.funcs = &ptn3460_bridge_funcs; ptn_bridge->bridge.ops = DRM_BRIDGE_OP_EDID; ptn_bridge->bridge.type = DRM_MODE_CONNECTOR_LVDS; ptn_bridge->bridge.of_node = dev->of_node; -- GitLab From 9cdc50b20509e55855ed53ab831ba73fd059ade9 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:33 +0200 Subject: [PATCH 0195/1479] drm/bridge: sii902x: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Acked-by: Maxime Ripard Reviewed-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-7-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/bridge/sii902x.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c index 6de61d9fe0648..882973e900628 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c @@ -1135,7 +1135,6 @@ static int sii902x_init(struct sii902x *sii902x) if (ret) goto err_unreg_audio; - sii902x->bridge.funcs = &sii902x_bridge_funcs; sii902x->bridge.of_node = dev->of_node; sii902x->bridge.timings = &default_sii902x_timings; sii902x->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID; @@ -1170,9 +1169,9 @@ static int sii902x_probe(struct i2c_client *client) return -EIO; } - sii902x = devm_kzalloc(dev, sizeof(*sii902x), GFP_KERNEL); - if (!sii902x) - return -ENOMEM; + sii902x = devm_drm_bridge_alloc(dev, struct sii902x, bridge, &sii902x_bridge_funcs); + if (IS_ERR(sii902x)) + return PTR_ERR(sii902x); sii902x->i2c = client; sii902x->regmap = devm_regmap_init_i2c(client, &sii902x_regmap_config); -- GitLab From ac5869aae6f3155bc9b8746f659a432af43c8942 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:34 +0200 Subject: [PATCH 0196/1479] drm/omap: dss: dpi: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Acked-by: Maxime Ripard Reviewed-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-8-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/omapdrm/dss/dpi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c index 6eff97a091602..9f86db774c395 100644 --- a/drivers/gpu/drm/omapdrm/dss/dpi.c +++ b/drivers/gpu/drm/omapdrm/dss/dpi.c @@ -562,7 +562,6 @@ static const struct drm_bridge_funcs dpi_bridge_funcs = { static void dpi_bridge_init(struct dpi_data *dpi) { - dpi->bridge.funcs = &dpi_bridge_funcs; dpi->bridge.of_node = dpi->pdev->dev.of_node; dpi->bridge.type = DRM_MODE_CONNECTOR_DPI; @@ -707,9 +706,9 @@ int dpi_init_port(struct dss_device *dss, struct platform_device *pdev, u32 datalines; int r; - dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL); - if (!dpi) - return -ENOMEM; + dpi = devm_drm_bridge_alloc(&pdev->dev, struct dpi_data, bridge, &dpi_bridge_funcs); + if (IS_ERR(dpi)) + return PTR_ERR(dpi); ep = of_graph_get_next_port_endpoint(port, NULL); if (!ep) -- GitLab From f35753992cda94d69e5e96224dc470516f2c45cd Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:35 +0200 Subject: [PATCH 0197/1479] drm/omap: dss: dsi: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Acked-by: Maxime Ripard Reviewed-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-9-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/omapdrm/dss/dsi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 91ee63bfe0bc7..b129e5a8d7915 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -4701,7 +4701,6 @@ static const struct drm_bridge_funcs dsi_bridge_funcs = { static void dsi_bridge_init(struct dsi_data *dsi) { - dsi->bridge.funcs = &dsi_bridge_funcs; dsi->bridge.of_node = dsi->host.dev->of_node; dsi->bridge.type = DRM_MODE_CONNECTOR_DSI; @@ -4894,9 +4893,9 @@ static int dsi_probe(struct platform_device *pdev) unsigned int i; int r; - dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); - if (!dsi) - return -ENOMEM; + dsi = devm_drm_bridge_alloc(dev, struct dsi_data, bridge, &dsi_bridge_funcs); + if (IS_ERR(dsi)) + return PTR_ERR(dsi); dsi->dev = dev; dev_set_drvdata(dev, dsi); -- GitLab From 0241b190acb8399b23efe7188aa43bbbeed2500e Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:36 +0200 Subject: [PATCH 0198/1479] drm/omap: dss: hdmi4: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Switching from a non-devm to a devm allocation allows removing the kfree() in the remove function and in the probe error management code, and as a consequence to simplify the code flow by removing now unnecessary gotos. Acked-by: Maxime Ripard Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-10-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index a3b22952fdc32..3cd612af24498 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -505,7 +505,6 @@ static const struct drm_bridge_funcs hdmi4_bridge_funcs = { static void hdmi4_bridge_init(struct omap_hdmi *hdmi) { - hdmi->bridge.funcs = &hdmi4_bridge_funcs; hdmi->bridge.of_node = hdmi->pdev->dev.of_node; hdmi->bridge.ops = DRM_BRIDGE_OP_EDID; hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA; @@ -761,9 +760,9 @@ static int hdmi4_probe(struct platform_device *pdev) int irq; int r; - hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL); - if (!hdmi) - return -ENOMEM; + hdmi = devm_drm_bridge_alloc(&pdev->dev, struct omap_hdmi, bridge, &hdmi4_bridge_funcs); + if (IS_ERR(hdmi)) + return PTR_ERR(hdmi); hdmi->pdev = pdev; @@ -774,25 +773,24 @@ static int hdmi4_probe(struct platform_device *pdev) r = hdmi4_probe_of(hdmi); if (r) - goto err_free; + return r; r = hdmi_wp_init(pdev, &hdmi->wp, 4); if (r) - goto err_free; + return r; r = hdmi_phy_init(pdev, &hdmi->phy, 4); if (r) - goto err_free; + return r; r = hdmi4_core_init(pdev, &hdmi->core); if (r) - goto err_free; + return r; irq = platform_get_irq(pdev, 0); if (irq < 0) { DSSERR("platform_get_irq failed\n"); - r = -ENODEV; - goto err_free; + return -ENODEV; } r = devm_request_threaded_irq(&pdev->dev, irq, @@ -800,7 +798,7 @@ static int hdmi4_probe(struct platform_device *pdev) IRQF_ONESHOT, "OMAP HDMI", hdmi); if (r) { DSSERR("HDMI IRQ request failed\n"); - goto err_free; + return r; } hdmi->vdda_reg = devm_regulator_get(&pdev->dev, "vdda"); @@ -808,7 +806,7 @@ static int hdmi4_probe(struct platform_device *pdev) r = PTR_ERR(hdmi->vdda_reg); if (r != -EPROBE_DEFER) DSSERR("can't get VDDA regulator\n"); - goto err_free; + return r; } pm_runtime_enable(&pdev->dev); @@ -827,8 +825,6 @@ static int hdmi4_probe(struct platform_device *pdev) hdmi4_uninit_output(hdmi); err_pm_disable: pm_runtime_disable(&pdev->dev); -err_free: - kfree(hdmi); return r; } @@ -841,8 +837,6 @@ static void hdmi4_remove(struct platform_device *pdev) hdmi4_uninit_output(hdmi); pm_runtime_disable(&pdev->dev); - - kfree(hdmi); } static const struct of_device_id hdmi_of_match[] = { -- GitLab From eb01c3cc550dfb9bdd021138e898fbf4a8ccd12f Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:37 +0200 Subject: [PATCH 0199/1479] drm/omap: dss: hdmi5: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Switching from a non-devm to a devm allocation allows removing the kfree() in the remove function and in the probe error management code, and as a consequence to simplify the code flow by removing now unnecessary gotos. Acked-by: Maxime Ripard Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-11-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/omapdrm/dss/hdmi5.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c index 0c98444d39a93..5636b3dfec1c9 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c @@ -480,7 +480,6 @@ static const struct drm_bridge_funcs hdmi5_bridge_funcs = { static void hdmi5_bridge_init(struct omap_hdmi *hdmi) { - hdmi->bridge.funcs = &hdmi5_bridge_funcs; hdmi->bridge.of_node = hdmi->pdev->dev.of_node; hdmi->bridge.ops = DRM_BRIDGE_OP_EDID; hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA; @@ -727,9 +726,9 @@ static int hdmi5_probe(struct platform_device *pdev) int irq; int r; - hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL); - if (!hdmi) - return -ENOMEM; + hdmi = devm_drm_bridge_alloc(&pdev->dev, struct omap_hdmi, bridge, &hdmi5_bridge_funcs); + if (IS_ERR(hdmi)) + return PTR_ERR(hdmi); hdmi->pdev = pdev; @@ -740,25 +739,24 @@ static int hdmi5_probe(struct platform_device *pdev) r = hdmi5_probe_of(hdmi); if (r) - goto err_free; + return r; r = hdmi_wp_init(pdev, &hdmi->wp, 5); if (r) - goto err_free; + return r; r = hdmi_phy_init(pdev, &hdmi->phy, 5); if (r) - goto err_free; + return r; r = hdmi5_core_init(pdev, &hdmi->core); if (r) - goto err_free; + return r; irq = platform_get_irq(pdev, 0); if (irq < 0) { DSSERR("platform_get_irq failed\n"); - r = -ENODEV; - goto err_free; + return -ENODEV; } r = devm_request_threaded_irq(&pdev->dev, irq, @@ -766,7 +764,7 @@ static int hdmi5_probe(struct platform_device *pdev) IRQF_ONESHOT, "OMAP HDMI", hdmi); if (r) { DSSERR("HDMI IRQ request failed\n"); - goto err_free; + return r; } hdmi->vdda_reg = devm_regulator_get(&pdev->dev, "vdda"); @@ -774,7 +772,7 @@ static int hdmi5_probe(struct platform_device *pdev) r = PTR_ERR(hdmi->vdda_reg); if (r != -EPROBE_DEFER) DSSERR("can't get VDDA regulator\n"); - goto err_free; + return r; } pm_runtime_enable(&pdev->dev); @@ -793,8 +791,6 @@ static int hdmi5_probe(struct platform_device *pdev) hdmi5_uninit_output(hdmi); err_pm_disable: pm_runtime_disable(&pdev->dev); -err_free: - kfree(hdmi); return r; } @@ -807,8 +803,6 @@ static void hdmi5_remove(struct platform_device *pdev) hdmi5_uninit_output(hdmi); pm_runtime_disable(&pdev->dev); - - kfree(hdmi); } static const struct of_device_id hdmi_of_match[] = { -- GitLab From af509dfc0b7390a59cdcb64b161bf6c9c7d6cb2a Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:38 +0200 Subject: [PATCH 0200/1479] drm/omap: dss: sdi: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Switching from a non-devm to a devm allocation allows removing the kfree() in the remove function and in the probe error management code, and as a consequence to simplify the code flow by removing now unnecessary gotos. Acked-by: Maxime Ripard Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-12-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/omapdrm/dss/sdi.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c index e78826e4b560a..df4cbc683e2ca 100644 --- a/drivers/gpu/drm/omapdrm/dss/sdi.c +++ b/drivers/gpu/drm/omapdrm/dss/sdi.c @@ -284,7 +284,6 @@ static const struct drm_bridge_funcs sdi_bridge_funcs = { static void sdi_bridge_init(struct sdi_device *sdi) { - sdi->bridge.funcs = &sdi_bridge_funcs; sdi->bridge.of_node = sdi->pdev->dev.of_node; sdi->bridge.type = DRM_MODE_CONNECTOR_LVDS; @@ -344,21 +343,19 @@ int sdi_init_port(struct dss_device *dss, struct platform_device *pdev, u32 datapairs; int r; - sdi = kzalloc(sizeof(*sdi), GFP_KERNEL); - if (!sdi) - return -ENOMEM; + sdi = devm_drm_bridge_alloc(&pdev->dev, struct sdi_device, bridge, &sdi_bridge_funcs); + if (IS_ERR(sdi)) + return PTR_ERR(sdi); ep = of_graph_get_next_port_endpoint(port, NULL); - if (!ep) { - r = 0; - goto err_free; - } + if (!ep) + return 0; r = of_property_read_u32(ep, "datapairs", &datapairs); of_node_put(ep); if (r) { DSSERR("failed to parse datapairs\n"); - goto err_free; + return r; } sdi->datapairs = datapairs; @@ -372,19 +369,14 @@ int sdi_init_port(struct dss_device *dss, struct platform_device *pdev, r = PTR_ERR(sdi->vdds_sdi_reg); if (r != -EPROBE_DEFER) DSSERR("can't get VDDS_SDI regulator\n"); - goto err_free; + return r; } r = sdi_init_output(sdi); if (r) - goto err_free; + return r; return 0; - -err_free: - kfree(sdi); - - return r; } void sdi_uninit_port(struct device_node *port) @@ -395,5 +387,4 @@ void sdi_uninit_port(struct device_node *port) return; sdi_uninit_output(sdi); - kfree(sdi); } -- GitLab From 7e61751b59576e5227d940a4d34f2f6b6400d192 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:39 +0200 Subject: [PATCH 0201/1479] drm/omap: dss: venc: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Switching from a non-devm to a devm allocation allows removing the kfree() in the remove function and in the probe error management code, and as a consequence to simplify the code flow by removing now unnecessary gotos. Acked-by: Maxime Ripard Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-13-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/omapdrm/dss/venc.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index 50349518eda16..9b5d53dc361e6 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -664,7 +664,6 @@ static const struct drm_bridge_funcs venc_bridge_funcs = { static void venc_bridge_init(struct venc_device *venc) { - venc->bridge.funcs = &venc_bridge_funcs; venc->bridge.of_node = venc->pdev->dev.of_node; venc->bridge.ops = DRM_BRIDGE_OP_MODES; venc->bridge.type = DRM_MODE_CONNECTOR_SVIDEO; @@ -809,9 +808,9 @@ static int venc_probe(struct platform_device *pdev) struct venc_device *venc; int r; - venc = kzalloc(sizeof(*venc), GFP_KERNEL); - if (!venc) - return -ENOMEM; + venc = devm_drm_bridge_alloc(&pdev->dev, struct venc_device, bridge, &venc_bridge_funcs); + if (IS_ERR(venc)) + return PTR_ERR(venc); venc->pdev = pdev; @@ -824,26 +823,24 @@ static int venc_probe(struct platform_device *pdev) venc->config = &venc_config_pal_trm; venc->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(venc->base)) { - r = PTR_ERR(venc->base); - goto err_free; - } + if (IS_ERR(venc->base)) + return PTR_ERR(venc->base); venc->vdda_dac_reg = devm_regulator_get(&pdev->dev, "vdda"); if (IS_ERR(venc->vdda_dac_reg)) { r = PTR_ERR(venc->vdda_dac_reg); if (r != -EPROBE_DEFER) DSSERR("can't get VDDA_DAC regulator\n"); - goto err_free; + return r; } r = venc_get_clocks(venc); if (r) - goto err_free; + return r; r = venc_probe_of(venc); if (r) - goto err_free; + return r; pm_runtime_enable(&pdev->dev); @@ -861,8 +858,6 @@ static int venc_probe(struct platform_device *pdev) venc_uninit_output(venc); err_pm_disable: pm_runtime_disable(&pdev->dev); -err_free: - kfree(venc); return r; } @@ -875,8 +870,6 @@ static void venc_remove(struct platform_device *pdev) venc_uninit_output(venc); pm_runtime_disable(&pdev->dev); - - kfree(venc); } static __maybe_unused int venc_runtime_suspend(struct device *dev) -- GitLab From db17fbc2d4de215592296a984b688495b62319e5 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:40 +0200 Subject: [PATCH 0202/1479] drm/rcar-du: dsi: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Acked-by: Maxime Ripard Reviewed-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-14-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c index 7ab8be46c7f65..1af4c73f7a887 100644 --- a/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c +++ b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c @@ -918,7 +918,6 @@ static int rcar_mipi_dsi_host_attach(struct mipi_dsi_host *host, } /* Initialize the DRM bridge. */ - dsi->bridge.funcs = &rcar_mipi_dsi_bridge_ops; dsi->bridge.of_node = dsi->dev->of_node; drm_bridge_add(&dsi->bridge); @@ -1004,9 +1003,10 @@ static int rcar_mipi_dsi_probe(struct platform_device *pdev) struct rcar_mipi_dsi *dsi; int ret; - dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL); - if (dsi == NULL) - return -ENOMEM; + dsi = devm_drm_bridge_alloc(&pdev->dev, struct rcar_mipi_dsi, bridge, + &rcar_mipi_dsi_bridge_ops); + if (IS_ERR(dsi)) + return PTR_ERR(dsi); platform_set_drvdata(pdev, dsi); -- GitLab From ee81a4a27d3311c79d69b2f446c6528a491dfa26 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:41 +0200 Subject: [PATCH 0203/1479] drm/bridge: stm_lvds: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. Acked-by: Raphael Gallais-Pou Acked-by: Maxime Ripard Reviewed-by: Anusha Srivatsa Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-15-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/stm/lvds.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/stm/lvds.c b/drivers/gpu/drm/stm/lvds.c index a3ae9a93ce667..07788e8d3d830 100644 --- a/drivers/gpu/drm/stm/lvds.c +++ b/drivers/gpu/drm/stm/lvds.c @@ -1049,9 +1049,9 @@ static int lvds_probe(struct platform_device *pdev) dev_dbg(dev, "Probing LVDS driver...\n"); - lvds = devm_kzalloc(dev, sizeof(*lvds), GFP_KERNEL); - if (!lvds) - return -ENOMEM; + lvds = devm_drm_bridge_alloc(dev, struct stm_lvds, lvds_bridge, &lvds_bridge_funcs); + if (IS_ERR(lvds)) + return PTR_ERR(lvds); lvds->dev = dev; @@ -1164,7 +1164,6 @@ static int lvds_probe(struct platform_device *pdev) goto err_lvds_probe; } - lvds->lvds_bridge.funcs = &lvds_bridge_funcs; lvds->lvds_bridge.of_node = dev->of_node; lvds->hw_version = lvds_read(lvds, LVDS_VERR); -- GitLab From 3d3f22799c89e6d0d210e0f666c77b3de11429d4 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:42 +0200 Subject: [PATCH 0204/1479] drm/sti: dvo: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. This driver allocates the DRM bridge separately from the main driver private struct, which prevents using the new devm_drm_bridge_alloc() API. Simplify the code by replacing the struct drm_bridge pointer with an embedded struct drm_bridge inside the private struct, to make use of the new API with the same code flow. Acked-by: Maxime Ripard Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-16-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/sti/sti_dvo.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c index 74a1eef4674ee..7484d3c3f4ed5 100644 --- a/drivers/gpu/drm/sti/sti_dvo.c +++ b/drivers/gpu/drm/sti/sti_dvo.c @@ -97,7 +97,7 @@ struct sti_dvo { struct dvo_config *config; bool enabled; struct drm_encoder *encoder; - struct drm_bridge *bridge; + struct drm_bridge bridge; }; struct sti_dvo_connector { @@ -439,7 +439,6 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data) struct drm_encoder *encoder; struct sti_dvo_connector *connector; struct drm_connector *drm_connector; - struct drm_bridge *bridge; int err; /* Set the drm device handle */ @@ -455,20 +454,14 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data) connector->dvo = dvo; - bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL); - if (!bridge) - return -ENOMEM; - - bridge->driver_private = dvo; - bridge->funcs = &sti_dvo_bridge_funcs; - bridge->of_node = dvo->dev.of_node; - drm_bridge_add(bridge); + dvo->bridge.driver_private = dvo; + dvo->bridge.of_node = dvo->dev.of_node; + drm_bridge_add(&dvo->bridge); - err = drm_bridge_attach(encoder, bridge, NULL, 0); + err = drm_bridge_attach(encoder, &dvo->bridge, NULL, 0); if (err) return err; - dvo->bridge = bridge; connector->encoder = encoder; dvo->encoder = encoder; @@ -490,7 +483,7 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data) return 0; err_sysfs: - drm_bridge_remove(bridge); + drm_bridge_remove(&dvo->bridge); return -EINVAL; } @@ -499,7 +492,7 @@ static void sti_dvo_unbind(struct device *dev, { struct sti_dvo *dvo = dev_get_drvdata(dev); - drm_bridge_remove(dvo->bridge); + drm_bridge_remove(&dvo->bridge); } static const struct component_ops sti_dvo_ops = { @@ -515,10 +508,10 @@ static int sti_dvo_probe(struct platform_device *pdev) DRM_INFO("%s\n", __func__); - dvo = devm_kzalloc(dev, sizeof(*dvo), GFP_KERNEL); - if (!dvo) { - DRM_ERROR("Failed to allocate memory for DVO\n"); - return -ENOMEM; + dvo = devm_drm_bridge_alloc(dev, struct sti_dvo, bridge, &sti_dvo_bridge_funcs); + if (IS_ERR(dvo)) { + DRM_ERROR("Failed to allocate DVO\n"); + return PTR_ERR(dvo); } dvo->dev = pdev->dev; -- GitLab From afb903c01b2b7af382392024fb02bbfea62696f7 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:43 +0200 Subject: [PATCH 0205/1479] drm: zynqmp_dp: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. This driver has a peculiar structure. zynqmp_dpsub.c is the actual driver, which delegates to a submodule (zynqmp_dp.c) the allocation of a sub-structure embedding the drm_bridge and its initialization, however it does not delegate the drm_bridge_add(). Hence, following carefully the code flow, it is correct to change the allocation function and .funcs assignment in the submodule, while the drm_bridge_add() is not in that submodule. Acked-by: Maxime Ripard Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-17-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/xlnx/zynqmp_dp.c | 31 ++++++++++------------------- drivers/gpu/drm/xlnx/zynqmp_dpsub.c | 1 - 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c index 238cbb49963ef..02e1feaa61159 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_dp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c @@ -2439,9 +2439,9 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub) struct zynqmp_dp *dp; int ret; - dp = kzalloc(sizeof(*dp), GFP_KERNEL); - if (!dp) - return -ENOMEM; + dp = devm_drm_bridge_alloc(&pdev->dev, struct zynqmp_dp, bridge, &zynqmp_dp_bridge_funcs); + if (IS_ERR(dp)) + return PTR_ERR(dp); dp->dev = &pdev->dev; dp->dpsub = dpsub; @@ -2454,31 +2454,25 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub) /* Acquire all resources (IOMEM, IRQ and PHYs). */ dp->iomem = devm_platform_ioremap_resource_byname(pdev, "dp"); - if (IS_ERR(dp->iomem)) { - ret = PTR_ERR(dp->iomem); - goto err_free; - } + if (IS_ERR(dp->iomem)) + return PTR_ERR(dp->iomem); dp->irq = platform_get_irq(pdev, 0); - if (dp->irq < 0) { - ret = dp->irq; - goto err_free; - } + if (dp->irq < 0) + return dp->irq; dp->reset = devm_reset_control_get(dp->dev, NULL); - if (IS_ERR(dp->reset)) { - ret = dev_err_probe(dp->dev, PTR_ERR(dp->reset), + if (IS_ERR(dp->reset)) + return dev_err_probe(dp->dev, PTR_ERR(dp->reset), "failed to get reset\n"); - goto err_free; - } ret = zynqmp_dp_reset(dp, true); if (ret < 0) - goto err_free; + return ret; ret = zynqmp_dp_reset(dp, false); if (ret < 0) - goto err_free; + return ret; ret = zynqmp_dp_phy_probe(dp); if (ret) @@ -2486,7 +2480,6 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub) /* Initialize the bridge. */ bridge = &dp->bridge; - bridge->funcs = &zynqmp_dp_bridge_funcs; bridge->ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD; bridge->type = DRM_MODE_CONNECTOR_DisplayPort; @@ -2539,8 +2532,6 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub) zynqmp_dp_phy_exit(dp); err_reset: zynqmp_dp_reset(dp, true); -err_free: - kfree(dp); return ret; } diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c index 3a9544b97bc53..2764c4b17c5e4 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c +++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c @@ -180,7 +180,6 @@ static int zynqmp_dpsub_parse_dt(struct zynqmp_dpsub *dpsub) void zynqmp_dpsub_release(struct zynqmp_dpsub *dpsub) { kfree(dpsub->disp); - kfree(dpsub->dp); kfree(dpsub); } -- GitLab From 5164553d739ef45b2c69c8cfe88b9ef26c9a0035 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:46 +0200 Subject: [PATCH 0206/1479] drm/bridge: add devm_drm_put_bridge() Bridges obtained via devm_drm_bridge_alloc(dev, ...) will be put when the requesting device (@dev) is removed. However drivers which obtained them may need to put the obtained reference explicitly. One such case is if they bind the devm removal action to a different device than the one implemented by the driver itself and which might be removed at a different time, such as bridge/panel.c. Add devm_drm_put_bridge() to manually release a devm-obtained bridge in such cases. This function is considered only a temporary workaround until the panel bridge is reworked and should be removed afterwards. Acked-by: Maxime Ripard Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-20-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/drm_bridge.c | 17 +++++++++++++++++ include/drm/drm_bridge.h | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index b4c89ec01998b..d0e81639927a7 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -1392,6 +1392,23 @@ struct drm_bridge *of_drm_find_bridge(struct device_node *np) EXPORT_SYMBOL(of_drm_find_bridge); #endif +/** + * devm_drm_put_bridge - Release a bridge reference obtained via devm + * @dev: device that got the bridge via devm + * @bridge: pointer to a struct drm_bridge obtained via devm + * + * Same as drm_bridge_put() for bridge pointers obtained via devm functions + * such as devm_drm_bridge_alloc(). + * + * This function is a temporary workaround and MUST NOT be used. Manual + * handling of bridge lifetime is inherently unsafe. + */ +void devm_drm_put_bridge(struct device *dev, struct drm_bridge *bridge) +{ + devm_release_action(dev, drm_bridge_put_void, bridge); +} +EXPORT_SYMBOL(devm_drm_put_bridge); + static void drm_bridge_debugfs_show_bridge(struct drm_printer *p, struct drm_bridge *bridge, unsigned int idx) diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index cc9f7df38102e..464da28f9134f 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -1311,6 +1311,8 @@ static inline struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, return ERR_PTR(-ENODEV); } +static inline void devm_drm_put_bridge(struct device *dev, struct drm_bridge *bridge) {} + static inline struct drm_bridge *drmm_of_get_bridge(struct drm_device *drm, struct device_node *node, u32 port, @@ -1320,6 +1322,8 @@ static inline struct drm_bridge *drmm_of_get_bridge(struct drm_device *drm, } #endif +void devm_drm_put_bridge(struct device *dev, struct drm_bridge *bridge); + void drm_bridge_debugfs_params(struct dentry *root); void drm_bridge_debugfs_encoder_params(struct dentry *root, struct drm_encoder *encoder); -- GitLab From 6ad88bf9e74dae83c992d8a16683360117b7e2d8 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:47 +0200 Subject: [PATCH 0207/1479] drm/bridge: panel: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. The devm lifetime management of this driver is peculiar. The underlying device for the panel_bridge is the panel, and the devm lifetime is tied the panel device (panel->dev). However the panel_bridge allocation is not performed by the panel driver, but rather by a separate entity (typically the previous bridge in the encoder chain). Thus when that separate entity is destroyed, the panel_bridge is not removed automatically by devm, so it is rather done explicitly by calling drm_panel_bridge_remove(). This is the function that does devm_kfree() the panel_bridge in current code, so update it as well to put the bridge reference instead. This is a temporary solution until the panel lifetime is reworked, which should make this workaround unnecessary, so add a comment to clarify that. Acked-by: Maxime Ripard Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-21-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/bridge/panel.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 79b009ab93960..6cbbfb1381a4a 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -287,15 +287,14 @@ struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel, if (!panel) return ERR_PTR(-EINVAL); - panel_bridge = devm_kzalloc(panel->dev, sizeof(*panel_bridge), - GFP_KERNEL); - if (!panel_bridge) - return ERR_PTR(-ENOMEM); + panel_bridge = devm_drm_bridge_alloc(panel->dev, struct panel_bridge, bridge, + &panel_bridge_bridge_funcs); + if (IS_ERR(panel_bridge)) + return (void *)panel_bridge; panel_bridge->connector_type = connector_type; panel_bridge->panel = panel; - panel_bridge->bridge.funcs = &panel_bridge_bridge_funcs; panel_bridge->bridge.of_node = panel->dev->of_node; panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES; panel_bridge->bridge.type = connector_type; @@ -327,7 +326,8 @@ void drm_panel_bridge_remove(struct drm_bridge *bridge) panel_bridge = drm_bridge_to_panel_bridge(bridge); drm_bridge_remove(bridge); - devm_kfree(panel_bridge->panel->dev, bridge); + /* TODO remove this after reworking panel_bridge lifetime */ + devm_drm_put_bridge(panel_bridge->panel->dev, bridge); } EXPORT_SYMBOL(drm_panel_bridge_remove); -- GitLab From 56764c845aa5be14cd53702fc9f2da23e25857de Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 20 May 2025 17:22:19 +0300 Subject: [PATCH 0208/1479] drm/i915/dp: Fix the enabling/disabling of audio SDP splitting Adjust the enabling/disabling steps of the DP audio SDP splitting according to a recent Bspec update. This moves the enabling to the audio codec enable sequence after the transcoder is enabled and disables SDP splitting explicitly during the audio disable sequence. Bspec requires waiting for a vblank event after the transcoder is enabled and before SDP splitting is enabled. There is no need for an explicit wait for this, since after the transcoder is enabled this vblank event is guaranteed to have happened via a flip done wait (see intel_atomic_commit_tail() -> drm_atomic_helper_wait_for_flip_done()). The bspec update is for LNL+ only, but the HW team clarified that this has been always the intended sequence on all platforms and bspec will be updated everywhere accordingly. The way SDP splitting was originally enabled matched the version of bspec at that time. Adding here the Fixes: line still, since this change fixes a FIFO underrun on PTL during output enabling when DSC is enabled. Bspec: 49283, 68943 Fixes: 8853750dbad8 ("drm/i915: Enable SDP split for DP2.0") Cc: Vinod Govindapillai Acked-by: Jani Nikula Reviewed-by: Vinod Govindapillai Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250520142219.1688401-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_audio.c | 27 +++++++++++++-------- drivers/gpu/drm/i915/display/intel_audio.h | 1 - drivers/gpu/drm/i915/display/intel_ddi.c | 3 --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 -- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 40d8bbd8107d6..55af3a553c58a 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -397,6 +397,19 @@ hsw_audio_config_update(struct intel_encoder *encoder, hsw_hdmi_audio_config_update(encoder, crtc_state); } +static void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state, + bool enable) +{ + struct intel_display *display = to_intel_display(crtc_state); + enum transcoder trans = crtc_state->cpu_transcoder; + + if (!HAS_DP20(display)) + return; + + intel_de_rmw(display, AUD_DP_2DOT0_CTRL(trans), AUD_ENABLE_SDP_SPLIT, + enable && crtc_state->sdp_split_enable ? AUD_ENABLE_SDP_SPLIT : 0); +} + static void hsw_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) @@ -430,6 +443,8 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder, if (needs_wa_14020863754(display)) intel_de_rmw(display, AUD_CHICKENBIT_REG3, DACBE_DISABLE_MIN_HBLANK_FIX, 0); + intel_audio_sdp_split_update(old_crtc_state, false); + mutex_unlock(&display->audio.mutex); } @@ -555,6 +570,8 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder, if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP)) enable_audio_dsc_wa(encoder, crtc_state); + intel_audio_sdp_split_update(crtc_state, true); + if (needs_wa_14020863754(display)) intel_de_rmw(display, AUD_CHICKENBIT_REG3, 0, DACBE_DISABLE_MIN_HBLANK_FIX); @@ -681,16 +698,6 @@ static void ibx_audio_codec_enable(struct intel_encoder *encoder, mutex_unlock(&display->audio.mutex); } -void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state) -{ - struct intel_display *display = to_intel_display(crtc_state); - enum transcoder trans = crtc_state->cpu_transcoder; - - if (HAS_DP20(display)) - intel_de_rmw(display, AUD_DP_2DOT0_CTRL(trans), AUD_ENABLE_SDP_SPLIT, - crtc_state->sdp_split_enable ? AUD_ENABLE_SDP_SPLIT : 0); -} - bool intel_audio_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state) diff --git a/drivers/gpu/drm/i915/display/intel_audio.h b/drivers/gpu/drm/i915/display/intel_audio.h index ad49eefa7182c..42cf886f3d24f 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.h +++ b/drivers/gpu/drm/i915/display/intel_audio.h @@ -31,6 +31,5 @@ int intel_audio_min_cdclk(const struct intel_crtc_state *crtc_state); void intel_audio_init(struct intel_display *display); void intel_audio_register(struct intel_display *display); void intel_audio_deinit(struct intel_display *display); -void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state); #endif /* __INTEL_AUDIO_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 0e6d618b53565..3d47d0ed3c37b 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3507,9 +3507,6 @@ static void intel_ddi_enable(struct intel_atomic_state *state, intel_vrr_transcoder_enable(crtc_state); - /* Enable/Disable DP2.0 SDP split config before transcoder */ - intel_audio_sdp_split_update(crtc_state); - /* 128b/132b SST */ if (!is_hdmi && intel_dp_is_uhbr(crtc_state)) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 57602606acd5a..cc00a73898f14 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -1336,8 +1336,6 @@ static void mst_stream_enable(struct intel_atomic_state *state, FECSTALL_DIS_DPTSTREAM_DPTTG, pipe_config->fec_enable ? FECSTALL_DIS_DPTSTREAM_DPTTG : 0); - intel_audio_sdp_split_update(pipe_config); - intel_enable_transcoder(pipe_config); for_each_pipe_crtc_modeset_enable(display, pipe_crtc, pipe_config, i) { -- GitLab From 49c6dc74b5968885f421f9f1b45eb4890b955870 Mon Sep 17 00:00:00 2001 From: Matt Atwood Date: Tue, 20 May 2025 12:57:49 -0700 Subject: [PATCH 0209/1479] drm/xe/ptl: Update the PTL pci id table Update to current bspec table. Bspec: 72574 Signed-off-by: Matt Atwood Reviewed-by: Tejas Upadhyay Reviewed-by: Clint Taylor Link: https://lore.kernel.org/r/20250520195749.371748-1-matthew.s.atwood@intel.com Signed-off-by: Matt Roper --- include/drm/intel/pciids.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/drm/intel/pciids.h b/include/drm/intel/pciids.h index d212848d07f3f..a7ce9523c50d3 100644 --- a/include/drm/intel/pciids.h +++ b/include/drm/intel/pciids.h @@ -861,6 +861,10 @@ MACRO__(0xB081, ## __VA_ARGS__), \ MACRO__(0xB082, ## __VA_ARGS__), \ MACRO__(0xB083, ## __VA_ARGS__), \ + MACRO__(0xB084, ## __VA_ARGS__), \ + MACRO__(0xB085, ## __VA_ARGS__), \ + MACRO__(0xB086, ## __VA_ARGS__), \ + MACRO__(0xB087, ## __VA_ARGS__), \ MACRO__(0xB08F, ## __VA_ARGS__), \ MACRO__(0xB090, ## __VA_ARGS__), \ MACRO__(0xB0A0, ## __VA_ARGS__), \ -- GitLab From a3436f63aa4f93b043a970cc72a196a501191ecc Mon Sep 17 00:00:00 2001 From: Langyan Ye Date: Wed, 21 May 2025 17:37:43 +0800 Subject: [PATCH 0210/1479] drm/panel-edp: Add KDC KD116N3730A05 Add support for the KDC KD116N3730A05, pleace the EDID here for subsequent reference. 00 ff ff ff ff ff ff 00 2c 83 20 12 00 00 00 00 30 22 01 04 95 1a 0e 78 03 3a 75 9b 5d 5b 96 28 19 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 09 1e 56 dc 50 00 28 30 30 20 36 00 00 90 10 00 00 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fe 00 4b 44 31 31 36 4e 33 37 33 30 41 30 35 00 e2 Signed-off-by: Langyan Ye Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20250521093743.1057466-1-yelangyan@huaqin.corp-partner.google.com --- drivers/gpu/drm/panel/panel-edp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index 9adbe0f114213..5426648e71168 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -2007,6 +2007,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('K', 'D', 'C', 0x044f, &delay_200_500_e50, "KD116N9-30NH-F3"), EDP_PANEL_ENTRY('K', 'D', 'C', 0x05f1, &delay_200_500_e80_d50, "KD116N5-30NV-G7"), EDP_PANEL_ENTRY('K', 'D', 'C', 0x0809, &delay_200_500_e50, "KD116N2930A15"), + EDP_PANEL_ENTRY('K', 'D', 'C', 0x1220, &delay_200_500_e50, "KD116N3730A05"), EDP_PANEL_ENTRY('L', 'G', 'D', 0x0000, &delay_200_500_e200_d200, "Unknown"), EDP_PANEL_ENTRY('L', 'G', 'D', 0x048d, &delay_200_500_e200_d200, "Unknown"), -- GitLab From ee1855582e5e0f8d73428875b91a30785bcc4b7c Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 22 May 2025 09:12:58 +0200 Subject: [PATCH 0211/1479] drm/bridge: fix build with CONFIG_OF=n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 5164553d739e ("drm/bridge: add devm_drm_put_bridge()") adds two declarations for devm_drm_put_bridge(): 1) an inline declaration in the #else branch of '#if defined(CONFIG_OF)...' 2) one outside of the same #if This results in a build failure with CONFIG_OF=n: ../drivers/gpu/drm/drm_bridge.c:1406:6: error: redefinition of ‘devm_drm_put_bridge’ The function has nothing to do with OF, thus fix by removing declaration 1. Fixes: 5164553d739e ("drm/bridge: add devm_drm_put_bridge()") Reported-by: Ville Syrjala Closes: https://oftc.catirclogs.org/dri-devel/2025-05-21#34288266; Tested-by: Chaitanya Kumar Borah Reviewed-by: Chaitanya Kumar Borah Link: https://lore.kernel.org/r/20250522-devm_drm_put_bridge-fix-non-of-build-v1-1-a05234dea046@bootlin.com Signed-off-by: Luca Ceresoli --- include/drm/drm_bridge.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 464da28f9134f..0af5db244db85 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -1311,8 +1311,6 @@ static inline struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, return ERR_PTR(-ENODEV); } -static inline void devm_drm_put_bridge(struct device *dev, struct drm_bridge *bridge) {} - static inline struct drm_bridge *drmm_of_get_bridge(struct drm_device *drm, struct device_node *node, u32 port, -- GitLab From 20a07782dacf7348a259efcc4a2ab56ecbe7aeb1 Mon Sep 17 00:00:00 2001 From: Tomasz Lis Date: Tue, 20 May 2025 01:00:35 +0200 Subject: [PATCH 0212/1479] drm/xe/vf: Fail migration recovery if fixups needed but platform not supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The post-migration recovery needs to be fully implemented for a specific platform in order to make continuation of workloads possible. New platforms introduce changes which affect the recovery procedure, and without a clear verification of support this leads to errors with no straight forward error message explaining the cause. This patch fixes that issue - it introduces a message to be logged when the current driver is known to not support the current platform. Wedging the driver immediately also decreases the amount of additional errors which would come afterwards if the driver continued operation. v2: Show the message during probe as well as during recovery; do not perform any recovery steps if the recovery is bound to fail v3: Use SRIOV-specific logging, fix typos v4: XE_DEBUG_SRIOV to XE_DEBUG check switch, to make testing more straightforward Signed-off-by: Tomasz Lis Cc: Michal Wajdeczko Cc: Michał Winiarski Reviewed-by: Michal Wajdeczko Acked-by: Michał Winiarski Signed-off-by: Michal Wajdeczko Link: https://lore.kernel.org/r/20250519230035.3143966-1-tomasz.lis@intel.com --- drivers/gpu/drm/xe/xe_sriov_vf.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_sriov_vf.c b/drivers/gpu/drm/xe/xe_sriov_vf.c index 2674fa948fda3..46466932375c2 100644 --- a/drivers/gpu/drm/xe/xe_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_sriov_vf.c @@ -123,6 +123,15 @@ * | | | */ +static bool vf_migration_supported(struct xe_device *xe) +{ + /* + * TODO: Add conditions to allow specific platforms, when they're + * supported at production quality. + */ + return IS_ENABLED(CONFIG_DRM_XE_DEBUG); +} + static void migration_worker_func(struct work_struct *w); /** @@ -132,6 +141,9 @@ static void migration_worker_func(struct work_struct *w); void xe_sriov_vf_init_early(struct xe_device *xe) { INIT_WORK(&xe->sriov.vf.migration.worker, migration_worker_func); + + if (!vf_migration_supported(xe)) + xe_sriov_info(xe, "migration not supported by this module version\n"); } /** @@ -236,6 +248,11 @@ static void vf_post_migration_recovery(struct xe_device *xe) goto defer; if (unlikely(err)) goto fail; + if (!vf_migration_supported(xe)) { + xe_sriov_err(xe, "migration not supported by this module version\n"); + err = -ENOTRECOVERABLE; + goto fail; + } need_fixups = vf_post_migration_fixup_ggtt_nodes(xe); /* FIXME: add the recovery steps */ -- GitLab From 370f86bc07bf8aa7f74cea5f6faa51ca1eb92b6f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 22 May 2025 12:34:44 +0200 Subject: [PATCH 0213/1479] drm: renesas: rcar-du: use proper naming for R-Car Not RCAR, but R-Car. Signed-off-by: Wolfram Sang Reviewed-by: Kieran Bingham Reviewed-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Link: https://lore.kernel.org/r/20250522103530.51972-2-wsa+renesas@sang-engineering.com Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/renesas/rcar-du/rcar_du_plane.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/renesas/rcar-du/rcar_du_plane.h index f9893d7d6dfce..e9e59c5e70d54 100644 --- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_plane.h +++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_plane.h @@ -16,7 +16,7 @@ struct rcar_du_format_info; struct rcar_du_group; /* - * The RCAR DU has 8 hardware planes, shared between primary and overlay planes. + * The R-Car DU has 8 hardware planes, shared between primary and overlay planes. * As using overlay planes requires at least one of the CRTCs being enabled, no * more than 7 overlay planes can be available. We thus create 1 primary plane * per CRTC and 7 overlay planes, for a total of up to 9 KMS planes. -- GitLab From 9528e54198f29548b18b0a5b343a31724e83c68b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 22 May 2025 13:00:36 +0300 Subject: [PATCH 0214/1479] drm/panel: abstract of_panel_find() Add a helper to wrap OF-specific calls in drm_panel_add_follower() in preparation for adding an ACPI equivalent in the future. No functional changes. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250522100036.2529624-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/drm_panel.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 650de4da08537..fee65dc65979d 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -473,6 +473,21 @@ int of_drm_get_panel_orientation(const struct device_node *np, EXPORT_SYMBOL(of_drm_get_panel_orientation); #endif +static struct drm_panel *of_find_panel(struct device *follower_dev) +{ + struct device_node *panel_np; + struct drm_panel *panel; + + panel_np = of_parse_phandle(follower_dev->of_node, "panel", 0); + if (!panel_np) + return ERR_PTR(-ENODEV); + + panel = of_drm_find_panel(panel_np); + of_node_put(panel_np); + + return panel; +} + /** * drm_is_panel_follower() - Check if the device is a panel follower * @dev: The 'struct device' to check @@ -518,16 +533,10 @@ EXPORT_SYMBOL(drm_is_panel_follower); int drm_panel_add_follower(struct device *follower_dev, struct drm_panel_follower *follower) { - struct device_node *panel_np; struct drm_panel *panel; int ret; - panel_np = of_parse_phandle(follower_dev->of_node, "panel", 0); - if (!panel_np) - return -ENODEV; - - panel = of_drm_find_panel(panel_np); - of_node_put(panel_np); + panel = of_find_panel(follower_dev); if (IS_ERR(panel)) return PTR_ERR(panel); -- GitLab From 42e5fc672fee07da071a37e06a2454aba85d8efe Mon Sep 17 00:00:00 2001 From: Yumeng Fang Date: Fri, 23 May 2025 14:14:22 +0800 Subject: [PATCH 0215/1479] drm/i915/display: Use str_true_false() helper Remove hard-coded strings by using the str_true_false() helper. Signed-off-by: Yumeng Fang Signed-off-by: Yunjian Long Link: https://lore.kernel.org/r/20250523141422844GEA-yzba-OvN0lZirDsS-@zte.com.cn Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 5 +++-- 1 file changed, 3 insertions(+), 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 3c323f694e694..b671b4ea1a24d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -972,7 +973,7 @@ static ssize_t i915_dsc_fec_support_write(struct file *file, return ret; drm_dbg(display->drm, "Got %s for DSC Enable\n", - (dsc_enable) ? "true" : "false"); + str_true_false(dsc_enable)); intel_dp->force_dsc_en = dsc_enable; *offp += len; @@ -1183,7 +1184,7 @@ static ssize_t i915_dsc_fractional_bpp_write(struct file *file, return ret; drm_dbg(display->drm, "Got %s for DSC Fractional BPP Enable\n", - (dsc_fractional_bpp_enable) ? "true" : "false"); + str_true_false(dsc_fractional_bpp_enable)); intel_dp->force_dsc_fractional_bpp_en = dsc_fractional_bpp_enable; *offp += len; -- GitLab From 9c399719cfb98fd92c7b76dcd57098e5e3ca5cda Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:28 +0200 Subject: [PATCH 0216/1479] drm: convert many bridge drivers from devm_kzalloc() to devm_drm_bridge_alloc() API devm_drm_bridge_alloc() is the new API to be used for allocating (and partially initializing) a private driver struct embedding a struct drm_bridge. For many drivers having a simple code flow in the probe function, this commit does a mass conversion automatically with the following semantic patch. The changes have been reviewed manually for correctness as well as to find any false positives. The patch has been applied with the explicit exclusion of bridge/panel.c, handled by a separate patch. After applying the semantic patch, manually fixed these issues: - 4 drivers need ERR_CAST() instead of PTR_ERR() as the function calling devm_drm_bridge_alloc() returns a pointer - re-added empty lines and comments that the script had removed but that should stay @@ type T; identifier C; identifier BR; expression DEV; expression FUNCS; @@ -T *C; +T *C; ... ( -C = devm_kzalloc(DEV, ...); -if (!C) - return -ENOMEM; +C = devm_drm_bridge_alloc(DEV, T, BR, FUNCS); +if (IS_ERR(C)) + return PTR_ERR(C); | -C = devm_kzalloc(DEV, ...); -if (!C) - return ERR_PTR(-ENOMEM); +C = devm_drm_bridge_alloc(DEV, T, BR, FUNCS); +if (IS_ERR(C)) + return PTR_ERR(C); ) ... -C->BR.funcs = FUNCS; Reviewed-by: Manikandan Muralidharan # microchip-lvds.c Reviewed-by: Douglas Anderson # parade-ps8640 Tested-by: Douglas Anderson # parade-ps8640 Acked-by: Maxime Ripard Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-2-b8bc1f16d7aa@bootlin.com [Luca: fixed trivial patch conflict in adv7511_drv.c while applying] Signed-off-by: Luca Ceresoli --- drivers/gpu/drm/adp/adp-mipi.c | 8 ++++---- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 8 ++++---- drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c | 9 ++++----- drivers/gpu/drm/bridge/aux-bridge.c | 8 ++++---- drivers/gpu/drm/bridge/aux-hpd-bridge.c | 9 +++++---- drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c | 8 ++++---- drivers/gpu/drm/bridge/chipone-icn6211.c | 8 ++++---- drivers/gpu/drm/bridge/chrontel-ch7033.c | 8 ++++---- drivers/gpu/drm/bridge/cros-ec-anx7688.c | 8 ++++---- drivers/gpu/drm/bridge/fsl-ldb.c | 7 +++---- drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c | 8 ++++---- drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c | 8 ++++---- drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c | 8 ++++---- drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c | 8 ++++---- drivers/gpu/drm/bridge/ite-it6263.c | 8 ++++---- drivers/gpu/drm/bridge/ite-it6505.c | 8 ++++---- drivers/gpu/drm/bridge/ite-it66121.c | 8 ++++---- drivers/gpu/drm/bridge/lontium-lt8912b.c | 8 ++++---- drivers/gpu/drm/bridge/lontium-lt9211.c | 7 +++---- drivers/gpu/drm/bridge/lontium-lt9611.c | 8 ++++---- drivers/gpu/drm/bridge/lvds-codec.c | 9 ++++----- drivers/gpu/drm/bridge/microchip-lvds.c | 8 ++++---- drivers/gpu/drm/bridge/nwl-dsi.c | 8 ++++---- drivers/gpu/drm/bridge/parade-ps8622.c | 8 ++++---- drivers/gpu/drm/bridge/parade-ps8640.c | 8 ++++---- drivers/gpu/drm/bridge/sii9234.c | 8 ++++---- drivers/gpu/drm/bridge/sil-sii8620.c | 8 ++++---- drivers/gpu/drm/bridge/simple-bridge.c | 8 ++++---- drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 8 ++++---- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 8 ++++---- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c | 8 ++++---- drivers/gpu/drm/bridge/tc358762.c | 8 ++++---- drivers/gpu/drm/bridge/tc358764.c | 8 ++++---- drivers/gpu/drm/bridge/tc358768.c | 8 ++++---- drivers/gpu/drm/bridge/tc358775.c | 8 ++++---- drivers/gpu/drm/bridge/thc63lvd1024.c | 8 ++++---- drivers/gpu/drm/bridge/ti-dlpc3433.c | 8 ++++---- drivers/gpu/drm/bridge/ti-tdp158.c | 8 ++++---- drivers/gpu/drm/bridge/ti-tfp410.c | 8 ++++---- drivers/gpu/drm/bridge/ti-tpd12s015.c | 8 ++++---- drivers/gpu/drm/mediatek/mtk_dp.c | 8 ++++---- drivers/gpu/drm/mediatek/mtk_dpi.c | 8 ++++---- drivers/gpu/drm/mediatek/mtk_dsi.c | 8 ++++---- drivers/gpu/drm/mediatek/mtk_hdmi.c | 8 ++++---- drivers/gpu/drm/meson/meson_encoder_cvbs.c | 10 ++++++---- drivers/gpu/drm/meson/meson_encoder_dsi.c | 10 ++++++---- drivers/gpu/drm/meson/meson_encoder_hdmi.c | 10 ++++++---- drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c | 8 ++++---- drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 8 ++++---- 49 files changed, 201 insertions(+), 198 deletions(-) diff --git a/drivers/gpu/drm/adp/adp-mipi.c b/drivers/gpu/drm/adp/adp-mipi.c index 2b60128e2c693..cba7d32150a98 100644 --- a/drivers/gpu/drm/adp/adp-mipi.c +++ b/drivers/gpu/drm/adp/adp-mipi.c @@ -229,9 +229,10 @@ static int adp_mipi_probe(struct platform_device *pdev) { struct adp_mipi_drv_private *adp; - adp = devm_kzalloc(&pdev->dev, sizeof(*adp), GFP_KERNEL); - if (!adp) - return -ENOMEM; + adp = devm_drm_bridge_alloc(&pdev->dev, struct adp_mipi_drv_private, + bridge, &adp_dsi_bridge_funcs); + if (IS_ERR(adp)) + return PTR_ERR(adp); adp->mipi = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(adp->mipi)) { @@ -241,7 +242,6 @@ static int adp_mipi_probe(struct platform_device *pdev) adp->dsi.dev = &pdev->dev; adp->dsi.ops = &adp_dsi_host_ops; - adp->bridge.funcs = &adp_dsi_bridge_funcs; adp->bridge.of_node = pdev->dev.of_node; adp->bridge.type = DRM_MODE_CONNECTOR_DSI; dev_set_drvdata(&pdev->dev, adp); diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index 8b7548448615f..022b6d9c2a1f7 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -1153,9 +1153,10 @@ static int adv7511_probe(struct i2c_client *i2c) if (!dev->of_node) return -EINVAL; - adv7511 = devm_kzalloc(dev, sizeof(*adv7511), GFP_KERNEL); - if (!adv7511) - return -ENOMEM; + adv7511 = devm_drm_bridge_alloc(dev, struct adv7511, bridge, + &adv7511_bridge_funcs); + if (IS_ERR(adv7511)) + return PTR_ERR(adv7511); adv7511->i2c_main = i2c; adv7511->powered = false; @@ -1255,7 +1256,6 @@ static int adv7511_probe(struct i2c_client *i2c) regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, ADV7511_CEC_CTRL_POWER_DOWN); - adv7511->bridge.funcs = &adv7511_bridge_funcs; adv7511->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HDMI | diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c index a83020d6576f7..ba0fc149a9e72 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c +++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c @@ -1193,9 +1193,10 @@ static int anx78xx_i2c_probe(struct i2c_client *client) bool found = false; int err; - anx78xx = devm_kzalloc(&client->dev, sizeof(*anx78xx), GFP_KERNEL); - if (!anx78xx) - return -ENOMEM; + anx78xx = devm_drm_bridge_alloc(&client->dev, struct anx78xx, bridge, + &anx78xx_bridge_funcs); + if (IS_ERR(anx78xx)) + return PTR_ERR(anx78xx); pdata = &anx78xx->pdata; @@ -1306,8 +1307,6 @@ static int anx78xx_i2c_probe(struct i2c_client *client) goto err_poweroff; } - anx78xx->bridge.funcs = &anx78xx_bridge_funcs; - drm_bridge_add(&anx78xx->bridge); /* If cable is pulled out, just poweroff and wait for HPD event */ diff --git a/drivers/gpu/drm/bridge/aux-bridge.c b/drivers/gpu/drm/bridge/aux-bridge.c index c179b86d208f7..5b219e3b87b1d 100644 --- a/drivers/gpu/drm/bridge/aux-bridge.c +++ b/drivers/gpu/drm/bridge/aux-bridge.c @@ -109,9 +109,10 @@ static int drm_aux_bridge_probe(struct auxiliary_device *auxdev, { struct drm_aux_bridge_data *data; - data = devm_kzalloc(&auxdev->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; + data = devm_drm_bridge_alloc(&auxdev->dev, struct drm_aux_bridge_data, + bridge, &drm_aux_bridge_funcs); + if (IS_ERR(data)) + return PTR_ERR(data); data->dev = &auxdev->dev; data->next_bridge = devm_drm_of_get_bridge(&auxdev->dev, auxdev->dev.of_node, 0, 0); @@ -119,7 +120,6 @@ static int drm_aux_bridge_probe(struct auxiliary_device *auxdev, return dev_err_probe(&auxdev->dev, PTR_ERR(data->next_bridge), "failed to acquire drm_bridge\n"); - data->bridge.funcs = &drm_aux_bridge_funcs; data->bridge.of_node = data->dev->of_node; /* passthrough data, allow everything */ diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c index b3f588b71a7d7..3eb411f874e41 100644 --- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c +++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c @@ -171,12 +171,13 @@ static int drm_aux_hpd_bridge_probe(struct auxiliary_device *auxdev, { struct drm_aux_hpd_bridge_data *data; - data = devm_kzalloc(&auxdev->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; + data = devm_drm_bridge_alloc(&auxdev->dev, + struct drm_aux_hpd_bridge_data, bridge, + &drm_aux_hpd_bridge_funcs); + if (IS_ERR(data)) + return PTR_ERR(data); data->dev = &auxdev->dev; - data->bridge.funcs = &drm_aux_hpd_bridge_funcs; data->bridge.of_node = dev_get_platdata(data->dev); data->bridge.ops = DRM_BRIDGE_OP_HPD; data->bridge.type = id->driver_data; diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index b431e7efd1f0d..cb5f5a8c539a4 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -2389,9 +2389,10 @@ static int cdns_mhdp_probe(struct platform_device *pdev) int ret; int irq; - mhdp = devm_kzalloc(dev, sizeof(*mhdp), GFP_KERNEL); - if (!mhdp) - return -ENOMEM; + mhdp = devm_drm_bridge_alloc(dev, struct cdns_mhdp_device, bridge, + &cdns_mhdp_bridge_funcs); + if (IS_ERR(mhdp)) + return PTR_ERR(mhdp); clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(clk)) { @@ -2481,7 +2482,6 @@ static int cdns_mhdp_probe(struct platform_device *pdev) mhdp->display_fmt.bpc = 8; mhdp->bridge.of_node = pdev->dev.of_node; - mhdp->bridge.funcs = &cdns_mhdp_bridge_funcs; mhdp->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD; mhdp->bridge.type = DRM_MODE_CONNECTOR_DisplayPort; diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index 634c5b0306679..814713c5bea97 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -691,9 +691,10 @@ static int chipone_common_probe(struct device *dev, struct chipone **icnr) struct chipone *icn; int ret; - icn = devm_kzalloc(dev, sizeof(struct chipone), GFP_KERNEL); - if (!icn) - return -ENOMEM; + icn = devm_drm_bridge_alloc(dev, struct chipone, bridge, + &chipone_bridge_funcs); + if (IS_ERR(icn)) + return PTR_ERR(icn); icn->dev = dev; @@ -701,7 +702,6 @@ static int chipone_common_probe(struct device *dev, struct chipone **icnr) if (ret) return ret; - icn->bridge.funcs = &chipone_bridge_funcs; icn->bridge.type = DRM_MODE_CONNECTOR_DPI; icn->bridge.of_node = dev->of_node; diff --git a/drivers/gpu/drm/bridge/chrontel-ch7033.c b/drivers/gpu/drm/bridge/chrontel-ch7033.c index 210c45c1efd48..ab92747933568 100644 --- a/drivers/gpu/drm/bridge/chrontel-ch7033.c +++ b/drivers/gpu/drm/bridge/chrontel-ch7033.c @@ -536,9 +536,10 @@ static int ch7033_probe(struct i2c_client *client) unsigned int val; int ret; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + priv = devm_drm_bridge_alloc(dev, struct ch7033_priv, bridge, + &ch7033_bridge_funcs); + if (IS_ERR(priv)) + return PTR_ERR(priv); dev_set_drvdata(dev, priv); @@ -575,7 +576,6 @@ static int ch7033_probe(struct i2c_client *client) } INIT_LIST_HEAD(&priv->bridge.list); - priv->bridge.funcs = &ch7033_bridge_funcs; priv->bridge.of_node = dev->of_node; drm_bridge_add(&priv->bridge); diff --git a/drivers/gpu/drm/bridge/cros-ec-anx7688.c b/drivers/gpu/drm/bridge/cros-ec-anx7688.c index c8abd9920fee9..a35dae9b56e24 100644 --- a/drivers/gpu/drm/bridge/cros-ec-anx7688.c +++ b/drivers/gpu/drm/bridge/cros-ec-anx7688.c @@ -103,9 +103,10 @@ static int cros_ec_anx7688_bridge_probe(struct i2c_client *client) u8 buffer[4]; int ret; - anx7688 = devm_kzalloc(dev, sizeof(*anx7688), GFP_KERNEL); - if (!anx7688) - return -ENOMEM; + anx7688 = devm_drm_bridge_alloc(dev, struct cros_ec_anx7688, bridge, + &cros_ec_anx7688_bridge_funcs); + if (IS_ERR(anx7688)) + return PTR_ERR(anx7688); anx7688->client = client; i2c_set_clientdata(client, anx7688); @@ -153,7 +154,6 @@ static int cros_ec_anx7688_bridge_probe(struct i2c_client *client) DRM_WARN("Old ANX7688 FW version (0x%04x), not filtering\n", fw_version); - anx7688->bridge.funcs = &cros_ec_anx7688_bridge_funcs; drm_bridge_add(&anx7688->bridge); return 0; diff --git a/drivers/gpu/drm/bridge/fsl-ldb.c b/drivers/gpu/drm/bridge/fsl-ldb.c index 2cb6dfc7a6d3d..5c3cf37200bce 100644 --- a/drivers/gpu/drm/bridge/fsl-ldb.c +++ b/drivers/gpu/drm/bridge/fsl-ldb.c @@ -298,16 +298,15 @@ static int fsl_ldb_probe(struct platform_device *pdev) struct fsl_ldb *fsl_ldb; int dual_link; - fsl_ldb = devm_kzalloc(dev, sizeof(*fsl_ldb), GFP_KERNEL); - if (!fsl_ldb) - return -ENOMEM; + fsl_ldb = devm_drm_bridge_alloc(dev, struct fsl_ldb, bridge, &funcs); + if (IS_ERR(fsl_ldb)) + return PTR_ERR(fsl_ldb); fsl_ldb->devdata = of_device_get_match_data(dev); if (!fsl_ldb->devdata) return -EINVAL; fsl_ldb->dev = &pdev->dev; - fsl_ldb->bridge.funcs = &funcs; fsl_ldb->bridge.of_node = dev->of_node; fsl_ldb->clk = devm_clk_get(dev, "ldb"); diff --git a/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c b/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c index f072c6ed39ef1..989bc497b0507 100644 --- a/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c +++ b/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c @@ -59,9 +59,10 @@ struct drm_bridge *devm_imx_drm_legacy_bridge(struct device *dev, struct imx_legacy_bridge *imx_bridge; int ret; - imx_bridge = devm_kzalloc(dev, sizeof(*imx_bridge), GFP_KERNEL); - if (!imx_bridge) - return ERR_PTR(-ENOMEM); + imx_bridge = devm_drm_bridge_alloc(dev, struct imx_legacy_bridge, + base, &imx_legacy_bridge_funcs); + if (IS_ERR(imx_bridge)) + return ERR_CAST(imx_bridge); ret = of_get_drm_display_mode(np, &imx_bridge->mode, @@ -72,7 +73,6 @@ struct drm_bridge *devm_imx_drm_legacy_bridge(struct device *dev, imx_bridge->mode.type |= DRM_MODE_TYPE_DRIVER; - imx_bridge->base.funcs = &imx_legacy_bridge_funcs; imx_bridge->base.of_node = np; imx_bridge->base.ops = DRM_BRIDGE_OP_MODES; imx_bridge->base.type = type; diff --git a/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c b/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c index 8a4fd7d77a8d5..3a6f8587a257c 100644 --- a/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c +++ b/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c @@ -140,9 +140,10 @@ static int imx8mp_hdmi_pvi_probe(struct platform_device *pdev) struct device_node *remote; struct imx8mp_hdmi_pvi *pvi; - pvi = devm_kzalloc(&pdev->dev, sizeof(*pvi), GFP_KERNEL); - if (!pvi) - return -ENOMEM; + pvi = devm_drm_bridge_alloc(&pdev->dev, struct imx8mp_hdmi_pvi, + bridge, &imx_hdmi_pvi_bridge_funcs); + if (IS_ERR(pvi)) + return PTR_ERR(pvi); platform_set_drvdata(pdev, pvi); pvi->dev = &pdev->dev; @@ -166,7 +167,6 @@ static int imx8mp_hdmi_pvi_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); /* Register the bridge. */ - pvi->bridge.funcs = &imx_hdmi_pvi_bridge_funcs; pvi->bridge.of_node = pdev->dev.of_node; pvi->bridge.timings = pvi->next_bridge->timings; diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c index e092c9ea99b02..e5943506981df 100644 --- a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c @@ -327,9 +327,10 @@ static int imx8qxp_pixel_link_bridge_probe(struct platform_device *pdev) struct device_node *np = dev->of_node; int ret; - pl = devm_kzalloc(dev, sizeof(*pl), GFP_KERNEL); - if (!pl) - return -ENOMEM; + pl = devm_drm_bridge_alloc(dev, struct imx8qxp_pixel_link, bridge, + &imx8qxp_pixel_link_bridge_funcs); + if (IS_ERR(pl)) + return PTR_ERR(pl); ret = imx_scu_get_handle(&pl->ipc_handle); if (ret) { @@ -384,7 +385,6 @@ static int imx8qxp_pixel_link_bridge_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pl); pl->bridge.driver_private = pl; - pl->bridge.funcs = &imx8qxp_pixel_link_bridge_funcs; pl->bridge.of_node = np; drm_bridge_add(&pl->bridge); diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c index da138ab51b3bd..111310acab2ce 100644 --- a/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c @@ -392,9 +392,10 @@ static int imx8qxp_pxl2dpi_bridge_probe(struct platform_device *pdev) struct device_node *np = dev->of_node; int ret; - p2d = devm_kzalloc(dev, sizeof(*p2d), GFP_KERNEL); - if (!p2d) - return -ENOMEM; + p2d = devm_drm_bridge_alloc(dev, struct imx8qxp_pxl2dpi, bridge, + &imx8qxp_pxl2dpi_bridge_funcs); + if (IS_ERR(p2d)) + return PTR_ERR(p2d); p2d->regmap = syscon_node_to_regmap(np->parent); if (IS_ERR(p2d->regmap)) { @@ -441,7 +442,6 @@ static int imx8qxp_pxl2dpi_bridge_probe(struct platform_device *pdev) pm_runtime_enable(dev); p2d->bridge.driver_private = p2d; - p2d->bridge.funcs = &imx8qxp_pxl2dpi_bridge_funcs; p2d->bridge.of_node = np; drm_bridge_add(&p2d->bridge); diff --git a/drivers/gpu/drm/bridge/ite-it6263.c b/drivers/gpu/drm/bridge/ite-it6263.c index a3a63a977b0a8..c4eedf643f39e 100644 --- a/drivers/gpu/drm/bridge/ite-it6263.c +++ b/drivers/gpu/drm/bridge/ite-it6263.c @@ -816,9 +816,10 @@ static int it6263_probe(struct i2c_client *client) struct it6263 *it; int ret; - it = devm_kzalloc(dev, sizeof(*it), GFP_KERNEL); - if (!it) - return -ENOMEM; + it = devm_drm_bridge_alloc(dev, struct it6263, bridge, + &it6263_bridge_funcs); + if (IS_ERR(it)) + return PTR_ERR(it); it->dev = dev; it->hdmi_i2c = client; @@ -866,7 +867,6 @@ static int it6263_probe(struct i2c_client *client) i2c_set_clientdata(client, it); - it->bridge.funcs = &it6263_bridge_funcs; it->bridge.of_node = dev->of_node; /* IT6263 chip doesn't support HPD interrupt. */ it->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index 1383d1e21afea..b0dc9280d870c 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -3583,9 +3583,10 @@ static int it6505_i2c_probe(struct i2c_client *client) struct extcon_dev *extcon; int err; - it6505 = devm_kzalloc(&client->dev, sizeof(*it6505), GFP_KERNEL); - if (!it6505) - return -ENOMEM; + it6505 = devm_drm_bridge_alloc(&client->dev, struct it6505, bridge, + &it6505_bridge_funcs); + if (IS_ERR(it6505)) + return PTR_ERR(it6505); mutex_init(&it6505->extcon_lock); mutex_init(&it6505->mode_lock); @@ -3660,7 +3661,6 @@ static int it6505_i2c_probe(struct i2c_client *client) it6505->aux.transfer = it6505_aux_transfer; drm_dp_aux_init(&it6505->aux); - it6505->bridge.funcs = &it6505_bridge_funcs; it6505->bridge.type = DRM_MODE_CONNECTOR_DisplayPort; it6505->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD; diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c index 7b110ae532918..6494f08427938 100644 --- a/drivers/gpu/drm/bridge/ite-it66121.c +++ b/drivers/gpu/drm/bridge/ite-it66121.c @@ -1516,9 +1516,10 @@ static int it66121_probe(struct i2c_client *client) return -ENXIO; } - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_bridge_alloc(dev, struct it66121_ctx, bridge, + &it66121_bridge_funcs); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); ep = of_graph_get_endpoint_by_regs(dev->of_node, 0, 0); if (!ep) @@ -1577,7 +1578,6 @@ static int it66121_probe(struct i2c_client *client) return -ENODEV; } - ctx->bridge.funcs = &it66121_bridge_funcs; ctx->bridge.of_node = dev->of_node; ctx->bridge.type = DRM_MODE_CONNECTOR_HDMIA; ctx->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID; diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c index 3e49d855b3648..bd83228b0f0eb 100644 --- a/drivers/gpu/drm/bridge/lontium-lt8912b.c +++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c @@ -761,9 +761,10 @@ static int lt8912_probe(struct i2c_client *client) int ret = 0; struct device *dev = &client->dev; - lt = devm_kzalloc(dev, sizeof(struct lt8912), GFP_KERNEL); - if (!lt) - return -ENOMEM; + lt = devm_drm_bridge_alloc(dev, struct lt8912, bridge, + <8912_bridge_funcs); + if (IS_ERR(lt)) + return PTR_ERR(lt); lt->dev = dev; lt->i2c_client[0] = client; @@ -778,7 +779,6 @@ static int lt8912_probe(struct i2c_client *client) i2c_set_clientdata(client, lt); - lt->bridge.funcs = <8912_bridge_funcs; lt->bridge.of_node = dev->of_node; lt->bridge.ops = (DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_DETECT); diff --git a/drivers/gpu/drm/bridge/lontium-lt9211.c b/drivers/gpu/drm/bridge/lontium-lt9211.c index 9b2dac9bd63c5..399fa7eebd49c 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9211.c +++ b/drivers/gpu/drm/bridge/lontium-lt9211.c @@ -727,9 +727,9 @@ static int lt9211_probe(struct i2c_client *client) struct lt9211 *ctx; int ret; - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_bridge_alloc(dev, struct lt9211, bridge, <9211_funcs); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); ctx->dev = dev; @@ -755,7 +755,6 @@ static int lt9211_probe(struct i2c_client *client) dev_set_drvdata(dev, ctx); i2c_set_clientdata(client, ctx); - ctx->bridge.funcs = <9211_funcs; ctx->bridge.of_node = dev->of_node; drm_bridge_add(&ctx->bridge); diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c index a35a8b8ca89c2..d6ee79c1e4277 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -1072,9 +1072,10 @@ static int lt9611_probe(struct i2c_client *client) return -ENODEV; } - lt9611 = devm_kzalloc(dev, sizeof(*lt9611), GFP_KERNEL); - if (!lt9611) - return -ENOMEM; + lt9611 = devm_drm_bridge_alloc(dev, struct lt9611, bridge, + <9611_bridge_funcs); + if (IS_ERR(lt9611)) + return PTR_ERR(lt9611); lt9611->dev = dev; lt9611->client = client; @@ -1127,7 +1128,6 @@ static int lt9611_probe(struct i2c_client *client) /* Disable Audio InfoFrame, enabled by default */ regmap_update_bits(lt9611->regmap, 0x843d, LT9611_INFOFRAME_AUDIO, 0); - lt9611->bridge.funcs = <9611_bridge_funcs; lt9611->bridge.of_node = client->dev.of_node; lt9611->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD | DRM_BRIDGE_OP_MODES | diff --git a/drivers/gpu/drm/bridge/lvds-codec.c b/drivers/gpu/drm/bridge/lvds-codec.c index 1646e454e0b0b..e6a7147e141b6 100644 --- a/drivers/gpu/drm/bridge/lvds-codec.c +++ b/drivers/gpu/drm/bridge/lvds-codec.c @@ -118,9 +118,10 @@ static int lvds_codec_probe(struct platform_device *pdev) u32 val; int ret; - lvds_codec = devm_kzalloc(dev, sizeof(*lvds_codec), GFP_KERNEL); - if (!lvds_codec) - return -ENOMEM; + lvds_codec = devm_drm_bridge_alloc(dev, struct lvds_codec, bridge, + &funcs); + if (IS_ERR(lvds_codec)) + return PTR_ERR(lvds_codec); lvds_codec->dev = &pdev->dev; lvds_codec->connector_type = (uintptr_t)of_device_get_match_data(dev); @@ -156,8 +157,6 @@ static int lvds_codec_probe(struct platform_device *pdev) if (IS_ERR(lvds_codec->panel_bridge)) return PTR_ERR(lvds_codec->panel_bridge); - lvds_codec->bridge.funcs = &funcs; - /* * Decoder input LVDS format is a property of the decoder chip or even * its strapping. Handle data-mapping the same way lvds-panel does. In diff --git a/drivers/gpu/drm/bridge/microchip-lvds.c b/drivers/gpu/drm/bridge/microchip-lvds.c index 1d4ae0097df84..9f4ff82bc6b49 100644 --- a/drivers/gpu/drm/bridge/microchip-lvds.c +++ b/drivers/gpu/drm/bridge/microchip-lvds.c @@ -157,9 +157,10 @@ static int mchp_lvds_probe(struct platform_device *pdev) if (!dev->of_node) return -ENODEV; - lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL); - if (!lvds) - return -ENOMEM; + lvds = devm_drm_bridge_alloc(&pdev->dev, struct mchp_lvds, bridge, + &mchp_lvds_bridge_funcs); + if (IS_ERR(lvds)) + return PTR_ERR(lvds); lvds->dev = dev; @@ -192,7 +193,6 @@ static int mchp_lvds_probe(struct platform_device *pdev) lvds->bridge.of_node = dev->of_node; lvds->bridge.type = DRM_MODE_CONNECTOR_LVDS; - lvds->bridge.funcs = &mchp_lvds_bridge_funcs; dev_set_drvdata(dev, lvds); ret = devm_pm_runtime_enable(dev); diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c index 55912ae11f46a..2f7429b24fc20 100644 --- a/drivers/gpu/drm/bridge/nwl-dsi.c +++ b/drivers/gpu/drm/bridge/nwl-dsi.c @@ -1149,9 +1149,10 @@ static int nwl_dsi_probe(struct platform_device *pdev) struct nwl_dsi *dsi; int ret; - dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); - if (!dsi) - return -ENOMEM; + dsi = devm_drm_bridge_alloc(dev, struct nwl_dsi, bridge, + &nwl_dsi_bridge_funcs); + if (IS_ERR(dsi)) + return PTR_ERR(dsi); dsi->dev = dev; @@ -1180,7 +1181,6 @@ static int nwl_dsi_probe(struct platform_device *pdev) dsi->quirks = (uintptr_t)attr->data; dsi->bridge.driver_private = dsi; - dsi->bridge.funcs = &nwl_dsi_bridge_funcs; dsi->bridge.of_node = dev->of_node; dsi->bridge.timings = &nwl_dsi_timings; dsi->bridge.type = DRM_MODE_CONNECTOR_DSI; diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c index 8726fefc5c654..f879a1df077d2 100644 --- a/drivers/gpu/drm/bridge/parade-ps8622.c +++ b/drivers/gpu/drm/bridge/parade-ps8622.c @@ -449,9 +449,10 @@ static int ps8622_probe(struct i2c_client *client) struct drm_bridge *panel_bridge; int ret; - ps8622 = devm_kzalloc(dev, sizeof(*ps8622), GFP_KERNEL); - if (!ps8622) - return -ENOMEM; + ps8622 = devm_drm_bridge_alloc(dev, struct ps8622_bridge, bridge, + &ps8622_bridge_funcs); + if (IS_ERR(ps8622)) + return PTR_ERR(ps8622); panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0); if (IS_ERR(panel_bridge)) @@ -509,7 +510,6 @@ static int ps8622_probe(struct i2c_client *client) ps8622->bl->props.brightness = PS8622_MAX_BRIGHTNESS; } - ps8622->bridge.funcs = &ps8622_bridge_funcs; ps8622->bridge.type = DRM_MODE_CONNECTOR_LVDS; ps8622->bridge.of_node = dev->of_node; drm_bridge_add(&ps8622->bridge); diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index 2422ff68c1042..825777a5758f6 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -636,9 +636,10 @@ static int ps8640_probe(struct i2c_client *client) int ret; u32 i; - ps_bridge = devm_kzalloc(dev, sizeof(*ps_bridge), GFP_KERNEL); - if (!ps_bridge) - return -ENOMEM; + ps_bridge = devm_drm_bridge_alloc(dev, struct ps8640, bridge, + &ps8640_bridge_funcs); + if (IS_ERR(ps_bridge)) + return PTR_ERR(ps_bridge); mutex_init(&ps_bridge->aux_lock); @@ -662,7 +663,6 @@ static int ps8640_probe(struct i2c_client *client) if (IS_ERR(ps_bridge->gpio_reset)) return PTR_ERR(ps_bridge->gpio_reset); - ps_bridge->bridge.funcs = &ps8640_bridge_funcs; ps_bridge->bridge.of_node = dev->of_node; ps_bridge->bridge.type = DRM_MODE_CONNECTOR_eDP; diff --git a/drivers/gpu/drm/bridge/sii9234.c b/drivers/gpu/drm/bridge/sii9234.c index cd7837c9a6e00..bb1bed03eb5b7 100644 --- a/drivers/gpu/drm/bridge/sii9234.c +++ b/drivers/gpu/drm/bridge/sii9234.c @@ -888,9 +888,10 @@ static int sii9234_probe(struct i2c_client *client) struct device *dev = &client->dev; int ret; - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_bridge_alloc(dev, struct sii9234, bridge, + &sii9234_bridge_funcs); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); ctx->dev = dev; mutex_init(&ctx->lock); @@ -921,7 +922,6 @@ static int sii9234_probe(struct i2c_client *client) i2c_set_clientdata(client, ctx); - ctx->bridge.funcs = &sii9234_bridge_funcs; ctx->bridge.of_node = dev->of_node; drm_bridge_add(&ctx->bridge); diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c index 3af650dc92a16..9e48ad39e1cc9 100644 --- a/drivers/gpu/drm/bridge/sil-sii8620.c +++ b/drivers/gpu/drm/bridge/sil-sii8620.c @@ -2291,9 +2291,10 @@ static int sii8620_probe(struct i2c_client *client) struct sii8620 *ctx; int ret; - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_bridge_alloc(dev, struct sii8620, bridge, + &sii8620_bridge_funcs); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); ctx->dev = dev; mutex_init(&ctx->lock); @@ -2336,7 +2337,6 @@ static int sii8620_probe(struct i2c_client *client) i2c_set_clientdata(client, ctx); - ctx->bridge.funcs = &sii8620_bridge_funcs; ctx->bridge.of_node = dev->of_node; drm_bridge_add(&ctx->bridge); diff --git a/drivers/gpu/drm/bridge/simple-bridge.c b/drivers/gpu/drm/bridge/simple-bridge.c index 70db5b99e5bb8..c66bd913e33ae 100644 --- a/drivers/gpu/drm/bridge/simple-bridge.c +++ b/drivers/gpu/drm/bridge/simple-bridge.c @@ -168,9 +168,10 @@ static int simple_bridge_probe(struct platform_device *pdev) struct simple_bridge *sbridge; struct device_node *remote; - sbridge = devm_kzalloc(&pdev->dev, sizeof(*sbridge), GFP_KERNEL); - if (!sbridge) - return -ENOMEM; + sbridge = devm_drm_bridge_alloc(&pdev->dev, struct simple_bridge, + bridge, &simple_bridge_bridge_funcs); + if (IS_ERR(sbridge)) + return PTR_ERR(sbridge); sbridge->info = of_device_get_match_data(&pdev->dev); @@ -204,7 +205,6 @@ static int simple_bridge_probe(struct platform_device *pdev) "Unable to retrieve enable GPIO\n"); /* Register the bridge. */ - sbridge->bridge.funcs = &simple_bridge_bridge_funcs; sbridge->bridge.of_node = pdev->dev.of_node; sbridge->bridge.timings = sbridge->info->timings; diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index 5e5f8c2f95be1..94dddaf49b3c1 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -1045,9 +1045,10 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev, return ERR_PTR(-ENODEV); } - hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); - if (!hdmi) - return ERR_PTR(-ENOMEM); + hdmi = devm_drm_bridge_alloc(dev, struct dw_hdmi_qp, bridge, + &dw_hdmi_qp_bridge_funcs); + if (IS_ERR(hdmi)) + return ERR_CAST(hdmi); hdmi->dev = dev; @@ -1073,7 +1074,6 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev, return ERR_PTR(ret); hdmi->bridge.driver_private = hdmi; - hdmi->bridge.funcs = &dw_hdmi_qp_bridge_funcs; hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HDMI | diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index b08ada920a501..c0dc0f2976b92 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -1194,9 +1194,10 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, struct dw_mipi_dsi *dsi; int ret; - dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); - if (!dsi) - return ERR_PTR(-ENOMEM); + dsi = devm_drm_bridge_alloc(dev, struct dw_mipi_dsi, bridge, + &dw_mipi_dsi_bridge_funcs); + if (IS_ERR(dsi)) + return ERR_CAST(dsi); dsi->dev = dev; dsi->plat_data = plat_data; @@ -1265,7 +1266,6 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, } dsi->bridge.driver_private = dsi; - dsi->bridge.funcs = &dw_mipi_dsi_bridge_funcs; dsi->bridge.of_node = pdev->dev.of_node; return dsi; diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c index c76f5f2e74d14..fc91aca95d126 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c @@ -914,9 +914,10 @@ __dw_mipi_dsi2_probe(struct platform_device *pdev, struct dw_mipi_dsi2 *dsi2; int ret; - dsi2 = devm_kzalloc(dev, sizeof(*dsi2), GFP_KERNEL); - if (!dsi2) - return ERR_PTR(-ENOMEM); + dsi2 = devm_drm_bridge_alloc(dev, struct dw_mipi_dsi2, bridge, + &dw_mipi_dsi2_bridge_funcs); + if (IS_ERR(dsi2)) + return ERR_CAST(dsi2); dsi2->dev = dev; dsi2->plat_data = plat_data; @@ -981,7 +982,6 @@ __dw_mipi_dsi2_probe(struct platform_device *pdev, } dsi2->bridge.driver_private = dsi2; - dsi2->bridge.funcs = &dw_mipi_dsi2_bridge_funcs; dsi2->bridge.of_node = pdev->dev.of_node; return dsi2; diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c index edf01476f2ef6..98df3e667d4aa 100644 --- a/drivers/gpu/drm/bridge/tc358762.c +++ b/drivers/gpu/drm/bridge/tc358762.c @@ -265,9 +265,10 @@ static int tc358762_probe(struct mipi_dsi_device *dsi) struct tc358762 *ctx; int ret; - ctx = devm_kzalloc(dev, sizeof(struct tc358762), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_bridge_alloc(dev, struct tc358762, bridge, + &tc358762_bridge_funcs); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); mipi_dsi_set_drvdata(dsi, ctx); @@ -288,7 +289,6 @@ static int tc358762_probe(struct mipi_dsi_device *dsi) if (ret < 0) return ret; - ctx->bridge.funcs = &tc358762_bridge_funcs; ctx->bridge.type = DRM_MODE_CONNECTOR_DPI; ctx->bridge.of_node = dev->of_node; ctx->bridge.pre_enable_prev_first = true; diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c index 3f76c890fad9f..084e9d898e226 100644 --- a/drivers/gpu/drm/bridge/tc358764.c +++ b/drivers/gpu/drm/bridge/tc358764.c @@ -347,9 +347,10 @@ static int tc358764_probe(struct mipi_dsi_device *dsi) struct tc358764 *ctx; int ret; - ctx = devm_kzalloc(dev, sizeof(struct tc358764), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = devm_drm_bridge_alloc(dev, struct tc358764, bridge, + &tc358764_bridge_funcs); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); mipi_dsi_set_drvdata(dsi, ctx); @@ -368,7 +369,6 @@ static int tc358764_probe(struct mipi_dsi_device *dsi) if (ret < 0) return ret; - ctx->bridge.funcs = &tc358764_bridge_funcs; ctx->bridge.of_node = dev->of_node; ctx->bridge.pre_enable_prev_first = true; diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c index 063f217a17b6c..fbdc44e162293 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -1287,9 +1287,10 @@ static int tc358768_i2c_probe(struct i2c_client *client) if (!np) return -ENODEV; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + priv = devm_drm_bridge_alloc(dev, struct tc358768_priv, bridge, + &tc358768_bridge_funcs); + if (IS_ERR(priv)) + return PTR_ERR(priv); dev_set_drvdata(dev, priv); priv->dev = dev; @@ -1321,7 +1322,6 @@ static int tc358768_i2c_probe(struct i2c_client *client) priv->dsi_host.dev = dev; priv->dsi_host.ops = &tc358768_dsi_host_ops; - priv->bridge.funcs = &tc358768_bridge_funcs; priv->bridge.timings = &default_tc358768_timings; priv->bridge.of_node = np; diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c index 1b10e6ee1724f..366b12db0e7cb 100644 --- a/drivers/gpu/drm/bridge/tc358775.c +++ b/drivers/gpu/drm/bridge/tc358775.c @@ -659,9 +659,10 @@ static int tc_probe(struct i2c_client *client) struct tc_data *tc; int ret; - tc = devm_kzalloc(dev, sizeof(*tc), GFP_KERNEL); - if (!tc) - return -ENOMEM; + tc = devm_drm_bridge_alloc(dev, struct tc_data, bridge, + &tc_bridge_funcs); + if (IS_ERR(tc)) + return PTR_ERR(tc); tc->dev = dev; tc->i2c = client; @@ -701,7 +702,6 @@ static int tc_probe(struct i2c_client *client) return ret; } - tc->bridge.funcs = &tc_bridge_funcs; tc->bridge.of_node = dev->of_node; tc->bridge.pre_enable_prev_first = true; drm_bridge_add(&tc->bridge); diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c b/drivers/gpu/drm/bridge/thc63lvd1024.c index e2fc78adebcf2..2cb7cd0c06082 100644 --- a/drivers/gpu/drm/bridge/thc63lvd1024.c +++ b/drivers/gpu/drm/bridge/thc63lvd1024.c @@ -181,9 +181,10 @@ static int thc63_probe(struct platform_device *pdev) struct thc63_dev *thc63; int ret; - thc63 = devm_kzalloc(&pdev->dev, sizeof(*thc63), GFP_KERNEL); - if (!thc63) - return -ENOMEM; + thc63 = devm_drm_bridge_alloc(&pdev->dev, struct thc63_dev, bridge, + &thc63_bridge_func); + if (IS_ERR(thc63)) + return PTR_ERR(thc63); thc63->dev = &pdev->dev; platform_set_drvdata(pdev, thc63); @@ -208,7 +209,6 @@ static int thc63_probe(struct platform_device *pdev) thc63->bridge.driver_private = thc63; thc63->bridge.of_node = pdev->dev.of_node; - thc63->bridge.funcs = &thc63_bridge_func; thc63->bridge.timings = &thc63->timings; drm_bridge_add(&thc63->bridge); diff --git a/drivers/gpu/drm/bridge/ti-dlpc3433.c b/drivers/gpu/drm/bridge/ti-dlpc3433.c index 47638d1c96ec5..b07f7c9d58909 100644 --- a/drivers/gpu/drm/bridge/ti-dlpc3433.c +++ b/drivers/gpu/drm/bridge/ti-dlpc3433.c @@ -348,9 +348,10 @@ static int dlpc3433_probe(struct i2c_client *client) struct dlpc *dlpc; int ret; - dlpc = devm_kzalloc(dev, sizeof(*dlpc), GFP_KERNEL); - if (!dlpc) - return -ENOMEM; + dlpc = devm_drm_bridge_alloc(dev, struct dlpc, bridge, + &dlpc_bridge_funcs); + if (IS_ERR(dlpc)) + return PTR_ERR(dlpc); dlpc->dev = dev; @@ -365,7 +366,6 @@ static int dlpc3433_probe(struct i2c_client *client) dev_set_drvdata(dev, dlpc); i2c_set_clientdata(client, dlpc); - dlpc->bridge.funcs = &dlpc_bridge_funcs; dlpc->bridge.of_node = dev->of_node; drm_bridge_add(&dlpc->bridge); diff --git a/drivers/gpu/drm/bridge/ti-tdp158.c b/drivers/gpu/drm/bridge/ti-tdp158.c index cca75443f0121..27053d020df7c 100644 --- a/drivers/gpu/drm/bridge/ti-tdp158.c +++ b/drivers/gpu/drm/bridge/ti-tdp158.c @@ -68,9 +68,10 @@ static int tdp158_probe(struct i2c_client *client) struct tdp158 *tdp158; struct device *dev = &client->dev; - tdp158 = devm_kzalloc(dev, sizeof(*tdp158), GFP_KERNEL); - if (!tdp158) - return -ENOMEM; + tdp158 = devm_drm_bridge_alloc(dev, struct tdp158, bridge, + &tdp158_bridge_funcs); + if (IS_ERR(tdp158)) + return PTR_ERR(tdp158); tdp158->next = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0); if (IS_ERR(tdp158->next)) @@ -89,7 +90,6 @@ static int tdp158_probe(struct i2c_client *client) return dev_err_probe(dev, PTR_ERR(tdp158->enable), "enable"); tdp158->bridge.of_node = dev->of_node; - tdp158->bridge.funcs = &tdp158_bridge_funcs; tdp158->bridge.driver_private = tdp158; tdp158->dev = dev; diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c index e15d232ddbac5..549e8e8edeb4f 100644 --- a/drivers/gpu/drm/bridge/ti-tfp410.c +++ b/drivers/gpu/drm/bridge/ti-tfp410.c @@ -341,14 +341,14 @@ static int tfp410_init(struct device *dev, bool i2c) return -ENXIO; } - dvi = devm_kzalloc(dev, sizeof(*dvi), GFP_KERNEL); - if (!dvi) - return -ENOMEM; + dvi = devm_drm_bridge_alloc(dev, struct tfp410, bridge, + &tfp410_bridge_funcs); + if (IS_ERR(dvi)) + return PTR_ERR(dvi); dvi->dev = dev; dev_set_drvdata(dev, dvi); - dvi->bridge.funcs = &tfp410_bridge_funcs; dvi->bridge.of_node = dev->of_node; dvi->bridge.timings = &dvi->timings; dvi->bridge.type = DRM_MODE_CONNECTOR_DVID; diff --git a/drivers/gpu/drm/bridge/ti-tpd12s015.c b/drivers/gpu/drm/bridge/ti-tpd12s015.c index 1c289051a5987..0919364e80d1f 100644 --- a/drivers/gpu/drm/bridge/ti-tpd12s015.c +++ b/drivers/gpu/drm/bridge/ti-tpd12s015.c @@ -116,13 +116,13 @@ static int tpd12s015_probe(struct platform_device *pdev) struct gpio_desc *gpio; int ret; - tpd = devm_kzalloc(&pdev->dev, sizeof(*tpd), GFP_KERNEL); - if (!tpd) - return -ENOMEM; + tpd = devm_drm_bridge_alloc(&pdev->dev, struct tpd12s015_device, + bridge, &tpd12s015_bridge_funcs); + if (IS_ERR(tpd)) + return PTR_ERR(tpd); platform_set_drvdata(pdev, tpd); - tpd->bridge.funcs = &tpd12s015_bridge_funcs; tpd->bridge.of_node = pdev->dev.of_node; tpd->bridge.type = DRM_MODE_CONNECTOR_HDMIA; tpd->bridge.ops = DRM_BRIDGE_OP_DETECT; diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index b2408abb9d491..bb80686a70e17 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -2725,9 +2725,10 @@ static int mtk_dp_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int ret; - mtk_dp = devm_kzalloc(dev, sizeof(*mtk_dp), GFP_KERNEL); - if (!mtk_dp) - return -ENOMEM; + mtk_dp = devm_drm_bridge_alloc(dev, struct mtk_dp, bridge, + &mtk_dp_bridge_funcs); + if (IS_ERR(mtk_dp)) + return PTR_ERR(mtk_dp); mtk_dp->dev = dev; mtk_dp->data = (struct mtk_dp_data *)of_device_get_match_data(dev); @@ -2785,7 +2786,6 @@ static int mtk_dp_probe(struct platform_device *pdev) if (ret) return ret; - mtk_dp->bridge.funcs = &mtk_dp_bridge_funcs; mtk_dp->bridge.of_node = dev->of_node; mtk_dp->bridge.type = mtk_dp->data->bridge_type; diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index 0f3b1ef8e4973..9669bf4b80a14 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -1179,9 +1179,10 @@ static int mtk_dpi_probe(struct platform_device *pdev) struct mtk_dpi *dpi; int ret; - dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL); - if (!dpi) - return -ENOMEM; + dpi = devm_drm_bridge_alloc(dev, struct mtk_dpi, bridge, + &mtk_dpi_bridge_funcs); + if (IS_ERR(dpi)) + return PTR_ERR(dpi); dpi->dev = dev; dpi->conf = (struct mtk_dpi_conf *)of_device_get_match_data(dev); @@ -1233,7 +1234,6 @@ static int mtk_dpi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dpi); - dpi->bridge.funcs = &mtk_dpi_bridge_funcs; dpi->bridge.of_node = dev->of_node; dpi->bridge.type = DRM_MODE_CONNECTOR_DPI; diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 4fe1f38a3c4b7..d7726091819c4 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -1196,9 +1196,10 @@ static int mtk_dsi_probe(struct platform_device *pdev) int irq_num; int ret; - dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); - if (!dsi) - return -ENOMEM; + dsi = devm_drm_bridge_alloc(dev, struct mtk_dsi, bridge, + &mtk_dsi_bridge_funcs); + if (IS_ERR(dsi)) + return PTR_ERR(dsi); dsi->driver_data = of_device_get_match_data(dev); @@ -1246,7 +1247,6 @@ static int mtk_dsi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dsi); - dsi->bridge.funcs = &mtk_dsi_bridge_funcs; dsi->bridge.of_node = dev->of_node; dsi->bridge.type = DRM_MODE_CONNECTOR_DSI; diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index c9d0c335c519d..76aecad116bad 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -1690,9 +1690,10 @@ static int mtk_hdmi_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int ret; - hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); - if (!hdmi) - return -ENOMEM; + hdmi = devm_drm_bridge_alloc(dev, struct mtk_hdmi, bridge, + &mtk_hdmi_bridge_funcs); + if (IS_ERR(hdmi)) + return PTR_ERR(hdmi); hdmi->dev = dev; hdmi->conf = of_device_get_match_data(dev); @@ -1719,7 +1720,6 @@ static int mtk_hdmi_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "Failed to register audio driver\n"); - hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs; hdmi->bridge.of_node = pdev->dev.of_node; hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD; diff --git a/drivers/gpu/drm/meson/meson_encoder_cvbs.c b/drivers/gpu/drm/meson/meson_encoder_cvbs.c index c9678dc68fa14..dc374bfc5951c 100644 --- a/drivers/gpu/drm/meson/meson_encoder_cvbs.c +++ b/drivers/gpu/drm/meson/meson_encoder_cvbs.c @@ -227,9 +227,12 @@ int meson_encoder_cvbs_probe(struct meson_drm *priv) struct device_node *remote; int ret; - meson_encoder_cvbs = devm_kzalloc(priv->dev, sizeof(*meson_encoder_cvbs), GFP_KERNEL); - if (!meson_encoder_cvbs) - return -ENOMEM; + meson_encoder_cvbs = devm_drm_bridge_alloc(priv->dev, + struct meson_encoder_cvbs, + bridge, + &meson_encoder_cvbs_bridge_funcs); + if (IS_ERR(meson_encoder_cvbs)) + return PTR_ERR(meson_encoder_cvbs); /* CVBS Connector Bridge */ remote = of_graph_get_remote_node(priv->dev->of_node, 0, 0); @@ -245,7 +248,6 @@ int meson_encoder_cvbs_probe(struct meson_drm *priv) "Failed to find CVBS Connector bridge\n"); /* CVBS Encoder Bridge */ - meson_encoder_cvbs->bridge.funcs = &meson_encoder_cvbs_bridge_funcs; meson_encoder_cvbs->bridge.of_node = priv->dev->of_node; meson_encoder_cvbs->bridge.type = DRM_MODE_CONNECTOR_Composite; meson_encoder_cvbs->bridge.ops = DRM_BRIDGE_OP_MODES; diff --git a/drivers/gpu/drm/meson/meson_encoder_dsi.c b/drivers/gpu/drm/meson/meson_encoder_dsi.c index 3db518e5f95d3..6c6624f9ba24a 100644 --- a/drivers/gpu/drm/meson/meson_encoder_dsi.c +++ b/drivers/gpu/drm/meson/meson_encoder_dsi.c @@ -106,9 +106,12 @@ int meson_encoder_dsi_probe(struct meson_drm *priv) struct device_node *remote; int ret; - meson_encoder_dsi = devm_kzalloc(priv->dev, sizeof(*meson_encoder_dsi), GFP_KERNEL); - if (!meson_encoder_dsi) - return -ENOMEM; + meson_encoder_dsi = devm_drm_bridge_alloc(priv->dev, + struct meson_encoder_dsi, + bridge, + &meson_encoder_dsi_bridge_funcs); + if (IS_ERR(meson_encoder_dsi)) + return PTR_ERR(meson_encoder_dsi); /* DSI Transceiver Bridge */ remote = of_graph_get_remote_node(priv->dev->of_node, 2, 0); @@ -123,7 +126,6 @@ int meson_encoder_dsi_probe(struct meson_drm *priv) "Failed to find DSI transceiver bridge\n"); /* DSI Encoder Bridge */ - meson_encoder_dsi->bridge.funcs = &meson_encoder_dsi_bridge_funcs; meson_encoder_dsi->bridge.of_node = priv->dev->of_node; meson_encoder_dsi->bridge.type = DRM_MODE_CONNECTOR_DSI; diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c index 040c04b5dff9f..5a0d37a257f53 100644 --- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c +++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c @@ -376,9 +376,12 @@ int meson_encoder_hdmi_probe(struct meson_drm *priv) struct device_node *remote; int ret; - meson_encoder_hdmi = devm_kzalloc(priv->dev, sizeof(*meson_encoder_hdmi), GFP_KERNEL); - if (!meson_encoder_hdmi) - return -ENOMEM; + meson_encoder_hdmi = devm_drm_bridge_alloc(priv->dev, + struct meson_encoder_hdmi, + bridge, + &meson_encoder_hdmi_bridge_funcs); + if (IS_ERR(meson_encoder_hdmi)) + return PTR_ERR(meson_encoder_hdmi); /* HDMI Transceiver Bridge */ remote = of_graph_get_remote_node(priv->dev->of_node, 1, 0); @@ -395,7 +398,6 @@ int meson_encoder_hdmi_probe(struct meson_drm *priv) } /* HDMI Encoder Bridge */ - meson_encoder_hdmi->bridge.funcs = &meson_encoder_hdmi_bridge_funcs; meson_encoder_hdmi->bridge.of_node = priv->dev->of_node; meson_encoder_hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA; meson_encoder_hdmi->bridge.interlace_allowed = true; diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c b/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c index a9145253294fc..af58b814e5887 100644 --- a/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c +++ b/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c @@ -878,9 +878,10 @@ static int rcar_lvds_probe(struct platform_device *pdev) struct rcar_lvds *lvds; int ret; - lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL); - if (lvds == NULL) - return -ENOMEM; + lvds = devm_drm_bridge_alloc(&pdev->dev, struct rcar_lvds, bridge, + &rcar_lvds_bridge_ops); + if (IS_ERR(lvds)) + return PTR_ERR(lvds); platform_set_drvdata(pdev, lvds); @@ -895,7 +896,6 @@ static int rcar_lvds_probe(struct platform_device *pdev) if (ret < 0) return ret; - lvds->bridge.funcs = &rcar_lvds_bridge_ops; lvds->bridge.of_node = pdev->dev.of_node; lvds->mmio = devm_platform_ioremap_resource(pdev, 0); diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c index dc6ab012cdb69..8ba0dde8d4822 100644 --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c @@ -701,9 +701,10 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev) u32 txsetr; int ret; - dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL); - if (!dsi) - return -ENOMEM; + dsi = devm_drm_bridge_alloc(&pdev->dev, struct rzg2l_mipi_dsi, bridge, + &rzg2l_mipi_dsi_bridge_ops); + if (IS_ERR(dsi)) + return PTR_ERR(dsi); platform_set_drvdata(pdev, dsi); dsi->dev = &pdev->dev; @@ -761,7 +762,6 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev) pm_runtime_put(dsi->dev); /* Initialize the DRM bridge. */ - dsi->bridge.funcs = &rzg2l_mipi_dsi_bridge_ops; dsi->bridge.of_node = dsi->dev->of_node; /* Init host device */ -- GitLab From 027ce1eff321684e028e0d80d5c1c29f97cf0da3 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 9 May 2025 15:53:48 +0200 Subject: [PATCH 0217/1479] drm/todo: add entry to remove devm_drm_put_bridge() devm_drm_put_bridge() is a temporary workaround waiting for the panel bridge lifetime rework. Add a TODO entry to not forget it must be removed after such rework. Suggested-by: Maxime Ripard Acked-by: Maxime Ripard Link: https://lore.kernel.org/r/20250509-drm-bridge-convert-to-alloc-api-v3-22-b8bc1f16d7aa@bootlin.com Signed-off-by: Luca Ceresoli --- Documentation/gpu/todo.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index c57777a24e03d..be8637da3fe95 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -515,6 +515,21 @@ Contact: Douglas Anderson Level: Starter +Remove devm_drm_put_bridge() +---------------------------- + +Due to how the panel bridge handles the drm_bridge object lifetime, special +care must be taken to dispose of the drm_bridge object when the +panel_bridge is removed. This is currently managed using +devm_drm_put_bridge(), but that is an unsafe, temporary workaround. To fix +that, the DRM panel lifetime needs to be reworked. After the rework is +done, remove devm_drm_put_bridge() and the TODO in +drm_panel_bridge_remove(). + +Contact: Maxime Ripard , + Luca Ceresoli + +Level: Intermediate Core refactorings ================= -- GitLab From 43adabbe3a7912b2db199a17d446a5d9fcde6fc7 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Tue, 6 May 2025 12:27:15 +0300 Subject: [PATCH 0218/1479] dt-bindings: display: panel: Document Renesas R61307 based DSI panel R61307 is liquid crystal driver for high-definition amorphous silicon (a-Si) panels and is ideal for tablets and smartphones. Signed-off-by: Svyatoslav Ryhel Reviewed-by: Rob Herring (Arm) Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20250506092718.106088-2-clamor95@gmail.com Signed-off-by: Dmitry Baryshkov --- .../display/panel/renesas,r61307.yaml | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/renesas,r61307.yaml diff --git a/Documentation/devicetree/bindings/display/panel/renesas,r61307.yaml b/Documentation/devicetree/bindings/display/panel/renesas,r61307.yaml new file mode 100644 index 0000000000000..90cce221c0d12 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/renesas,r61307.yaml @@ -0,0 +1,94 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/renesas,r61307.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas R61307 based DSI Display Panel + +maintainers: + - Svyatoslav Ryhel + +description: + The Renesas R61307 is a generic DSI Panel IC used to control LCD panels. + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + items: + - enum: + # KOE/HITACHI TX13D100VM0EAA 5.0" XGA TFT LCD panel + - hit,tx13d100vm0eaa + - koe,tx13d100vm0eaa + - const: renesas,r61307 + + reg: + maxItems: 1 + + vcc-supply: + description: Regulator for main power supply. + + iovcc-supply: + description: Regulator for 1.8V IO power supply. + + backlight: true + + renesas,gamma: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + 0 - disabled + 1-3 - gamma setting A presets + enum: [0, 1, 2, 3] + + renesas,column-inversion: + type: boolean + description: switch between line and column inversion. The line + inversion is set by default. + + renesas,contrast: + type: boolean + description: digital contrast adjustment + + reset-gpios: true + port: true + +required: + - compatible + - port + - backlight + +additionalProperties: false + +examples: + - | + #include + + dsi { + #address-cells = <1>; + #size-cells = <0>; + + panel@1 { + compatible = "koe,tx13d100vm0eaa", "renesas,r61307"; + reg = <1>; + + reset-gpios = <&gpio 176 GPIO_ACTIVE_LOW>; + + renesas,gamma = <3>; + renesas,column-inversion; + renesas,contrast; + + vcc-supply = <&vcc_3v0_lcd>; + iovcc-supply = <&iovcc_1v8_lcd>; + + backlight = <&backlight>; + + port { + panel_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + }; + }; +... -- GitLab From cb6c01ead1eb78f7676ea09fe407c4aa1c5855b3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Tue, 6 May 2025 12:27:16 +0300 Subject: [PATCH 0219/1479] drm: panel: Add support for Renesas R61307 based MIPI DSI panel R61307 is liquid crystal driver for high-definition amorphous silicon (a-Si) panels and is ideal for tablets and smartphones. Supported compatibles are: - hit,tx13d100vm0eaa - koe,tx13d100vm0eaa Signed-off-by: Svyatoslav Ryhel Reviewed-by: Neil Armstrong Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20250506092718.106088-3-clamor95@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/panel/Kconfig | 13 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-renesas-r61307.c | 325 +++++++++++++++++++ 3 files changed, 339 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-renesas-r61307.c diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 721581d425b44..b058959de717d 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -645,6 +645,19 @@ config DRM_PANEL_RAYDIUM_RM69380 This panel controller can be found in the Lenovo Xiaoxin Pad Pro 2021 in combination with an EDO OLED panel. +config DRM_PANEL_RENESAS_R61307 + tristate "Renesas R61307 DSI video mode panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for KOE tx13d100vm0eaa + IPS-LCD module with Renesas R69328 IC. The panel has a 1024x768 + resolution and uses 24 bit RGB per pixel. + + This panel controller can be found in LG Optimus Vu P895 smartphone + in combination with LCD panel. + config DRM_PANEL_RONBO_RB070D30 tristate "Ronbo Electronics RB070D30 panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index 714cbac830e3f..df0105ed7622a 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -65,6 +65,7 @@ obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM67200) += panel-raydium-rm67200.o obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM692E5) += panel-raydium-rm692e5.o obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM69380) += panel-raydium-rm69380.o +obj-$(CONFIG_DRM_PANEL_RENESAS_R61307) += panel-renesas-r61307.o obj-$(CONFIG_DRM_PANEL_RONBO_RB070D30) += panel-ronbo-rb070d30.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_AMS581VF01) += panel-samsung-ams581vf01.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_AMS639RQ08) += panel-samsung-ams639rq08.o diff --git a/drivers/gpu/drm/panel/panel-renesas-r61307.c b/drivers/gpu/drm/panel/panel-renesas-r61307.c new file mode 100644 index 0000000000000..319415194839a --- /dev/null +++ b/drivers/gpu/drm/panel/panel-renesas-r61307.c @@ -0,0 +1,325 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include